diff options
Diffstat (limited to 'sys/compat/linux/linux_uid16.c')
-rw-r--r-- | sys/compat/linux/linux_uid16.c | 32 |
1 files changed, 20 insertions, 12 deletions
diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c index b29368c..ee39025 100644 --- a/sys/compat/linux/linux_uid16.c +++ b/sys/compat/linux/linux_uid16.c @@ -30,6 +30,8 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/lock.h> +#include <sys/mutex.h> #include <sys/proc.h> #include <sys/sysproto.h> @@ -93,6 +95,7 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) l_gid16_t linux_gidset[NGROUPS]; gid_t *bsd_gidset; int ngrp, error; + struct proc *p; #ifdef DEBUG if (ldebug(setgroups16)) @@ -100,7 +103,16 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) #endif ngrp = args->gidsetsize; - oldcred = td->td_proc->p_ucred; + if (ngrp >= NGROUPS) + return (EINVAL); + error = copyin((caddr_t)args->gidset, linux_gidset, + ngrp * sizeof(l_gid16_t)); + if (error) + return (error); + newcred = crget(); + p = td->td_proc; + PROC_LOCK(p); + oldcred = p->p_ucred; /* * cr_groups[0] holds egid. Setting the whole set from @@ -108,19 +120,14 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) * Keep cr_groups[0] unchanged to prevent that. */ - if ((error = suser_cred(oldcred, PRISON_ROOT)) != 0) + if ((error = suser_cred(oldcred, PRISON_ROOT)) != 0) { + PROC_UNLOCK(p); + crfree(newcred); return (error); + } - if (ngrp >= NGROUPS) - return (EINVAL); - - newcred = crdup(oldcred); + crcopy(newcred, oldcred); if (ngrp > 0) { - error = copyin((caddr_t)args->gidset, linux_gidset, - ngrp * sizeof(l_gid16_t)); - if (error) - return (error); - newcred->cr_ngroups = ngrp + 1; bsd_gidset = newcred->cr_groups; @@ -134,7 +141,8 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) newcred->cr_ngroups = 1; setsugid(td->td_proc); - td->td_proc->p_ucred = newcred; + p->p_ucred = newcred; + PROC_UNLOCK(p); crfree(oldcred); return (0); } |