diff options
Diffstat (limited to 'sys/kern/vfs_extattr.c')
-rw-r--r-- | sys/kern/vfs_extattr.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 9b68dd7..4dd6f37 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.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); } |