summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2006-07-06 21:32:20 +0000
committerjhb <jhb@FreeBSD.org>2006-07-06 21:32:20 +0000
commit54c687571c8f72bead8ce1053420ca0930c940ec (patch)
tree7d521d8fd39be4b32b8ff3987e7932bc3716c43f /sys/kern
parent6fe08fdbd364751465599ae63ca8f140a122cce0 (diff)
downloadFreeBSD-src-54c687571c8f72bead8ce1053420ca0930c940ec.zip
FreeBSD-src-54c687571c8f72bead8ce1053420ca0930c940ec.tar.gz
Add kern_setgroups() and kern_getgroups() and use them to implement
ibcs2_[gs]etgroups() rather than using the stackgap. This also makes ibcs2_[gs]etgroups() MPSAFE. Also, it cleans up one bit of weirdness in the old setgroups() where it allocated an entire credential just so it had a place to copy the group list into. Now setgroups just allocates a NGROUPS_MAX array on the stack that it copies into and then passes to kern_setgroups().
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_prot.c67
1 files changed, 42 insertions, 25 deletions
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 469659a..2943939 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <sys/resourcevar.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
+#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <security/audit/audit.h>
@@ -297,22 +298,36 @@ struct getgroups_args {
int
getgroups(struct thread *td, register struct getgroups_args *uap)
{
- struct ucred *cred;
+ gid_t groups[NGROUPS];
u_int ngrp;
int error;
+ ngrp = MIN(uap->gidsetsize, NGROUPS);
+ error = kern_getgroups(td, &ngrp, groups);
+ if (error)
+ return (error);
+ if (uap->gidsetsize > 0)
+ error = copyout(groups, uap->gidset, ngrp * sizeof(gid_t));
+ if (error == 0)
+ td->td_retval[0] = ngrp;
+ return (error);
+}
+
+int
+kern_getgroups(struct thread *td, u_int *ngrp, gid_t *groups)
+{
+ struct ucred *cred;
+
cred = td->td_ucred;
- if ((ngrp = uap->gidsetsize) == 0) {
- td->td_retval[0] = cred->cr_ngroups;
+ if (*ngrp == 0) {
+ *ngrp = cred->cr_ngroups;
return (0);
}
- if (ngrp < cred->cr_ngroups)
+ if (*ngrp < cred->cr_ngroups)
return (EINVAL);
- ngrp = cred->cr_ngroups;
- error = copyout(cred->cr_groups, uap->gidset, ngrp * sizeof(gid_t));
- if (error == 0)
- td->td_retval[0] = ngrp;
- return (error);
+ *ngrp = cred->cr_ngroups;
+ bcopy(cred->cr_groups, groups, *ngrp * sizeof(gid_t));
+ return (0);
}
#ifndef _SYS_SYSPROTO_H_
@@ -815,28 +830,33 @@ struct setgroups_args {
int
setgroups(struct thread *td, struct setgroups_args *uap)
{
+ gid_t groups[NGROUPS];
+ int error;
+
+ if (uap->gidsetsize > NGROUPS)
+ return (EINVAL);
+ error = copyin(uap->gidset, groups, uap->gidsetsize * sizeof(gid_t));
+ if (error)
+ return (error);
+ return (kern_setgroups(td, uap->gidsetsize, groups));
+}
+
+int
+kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups)
+{
struct proc *p = td->td_proc;
- struct ucred *newcred, *tempcred, *oldcred;
- u_int ngrp;
+ struct ucred *newcred, *oldcred;
int error;
- ngrp = uap->gidsetsize;
if (ngrp > NGROUPS)
return (EINVAL);
- tempcred = crget();
- error = copyin(uap->gidset, tempcred->cr_groups, ngrp * sizeof(gid_t));
- if (error != 0) {
- crfree(tempcred);
- return (error);
- }
- AUDIT_ARG(groupset, tempcred->cr_groups, ngrp);
+ AUDIT_ARG(groupset, groups, ngrp);
newcred = crget();
PROC_LOCK(p);
oldcred = p->p_ucred;
#ifdef MAC
- error = mac_check_proc_setgroups(p, oldcred, ngrp,
- tempcred->cr_groups);
+ error = mac_check_proc_setgroups(p, oldcred, ngrp, groups);
if (error)
goto fail;
#endif
@@ -859,21 +879,18 @@ setgroups(struct thread *td, struct setgroups_args *uap)
*/
newcred->cr_ngroups = 1;
} else {
- bcopy(tempcred->cr_groups, newcred->cr_groups,
- ngrp * sizeof(gid_t));
+ bcopy(groups, newcred->cr_groups, ngrp * sizeof(gid_t));
newcred->cr_ngroups = ngrp;
}
setsugid(p);
p->p_ucred = newcred;
PROC_UNLOCK(p);
- crfree(tempcred);
crfree(oldcred);
return (0);
fail:
PROC_UNLOCK(p);
crfree(newcred);
- crfree(tempcred);
return (error);
}
OpenPOWER on IntegriCloud