Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_lookup.c
Show First 20 Lines • Show All 309 Lines • ▼ Show 20 Lines | namei(struct nameidata *ndp) | ||||
struct file *dfp; | struct file *dfp; | ||||
struct thread *td; | struct thread *td; | ||||
struct proc *p; | struct proc *p; | ||||
struct pwd *pwd; | struct pwd *pwd; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
struct filecaps dirfd_caps; | struct filecaps dirfd_caps; | ||||
struct uio auio; | struct uio auio; | ||||
int error, linklen, startdir_used; | int error, linklen, startdir_used; | ||||
bool handled; | |||||
cnp = &ndp->ni_cnd; | cnp = &ndp->ni_cnd; | ||||
td = cnp->cn_thread; | td = cnp->cn_thread; | ||||
p = td->td_proc; | p = td->td_proc; | ||||
ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_thread->td_ucred; | ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_thread->td_ucred; | ||||
KASSERT(cnp->cn_cred && p, ("namei: bad cred/proc")); | KASSERT(cnp->cn_cred && p, ("namei: bad cred/proc")); | ||||
KASSERT((cnp->cn_nameiop & (~OPMASK)) == 0, | KASSERT((cnp->cn_nameiop & (~OPMASK)) == 0, | ||||
("namei: nameiop contaminated with flags")); | ("namei: nameiop contaminated with flags")); | ||||
KASSERT((cnp->cn_flags & OPMASK) == 0, | KASSERT((cnp->cn_flags & OPMASK) == 0, | ||||
("namei: flags contaminated with nameiops")); | ("namei: flags contaminated with nameiops")); | ||||
MPASS(ndp->ni_startdir == NULL || ndp->ni_startdir->v_type == VDIR || | MPASS(ndp->ni_startdir == NULL || ndp->ni_startdir->v_type == VDIR || | ||||
ndp->ni_startdir->v_type == VBAD); | ndp->ni_startdir->v_type == VBAD); | ||||
TAILQ_INIT(&ndp->ni_cap_tracker); | TAILQ_INIT(&ndp->ni_cap_tracker); | ||||
ndp->ni_lcf = 0; | ndp->ni_lcf = 0; | ||||
ndp->ni_loopcnt = 0; | |||||
startdir_used = 0; | |||||
dp = NULL; | |||||
/* We will set this ourselves if we need it. */ | /* We will set this ourselves if we need it. */ | ||||
cnp->cn_flags &= ~TRAILINGSLASH; | cnp->cn_flags &= ~TRAILINGSLASH; | ||||
ndp->ni_vp = NULL; | |||||
/* | /* | ||||
* Get a buffer for the name to be translated, and copy the | * Get a buffer for the name to be translated, and copy the | ||||
* name into the buffer. | * name into the buffer. | ||||
*/ | */ | ||||
if ((cnp->cn_flags & HASBUF) == 0) | if ((cnp->cn_flags & HASBUF) == 0) | ||||
cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); | cnp->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); | ||||
if (ndp->ni_segflg == UIO_SYSSPACE) | if (ndp->ni_segflg == UIO_SYSSPACE) | ||||
error = copystr(ndp->ni_dirp, cnp->cn_pnbuf, MAXPATHLEN, | error = copystr(ndp->ni_dirp, cnp->cn_pnbuf, MAXPATHLEN, | ||||
&ndp->ni_pathlen); | &ndp->ni_pathlen); | ||||
else | else | ||||
error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, MAXPATHLEN, | error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, MAXPATHLEN, | ||||
&ndp->ni_pathlen); | &ndp->ni_pathlen); | ||||
if (error != 0) { | |||||
namei_cleanup_cnp(cnp); | |||||
return (error); | |||||
} | |||||
cnp->cn_nameptr = cnp->cn_pnbuf; | |||||
/* | /* | ||||
* Don't allow empty pathnames. | * Don't allow empty pathnames. | ||||
*/ | */ | ||||
if (error == 0 && *cnp->cn_pnbuf == '\0') | if (*cnp->cn_pnbuf == '\0') { | ||||
error = ENOENT; | namei_cleanup_cnp(cnp); | ||||
return (ENOENT); | |||||
} | |||||
error = cache_fplookup(ndp, &handled); | |||||
if (handled) | |||||
return (error); | |||||
/* | |||||
* Ignore fast path. | |||||
*/ | |||||
error = 0; | |||||
#ifdef CAPABILITY_MODE | #ifdef CAPABILITY_MODE | ||||
/* | /* | ||||
* In capability mode, lookups must be restricted to happen in | * In capability mode, lookups must be restricted to happen in | ||||
* the subtree with the root specified by the file descriptor: | * the subtree with the root specified by the file descriptor: | ||||
* - The root must be real file descriptor, not the pseudo-descriptor | * - The root must be real file descriptor, not the pseudo-descriptor | ||||
* AT_FDCWD. | * AT_FDCWD. | ||||
* - The passed path must be relative and not absolute. | * - The passed path must be relative and not absolute. | ||||
* - If lookup_cap_dotdot is disabled, path must not contain the | * - If lookup_cap_dotdot is disabled, path must not contain the | ||||
Show All 12 Lines | #ifdef KTRACE | ||||
ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL); | ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL); | ||||
#endif | #endif | ||||
error = ECAPMODE; | error = ECAPMODE; | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
if (error != 0) { | if (error != 0) { | ||||
namei_cleanup_cnp(cnp); | namei_cleanup_cnp(cnp); | ||||
ndp->ni_vp = NULL; | |||||
return (error); | return (error); | ||||
} | } | ||||
ndp->ni_loopcnt = 0; | |||||
#ifdef KTRACE | #ifdef KTRACE | ||||
if (KTRPOINT(td, KTR_NAMEI)) { | if (KTRPOINT(td, KTR_NAMEI)) { | ||||
KASSERT(cnp->cn_thread == curthread, | KASSERT(cnp->cn_thread == curthread, | ||||
("namei not using curthread")); | ("namei not using curthread")); | ||||
ktrnamei(cnp->cn_pnbuf); | ktrnamei(cnp->cn_pnbuf); | ||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* Get starting point for the translation. | * Get starting point for the translation. | ||||
*/ | */ | ||||
pwd = pwd_hold(td); | pwd = pwd_hold(td); | ||||
/* | /* | ||||
* The reference on ni_rootdir is acquired in the block below to avoid | * The reference on ni_rootdir is acquired in the block below to avoid | ||||
* back-to-back atomics for absolute lookups. | * back-to-back atomics for absolute lookups. | ||||
*/ | */ | ||||
ndp->ni_rootdir = pwd->pwd_rdir; | ndp->ni_rootdir = pwd->pwd_rdir; | ||||
ndp->ni_topdir = pwd->pwd_jdir; | ndp->ni_topdir = pwd->pwd_jdir; | ||||
startdir_used = 0; | |||||
dp = NULL; | |||||
cnp->cn_nameptr = cnp->cn_pnbuf; | |||||
if (cnp->cn_pnbuf[0] == '/') { | if (cnp->cn_pnbuf[0] == '/') { | ||||
ndp->ni_resflags |= NIRES_ABS; | ndp->ni_resflags |= NIRES_ABS; | ||||
error = namei_handle_root(ndp, &dp); | error = namei_handle_root(ndp, &dp); | ||||
} else { | } else { | ||||
if (ndp->ni_startdir != NULL) { | if (ndp->ni_startdir != NULL) { | ||||
dp = ndp->ni_startdir; | dp = ndp->ni_startdir; | ||||
startdir_used = 1; | startdir_used = 1; | ||||
} else if (ndp->ni_dirfd == AT_FDCWD) { | } else if (ndp->ni_dirfd == AT_FDCWD) { | ||||
▲ Show 20 Lines • Show All 1,086 Lines • Show Last 20 Lines |