linux_uid16.c revision 102814
182745Smarcel/*- 282745Smarcel * Copyright (c) 2001 The FreeBSD Project 382745Smarcel * All rights reserved. 482745Smarcel * 582745Smarcel * Redistribution and use in source and binary forms, with or without 682745Smarcel * modification, are permitted provided that the following conditions 782745Smarcel * are met: 882745Smarcel * 1. Redistributions of source code must retain the above copyright 982745Smarcel * notice, this list of conditions and the following disclaimer. 1082745Smarcel * 2. Redistributions in binary form must reproduce the above copyright 1182745Smarcel * notice, this list of conditions and the following disclaimer in the 1282745Smarcel * documentation and/or other materials provided with the distribution. 1382745Smarcel * 1482745Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1582745Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1682745Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1782745Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1882745Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1982745Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2082745Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2182745Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2282745Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2382745Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2482745Smarcel * SUCH DAMAGE. 2582745Smarcel * 2682745Smarcel * $FreeBSD: head/sys/compat/linux/linux_uid16.c 102814 2002-09-01 22:30:27Z iedowse $ 2782745Smarcel */ 2882745Smarcel 2982745Smarcel#include "opt_compat.h" 3082745Smarcel 3182745Smarcel#include <sys/param.h> 3282745Smarcel#include <sys/systm.h> 3394621Sjhb#include <sys/lock.h> 3494621Sjhb#include <sys/mutex.h> 3582745Smarcel#include <sys/proc.h> 36102814Siedowse#include <sys/syscallsubr.h> 3782745Smarcel#include <sys/sysproto.h> 3882745Smarcel 3982745Smarcel#include <machine/../linux/linux.h> 4082745Smarcel#include <machine/../linux/linux_proto.h> 4182745Smarcel#include <compat/linux/linux_util.h> 4282745Smarcel 4382745SmarcelDUMMY(setfsuid16); 4482745SmarcelDUMMY(setfsgid16); 4582745SmarcelDUMMY(getresuid16); 4682745SmarcelDUMMY(getresgid16); 4782745Smarcel 48102814Siedowse#define CAST_NOCHG(x) ((x == 0xFFFF) ? -1 : x) 4984916Smarcel 5082745Smarcelint 5183366Sjulianlinux_chown16(struct thread *td, struct linux_chown16_args *args) 5282745Smarcel{ 53102814Siedowse char *path; 54102814Siedowse int error; 5582745Smarcel 56102814Siedowse LCONVPATHEXIST(td, args->path, &path); 5782745Smarcel 5882745Smarcel#ifdef DEBUG 5982745Smarcel if (ldebug(chown16)) 60102814Siedowse printf(ARGS(chown16, "%s, %d, %d"), path, args->uid, args->gid); 6182745Smarcel#endif 62102814Siedowse error = kern_chown(td, path, UIO_SYSSPACE, CAST_NOCHG(args->uid), 63102814Siedowse CAST_NOCHG(args->gid)); 64102814Siedowse LFREEPATH(path); 65102814Siedowse return (error); 6682745Smarcel} 6782745Smarcel 6882745Smarcelint 6983366Sjulianlinux_lchown16(struct thread *td, struct linux_lchown16_args *args) 7082745Smarcel{ 71102814Siedowse char *path; 72102814Siedowse int error; 7382745Smarcel 74102814Siedowse LCONVPATHEXIST(td, args->path, &path); 7582745Smarcel 7682745Smarcel#ifdef DEBUG 7782745Smarcel if (ldebug(lchown16)) 78102814Siedowse printf(ARGS(lchown16, "%s, %d, %d"), path, args->uid, 7982745Smarcel args->gid); 8082745Smarcel#endif 81102814Siedowse error = kern_lchown(td, path, UIO_SYSSPACE, CAST_NOCHG(args->uid), 82102814Siedowse CAST_NOCHG(args->gid)); 83102814Siedowse LFREEPATH(path); 84102814Siedowse return (error); 8582745Smarcel} 8682745Smarcel 8782745Smarcelint 8883366Sjulianlinux_setgroups16(struct thread *td, struct linux_setgroups16_args *args) 8982745Smarcel{ 9082745Smarcel struct ucred *newcred, *oldcred; 9182745Smarcel l_gid16_t linux_gidset[NGROUPS]; 9282745Smarcel gid_t *bsd_gidset; 9382745Smarcel int ngrp, error; 9494621Sjhb struct proc *p; 9582745Smarcel 9682745Smarcel#ifdef DEBUG 9782745Smarcel if (ldebug(setgroups16)) 9882745Smarcel printf(ARGS(setgroups16, "%d, *"), args->gidsetsize); 9982745Smarcel#endif 10082745Smarcel 10182745Smarcel ngrp = args->gidsetsize; 10294621Sjhb if (ngrp >= NGROUPS) 10394621Sjhb return (EINVAL); 10494621Sjhb error = copyin((caddr_t)args->gidset, linux_gidset, 10594621Sjhb ngrp * sizeof(l_gid16_t)); 10694621Sjhb if (error) 10794621Sjhb return (error); 10894621Sjhb newcred = crget(); 10994621Sjhb p = td->td_proc; 11094621Sjhb PROC_LOCK(p); 11194621Sjhb oldcred = p->p_ucred; 11282745Smarcel 11382745Smarcel /* 11482745Smarcel * cr_groups[0] holds egid. Setting the whole set from 11582745Smarcel * the supplied set will cause egid to be changed too. 11682745Smarcel * Keep cr_groups[0] unchanged to prevent that. 11782745Smarcel */ 11882745Smarcel 11994621Sjhb if ((error = suser_cred(oldcred, PRISON_ROOT)) != 0) { 12094621Sjhb PROC_UNLOCK(p); 12194621Sjhb crfree(newcred); 12282745Smarcel return (error); 12394621Sjhb } 12482745Smarcel 12594621Sjhb crcopy(newcred, oldcred); 12682745Smarcel if (ngrp > 0) { 12782745Smarcel newcred->cr_ngroups = ngrp + 1; 12882745Smarcel 12982745Smarcel bsd_gidset = newcred->cr_groups; 13082745Smarcel ngrp--; 13182745Smarcel while (ngrp >= 0) { 13282745Smarcel bsd_gidset[ngrp + 1] = linux_gidset[ngrp]; 13382745Smarcel ngrp--; 13482745Smarcel } 13582745Smarcel } 13682745Smarcel else 13782745Smarcel newcred->cr_ngroups = 1; 13882745Smarcel 13983366Sjulian setsugid(td->td_proc); 14094621Sjhb p->p_ucred = newcred; 14194621Sjhb PROC_UNLOCK(p); 14282745Smarcel crfree(oldcred); 14382745Smarcel return (0); 14482745Smarcel} 14582745Smarcel 14682745Smarcelint 14783366Sjulianlinux_getgroups16(struct thread *td, struct linux_getgroups16_args *args) 14882745Smarcel{ 14982745Smarcel struct ucred *cred; 15082745Smarcel l_gid16_t linux_gidset[NGROUPS]; 15182745Smarcel gid_t *bsd_gidset; 15282745Smarcel int bsd_gidsetsz, ngrp, error; 15382745Smarcel 15482745Smarcel#ifdef DEBUG 15582745Smarcel if (ldebug(getgroups16)) 15682745Smarcel printf(ARGS(getgroups16, "%d, *"), args->gidsetsize); 15782745Smarcel#endif 15882745Smarcel 15991406Sjhb cred = td->td_ucred; 16082745Smarcel bsd_gidset = cred->cr_groups; 16182745Smarcel bsd_gidsetsz = cred->cr_ngroups - 1; 16282745Smarcel 16382745Smarcel /* 16482745Smarcel * cr_groups[0] holds egid. Returning the whole set 16582745Smarcel * here will cause a duplicate. Exclude cr_groups[0] 16682745Smarcel * to prevent that. 16782745Smarcel */ 16882745Smarcel 16982745Smarcel if ((ngrp = args->gidsetsize) == 0) { 17083366Sjulian td->td_retval[0] = bsd_gidsetsz; 17182745Smarcel return (0); 17282745Smarcel } 17382745Smarcel 17482745Smarcel if (ngrp < bsd_gidsetsz) 17582745Smarcel return (EINVAL); 17682745Smarcel 17782745Smarcel ngrp = 0; 17882745Smarcel while (ngrp < bsd_gidsetsz) { 17982745Smarcel linux_gidset[ngrp] = bsd_gidset[ngrp + 1]; 18082745Smarcel ngrp++; 18182745Smarcel } 18282745Smarcel 18382745Smarcel error = copyout(linux_gidset, (caddr_t)args->gidset, 18482745Smarcel ngrp * sizeof(l_gid16_t)); 18582745Smarcel if (error) 18682745Smarcel return (error); 18782745Smarcel 18883366Sjulian td->td_retval[0] = ngrp; 18982745Smarcel return (0); 19082745Smarcel} 19182745Smarcel 19282745Smarcel/* 19383366Sjulian * The FreeBSD native getgid(2) and getuid(2) also modify td->td_retval[1] 19482745Smarcel * when COMPAT_43 or COMPAT_SUNOS is defined. This globbers registers that 19582745Smarcel * are assumed to be preserved. The following lightweight syscalls fixes 19682745Smarcel * this. See also linux_getpid(2), linux_getgid(2) and linux_getuid(2) in 19782745Smarcel * linux_misc.c 19882745Smarcel * 19982745Smarcel * linux_getgid16() - MP SAFE 20082745Smarcel * linux_getuid16() - MP SAFE 20182745Smarcel */ 20282745Smarcel 20382745Smarcelint 20483366Sjulianlinux_getgid16(struct thread *td, struct linux_getgid16_args *args) 20582745Smarcel{ 20683366Sjulian 20791406Sjhb td->td_retval[0] = td->td_ucred->cr_rgid; 20882745Smarcel return (0); 20982745Smarcel} 21082745Smarcel 21182745Smarcelint 21283366Sjulianlinux_getuid16(struct thread *td, struct linux_getuid16_args *args) 21382745Smarcel{ 21483366Sjulian 21591406Sjhb td->td_retval[0] = td->td_ucred->cr_ruid; 21682745Smarcel return (0); 21782745Smarcel} 21882745Smarcel 21982745Smarcelint 22083366Sjulianlinux_getegid16(struct thread *td, struct linux_getegid16_args *args) 22182745Smarcel{ 22282745Smarcel struct getegid_args bsd; 22382745Smarcel 22483366Sjulian return (getegid(td, &bsd)); 22582745Smarcel} 22682745Smarcel 22782745Smarcelint 22883366Sjulianlinux_geteuid16(struct thread *td, struct linux_geteuid16_args *args) 22982745Smarcel{ 23082745Smarcel struct geteuid_args bsd; 23182745Smarcel 23283366Sjulian return (geteuid(td, &bsd)); 23382745Smarcel} 23482745Smarcel 23582745Smarcelint 23683366Sjulianlinux_setgid16(struct thread *td, struct linux_setgid16_args *args) 23782745Smarcel{ 23882745Smarcel struct setgid_args bsd; 23982745Smarcel 24082745Smarcel bsd.gid = args->gid; 24183366Sjulian return (setgid(td, &bsd)); 24282745Smarcel} 24382745Smarcel 24482745Smarcelint 24583366Sjulianlinux_setuid16(struct thread *td, struct linux_setuid16_args *args) 24682745Smarcel{ 24782745Smarcel struct setuid_args bsd; 24882745Smarcel 24982745Smarcel bsd.uid = args->uid; 25083366Sjulian return (setuid(td, &bsd)); 25182745Smarcel} 25282745Smarcel 25382745Smarcelint 25483366Sjulianlinux_setregid16(struct thread *td, struct linux_setregid16_args *args) 25582745Smarcel{ 25682745Smarcel struct setregid_args bsd; 25782745Smarcel 25884916Smarcel bsd.rgid = CAST_NOCHG(args->rgid); 25984916Smarcel bsd.egid = CAST_NOCHG(args->egid); 26083366Sjulian return (setregid(td, &bsd)); 26182745Smarcel} 26282745Smarcel 26382745Smarcelint 26483366Sjulianlinux_setreuid16(struct thread *td, struct linux_setreuid16_args *args) 26582745Smarcel{ 26682745Smarcel struct setreuid_args bsd; 26782745Smarcel 26884916Smarcel bsd.ruid = CAST_NOCHG(args->ruid); 26984916Smarcel bsd.euid = CAST_NOCHG(args->euid); 27083366Sjulian return (setreuid(td, &bsd)); 27182745Smarcel} 27282745Smarcel 27382745Smarcelint 27483366Sjulianlinux_setresgid16(struct thread *td, struct linux_setresgid16_args *args) 27582745Smarcel{ 27682745Smarcel struct setresgid_args bsd; 27782745Smarcel 27884916Smarcel bsd.rgid = CAST_NOCHG(args->rgid); 27984916Smarcel bsd.egid = CAST_NOCHG(args->egid); 28084916Smarcel bsd.sgid = CAST_NOCHG(args->sgid); 28183366Sjulian return (setresgid(td, &bsd)); 28282745Smarcel} 28382745Smarcel 28482745Smarcelint 28583366Sjulianlinux_setresuid16(struct thread *td, struct linux_setresuid16_args *args) 28682745Smarcel{ 28782745Smarcel struct setresuid_args bsd; 28882745Smarcel 28984916Smarcel bsd.ruid = CAST_NOCHG(args->ruid); 29084916Smarcel bsd.euid = CAST_NOCHG(args->euid); 29184916Smarcel bsd.suid = CAST_NOCHG(args->suid); 29283366Sjulian return (setresuid(td, &bsd)); 29382745Smarcel} 294