diff options
Diffstat (limited to 'sys/i386/linux/linux_misc.c')
| -rw-r--r-- | sys/i386/linux/linux_misc.c | 125 |
1 files changed, 71 insertions, 54 deletions
diff --git a/sys/i386/linux/linux_misc.c b/sys/i386/linux/linux_misc.c index 6cda44b67414..77c3060afcad 100644 --- a/sys/i386/linux/linux_misc.c +++ b/sys/i386/linux/linux_misc.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: linux_misc.c,v 1.51.2.5 1999/08/17 21:06:04 marcel Exp $ + * $Id: linux_misc.c,v 1.51.2.6 1999/08/28 20:45:06 marcel Exp $ */ #include "opt_compat.h" @@ -182,7 +182,7 @@ linux_uselib(struct proc *p, struct linux_uselib_args *args) locked = 0; vp = NULL; - NDINIT(&ni, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, args->library, p); + NDINIT(&ni, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, args->library, p); if (error = namei(&ni)) goto cleanup; @@ -1168,75 +1168,92 @@ linux_nice(struct proc *p, struct linux_nice_args *args) int linux_setgroups(p, uap) - struct proc *p; - struct linux_setgroups_args *uap; + struct proc *p; + struct linux_setgroups_args *uap; { - struct pcred *pc = p->p_cred; - linux_gid_t linux_gidset[NGROUPS]; - gid_t *bsd_gidset; - int ngrp, error; + struct pcred *pc; + linux_gid_t linux_gidset[NGROUPS]; + gid_t *bsd_gidset; + int ngrp, error; - if ((error = suser(pc->pc_ucred, &p->p_acflag))) - return error; + pc = p->p_cred; + ngrp = uap->gidsetsize; - if (uap->gidsetsize > NGROUPS) - return EINVAL; + /* + * cr_groups[0] holds egid. Setting the whole set from + * the supplied set will cause egid to be changed too. + * Keep cr_groups[0] unchanged to prevent that. + */ - ngrp = uap->gidsetsize; - pc->pc_ucred = crcopy(pc->pc_ucred); - if (ngrp >= 1) { - if ((error = copyin((caddr_t)uap->gidset, - (caddr_t)linux_gidset, - ngrp * sizeof(linux_gid_t)))) - return error; + if ((error = suser(pc->pc_ucred, &p->p_acflag))) + return (error); - pc->pc_ucred->cr_ngroups = ngrp; + if (ngrp >= NGROUPS) + return (EINVAL); - bsd_gidset = pc->pc_ucred->cr_groups; - ngrp--; - while (ngrp >= 0) { - bsd_gidset[ngrp] = linux_gidset[ngrp]; - ngrp--; - } - } - else - pc->pc_ucred->cr_ngroups = 1; + pc->pc_ucred = crcopy(pc->pc_ucred); + if (ngrp > 0) { + error = copyin((caddr_t)uap->gidset, (caddr_t)linux_gidset, + ngrp * sizeof(linux_gid_t)); + if (error) + return (error); + + pc->pc_ucred->cr_ngroups = ngrp + 1; + + bsd_gidset = pc->pc_ucred->cr_groups; + ngrp--; + while (ngrp >= 0) { + bsd_gidset[ngrp + 1] = linux_gidset[ngrp]; + ngrp--; + } + } + else + pc->pc_ucred->cr_ngroups = 1; - setsugid(p); - return 0; + setsugid(p); + return (0); } int linux_getgroups(p, uap) - struct proc *p; - struct linux_getgroups_args *uap; + struct proc *p; + struct linux_getgroups_args *uap; { - struct pcred *pc = p->p_cred; - linux_gid_t linux_gidset[NGROUPS]; - gid_t *bsd_gidset; - int ngrp, error; + struct pcred *pc; + linux_gid_t linux_gidset[NGROUPS]; + gid_t *bsd_gidset; + int bsd_gidsetsz, ngrp, error; - if ((ngrp = uap->gidsetsize) == 0) { - p->p_retval[0] = pc->pc_ucred->cr_ngroups; - return 0; - } + pc = p->p_cred; + bsd_gidset = pc->pc_ucred->cr_groups; + bsd_gidsetsz = pc->pc_ucred->cr_ngroups - 1; - if (ngrp < pc->pc_ucred->cr_ngroups) - return EINVAL; + /* + * cr_groups[0] holds egid. Returning the whole set + * here will cause a duplicate. Exclude cr_groups[0] + * to prevent that. + */ - ngrp = 0; - bsd_gidset = pc->pc_ucred->cr_groups; - while (ngrp < pc->pc_ucred->cr_ngroups) { - linux_gidset[ngrp] = bsd_gidset[ngrp]; - ngrp++; - } + if ((ngrp = uap->gidsetsize) == 0) { + p->p_retval[0] = bsd_gidsetsz; + return (0); + } - if ((error = copyout((caddr_t)linux_gidset, (caddr_t)uap->gidset, - ngrp * sizeof(linux_gid_t)))) - return error; + if (ngrp < bsd_gidsetsz) + return (EINVAL); + + ngrp = 0; + while (ngrp < bsd_gidsetsz) { + linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; + ngrp++; + } + + if ((error = copyout((caddr_t)linux_gidset, (caddr_t)uap->gidset, + ngrp * sizeof(linux_gid_t)))) + return (error); - p->p_retval[0] = ngrp; - return (0); + p->p_retval[0] = ngrp; + return (0); } int |
