summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_extattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_extattr.c')
-rw-r--r--sys/kern/vfs_extattr.c26
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);
}
OpenPOWER on IntegriCloud