Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/vfs_syscalls.c
Show First 20 Lines • Show All 1,569 Lines • ▼ Show 20 Lines | kern_linkat(struct thread *td, int fd1, int fd2, const char *path1, | ||||
do { | do { | ||||
bwillwrite(); | bwillwrite(); | ||||
NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, segflag, | NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, segflag, | ||||
path1, fd1, &cap_linkat_source_rights, td); | path1, fd1, &cap_linkat_source_rights, td); | ||||
if ((error = namei(&nd)) != 0) | if ((error = namei(&nd)) != 0) | ||||
return (error); | return (error); | ||||
NDFREE(&nd, NDF_ONLY_PNBUF); | NDFREE(&nd, NDF_ONLY_PNBUF); | ||||
if ((nd.ni_resflags & NIRES_EMPTYPATH) != 0) { | |||||
error = priv_check(td, PRIV_VFS_FHOPEN); | |||||
if (error != 0) { | |||||
if (nd.ni_vp != NULL) | |||||
markj: How can it be null? kern_linkat_vp() dereferences nd.ni_vp unconditionally. | |||||
kibAuthorUnsubmitted Done Inline ActionsYes, LOOKUP only returns success when there is something to lookup. kib: Yes, LOOKUP only returns success when there is something to lookup. | |||||
vrele(nd.ni_vp); | |||||
return (error); | |||||
} | |||||
} | |||||
error = kern_linkat_vp(td, nd.ni_vp, fd2, path2, segflag); | error = kern_linkat_vp(td, nd.ni_vp, fd2, path2, segflag); | ||||
} while (error == EAGAIN || error == ERELOOKUP); | } while (error == EAGAIN || error == ERELOOKUP); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
kern_linkat_vp(struct thread *td, struct vnode *vp, int fd, const char *path, | kern_linkat_vp(struct thread *td, struct vnode *vp, int fd, const char *path, | ||||
enum uio_seg segflag) | enum uio_seg segflag) | ||||
{ | { | ||||
struct nameidata nd; | struct nameidata nd; | ||||
struct mount *mp; | struct mount *mp; | ||||
int error; | int error; | ||||
if (vp->v_type == VDIR) { | if (vp->v_type == VDIR) { | ||||
vrele(vp); | vrele(vp); | ||||
return (EPERM); /* POSIX */ | return (EPERM); /* POSIX */ | ||||
} | } | ||||
NDINIT_ATRIGHTS(&nd, CREATE, | NDINIT_ATRIGHTS(&nd, CREATE, | ||||
LOCKPARENT | SAVENAME | AUDITVNODE2 | NOCACHE, segflag, path, fd, | LOCKPARENT | SAVENAME | AUDITVNODE2 | NOCACHE, segflag, path, fd, | ||||
&cap_linkat_target_rights, td); | &cap_linkat_target_rights, td); | ||||
if ((error = namei(&nd)) == 0) { | if ((error = namei(&nd)) == 0) { | ||||
if ((nd.ni_resflags & NIRES_EMPTYPATH) != 0) { | |||||
error = priv_check(td, PRIV_VFS_FHOPEN); | |||||
if (error != 0) { | |||||
NDFREE(&nd, NDF_ONLY_PNBUF); | |||||
if (nd.ni_vp != NULL) { | |||||
if (nd.ni_dvp == nd.ni_vp) | |||||
vrele(nd.ni_dvp); | |||||
else | |||||
vput(nd.ni_dvp); | |||||
vrele(nd.ni_vp); | |||||
} else { | |||||
vput(nd.ni_dvp); | |||||
} | |||||
vrele(vp); | |||||
return (error); | |||||
} | |||||
} | |||||
if (nd.ni_vp != NULL) { | if (nd.ni_vp != NULL) { | ||||
NDFREE(&nd, NDF_ONLY_PNBUF); | NDFREE(&nd, NDF_ONLY_PNBUF); | ||||
if (nd.ni_dvp == nd.ni_vp) | if (nd.ni_dvp == nd.ni_vp) | ||||
vrele(nd.ni_dvp); | vrele(nd.ni_dvp); | ||||
else | else | ||||
vput(nd.ni_dvp); | vput(nd.ni_dvp); | ||||
vrele(nd.ni_vp); | vrele(nd.ni_vp); | ||||
vrele(vp); | vrele(vp); | ||||
▲ Show 20 Lines • Show All 3,368 Lines • Show Last 20 Lines |
How can it be null? kern_linkat_vp() dereferences nd.ni_vp unconditionally.