FreeBSD/sys/security/audit/audit_bsm_klib.c
/*
 * Create a canonical path from given path by prefixing either the root
 * directory, or the current working directory.  If the process working
 * directory is NULL, we could use 'rootvnode' to obtain the root directory,
 * but this results in a volfs name written to the audit log. So we will
 * leave the filename starting with '/' in the audit log in this case.
 */
Create a canonical path from given path by prefixing either the root
directory, or the current working directory.  If the process working
directory is NULL, we could use 'rootvnode' to obtain the root directory,
but this results in a volfs name written to the audit log. So we will
leave the filename starting with '/' in the audit log in this case.
Create a canonical path from given path by prefixing either the root directory or the current working directory . If the process working directory is NULL we could use ' rootvnode ' to obtain the root directory but this results in a volfs name written to the audit log . So we will leave the filename starting with ' / ' in the audit log in this case .
void
audit_canon_path(struct thread *td, int dirfd, char *path, char *cpath)
{
	struct vnode *cvnp, *rvnp;
	char *rbuf, *fbuf, *copy;
	struct filedesc *fdp;
	struct sbuf sbf;
	cap_rights_t rights;
	int error, needslash;
	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s: at %s:%d",
	    __func__,  __FILE__, __LINE__);
	copy = path;
	rvnp = cvnp = NULL;
	fdp = td->td_proc->p_fd;
	FILEDESC_SLOCK(fdp);
	if (fdp->fd_rdir != NULL && fdp->fd_rdir != rootvnode) {
		rvnp = fdp->fd_rdir;
		vhold(rvnp);
	}
	if (*path != '/') {
		if (dirfd == AT_FDCWD) {
			cvnp = fdp->fd_cdir;
			vhold(cvnp);
		} else {
			error = fgetvp(td, dirfd, cap_rights_init(&rights), &cvnp);
			if (error) {
				FILEDESC_SUNLOCK(fdp);
				cpath[0] = '\0';
				if (rvnp != NULL)
					vdrop(rvnp);
				return;
			}
			vhold(cvnp);
			vrele(cvnp);
		}
		needslash = (fdp->fd_rdir != cvnp);
	} else {
		needslash = 1;
	}
	FILEDESC_SUNLOCK(fdp);
	(void) sbuf_new(&sbf, cpath, MAXPATHLEN, SBUF_FIXEDLEN);
	while (*copy == '/')
		copy++;
	if (rvnp != NULL) {
		error = vn_fullpath_global(td, rvnp, &rbuf, &fbuf);
		vdrop(rvnp);
		if (error) {
			cpath[0] = '\0';
			if (cvnp != NULL)
				vdrop(cvnp);
			return;
		}
		(void) sbuf_cat(&sbf, rbuf);
		free(fbuf, M_TEMP);
	}
	if (cvnp != NULL) {
		error = vn_fullpath(td, cvnp, &rbuf, &fbuf);
		vdrop(cvnp);
		if (error) {
			cpath[0] = '\0';
			return;
		}
		(void) sbuf_cat(&sbf, rbuf);
		free(fbuf, M_TEMP);
	}
	if (needslash)
		(void) sbuf_putc(&sbf, '/');
        (void) sbuf_cat(&sbf, copy);
	if (sbuf_error(&sbf) != 0) {
		cpath[0] = '\0';
		return;
	}
	sbuf_finish(&sbf);
}
void audit_canon_path ( struct thread * td , int dirfd , char * path , char * cpath ) { struct vnode * cvnp , * rvnp ; char * rbuf , * fbuf , * copy ; struct filedesc * fdp ; struct sbuf sbf ; cap_rights_t rights ; int error , needslash ; WITNESS_WARN ( WARN_GIANTOK | WARN_SLEEPOK , NULL , " " , __func__ , __FILE__ , __LINE__ ) ; copy = path ; rvnp = cvnp = NULL ; fdp = td -> td_proc -> p_fd ; FILEDESC_SLOCK ( fdp ) ; if ( fdp -> fd_rdir != NULL && fdp -> fd_rdir != rootvnode ) { rvnp = fdp -> fd_rdir ; vhold ( rvnp ) ; } if ( * path != ' ' ) { if ( dirfd == AT_FDCWD ) { cvnp = fdp -> fd_cdir ; vhold ( cvnp ) ; } else { error = fgetvp ( td , dirfd , cap_rights_init ( & rights ) , & cvnp ) ; if ( error ) { FILEDESC_SUNLOCK ( fdp ) ; cpath [ 0 ] = ' \0 ' ; if ( rvnp != NULL ) vdrop ( rvnp ) ; return ; } vhold ( cvnp ) ; vrele ( cvnp ) ; } needslash = ( fdp -> fd_rdir != cvnp ) ; } else { needslash = 1 ; } FILEDESC_SUNLOCK ( fdp ) ; ( void ) sbuf_new ( & sbf , cpath , MAXPATHLEN , SBUF_FIXEDLEN ) ; while ( * copy == ' ' ) copy ++ ; if ( rvnp != NULL ) { error = vn_fullpath_global ( td , rvnp , & rbuf , & fbuf ) ; vdrop ( rvnp ) ; if ( error ) { cpath [ 0 ] = ' \0 ' ; if ( cvnp != NULL ) vdrop ( cvnp ) ; return ; } ( void ) sbuf_cat ( & sbf , rbuf ) ; free ( fbuf , M_TEMP ) ; } if ( cvnp != NULL ) { error = vn_fullpath ( td , cvnp , & rbuf , & fbuf ) ; vdrop ( cvnp ) ; if ( error ) { cpath [ 0 ] = ' \0 ' ; return ; } ( void ) sbuf_cat ( & sbf , rbuf ) ; free ( fbuf , M_TEMP ) ; } if ( needslash ) ( void ) sbuf_putc ( & sbf , ' ' ) ; ( void ) sbuf_cat ( & sbf , copy ) ; if ( sbuf_error ( & sbf ) != 0 ) { cpath [ 0 ] = ' \0 ' ; return ; } sbuf_finish ( & sbf ) ; }
Create a canonical path from given path by prefixing either the root
 directory, or the current working directory.
Create a canonical path from given path by prefixing either the root directory or the current working directory .
/*
	 * Make sure that we handle the chroot(2) case.  If there is an
	 * alternate root directory, prepend it to the audited pathname.
	 */ /*
	 * If the supplied path is relative, make sure we capture the current
	 * working directory so we can prepend it to the supplied relative
	 * path.
	 */ /* XXX: fgetvp() that vhold()s vnode instead of vref()ing it would be better */ /*
	 * NB: We require that the supplied array be at least MAXPATHLEN bytes
	 * long.  If this is not the case, then we can run into serious trouble.
	 */ /*
	 * Strip leading forward slashes.
	 */ /*
	 * Make sure we handle chroot(2) and prepend the global path to these
	 * environments.
	 *
	 * NB: vn_fullpath(9) on FreeBSD is less reliable than vn_getpath(9)
	 * on Darwin.  As a result, this may need some additional attention
	 * in the future.
	 */ /*
	 * Now that we have processed any alternate root and relative path
	 * names, add the supplied pathname.
	 */ /*
	 * One or more of the previous sbuf operations could have resulted in
	 * the supplied buffer being overflowed.  Check to see if this is the
	 * case.
	 */