diff options
Diffstat (limited to 'sys/compat/linux')
-rw-r--r-- | sys/compat/linux/linux_misc.c | 24 | ||||
-rw-r--r-- | sys/compat/linux/linux_uid16.c | 18 |
2 files changed, 27 insertions, 15 deletions
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 9595fed..267da07 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -1132,7 +1132,7 @@ int linux_setgroups(struct thread *td, struct linux_setgroups_args *args) { struct ucred *newcred, *oldcred; - l_gid_t linux_gidset[NGROUPS]; + l_gid_t *linux_gidset; gid_t *bsd_gidset; int ngrp, error; struct proc *p; @@ -1140,13 +1140,14 @@ linux_setgroups(struct thread *td, struct linux_setgroups_args *args) ngrp = args->gidsetsize; if (ngrp < 0 || ngrp >= NGROUPS) return (EINVAL); + linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_TEMP, M_WAITOK); error = copyin(args->grouplist, linux_gidset, ngrp * sizeof(l_gid_t)); if (error) - return (error); + goto out; newcred = crget(); p = td->td_proc; PROC_LOCK(p); - oldcred = p->p_ucred; + oldcred = crcopysafe(p, newcred); /* * cr_groups[0] holds egid. Setting the whole set from @@ -1157,10 +1158,9 @@ linux_setgroups(struct thread *td, struct linux_setgroups_args *args) if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) != 0) { PROC_UNLOCK(p); crfree(newcred); - return (error); + goto out; } - crcopy(newcred, oldcred); if (ngrp > 0) { newcred->cr_ngroups = ngrp + 1; @@ -1177,14 +1177,17 @@ linux_setgroups(struct thread *td, struct linux_setgroups_args *args) p->p_ucred = newcred; PROC_UNLOCK(p); crfree(oldcred); - return (0); + error = 0; +out: + free(linux_gidset, M_TEMP); + return (error); } int linux_getgroups(struct thread *td, struct linux_getgroups_args *args) { struct ucred *cred; - l_gid_t linux_gidset[NGROUPS]; + l_gid_t *linux_gidset; gid_t *bsd_gidset; int bsd_gidsetsz, ngrp, error; @@ -1207,13 +1210,16 @@ linux_getgroups(struct thread *td, struct linux_getgroups_args *args) return (EINVAL); ngrp = 0; + linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset), + M_TEMP, M_WAITOK); while (ngrp < bsd_gidsetsz) { linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; ngrp++; } - if ((error = copyout(linux_gidset, args->grouplist, - ngrp * sizeof(l_gid_t)))) + error = copyout(linux_gidset, args->grouplist, ngrp * sizeof(l_gid_t)); + free(linux_gidset, M_TEMP); + if (error) return (error); td->td_retval[0] = ngrp; diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c index 2685eaa..b49bf78 100644 --- a/sys/compat/linux/linux_uid16.c +++ b/sys/compat/linux/linux_uid16.c @@ -98,7 +98,7 @@ int linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) { struct ucred *newcred, *oldcred; - l_gid16_t linux_gidset[NGROUPS]; + l_gid16_t *linux_gidset; gid_t *bsd_gidset; int ngrp, error; struct proc *p; @@ -111,13 +111,14 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) ngrp = args->gidsetsize; if (ngrp < 0 || ngrp >= NGROUPS) return (EINVAL); + linux_gidset = malloc(ngrp * sizeof(*linux_gidset), M_TEMP, M_WAITOK); error = copyin(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; + oldcred = crcopysafe(p, newcred); /* * cr_groups[0] holds egid. Setting the whole set from @@ -128,10 +129,9 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) if ((error = priv_check_cred(oldcred, PRIV_CRED_SETGROUPS, 0)) != 0) { PROC_UNLOCK(p); crfree(newcred); - return (error); + goto out; } - crcopy(newcred, oldcred); if (ngrp > 0) { newcred->cr_ngroups = ngrp + 1; @@ -149,14 +149,17 @@ linux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) p->p_ucred = newcred; PROC_UNLOCK(p); crfree(oldcred); - return (0); + error = 0; +out: + free(linux_gidset, M_TEMP); + return (error); } int linux_getgroups16(struct thread *td, struct linux_getgroups16_args *args) { struct ucred *cred; - l_gid16_t linux_gidset[NGROUPS]; + l_gid16_t *linux_gidset; gid_t *bsd_gidset; int bsd_gidsetsz, ngrp, error; @@ -184,12 +187,15 @@ linux_getgroups16(struct thread *td, struct linux_getgroups16_args *args) return (EINVAL); ngrp = 0; + linux_gidset = malloc(bsd_gidsetsz * sizeof(*linux_gidset), + M_TEMP, M_WAITOK); while (ngrp < bsd_gidsetsz) { linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; ngrp++; } error = copyout(linux_gidset, args->gidset, ngrp * sizeof(l_gid16_t)); + free(linux_gidset, M_TEMP); if (error) return (error); |