diff options
author | truckman <truckman@FreeBSD.org> | 2000-09-02 12:31:55 +0000 |
---|---|---|
committer | truckman <truckman@FreeBSD.org> | 2000-09-02 12:31:55 +0000 |
commit | bc29ebd97dbc86ef2ec1f9786d989e9f428fe39d (patch) | |
tree | 310403692683fa82ff9f717d04a11858b54fb1e1 /sys/kern/vfs_syscalls.c | |
parent | b4e857d1de6a7709bf95206b7b897a7d18863d12 (diff) | |
download | FreeBSD-src-bc29ebd97dbc86ef2ec1f9786d989e9f428fe39d.zip FreeBSD-src-bc29ebd97dbc86ef2ec1f9786d989e9f428fe39d.tar.gz |
access() shouldn't diddle with the contents of a potentially shared
credential. Create a temporary copy of the current credential and
modify the copy.
Submitted by: tegge
Diffstat (limited to 'sys/kern/vfs_syscalls.c')
-rw-r--r-- | sys/kern/vfs_syscalls.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 9b68dd7..4dd6f37 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1593,15 +1593,25 @@ access(p, uap) syscallarg(int) flags; } */ *uap; { - register struct ucred *cred = p->p_ucred; + struct ucred *cred, *tmpcred; register struct vnode *vp; - int error, flags, t_gid, t_uid; + int error, flags; struct nameidata nd; - t_uid = cred->cr_uid; - t_gid = cred->cr_groups[0]; - cred->cr_uid = p->p_cred->p_ruid; - cred->cr_groups[0] = p->p_cred->p_rgid; + cred = p->p_ucred; + /* + * Create and modify a temporary credential instead of one that + * is potentially shared. This could also mess up socket + * buffer accounting which can run in an interrupt context. + * + * XXX - Depending on how "threads" are finally implemented, it + * may be better to explicitly pass the credential to namei() + * rather than to modify the potentially shared process structure. + */ + tmpcred = crdup(cred); + tmpcred->cr_uid = p->p_cred->p_ruid; + tmpcred->cr_groups[0] = p->p_cred->p_rgid; + p->p_ucred = tmpcred; NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) @@ -1623,8 +1633,8 @@ access(p, uap) NDFREE(&nd, NDF_ONLY_PNBUF); vput(vp); out1: - cred->cr_uid = t_uid; - cred->cr_groups[0] = t_gid; + p->p_ucred = cred; + crfree(tmpcred); return (error); } |