summaryrefslogtreecommitdiffstats
path: root/sys
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
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')
-rw-r--r--sys/i386/ibcs2/ibcs2_misc.c67
-rw-r--r--sys/i386/ibcs2/syscalls.xenix4
-rw-r--r--sys/kern/kern_prot.c67
-rw-r--r--sys/sys/syscallsubr.h2
4 files changed, 71 insertions, 69 deletions
diff --git a/sys/i386/ibcs2/ibcs2_misc.c b/sys/i386/ibcs2/ibcs2_misc.c
index c4efc02..c875075 100644
--- a/sys/i386/ibcs2/ibcs2_misc.c
+++ b/sys/i386/ibcs2/ibcs2_misc.c
@@ -651,35 +651,25 @@ ibcs2_getgroups(td, uap)
struct thread *td;
struct ibcs2_getgroups_args *uap;
{
- int error, i;
- ibcs2_gid_t *iset = NULL;
- struct getgroups_args sa;
- gid_t *gp;
- caddr_t sg = stackgap_init();
+ ibcs2_gid_t iset[NGROUPS_MAX];
+ gid_t gp[NGROUPS_MAX];
+ u_int i, ngrp;
+ int error;
if (uap->gidsetsize < 0)
return (EINVAL);
- if (uap->gidsetsize > NGROUPS_MAX)
- uap->gidsetsize = NGROUPS_MAX;
- sa.gidsetsize = uap->gidsetsize;
- if (uap->gidsetsize) {
- sa.gidset = stackgap_alloc(&sg, NGROUPS_MAX *
- sizeof(gid_t *));
- iset = stackgap_alloc(&sg, uap->gidsetsize *
- sizeof(ibcs2_gid_t));
+ ngrp = MIN(uap->gidsetsize, NGROUPS_MAX);
+ error = kern_getgroups(td, &ngrp, gp);
+ if (error)
+ return (error);
+ if (uap->gidsetsize > 0) {
+ for (i = 0; i < ngrp; i++)
+ iset[i] = (ibcs2_gid_t)gp[i];
+ error = copyout(iset, uap->gidset, ngrp * sizeof(ibcs2_gid_t));
}
- if ((error = getgroups(td, &sa)) != 0)
- return error;
- if (uap->gidsetsize == 0)
- return 0;
-
- for (i = 0, gp = sa.gidset; i < td->td_retval[0]; i++)
- iset[i] = (ibcs2_gid_t)*gp++;
- if (td->td_retval[0] && (error = copyout((caddr_t)iset,
- (caddr_t)uap->gidset,
- sizeof(ibcs2_gid_t) * td->td_retval[0])))
- return error;
- return 0;
+ if (error == 0)
+ td->td_retval[0] = ngrp;
+ return (error);
}
int
@@ -687,28 +677,21 @@ ibcs2_setgroups(td, uap)
struct thread *td;
struct ibcs2_setgroups_args *uap;
{
+ ibcs2_gid_t iset[NGROUPS_MAX];
+ gid_t gp[NGROUPS_MAX];
int error, i;
- ibcs2_gid_t *iset;
- struct setgroups_args sa;
- gid_t *gp;
- caddr_t sg = stackgap_init();
if (uap->gidsetsize < 0 || uap->gidsetsize > NGROUPS_MAX)
return (EINVAL);
- sa.gidsetsize = uap->gidsetsize;
- sa.gidset = stackgap_alloc(&sg, sa.gidsetsize *
- sizeof(gid_t *));
- iset = stackgap_alloc(&sg, sa.gidsetsize *
- sizeof(ibcs2_gid_t *));
- if (sa.gidsetsize) {
- if ((error = copyin((caddr_t)uap->gidset, (caddr_t)iset,
- sizeof(ibcs2_gid_t *) *
- uap->gidsetsize)) != 0)
- return error;
+ if (uap->gidsetsize && uap->gidset) {
+ error = copyin(uap->gidset, iset, sizeof(ibcs2_gid_t) *
+ uap->gidsetsize);
+ if (error)
+ return (error);
+ for (i = 0; i < uap->gidsetsize; i++)
+ gp[i] = (gid_t)iset[i];
}
- for (i = 0, gp = sa.gidset; i < sa.gidsetsize; i++)
- *gp++ = (gid_t)iset[i];
- return setgroups(td, &sa);
+ return (kern_setgroups(td, uap->gidsetsize, gp));
}
int
diff --git a/sys/i386/ibcs2/syscalls.xenix b/sys/i386/ibcs2/syscalls.xenix
index ae8be83..8b9b84a 100644
--- a/sys/i386/ibcs2/syscalls.xenix
+++ b/sys/i386/ibcs2/syscalls.xenix
@@ -56,9 +56,9 @@
ibcs2_sigset_t *oset); }
41 AUE_NULL MSTD { int ibcs2_sigpending(ibcs2_sigset_t *mask); }
42 AUE_NULL MSTD { int ibcs2_sigsuspend(ibcs2_sigset_t *mask); }
-43 AUE_GETGROUPS STD { int ibcs2_getgroups(int gidsetsize, \
+43 AUE_GETGROUPS MSTD { int ibcs2_getgroups(int gidsetsize, \
ibcs2_gid_t *gidset); }
-44 AUE_SETGROUPS STD { int ibcs2_setgroups(int gidsetsize, \
+44 AUE_SETGROUPS MSTD { int ibcs2_setgroups(int gidsetsize, \
ibcs2_gid_t *gidset); }
45 AUE_NULL MSTD { int ibcs2_sysconf(int name); }
46 AUE_PATHCONF MSTD { int ibcs2_pathconf(char *path, int name); }
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);
}
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index d4f818b..c7a0cd5 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -81,6 +81,7 @@ int kern_futimes(struct thread *td, int fd, struct timeval *tptr,
enum uio_seg tptrseg);
int kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
enum uio_seg bufseg, int flags);
+int kern_getgroups(struct thread *td, u_int *ngrp, gid_t *groups);
int kern_getitimer(struct thread *, u_int, struct itimerval *);
int kern_getrusage(struct thread *td, int who, struct rusage *rup);
int kern_getsockopt(struct thread *td, int s, int level, int name,
@@ -132,6 +133,7 @@ int kern_sendfile(struct thread *td, struct sendfile_args *uap,
struct uio *hdr_uio, struct uio *trl_uio, int compat);
int kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags,
struct mbuf *control, enum uio_seg segflg);
+int kern_setgroups(struct thread *td, u_int ngrp, gid_t *groups);
int kern_setitimer(struct thread *, u_int, struct itimerval *,
struct itimerval *);
int kern_setrlimit(struct thread *, u_int, struct rlimit *);
OpenPOWER on IntegriCloud