1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-26 16:18:31 +00:00

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().
This commit is contained in:
John Baldwin 2006-07-06 21:32:20 +00:00
parent c79c04f176
commit 3cb83e714d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=160139
4 changed files with 73 additions and 71 deletions

View File

@ -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

View File

@ -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); }

View File

@ -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,24 +298,38 @@ 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;
cred = td->td_ucred;
if ((ngrp = uap->gidsetsize) == 0) {
td->td_retval[0] = cred->cr_ngroups;
return (0);
}
if (ngrp < cred->cr_ngroups)
return (EINVAL);
ngrp = cred->cr_ngroups;
error = copyout(cred->cr_groups, uap->gidset, ngrp * sizeof(gid_t));
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 == 0) {
*ngrp = cred->cr_ngroups;
return (0);
}
if (*ngrp < cred->cr_ngroups)
return (EINVAL);
*ngrp = cred->cr_ngroups;
bcopy(cred->cr_groups, groups, *ngrp * sizeof(gid_t));
return (0);
}
#ifndef _SYS_SYSPROTO_H_
struct setsid_args {
int dummy;
@ -815,28 +830,33 @@ struct setgroups_args {
int
setgroups(struct thread *td, struct setgroups_args *uap)
{
struct proc *p = td->td_proc;
struct ucred *newcred, *tempcred, *oldcred;
u_int ngrp;
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, *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);
}

View File

@ -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 *);