Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_lookup.c
Show First 20 Lines • Show All 171 Lines • ▼ Show 20 Lines | |||||
static void | static void | ||||
nameicap_tracker_add(struct nameidata *ndp, struct vnode *dp) | nameicap_tracker_add(struct nameidata *ndp, struct vnode *dp) | ||||
{ | { | ||||
struct nameicap_tracker *nt; | struct nameicap_tracker *nt; | ||||
if ((ndp->ni_lcf & NI_LCF_CAP_DOTDOT) == 0 || dp->v_type != VDIR) | if ((ndp->ni_lcf & NI_LCF_CAP_DOTDOT) == 0 || dp->v_type != VDIR) | ||||
return; | return; | ||||
if ((ndp->ni_lcf & (NI_LCF_BENEATH_ABS | NI_LCF_BENEATH_LATCHED)) == | |||||
NI_LCF_BENEATH_ABS) { | |||||
MPASS((ndp->ni_lcf & NI_LCF_LATCH) != 0); | |||||
if (dp != ndp->ni_beneath_latch) | |||||
return; | |||||
ndp->ni_lcf |= NI_LCF_BENEATH_LATCHED; | |||||
} | |||||
nt = uma_zalloc(nt_zone, M_WAITOK); | nt = uma_zalloc(nt_zone, M_WAITOK); | ||||
vhold(dp); | vhold(dp); | ||||
nt->dp = dp; | nt->dp = dp; | ||||
TAILQ_INSERT_TAIL(&ndp->ni_cap_tracker, nt, nm_link); | TAILQ_INSERT_TAIL(&ndp->ni_cap_tracker, nt, nm_link); | ||||
} | } | ||||
static void | static void | ||||
nameicap_cleanup(struct nameidata *ndp) | nameicap_cleanup(struct nameidata *ndp) | ||||
Show All 29 Lines | nameicap_check_dotdot(struct nameidata *ndp, struct vnode *dp) | ||||
if (lookup_cap_dotdot_nonlocal == 0 && mp != NULL && | if (lookup_cap_dotdot_nonlocal == 0 && mp != NULL && | ||||
(mp->mnt_flag & MNT_LOCAL) == 0) | (mp->mnt_flag & MNT_LOCAL) == 0) | ||||
return (ENOTCAPABLE); | return (ENOTCAPABLE); | ||||
TAILQ_FOREACH_REVERSE(nt, &ndp->ni_cap_tracker, nameicap_tracker_head, | TAILQ_FOREACH_REVERSE(nt, &ndp->ni_cap_tracker, nameicap_tracker_head, | ||||
nm_link) { | nm_link) { | ||||
if (dp == nt->dp) | if (dp == nt->dp) | ||||
return (0); | return (0); | ||||
} | } | ||||
if ((ndp->ni_lcf & NI_LCF_BENEATH_ABS) != 0) { | |||||
ndp->ni_lcf &= ~NI_LCF_BENEATH_LATCHED; | |||||
nameicap_cleanup(ndp); | |||||
} | |||||
return (ENOTCAPABLE); | return (ENOTCAPABLE); | ||||
} | } | ||||
static void | static void | ||||
namei_cleanup_cnp(struct componentname *cnp) | namei_cleanup_cnp(struct componentname *cnp) | ||||
{ | { | ||||
uma_zfree(namei_zone, cnp->cn_pnbuf); | uma_zfree(namei_zone, cnp->cn_pnbuf); | ||||
#ifdef DIAGNOSTIC | #ifdef DIAGNOSTIC | ||||
cnp->cn_pnbuf = NULL; | cnp->cn_pnbuf = NULL; | ||||
cnp->cn_nameptr = NULL; | cnp->cn_nameptr = NULL; | ||||
#endif | #endif | ||||
} | } | ||||
static void | |||||
namei_cleanup_vp(struct nameidata *ndp) | |||||
{ | |||||
vput(ndp->ni_vp); | |||||
ndp->ni_vp = NULL; | |||||
vrele(ndp->ni_dvp); | |||||
} | |||||
static int | static int | ||||
namei_handle_root(struct nameidata *ndp, struct vnode **dpp) | namei_handle_root(struct nameidata *ndp, struct vnode **dpp) | ||||
{ | { | ||||
struct componentname *cnp; | struct componentname *cnp; | ||||
cnp = &ndp->ni_cnd; | cnp = &ndp->ni_cnd; | ||||
if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0 || | if ((ndp->ni_lcf & NI_LCF_STRICTRELATIVE) != 0) { | ||||
(cnp->cn_flags & BENEATH) != 0) { | |||||
#ifdef KTRACE | #ifdef KTRACE | ||||
if (KTRPOINT(curthread, KTR_CAPFAIL)) | if (KTRPOINT(curthread, KTR_CAPFAIL)) | ||||
ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL); | ktrcapfail(CAPFAIL_LOOKUP, NULL, NULL); | ||||
#endif | #endif | ||||
return (ENOTCAPABLE); | return (ENOTCAPABLE); | ||||
} | } | ||||
if ((cnp->cn_flags & BENEATH) != 0) { | |||||
ndp->ni_lcf |= NI_LCF_BENEATH_ABS; | |||||
ndp->ni_lcf &= ~NI_LCF_BENEATH_LATCHED; | |||||
nameicap_cleanup(ndp); | |||||
} | |||||
while (*(cnp->cn_nameptr) == '/') { | while (*(cnp->cn_nameptr) == '/') { | ||||
cnp->cn_nameptr++; | cnp->cn_nameptr++; | ||||
ndp->ni_pathlen--; | ndp->ni_pathlen--; | ||||
} | } | ||||
*dpp = ndp->ni_rootdir; | *dpp = ndp->ni_rootdir; | ||||
vrefact(*dpp); | vrefact(*dpp); | ||||
return (0); | return (0); | ||||
} | } | ||||
Show All 24 Lines | namei(struct nameidata *ndp) | ||||
struct filedesc *fdp; /* pointer to file descriptor state */ | struct filedesc *fdp; /* pointer to file descriptor state */ | ||||
char *cp; /* pointer into pathname argument */ | char *cp; /* pointer into pathname argument */ | ||||
struct vnode *dp; /* the directory we are searching */ | struct vnode *dp; /* the directory we are searching */ | ||||
struct iovec aiov; /* uio for reading symbolic links */ | struct iovec aiov; /* uio for reading symbolic links */ | ||||
struct componentname *cnp; | struct componentname *cnp; | ||||
struct thread *td; | struct thread *td; | ||||
struct proc *p; | struct proc *p; | ||||
cap_rights_t rights; | cap_rights_t rights; | ||||
struct filecaps dirfd_caps; | |||||
struct uio auio; | struct uio auio; | ||||
int error, linklen, startdir_used; | int error, linklen, startdir_used; | ||||
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")); | ||||
▲ Show 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | #ifdef CAPABILITIES | ||||
ndp->ni_filecaps.fc_nioctls != -1) { | ndp->ni_filecaps.fc_nioctls != -1) { | ||||
ndp->ni_lcf |= NI_LCF_STRICTRELATIVE; | ndp->ni_lcf |= NI_LCF_STRICTRELATIVE; | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
if (error == 0 && dp->v_type != VDIR) | if (error == 0 && dp->v_type != VDIR) | ||||
error = ENOTDIR; | error = ENOTDIR; | ||||
} | } | ||||
if (error == 0 && (ndp->ni_lcf & NI_LCF_BENEATH_ABS) != 0) { | |||||
if (ndp->ni_dirfd == AT_FDCWD) { | |||||
ndp->ni_beneath_latch = fdp->fd_cdir; | |||||
vrefact(ndp->ni_beneath_latch); | |||||
} else { | |||||
rights = ndp->ni_rightsneeded; | |||||
cap_rights_set(&rights, CAP_LOOKUP); | |||||
error = fgetvp_rights(td, ndp->ni_dirfd, &rights, | |||||
&dirfd_caps, &ndp->ni_beneath_latch); | |||||
if (error == 0 && dp->v_type != VDIR) { | |||||
vrele(ndp->ni_beneath_latch); | |||||
error = ENOTDIR; | |||||
} | |||||
} | |||||
if (error == 0) | |||||
ndp->ni_lcf |= NI_LCF_LATCH; | |||||
} | |||||
FILEDESC_SUNLOCK(fdp); | FILEDESC_SUNLOCK(fdp); | ||||
if (ndp->ni_startdir != NULL && !startdir_used) | if (ndp->ni_startdir != NULL && !startdir_used) | ||||
vrele(ndp->ni_startdir); | vrele(ndp->ni_startdir); | ||||
if (error != 0) { | if (error != 0) { | ||||
if (dp != NULL) | if (dp != NULL) | ||||
vrele(dp); | vrele(dp); | ||||
goto out; | goto out; | ||||
} | } | ||||
Show All 13 Lines | for (;;) { | ||||
* If not a symbolic link, we're done. | * If not a symbolic link, we're done. | ||||
*/ | */ | ||||
if ((cnp->cn_flags & ISSYMLINK) == 0) { | if ((cnp->cn_flags & ISSYMLINK) == 0) { | ||||
vrele(ndp->ni_rootdir); | vrele(ndp->ni_rootdir); | ||||
if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) { | if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) { | ||||
namei_cleanup_cnp(cnp); | namei_cleanup_cnp(cnp); | ||||
} else | } else | ||||
cnp->cn_flags |= HASBUF; | cnp->cn_flags |= HASBUF; | ||||
if ((ndp->ni_lcf & (NI_LCF_BENEATH_ABS | | |||||
NI_LCF_BENEATH_LATCHED)) == NI_LCF_BENEATH_ABS) | |||||
error = ENOTCAPABLE; | |||||
nameicap_cleanup(ndp); | nameicap_cleanup(ndp); | ||||
if ((ndp->ni_lcf & NI_LCF_LATCH) != 0) | |||||
vrele(ndp->ni_beneath_latch); | |||||
SDT_PROBE2(vfs, namei, lookup, return, 0, ndp->ni_vp); | SDT_PROBE2(vfs, namei, lookup, return, 0, ndp->ni_vp); | ||||
return (0); | return (error); | ||||
} | } | ||||
if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { | if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { | ||||
error = ELOOP; | error = ELOOP; | ||||
break; | break; | ||||
} | } | ||||
#ifdef MAC | #ifdef MAC | ||||
if ((cnp->cn_flags & NOMACCHECK) == 0) { | if ((cnp->cn_flags & NOMACCHECK) == 0) { | ||||
error = mac_vnode_check_readlink(td->td_ucred, | error = mac_vnode_check_readlink(td->td_ucred, | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | #endif | ||||
cnp->cn_nameptr = cnp->cn_pnbuf; | cnp->cn_nameptr = cnp->cn_pnbuf; | ||||
if (*(cnp->cn_nameptr) == '/') { | if (*(cnp->cn_nameptr) == '/') { | ||||
vrele(dp); | vrele(dp); | ||||
error = namei_handle_root(ndp, &dp); | error = namei_handle_root(ndp, &dp); | ||||
if (error != 0) | if (error != 0) | ||||
goto out; | goto out; | ||||
} | } | ||||
} | } | ||||
vput(ndp->ni_vp); | namei_cleanup_vp(ndp); | ||||
ndp->ni_vp = NULL; | |||||
vrele(ndp->ni_dvp); | |||||
out: | out: | ||||
vrele(ndp->ni_rootdir); | vrele(ndp->ni_rootdir); | ||||
if (error == 0 && (ndp->ni_lcf & (NI_LCF_BENEATH_ABS | | |||||
NI_LCF_BENEATH_LATCHED)) == NI_LCF_BENEATH_ABS) { | |||||
namei_cleanup_vp(ndp); | |||||
error = ENOTCAPABLE; | |||||
} | |||||
namei_cleanup_cnp(cnp); | namei_cleanup_cnp(cnp); | ||||
nameicap_cleanup(ndp); | nameicap_cleanup(ndp); | ||||
if ((ndp->ni_lcf & NI_LCF_LATCH) != 0) | |||||
vrele(ndp->ni_beneath_latch); | |||||
SDT_PROBE2(vfs, namei, lookup, return, error, NULL); | SDT_PROBE2(vfs, namei, lookup, return, error, NULL); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
compute_cn_lkflags(struct mount *mp, int lkflags, int cnflags) | compute_cn_lkflags(struct mount *mp, int lkflags, int cnflags) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 890 Lines • Show Last 20 Lines |