kern_prot.c revision 76166
11541Srgrimes/* 210937Swollman * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * (c) UNIX System Laboratories, Inc. 51541Srgrimes * All or some portions of this file are derived from material licensed 61541Srgrimes * to the University of California by American Telephone and Telegraph 71541Srgrimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 81541Srgrimes * the permission of UNIX System Laboratories, Inc. 91541Srgrimes * 101541Srgrimes * Redistribution and use in source and binary forms, with or without 111541Srgrimes * modification, are permitted provided that the following conditions 121541Srgrimes * are met: 131541Srgrimes * 1. Redistributions of source code must retain the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer. 151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161541Srgrimes * notice, this list of conditions and the following disclaimer in the 171541Srgrimes * documentation and/or other materials provided with the distribution. 181541Srgrimes * 3. All advertising materials mentioning features or use of this software 191541Srgrimes * must display the following acknowledgement: 201541Srgrimes * This product includes software developed by the University of 211541Srgrimes * California, Berkeley and its contributors. 221541Srgrimes * 4. Neither the name of the University nor the names of its contributors 231541Srgrimes * may be used to endorse or promote products derived from this software 241541Srgrimes * without specific prior written permission. 251541Srgrimes * 261541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 271541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 281541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 291541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 301541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 311541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 321541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3310937Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3450477Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 351541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 361541Srgrimes * SUCH DAMAGE. 372169Spaul * 382169Spaul * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 3986764Sjlemon * $FreeBSD: head/sys/kern/kern_prot.c 76166 2001-05-01 08:13:21Z markm $ 4086764Sjlemon */ 4198102Shsu 4286764Sjlemon/* 431541Srgrimes * System calls related to processes and protection 441541Srgrimes */ 451541Srgrimes 4686764Sjlemon#include "opt_compat.h" 4786764Sjlemon#include "opt_global.h" 481541Srgrimes 4955679Sshin#include <sys/param.h> 5055679Sshin#include <sys/systm.h> 5160938Sjake#include <sys/acct.h> 5255679Sshin#include <sys/kernel.h> 5355679Sshin#include <sys/lock.h> 5455679Sshin#include <sys/mutex.h> 5555679Sshin#include <sys/proc.h> 5660938Sjake#include <sys/sysproto.h> 5755679Sshin#include <sys/malloc.h> 5855679Sshin#include <sys/pioctl.h> 5955679Sshin#include <sys/resourcevar.h> 6055679Sshin#include <sys/sysctl.h> 6155679Sshin#include <sys/jail.h> 6255679Sshin 6355679Sshinstatic MALLOC_DEFINE(M_CRED, "cred", "credentials"); 6455679Sshin 6555679Sshin#ifndef _SYS_SYSPROTO_H_ 6655679Sshinstruct getpid_args { 6755679Sshin int dummy; 681541Srgrimes}; 691541Srgrimes#endif 7032821Sdg 711541Srgrimes/* 721541Srgrimes * getpid - MP SAFE 7355679Sshin */ 7432821Sdg 7578642Ssilby/* ARGSUSED */ 7632821Sdgint 7750673Sjlemongetpid(p, uap) 7850673Sjlemon struct proc *p; 7950673Sjlemon struct getpid_args *uap; 8050673Sjlemon{ 8150673Sjlemon 8232821Sdg p->p_retval[0] = p->p_pid; 8332821Sdg#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 8411187Swollman PROC_LOCK(p); 8511187Swollman p->p_retval[1] = p->p_pptr->p_pid; 86117650Shsu PROC_UNLOCK(p); 87117650Shsu#endif 88117650Shsu return (0); 89117650Shsu} 90117650Shsu 91117650Shsu/* 92117650Shsu * getppid - MP SAFE 93117650Shsu */ 94117650Shsu 95117650Shsu#ifndef _SYS_SYSPROTO_H_ 96117650Shsustruct getppid_args { 97117650Shsu int dummy; 98117650Shsu}; 99117650Shsu#endif 100117650Shsu/* ARGSUSED */ 101117650Shsuint 102117650Shsugetppid(p, uap) 103117650Shsu struct proc *p; 104117650Shsu struct getppid_args *uap; 105117650Shsu{ 106117650Shsu 107117650Shsu PROC_LOCK(p); 10832821Sdg p->p_retval[0] = p->p_pptr->p_pid; 1091541Srgrimes PROC_UNLOCK(p); 1101541Srgrimes return (0); 11132821Sdg} 11232821Sdg 11332821Sdg/* 1141541Srgrimes * Get process group ID; note that POSIX getpgrp takes no parameter 1151541Srgrimes * 11632821Sdg * MP SAFE 1171541Srgrimes */ 1181541Srgrimes#ifndef _SYS_SYSPROTO_H_ 1191541Srgrimesstruct getpgrp_args { 12032821Sdg int dummy; 12132821Sdg}; 12232821Sdg#endif 12332821Sdg 1241541Srgrimesint 1251541Srgrimesgetpgrp(p, uap) 12632821Sdg struct proc *p; 12732821Sdg struct getpgrp_args *uap; 1281541Srgrimes{ 129102017Sdillon 13013765Smpp p->p_retval[0] = p->p_pgrp->pg_id; 1311541Srgrimes return (0); 1321541Srgrimes} 1331541Srgrimes 134102017Sdillon/* Get an arbitary pid's process group id */ 135109175Shsu#ifndef _SYS_SYSPROTO_H_ 13660067Sjlemonstruct getpgid_args { 13732821Sdg pid_t pid; 13832821Sdg}; 13950673Sjlemon#endif 14050673Sjlemon 14150673Sjlemonint 1421541Srgrimesgetpgid(p, uap) 14332821Sdg struct proc *p; 144102017Sdillon struct getpgid_args *uap; 145102017Sdillon{ 146102017Sdillon struct proc *pt; 14750673Sjlemon int error; 14832821Sdg 14911187Swollman if (uap->pid == 0) 15011187Swollman p->p_retval[0] = p->p_pgrp->pg_id; 15132821Sdg else { 15232821Sdg if ((pt = pfind(uap->pid)) == NULL) 15311187Swollman return ESRCH; 154102017Sdillon if ((error = p_can(p, pt, P_CAN_SEE, NULL))) { 15532821Sdg PROC_UNLOCK(pt); 1561541Srgrimes return (error); 1571541Srgrimes } 15832821Sdg p->p_retval[0] = pt->p_pgrp->pg_id; 1591541Srgrimes PROC_UNLOCK(pt); 1601541Srgrimes } 1611541Srgrimes return 0; 1621541Srgrimes} 1631541Srgrimes 1641541Srgrimes/* 1651541Srgrimes * Get an arbitary pid's session id. 1661541Srgrimes */ 1671541Srgrimes#ifndef _SYS_SYSPROTO_H_ 1681541Srgrimesstruct getsid_args { 1691541Srgrimes pid_t pid; 17032821Sdg}; 1711541Srgrimes#endif 1721541Srgrimes 1736247Swollmanint 1746247Swollmangetsid(p, uap) 1756247Swollman struct proc *p; 17650673Sjlemon struct getsid_args *uap; 17750673Sjlemon{ 17850673Sjlemon struct proc *pt; 179117650Shsu int error; 18050673Sjlemon 181112957Shsu if (uap->pid == 0) 1821541Srgrimes p->p_retval[0] = p->p_session->s_sid; 1831541Srgrimes else { 184117650Shsu if ((pt = pfind(uap->pid)) == NULL) 185117650Shsu return ESRCH; 186117650Shsu if ((error = p_can(p, pt, P_CAN_SEE, NULL))) { 187117650Shsu PROC_UNLOCK(pt); 1886247Swollman return (error); 1896247Swollman } 1906247Swollman p->p_retval[0] = pt->p_session->s_sid; 1916247Swollman PROC_UNLOCK(pt); 1926247Swollman } 1936247Swollman return 0; 1946247Swollman} 19586764Sjlemon 1966247Swollman 1976247Swollman/* 1986247Swollman * getuid() - MP SAFE 1996247Swollman */ 20086764Sjlemon#ifndef _SYS_SYSPROTO_H_ 20186764Sjlemonstruct getuid_args { 20286764Sjlemon int dummy; 20386764Sjlemon}; 20486764Sjlemon#endif 20586764Sjlemon 20686764Sjlemon/* ARGSUSED */ 20786764Sjlemonint 20886764Sjlemongetuid(p, uap) 2096247Swollman struct proc *p; 2106247Swollman struct getuid_args *uap; 21186764Sjlemon{ 21286764Sjlemon 21386764Sjlemon p->p_retval[0] = p->p_cred->p_ruid; 21486764Sjlemon#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 21586764Sjlemon p->p_retval[1] = p->p_ucred->cr_uid; 21686764Sjlemon#endif 21786764Sjlemon return (0); 21886764Sjlemon} 21986764Sjlemon 22086764Sjlemon/* 22186764Sjlemon * geteuid() - MP SAFE 22286764Sjlemon */ 22386764Sjlemon#ifndef _SYS_SYSPROTO_H_ 22486764Sjlemonstruct geteuid_args { 22586764Sjlemon int dummy; 22686764Sjlemon}; 22786764Sjlemon#endif 22886764Sjlemon 22986764Sjlemon/* ARGSUSED */ 23086764Sjlemonint 23186764Sjlemongeteuid(p, uap) 23286764Sjlemon struct proc *p; 23386764Sjlemon struct geteuid_args *uap; 23486764Sjlemon{ 23586764Sjlemon 23686764Sjlemon p->p_retval[0] = p->p_ucred->cr_uid; 23786764Sjlemon return (0); 23886764Sjlemon} 23986764Sjlemon 24086764Sjlemon/* 24186764Sjlemon * getgid() - MP SAFE 24286764Sjlemon */ 24386764Sjlemon#ifndef _SYS_SYSPROTO_H_ 244111145Sjlemonstruct getgid_args { 245111145Sjlemon int dummy; 246111145Sjlemon}; 247111145Sjlemon#endif 248111145Sjlemon 249121850Ssilby/* ARGSUSED */ 250111145Sjlemonint 251111145Sjlemongetgid(p, uap) 252111145Sjlemon struct proc *p; 253111145Sjlemon struct getgid_args *uap; 254111145Sjlemon{ 255111145Sjlemon 256111145Sjlemon p->p_retval[0] = p->p_cred->p_rgid; 257112009Sjlemon#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 258112009Sjlemon p->p_retval[1] = p->p_ucred->cr_groups[0]; 259111145Sjlemon#endif 26086764Sjlemon return (0); 2616247Swollman} 2626247Swollman 2636247Swollman/* 2646247Swollman * Get effective group ID. The "egid" is groups[0], and could be obtained 2656247Swollman * via getgroups. This syscall exists because it is somewhat painful to do 2666247Swollman * correctly in a library function. 2676247Swollman */ 2686247Swollman#ifndef _SYS_SYSPROTO_H_ 2696247Swollmanstruct getegid_args { 2706247Swollman int dummy; 2716247Swollman}; 2726247Swollman#endif 2736247Swollman 2746247Swollman/* ARGSUSED */ 2756247Swollmanint 2766283Swollmangetegid(p, uap) 2776247Swollman struct proc *p; 2781541Srgrimes struct getegid_args *uap; 279111145Sjlemon{ 2801541Srgrimes 2811541Srgrimes p->p_retval[0] = p->p_ucred->cr_groups[0]; 2821541Srgrimes return (0); 2831541Srgrimes} 2841541Srgrimes 2851541Srgrimes#ifndef _SYS_SYSPROTO_H_ 2861541Srgrimesstruct getgroups_args { 2871541Srgrimes u_int gidsetsize; 2881541Srgrimes gid_t *gidset; 2891541Srgrimes}; 2901541Srgrimes#endif 29114753Swollmanint 29214753Swollmangetgroups(p, uap) 29314753Swollman struct proc *p; 29414753Swollman register struct getgroups_args *uap; 29514753Swollman{ 2961541Srgrimes register struct pcred *pc = p->p_cred; 2971541Srgrimes register u_int ngrp; 2981541Srgrimes int error; 2991541Srgrimes 3001541Srgrimes if ((ngrp = uap->gidsetsize) == 0) { 3011541Srgrimes p->p_retval[0] = pc->pc_ucred->cr_ngroups; 3021541Srgrimes return (0); 3031541Srgrimes } 3041541Srgrimes if (ngrp < pc->pc_ucred->cr_ngroups) 3051541Srgrimes return (EINVAL); 3061541Srgrimes ngrp = pc->pc_ucred->cr_ngroups; 30714753Swollman if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups, 30814753Swollman (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) 30914753Swollman return (error); 31014753Swollman p->p_retval[0] = ngrp; 31114753Swollman return (0); 3121541Srgrimes} 3131541Srgrimes 31435419Sdg#ifndef _SYS_SYSPROTO_H_ 31516141Swollmanstruct setsid_args { 3161541Srgrimes int dummy; 3171541Srgrimes}; 3181541Srgrimes#endif 3191541Srgrimes 3201541Srgrimes/* ARGSUSED */ 3211541Srgrimesint 3221541Srgrimessetsid(p, uap) 3231541Srgrimes register struct proc *p; 3241541Srgrimes struct setsid_args *uap; 3251541Srgrimes{ 3261541Srgrimes 3271541Srgrimes if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { 3281541Srgrimes return (EPERM); 3291541Srgrimes } else { 3301541Srgrimes (void)enterpgrp(p, p->p_pid, 1); 3311541Srgrimes p->p_retval[0] = p->p_pid; 3321541Srgrimes return (0); 3331541Srgrimes } 3341541Srgrimes} 3351541Srgrimes 3361541Srgrimes/* 3371541Srgrimes * set process group (setpgid/old setpgrp) 3381541Srgrimes * 3391541Srgrimes * caller does setpgid(targpid, targpgid) 3401541Srgrimes * 3411541Srgrimes * pid must be caller or child of caller (ESRCH) 3421541Srgrimes * if a child 3431541Srgrimes * pid must be in same session (EPERM) 344100373Sdillon * pid can't have done an exec (EACCES) 3451541Srgrimes * if pgid != pid 3461541Srgrimes * there must exist some pid in same session having pgid (EPERM) 3471541Srgrimes * pid must not be session leader (EPERM) 3481541Srgrimes */ 3491541Srgrimes#ifndef _SYS_SYSPROTO_H_ 3501541Srgrimesstruct setpgid_args { 3511541Srgrimes int pid; /* target process id */ 3521541Srgrimes int pgid; /* target pgrp id */ 3531541Srgrimes}; 3541541Srgrimes#endif 3551541Srgrimes/* ARGSUSED */ 35652904Sshinint 3571541Srgrimessetpgid(curp, uap) 3581541Srgrimes struct proc *curp; 3591541Srgrimes register struct setpgid_args *uap; 3601541Srgrimes{ 3611541Srgrimes register struct proc *targp; /* target process */ 3621541Srgrimes register struct pgrp *pgrp; /* target pgrp */ 3631541Srgrimes int error; 3641541Srgrimes 3651541Srgrimes if (uap->pgid < 0) 3661541Srgrimes return (EINVAL); 3671541Srgrimes if (uap->pid != 0 && uap->pid != curp->p_pid) { 3681541Srgrimes if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) { 3691541Srgrimes if (targp) 3701541Srgrimes PROC_UNLOCK(targp); 3711541Srgrimes return (ESRCH); 3721541Srgrimes } 3731541Srgrimes if ((error = p_can(curproc, targp, P_CAN_SEE, NULL))) { 3741541Srgrimes PROC_UNLOCK(targp); 3751541Srgrimes return (error); 3761541Srgrimes } 3779263Swollman if (targp->p_pgrp == NULL || 3789263Swollman targp->p_session != curp->p_session) { 3799263Swollman PROC_UNLOCK(targp); 3809470Swollman return (EPERM); 3819470Swollman } 3829470Swollman if (targp->p_flag & P_EXEC) { 38310937Swollman PROC_UNLOCK(targp); 38410937Swollman return (EACCES); 38511415Swollman } 38614281Sbde } else { 38786764Sjlemon targp = curp; 38886764Sjlemon PROC_LOCK(curp); /* XXX: not needed */ 38986764Sjlemon } 39086764Sjlemon if (SESS_LEADER(targp)) { 39186764Sjlemon PROC_UNLOCK(targp); 39286764Sjlemon return (EPERM); 39386764Sjlemon } 39486764Sjlemon if (uap->pgid == 0) 39586764Sjlemon uap->pgid = targp->p_pid; 39686764Sjlemon else if (uap->pgid != targp->p_pid) 39786764Sjlemon if ((pgrp = pgfind(uap->pgid)) == 0 || 39886764Sjlemon pgrp->pg_session != curp->p_session) { 39986764Sjlemon PROC_UNLOCK(targp); 40086764Sjlemon return (EPERM); 40186764Sjlemon } 40286764Sjlemon /* XXX: We should probably hold the lock across enterpgrp. */ 4031541Srgrimes PROC_UNLOCK(targp); 4041541Srgrimes return (enterpgrp(targp, uap->pgid, 0)); 4056247Swollman} 40636079Swollman 40737183Sjhay/* 40837183Sjhay * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 40936079Swollman * compatible. It says that setting the uid/gid to euid/egid is a special 41037183Sjhay * case of "appropriate privilege". Once the rules are expanded out, this 41136079Swollman * basically means that setuid(nnn) sets all three id's, in all permitted 41236079Swollman * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 41336079Swollman * does not set the saved id - this is dangerous for traditional BSD 41436079Swollman * programs. For this reason, we *really* do not want to set 41536079Swollman * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 41636079Swollman */ 41736079Swollman#define POSIX_APPENDIX_B_4_2_2 41836079Swollman 41936079Swollman#ifndef _SYS_SYSPROTO_H_ 42036079Swollmanstruct setuid_args { 4216247Swollman uid_t uid; 4226247Swollman}; 4236247Swollman#endif 4246247Swollman/* ARGSUSED */ 4256247Swollmanint 4266472Swollmansetuid(p, uap) 4276472Swollman struct proc *p; 4286472Swollman struct setuid_args *uap; 4296472Swollman{ 43018281Spst register struct pcred *pc = p->p_cred; 43118281Spst register uid_t uid; 43263431Ssheldonh int error; 43336079Swollman 43450673Sjlemon /* 43552904Sshin * See if we have "permission" by POSIX 1003.1 rules. 43652904Sshin * 4376247Swollman * Note that setuid(geteuid()) is a special case of 4386247Swollman * "appropriate privileges" in appendix B.4.2.2. We need 4396247Swollman * to use this clause to be compatible with traditional BSD 4406348Swollman * semantics. Basically, it means that "setuid(xx)" sets all 4416348Swollman * three id's (assuming you have privs). 4426247Swollman * 4436472Swollman * Notes on the logic. We do things in three steps. 4446472Swollman * 1: We determine if the euid is going to change, and do EPERM 4456472Swollman * right away. We unconditionally change the euid later if this 4466472Swollman * test is satisfied, simplifying that part of the logic. 4476472Swollman * 2: We determine if the real and/or saved uid's are going to 4486472Swollman * change. Determined by compile options. 44918281Spst * 3: Change euid last. (after tests in #2 for "appropriate privs") 45036079Swollman */ 45150673Sjlemon uid = uap->uid; 45252904Sshin if (uid != pc->p_ruid && /* allow setuid(getuid()) */ 4536247Swollman#ifdef _POSIX_SAVED_IDS 4546247Swollman uid != pc->p_svuid && /* allow setuid(saved gid) */ 45544078Sdfr#endif 45655205Speter#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 45744078Sdfr uid != pc->pc_ucred->cr_uid && /* allow setuid(geteuid()) */ 45844078Sdfr#endif 45944078Sdfr (error = suser_xxx(0, p, PRISON_ROOT))) 46044078Sdfr return (error); 4617684Sdg 4627684Sdg#ifdef _POSIX_SAVED_IDS 4636348Swollman /* 4647090Sbde * Do we have "appropriate privileges" (are we root or uid == euid) 46533846Sdg * If so, we are changing the real uid and/or saved uid. 46660067Sjlemon */ 46798204Ssilby if ( 46850673Sjlemon#ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 46950673Sjlemon uid == pc->pc_ucred->cr_uid || 4701541Srgrimes#endif 47192723Salfred suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ 4721541Srgrimes#endif 47392723Salfred { 474111145Sjlemon /* 475121850Ssilby * Set the real uid and transfer proc count to new user. 476112009Sjlemon */ 477112009Sjlemon if (uid != pc->p_ruid) { 47892723Salfred change_ruid(p, uid); 47992723Salfred setsugid(p); 4801541Srgrimes } 48192723Salfred /* 48292723Salfred * Set saved uid 48392723Salfred * 4846247Swollman * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 48592723Salfred * the security of seteuid() depends on it. B.4.2.2 says it 48692723Salfred * is important that we should do this. 48792723Salfred */ 48892723Salfred if (pc->p_svuid != uid) { 48992723Salfred pc->p_svuid = uid; 49098211Shsu setsugid(p); 49198211Shsu } 49298211Shsu } 49398211Shsu 4941541Srgrimes /* 49592723Salfred * In all permitted cases, we are changing the euid. 49692723Salfred * Copy credentials so other references do not see our changes. 49798211Shsu */ 49898211Shsu if (pc->pc_ucred->cr_uid != uid) { 49992723Salfred change_euid(p, uid); 50092723Salfred setsugid(p); 501114794Srwatson } 5026247Swollman return (0); 50392723Salfred} 50492723Salfred 50592723Salfred#ifndef _SYS_SYSPROTO_H_ 50655679Sshinstruct seteuid_args { 507111144Sjlemon uid_t euid; 508111144Sjlemon}; 5091541Srgrimes#endif 51092723Salfred/* ARGSUSED */ 51192723Salfredint 512102017Sdillonseteuid(p, uap) 51386764Sjlemon struct proc *p; 51486764Sjlemon struct seteuid_args *uap; 51586764Sjlemon{ 51686764Sjlemon register struct pcred *pc = p->p_cred; 51786764Sjlemon register uid_t euid; 51886764Sjlemon int error; 51986764Sjlemon 52086764Sjlemon euid = uap->euid; 5219470Swollman if (euid != pc->p_ruid && /* allow seteuid(getuid()) */ 52217096Swollman euid != pc->p_svuid && /* allow seteuid(saved uid) */ 5239470Swollman (error = suser_xxx(0, p, PRISON_ROOT))) 5249470Swollman return (error); 52592723Salfred /* 5269470Swollman * Everything's okay, do it. Copy credentials so other references do 52755205Speter * not see our changes. 5282169Spaul */ 5296348Swollman if (pc->pc_ucred->cr_uid != euid) { 530 change_euid(p, euid); 531 setsugid(p); 532 } 533 return (0); 534} 535 536#ifndef _SYS_SYSPROTO_H_ 537struct setgid_args { 538 gid_t gid; 539}; 540#endif 541/* ARGSUSED */ 542int 543setgid(p, uap) 544 struct proc *p; 545 struct setgid_args *uap; 546{ 547 register struct pcred *pc = p->p_cred; 548 register gid_t gid; 549 int error; 550 551 /* 552 * See if we have "permission" by POSIX 1003.1 rules. 553 * 554 * Note that setgid(getegid()) is a special case of 555 * "appropriate privileges" in appendix B.4.2.2. We need 556 * to use this clause to be compatible with traditional BSD 557 * semantics. Basically, it means that "setgid(xx)" sets all 558 * three id's (assuming you have privs). 559 * 560 * For notes on the logic here, see setuid() above. 561 */ 562 gid = uap->gid; 563 if (gid != pc->p_rgid && /* allow setgid(getgid()) */ 564#ifdef _POSIX_SAVED_IDS 565 gid != pc->p_svgid && /* allow setgid(saved gid) */ 566#endif 567#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 568 gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */ 569#endif 570 (error = suser_xxx(0, p, PRISON_ROOT))) 571 return (error); 572 573#ifdef _POSIX_SAVED_IDS 574 /* 575 * Do we have "appropriate privileges" (are we root or gid == egid) 576 * If so, we are changing the real uid and saved gid. 577 */ 578 if ( 579#ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 580 gid == pc->pc_ucred->cr_groups[0] || 581#endif 582 suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ 583#endif 584 { 585 /* 586 * Set real gid 587 */ 588 if (pc->p_rgid != gid) { 589 pc->p_rgid = gid; 590 setsugid(p); 591 } 592 /* 593 * Set saved gid 594 * 595 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 596 * the security of setegid() depends on it. B.4.2.2 says it 597 * is important that we should do this. 598 */ 599 if (pc->p_svgid != gid) { 600 pc->p_svgid = gid; 601 setsugid(p); 602 } 603 } 604 /* 605 * In all cases permitted cases, we are changing the egid. 606 * Copy credentials so other references do not see our changes. 607 */ 608 if (pc->pc_ucred->cr_groups[0] != gid) { 609 pc->pc_ucred = crcopy(pc->pc_ucred); 610 pc->pc_ucred->cr_groups[0] = gid; 611 setsugid(p); 612 } 613 return (0); 614} 615 616#ifndef _SYS_SYSPROTO_H_ 617struct setegid_args { 618 gid_t egid; 619}; 620#endif 621/* ARGSUSED */ 622int 623setegid(p, uap) 624 struct proc *p; 625 struct setegid_args *uap; 626{ 627 register struct pcred *pc = p->p_cred; 628 register gid_t egid; 629 int error; 630 631 egid = uap->egid; 632 if (egid != pc->p_rgid && /* allow setegid(getgid()) */ 633 egid != pc->p_svgid && /* allow setegid(saved gid) */ 634 (error = suser_xxx(0, p, PRISON_ROOT))) 635 return (error); 636 if (pc->pc_ucred->cr_groups[0] != egid) { 637 pc->pc_ucred = crcopy(pc->pc_ucred); 638 pc->pc_ucred->cr_groups[0] = egid; 639 setsugid(p); 640 } 641 return (0); 642} 643 644#ifndef _SYS_SYSPROTO_H_ 645struct setgroups_args { 646 u_int gidsetsize; 647 gid_t *gidset; 648}; 649#endif 650/* ARGSUSED */ 651int 652setgroups(p, uap) 653 struct proc *p; 654 struct setgroups_args *uap; 655{ 656 register struct pcred *pc = p->p_cred; 657 register u_int ngrp; 658 int error; 659 660 if ((error = suser_xxx(0, p, PRISON_ROOT))) 661 return (error); 662 ngrp = uap->gidsetsize; 663 if (ngrp > NGROUPS) 664 return (EINVAL); 665 /* 666 * XXX A little bit lazy here. We could test if anything has 667 * changed before crcopy() and setting P_SUGID. 668 */ 669 pc->pc_ucred = crcopy(pc->pc_ucred); 670 if (ngrp < 1) { 671 /* 672 * setgroups(0, NULL) is a legitimate way of clearing the 673 * groups vector on non-BSD systems (which generally do not 674 * have the egid in the groups[0]). We risk security holes 675 * when running non-BSD software if we do not do the same. 676 */ 677 pc->pc_ucred->cr_ngroups = 1; 678 } else { 679 if ((error = copyin((caddr_t)uap->gidset, 680 (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))) 681 return (error); 682 pc->pc_ucred->cr_ngroups = ngrp; 683 } 684 setsugid(p); 685 return (0); 686} 687 688#ifndef _SYS_SYSPROTO_H_ 689struct setreuid_args { 690 uid_t ruid; 691 uid_t euid; 692}; 693#endif 694/* ARGSUSED */ 695int 696setreuid(p, uap) 697 register struct proc *p; 698 struct setreuid_args *uap; 699{ 700 register struct pcred *pc = p->p_cred; 701 register uid_t ruid, euid; 702 int error; 703 704 ruid = uap->ruid; 705 euid = uap->euid; 706 if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) || 707 (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid && 708 euid != pc->p_ruid && euid != pc->p_svuid)) && 709 (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 710 return (error); 711 712 if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { 713 change_euid(p, euid); 714 setsugid(p); 715 } 716 if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { 717 change_ruid(p, ruid); 718 setsugid(p); 719 } 720 if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) && 721 pc->p_svuid != pc->pc_ucred->cr_uid) { 722 pc->p_svuid = pc->pc_ucred->cr_uid; 723 setsugid(p); 724 } 725 return (0); 726} 727 728#ifndef _SYS_SYSPROTO_H_ 729struct setregid_args { 730 gid_t rgid; 731 gid_t egid; 732}; 733#endif 734/* ARGSUSED */ 735int 736setregid(p, uap) 737 register struct proc *p; 738 struct setregid_args *uap; 739{ 740 register struct pcred *pc = p->p_cred; 741 register gid_t rgid, egid; 742 int error; 743 744 rgid = uap->rgid; 745 egid = uap->egid; 746 if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) || 747 (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] && 748 egid != pc->p_rgid && egid != pc->p_svgid)) && 749 (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 750 return (error); 751 752 if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { 753 pc->pc_ucred = crcopy(pc->pc_ucred); 754 pc->pc_ucred->cr_groups[0] = egid; 755 setsugid(p); 756 } 757 if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { 758 pc->p_rgid = rgid; 759 setsugid(p); 760 } 761 if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) && 762 pc->p_svgid != pc->pc_ucred->cr_groups[0]) { 763 pc->p_svgid = pc->pc_ucred->cr_groups[0]; 764 setsugid(p); 765 } 766 return (0); 767} 768 769/* 770 * setresuid(ruid, euid, suid) is like setreuid except control over the 771 * saved uid is explicit. 772 */ 773 774#ifndef _SYS_SYSPROTO_H_ 775struct setresuid_args { 776 uid_t ruid; 777 uid_t euid; 778 uid_t suid; 779}; 780#endif 781/* ARGSUSED */ 782int 783setresuid(p, uap) 784 register struct proc *p; 785 struct setresuid_args *uap; 786{ 787 register struct pcred *pc = p->p_cred; 788 register uid_t ruid, euid, suid; 789 int error; 790 791 ruid = uap->ruid; 792 euid = uap->euid; 793 suid = uap->suid; 794 if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid && 795 ruid != pc->pc_ucred->cr_uid) || 796 (euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid && 797 euid != pc->pc_ucred->cr_uid) || 798 (suid != (uid_t)-1 && suid != pc->p_ruid && suid != pc->p_svuid && 799 suid != pc->pc_ucred->cr_uid)) && 800 (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 801 return (error); 802 if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { 803 change_euid(p, euid); 804 setsugid(p); 805 } 806 if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { 807 change_ruid(p, ruid); 808 setsugid(p); 809 } 810 if (suid != (uid_t)-1 && pc->p_svuid != suid) { 811 pc->p_svuid = suid; 812 setsugid(p); 813 } 814 return (0); 815} 816 817/* 818 * setresgid(rgid, egid, sgid) is like setregid except control over the 819 * saved gid is explicit. 820 */ 821 822#ifndef _SYS_SYSPROTO_H_ 823struct setresgid_args { 824 gid_t rgid; 825 gid_t egid; 826 gid_t sgid; 827}; 828#endif 829/* ARGSUSED */ 830int 831setresgid(p, uap) 832 register struct proc *p; 833 struct setresgid_args *uap; 834{ 835 register struct pcred *pc = p->p_cred; 836 register gid_t rgid, egid, sgid; 837 int error; 838 839 rgid = uap->rgid; 840 egid = uap->egid; 841 sgid = uap->sgid; 842 if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid && 843 rgid != pc->pc_ucred->cr_groups[0]) || 844 (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid && 845 egid != pc->pc_ucred->cr_groups[0]) || 846 (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid && 847 sgid != pc->pc_ucred->cr_groups[0])) && 848 (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 849 return (error); 850 851 if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { 852 pc->pc_ucred = crcopy(pc->pc_ucred); 853 pc->pc_ucred->cr_groups[0] = egid; 854 setsugid(p); 855 } 856 if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { 857 pc->p_rgid = rgid; 858 setsugid(p); 859 } 860 if (sgid != (gid_t)-1 && pc->p_svgid != sgid) { 861 pc->p_svgid = sgid; 862 setsugid(p); 863 } 864 return (0); 865} 866 867#ifndef _SYS_SYSPROTO_H_ 868struct getresuid_args { 869 uid_t *ruid; 870 uid_t *euid; 871 uid_t *suid; 872}; 873#endif 874/* ARGSUSED */ 875int 876getresuid(p, uap) 877 register struct proc *p; 878 struct getresuid_args *uap; 879{ 880 struct pcred *pc = p->p_cred; 881 int error1 = 0, error2 = 0, error3 = 0; 882 883 if (uap->ruid) 884 error1 = copyout((caddr_t)&pc->p_ruid, 885 (caddr_t)uap->ruid, sizeof(pc->p_ruid)); 886 if (uap->euid) 887 error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid, 888 (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid)); 889 if (uap->suid) 890 error3 = copyout((caddr_t)&pc->p_svuid, 891 (caddr_t)uap->suid, sizeof(pc->p_svuid)); 892 return error1 ? error1 : (error2 ? error2 : error3); 893} 894 895#ifndef _SYS_SYSPROTO_H_ 896struct getresgid_args { 897 gid_t *rgid; 898 gid_t *egid; 899 gid_t *sgid; 900}; 901#endif 902/* ARGSUSED */ 903int 904getresgid(p, uap) 905 register struct proc *p; 906 struct getresgid_args *uap; 907{ 908 struct pcred *pc = p->p_cred; 909 int error1 = 0, error2 = 0, error3 = 0; 910 911 if (uap->rgid) 912 error1 = copyout((caddr_t)&pc->p_rgid, 913 (caddr_t)uap->rgid, sizeof(pc->p_rgid)); 914 if (uap->egid) 915 error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0], 916 (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0])); 917 if (uap->sgid) 918 error3 = copyout((caddr_t)&pc->p_svgid, 919 (caddr_t)uap->sgid, sizeof(pc->p_svgid)); 920 return error1 ? error1 : (error2 ? error2 : error3); 921} 922 923 924#ifndef _SYS_SYSPROTO_H_ 925struct issetugid_args { 926 int dummy; 927}; 928#endif 929/* ARGSUSED */ 930int 931issetugid(p, uap) 932 register struct proc *p; 933 struct issetugid_args *uap; 934{ 935 /* 936 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 937 * we use P_SUGID because we consider changing the owners as 938 * "tainting" as well. 939 * This is significant for procs that start as root and "become" 940 * a user without an exec - programs cannot know *everything* 941 * that libc *might* have put in their data segment. 942 */ 943 p->p_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 944 return (0); 945} 946 947int 948__setugid(p, uap) 949 struct proc *p; 950 struct __setugid_args *uap; 951{ 952 953#ifdef REGRESSION 954 switch (uap->flag) { 955 case 0: 956 p->p_flag &= ~P_SUGID; 957 return (0); 958 case 1: 959 p->p_flag |= P_SUGID; 960 return (0); 961 default: 962 return (EINVAL); 963 } 964#else /* !REGRESSION */ 965 return (ENOSYS); 966#endif /* !REGRESSION */ 967} 968 969/* 970 * Check if gid is a member of the group set. 971 */ 972int 973groupmember(gid, cred) 974 gid_t gid; 975 register struct ucred *cred; 976{ 977 register gid_t *gp; 978 gid_t *egp; 979 980 egp = &(cred->cr_groups[cred->cr_ngroups]); 981 for (gp = cred->cr_groups; gp < egp; gp++) 982 if (*gp == gid) 983 return (1); 984 return (0); 985} 986 987static int suser_permitted = 1; 988 989SYSCTL_INT(_kern, OID_AUTO, suser_permitted, CTLFLAG_RW, &suser_permitted, 0, 990 "processes with uid 0 have privilege"); 991 992/* 993 * Test whether the specified credentials imply "super-user" 994 * privilege; if so, and we have accounting info, set the flag 995 * indicating use of super-powers. 996 * Returns 0 or error. 997 */ 998int 999suser(p) 1000 struct proc *p; 1001{ 1002 return suser_xxx(0, p, 0); 1003} 1004 1005int 1006suser_xxx(cred, proc, flag) 1007 struct ucred *cred; 1008 struct proc *proc; 1009 int flag; 1010{ 1011 if (!suser_permitted) 1012 return (EPERM); 1013 if (!cred && !proc) { 1014 printf("suser_xxx(): THINK!\n"); 1015 return (EPERM); 1016 } 1017 if (!cred) 1018 cred = proc->p_ucred; 1019 if (cred->cr_uid != 0) 1020 return (EPERM); 1021 if (jailed(cred) && !(flag & PRISON_ROOT)) 1022 return (EPERM); 1023 return (0); 1024} 1025 1026/* 1027 * u_cansee(u1, u2): determine if u1 "can see" the subject specified by u2 1028 * Arguments: imutable credentials u1, u2 1029 * Returns: 0 for permitted, an errno value otherwise 1030 * Locks: none 1031 * References: u1 and u2 must be valid for the lifetime of the call 1032 * u1 may equal u2, in which case only one reference is required 1033 */ 1034int 1035u_cansee(struct ucred *u1, struct ucred *u2) 1036{ 1037 int error; 1038 1039 if ((error = prison_check(u1, u2))) 1040 return (error); 1041 if (!ps_showallprocs && u1->cr_uid != u2->cr_uid) { 1042 if (suser_xxx(u1, NULL, PRISON_ROOT) != 0) 1043 return (ESRCH); 1044 } 1045 return (0); 1046} 1047 1048static int 1049p_cansee(struct proc *p1, struct proc *p2, int *privused) 1050{ 1051 1052 /* XXX: privused is going away, so don't do that here. */ 1053 if (privused != NULL) 1054 *privused = 0; 1055 /* Wrap u_cansee() for all functionality. */ 1056 return (u_cansee(p1->p_ucred, p2->p_ucred)); 1057} 1058 1059/* 1060 * Can process p1 send the signal signum to process p2? 1061 */ 1062int 1063p_cansignal(struct proc *p1, struct proc *p2, int signum) 1064{ 1065 int error; 1066 1067 if (p1 == p2) 1068 return (0); 1069 1070 /* 1071 * Jail semantics limit the scope of signalling to p2 in the same 1072 * jail as p1, if p1 is in jail. 1073 */ 1074 if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 1075 return (error); 1076 1077 /* 1078 * UNIX signalling semantics require that processes in the same 1079 * session always be able to deliver SIGCONT to one another, 1080 * overriding the remaining protections. 1081 */ 1082 if (signum == SIGCONT && p1->p_session == p2->p_session) 1083 return (0); 1084 1085 /* 1086 * UNIX uid semantics depend on the status of the P_SUGID 1087 * bit on the target process. If the bit is set, then more 1088 * restricted signal sets are permitted. 1089 */ 1090 if (p2->p_flag & P_SUGID) { 1091 switch (signum) { 1092 case 0: 1093 case SIGKILL: 1094 case SIGINT: 1095 case SIGTERM: 1096 case SIGSTOP: 1097 case SIGTTIN: 1098 case SIGTTOU: 1099 case SIGTSTP: 1100 case SIGHUP: 1101 case SIGUSR1: 1102 case SIGUSR2: 1103 break; 1104 default: 1105 /* Not permitted, try privilege. */ 1106 error = suser_xxx(NULL, p1, PRISON_ROOT); 1107 if (error) 1108 return (error); 1109 } 1110 } 1111 1112 /* 1113 * Generally, the object credential's ruid or svuid must match the 1114 * subject credential's ruid or euid. 1115 */ 1116 if (p1->p_cred->p_ruid != p2->p_cred->p_ruid && 1117 p1->p_cred->p_ruid != p2->p_cred->p_svuid && 1118 p1->p_ucred->cr_uid != p2->p_cred->p_ruid && 1119 p1->p_ucred->cr_uid != p2->p_cred->p_svuid) { 1120 /* Not permitted, try privilege. */ 1121 error = suser_xxx(NULL, p1, PRISON_ROOT); 1122 if (error) 1123 return (error); 1124 } 1125 1126 return (0); 1127} 1128 1129static int 1130p_cansched(struct proc *p1, struct proc *p2, int *privused) 1131{ 1132 int error; 1133 1134 if (privused != NULL) 1135 *privused = 0; 1136 1137 if (p1 == p2) 1138 return (0); 1139 1140 if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 1141 return (error); 1142 1143 if (p1->p_cred->p_ruid == p2->p_cred->p_ruid) 1144 return (0); 1145 if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid) 1146 return (0); 1147 1148 if (!suser_xxx(0, p1, PRISON_ROOT)) { 1149 if (privused != NULL) 1150 *privused = 1; 1151 return (0); 1152 } 1153 1154#ifdef CAPABILITIES 1155 if (!cap_check_xxx(0, p1, CAP_SYS_NICE, PRISON_ROOT)) { 1156 if (privused != NULL) 1157 *privused = 1; 1158 return (0); 1159 } 1160#endif 1161 1162 return (EPERM); 1163} 1164 1165static int 1166p_candebug(struct proc *p1, struct proc *p2, int *privused) 1167{ 1168 int error; 1169 1170 if (privused != NULL) 1171 *privused = 0; 1172 1173 if (p1 == p2) 1174 return (0); 1175 1176 if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 1177 return (error); 1178 1179 /* not owned by you, has done setuid (unless you're root) */ 1180 /* add a CAP_SYS_PTRACE here? */ 1181 if (p1->p_cred->pc_ucred->cr_uid != p2->p_cred->p_ruid || 1182 p1->p_cred->p_ruid != p2->p_cred->p_ruid || 1183 p1->p_cred->p_svuid != p2->p_cred->p_ruid || 1184 p2->p_flag & P_SUGID) { 1185 if ((error = suser_xxx(0, p1, PRISON_ROOT))) 1186 return (error); 1187 if (privused != NULL) 1188 *privused = 1; 1189 } 1190 1191 /* can't trace init when securelevel > 0 */ 1192 if (securelevel > 0 && p2->p_pid == 1) 1193 return (EPERM); 1194 1195 return (0); 1196} 1197 1198int 1199p_can(struct proc *p1, struct proc *p2, int operation, 1200 int *privused) 1201{ 1202 1203 switch(operation) { 1204 case P_CAN_SEE: 1205 return (p_cansee(p1, p2, privused)); 1206 1207 case P_CAN_SCHED: 1208 return (p_cansched(p1, p2, privused)); 1209 1210 case P_CAN_DEBUG: 1211 return (p_candebug(p1, p2, privused)); 1212 1213 default: 1214 panic("p_can: invalid operation"); 1215 } 1216} 1217 1218 1219/* 1220 * Allocate a zeroed cred structure. 1221 */ 1222struct ucred * 1223crget() 1224{ 1225 register struct ucred *cr; 1226 1227 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK|M_ZERO); 1228 cr->cr_ref = 1; 1229 mtx_init(&cr->cr_mtx, "ucred", MTX_DEF); 1230 return (cr); 1231} 1232 1233/* 1234 * Claim another reference to a ucred structure 1235 */ 1236void 1237crhold(cr) 1238 struct ucred *cr; 1239{ 1240 1241 mtx_lock(&cr->cr_mtx); 1242 cr->cr_ref++; 1243 mtx_unlock(&(cr)->cr_mtx); 1244} 1245 1246 1247/* 1248 * Free a cred structure. 1249 * Throws away space when ref count gets to 0. 1250 */ 1251void 1252crfree(cr) 1253 struct ucred *cr; 1254{ 1255 1256 mtx_lock(&cr->cr_mtx); 1257 KASSERT(cr->cr_ref > 0, ("bad ucred refcount: %d", cr->cr_ref)); 1258 if (--cr->cr_ref == 0) { 1259 mtx_destroy(&cr->cr_mtx); 1260 /* 1261 * Some callers of crget(), such as nfs_statfs(), 1262 * allocate a temporary credential, but don't 1263 * allocate a uidinfo structure. 1264 */ 1265 if (cr->cr_uidinfo != NULL) 1266 uifree(cr->cr_uidinfo); 1267 /* 1268 * Free a prison, if any. 1269 */ 1270 if (jailed(cr)) 1271 prison_free(cr->cr_prison); 1272 FREE((caddr_t)cr, M_CRED); 1273 } else { 1274 mtx_unlock(&cr->cr_mtx); 1275 } 1276} 1277 1278/* 1279 * Copy cred structure to a new one and free the old one. 1280 */ 1281struct ucred * 1282crcopy(cr) 1283 struct ucred *cr; 1284{ 1285 struct ucred *newcr; 1286 1287 mtx_lock(&cr->cr_mtx); 1288 if (cr->cr_ref == 1) { 1289 mtx_unlock(&cr->cr_mtx); 1290 return (cr); 1291 } 1292 mtx_unlock(&cr->cr_mtx); 1293 newcr = crdup(cr); 1294 crfree(cr); 1295 return (newcr); 1296} 1297 1298/* 1299 * Dup cred struct to a new held one. 1300 */ 1301struct ucred * 1302crdup(cr) 1303 struct ucred *cr; 1304{ 1305 struct ucred *newcr; 1306 1307 MALLOC(newcr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 1308 *newcr = *cr; 1309 mtx_init(&newcr->cr_mtx, "ucred", MTX_DEF); 1310 uihold(newcr->cr_uidinfo); 1311 if (jailed(newcr)) 1312 prison_hold(newcr->cr_prison); 1313 newcr->cr_ref = 1; 1314 return (newcr); 1315} 1316 1317/* 1318 * Get login name, if available. 1319 */ 1320#ifndef _SYS_SYSPROTO_H_ 1321struct getlogin_args { 1322 char *namebuf; 1323 u_int namelen; 1324}; 1325#endif 1326/* ARGSUSED */ 1327int 1328getlogin(p, uap) 1329 struct proc *p; 1330 struct getlogin_args *uap; 1331{ 1332 1333 if (uap->namelen > MAXLOGNAME) 1334 uap->namelen = MAXLOGNAME; 1335 return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, 1336 (caddr_t) uap->namebuf, uap->namelen)); 1337} 1338 1339/* 1340 * Set login name. 1341 */ 1342#ifndef _SYS_SYSPROTO_H_ 1343struct setlogin_args { 1344 char *namebuf; 1345}; 1346#endif 1347/* ARGSUSED */ 1348int 1349setlogin(p, uap) 1350 struct proc *p; 1351 struct setlogin_args *uap; 1352{ 1353 int error; 1354 char logintmp[MAXLOGNAME]; 1355 1356 if ((error = suser_xxx(0, p, PRISON_ROOT))) 1357 return (error); 1358 error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, 1359 sizeof(logintmp), (size_t *)0); 1360 if (error == ENAMETOOLONG) 1361 error = EINVAL; 1362 else if (!error) 1363 (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp, 1364 sizeof(logintmp)); 1365 return (error); 1366} 1367 1368void 1369setsugid(p) 1370 struct proc *p; 1371{ 1372 p->p_flag |= P_SUGID; 1373 if (!(p->p_pfsflags & PF_ISUGID)) 1374 p->p_stops = 0; 1375} 1376 1377/* 1378 * Helper function to change the effective uid of a process 1379 */ 1380void 1381change_euid(p, euid) 1382 struct proc *p; 1383 uid_t euid; 1384{ 1385 struct pcred *pc; 1386 struct uidinfo *uip; 1387 1388 pc = p->p_cred; 1389 /* 1390 * crcopy is essentially a NOP if ucred has a reference count 1391 * of 1, which is true if it has already been copied. 1392 */ 1393 pc->pc_ucred = crcopy(pc->pc_ucred); 1394 uip = pc->pc_ucred->cr_uidinfo; 1395 pc->pc_ucred->cr_uid = euid; 1396 pc->pc_ucred->cr_uidinfo = uifind(euid); 1397 uifree(uip); 1398} 1399 1400/* 1401 * Helper function to change the real uid of a process 1402 * 1403 * The per-uid process count for this process is transfered from 1404 * the old uid to the new uid. 1405 */ 1406void 1407change_ruid(p, ruid) 1408 struct proc *p; 1409 uid_t ruid; 1410{ 1411 struct pcred *pc; 1412 struct uidinfo *uip; 1413 1414 pc = p->p_cred; 1415 (void)chgproccnt(pc->p_uidinfo, -1, 0); 1416 uip = pc->p_uidinfo; 1417 /* It is assumed that pcred is not shared between processes */ 1418 pc->p_ruid = ruid; 1419 pc->p_uidinfo = uifind(ruid); 1420 (void)chgproccnt(pc->p_uidinfo, 1, 0); 1421 uifree(uip); 1422} 1423