123372Smckusick /* 2*37578Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3*37578Smckusick * All rights reserved. 423372Smckusick * 5*37578Smckusick * Redistribution and use in source and binary forms are permitted 6*37578Smckusick * provided that the above copyright notice and this paragraph are 7*37578Smckusick * duplicated in all such forms and that any documentation, 8*37578Smckusick * advertising materials, and other materials related to such 9*37578Smckusick * distribution and use acknowledge that the software was developed 10*37578Smckusick * by the University of California, Berkeley. The name of the 11*37578Smckusick * University may not be used to endorse or promote products derived 12*37578Smckusick * from this software without specific prior written permission. 13*37578Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*37578Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*37578Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16*37578Smckusick * 17*37578Smckusick * @(#)kern_prot.c 7.1.1.1 (Berkeley) 05/01/89 1823372Smckusick */ 197420Sroot 207420Sroot /* 217498Sroot * System calls related to processes and protection 227420Sroot */ 237420Sroot 24*37578Smckusick #include "machine/reg.h" 25*37578Smckusick 2617092Sbloom #include "param.h" 27*37578Smckusick #include "acct.h" 2817092Sbloom #include "systm.h" 2917092Sbloom #include "user.h" 3017092Sbloom #include "proc.h" 3117092Sbloom #include "timeb.h" 3217092Sbloom #include "times.h" 3317092Sbloom #include "reboot.h" 34*37578Smckusick #include "mount.h" 3517092Sbloom #include "buf.h" 36*37578Smckusick #include "../ufs/quota.h" 37*37578Smckusick #include "malloc.h" 38*37578Smckusick #define GRPSTART 0 397420Sroot 407498Sroot getpid() 417498Sroot { 427498Sroot 437498Sroot u.u_r.r_val1 = u.u_procp->p_pid; 447498Sroot u.u_r.r_val2 = u.u_procp->p_ppid; 457498Sroot } 467498Sroot 477498Sroot getpgrp() 487498Sroot { 497498Sroot register struct a { 507498Sroot int pid; 517498Sroot } *uap = (struct a *)u.u_ap; 527498Sroot register struct proc *p; 537498Sroot 547498Sroot if (uap->pid == 0) 55*37578Smckusick uap->pid = u.u_procp->p_pid; 56*37578Smckusick p = pfind(uap->pid); 57*37578Smckusick if (p == 0) { 587498Sroot u.u_error = ESRCH; 597498Sroot return; 607498Sroot } 61*37578Smckusick u.u_r.r_val1 = p->p_pgrp; 627498Sroot } 637498Sroot 647420Sroot getuid() 657420Sroot { 667420Sroot 677420Sroot u.u_r.r_val1 = u.u_ruid; 687420Sroot u.u_r.r_val2 = u.u_uid; 697420Sroot } 707420Sroot 717498Sroot getgid() 727498Sroot { 737498Sroot 747498Sroot u.u_r.r_val1 = u.u_rgid; 757498Sroot u.u_r.r_val2 = u.u_gid; 767498Sroot } 777498Sroot 787866Sroot getgroups() 797498Sroot { 807498Sroot register struct a { 818624Sroot u_int gidsetsize; 827498Sroot int *gidset; 837498Sroot } *uap = (struct a *)u.u_ap; 8418362Skarels register gid_t *gp; 8518362Skarels register int *lp; 8618362Skarels int groups[NGROUPS]; 877498Sroot 88*37578Smckusick if (uap->gidsetsize == 0) { 89*37578Smckusick u.u_r.r_val1 = u.u_ngroups - GRPSTART; 90*37578Smckusick return; 91*37578Smckusick } 92*37578Smckusick if (uap->gidsetsize < u.u_ngroups - GRPSTART) { 937866Sroot u.u_error = EINVAL; 947866Sroot return; 957866Sroot } 96*37578Smckusick uap->gidsetsize = u.u_ngroups - GRPSTART; 97*37578Smckusick gp = &u.u_groups[GRPSTART]; 98*37578Smckusick for (lp = groups; lp < &groups[uap->gidsetsize]; ) 9918362Skarels *lp++ = *gp++; 10018362Skarels u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset, 10118362Skarels uap->gidsetsize * sizeof (groups[0])); 1029997Ssam if (u.u_error) 1037498Sroot return; 1047866Sroot u.u_r.r_val1 = uap->gidsetsize; 1057498Sroot } 1067498Sroot 1077498Sroot setpgrp() 1087498Sroot { 109*37578Smckusick register struct proc *p; 1107498Sroot register struct a { 1117498Sroot int pid; 112*37578Smckusick int pgrp; 1137498Sroot } *uap = (struct a *)u.u_ap; 1147498Sroot 1157498Sroot if (uap->pid == 0) 116*37578Smckusick uap->pid = u.u_procp->p_pid; 117*37578Smckusick p = pfind(uap->pid); 118*37578Smckusick if (p == 0) { 1197498Sroot u.u_error = ESRCH; 1207498Sroot return; 1217498Sroot } 122*37578Smckusick /* need better control mechanisms for process groups */ 123*37578Smckusick if (p->p_uid != u.u_uid && u.u_uid && !inferior(p)) { 1247498Sroot u.u_error = EPERM; 1257498Sroot return; 1267498Sroot } 127*37578Smckusick p->p_pgrp = uap->pgrp; 1287498Sroot } 1297498Sroot 1309160Ssam setreuid() 1317420Sroot { 1329160Ssam struct a { 1339160Ssam int ruid; 1349160Ssam int euid; 1359160Ssam } *uap; 1369160Ssam register int ruid, euid; 1379160Ssam 1389160Ssam uap = (struct a *)u.u_ap; 1399160Ssam ruid = uap->ruid; 1409160Ssam if (ruid == -1) 1419160Ssam ruid = u.u_ruid; 14237553Smckusick if (u.u_ruid != ruid && u.u_uid != ruid && 14337553Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 1449160Ssam return; 1459160Ssam euid = uap->euid; 1469160Ssam if (euid == -1) 1479160Ssam euid = u.u_uid; 14837553Smckusick if (u.u_ruid != euid && u.u_uid != euid && 14937553Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 1509160Ssam return; 1519160Ssam /* 1529160Ssam * Everything's okay, do it. 153*37578Smckusick * Copy credentials so other references do not 154*37578Smckusick * see our changes. 1559160Ssam */ 1569160Ssam #ifdef QUOTA 1579320Ssam if (u.u_quota->q_uid != ruid) { 1589320Ssam qclean(); 15926354Skarels qstart(getquota((uid_t)ruid, 0, 0)); 1609320Ssam } 1619160Ssam #endif 162*37578Smckusick if (u.u_cred->cr_ref > 1) 163*37578Smckusick u.u_cred = crcopy(u.u_cred); 16425627Skarels u.u_procp->p_uid = euid; 1659320Ssam u.u_ruid = ruid; 1669160Ssam u.u_uid = euid; 1679160Ssam } 1689160Ssam 1699160Ssam setregid() 1707420Sroot { 1719160Ssam register struct a { 1729160Ssam int rgid; 1739160Ssam int egid; 1749160Ssam } *uap; 1759160Ssam register int rgid, egid; 1769160Ssam 1779160Ssam uap = (struct a *)u.u_ap; 1789160Ssam rgid = uap->rgid; 1799160Ssam if (rgid == -1) 1809160Ssam rgid = u.u_rgid; 18137553Smckusick if (u.u_rgid != rgid && u.u_gid != rgid && 18237553Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 1839160Ssam return; 1849160Ssam egid = uap->egid; 1859160Ssam if (egid == -1) 1869160Ssam egid = u.u_gid; 18737553Smckusick if (u.u_rgid != egid && u.u_gid != egid && 18837553Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 1899160Ssam return; 190*37578Smckusick if (u.u_cred->cr_ref > 1) 191*37578Smckusick u.u_cred = crcopy(u.u_cred); 192*37578Smckusick u.u_rgid = rgid; 19311164Ssam u.u_gid = egid; 1949160Ssam } 1959160Ssam 1967866Sroot setgroups() 1977498Sroot { 1987498Sroot register struct a { 1998624Sroot u_int gidsetsize; 2007498Sroot int *gidset; 2017498Sroot } *uap = (struct a *)u.u_ap; 20218362Skarels register gid_t *gp; 20318362Skarels register int *lp; 204*37578Smckusick int ngrp, groups[NGROUPS]; 2057498Sroot 20637553Smckusick if (u.u_error = suser(u.u_cred, &u.u_acflag)) 2077498Sroot return; 208*37578Smckusick ngrp = uap->gidsetsize + GRPSTART; 209*37578Smckusick if (ngrp > sizeof (u.u_groups) / sizeof (u.u_groups[0])) { 2107866Sroot u.u_error = EINVAL; 2117498Sroot return; 2127498Sroot } 21318362Skarels u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups, 21418362Skarels uap->gidsetsize * sizeof (groups[0])); 2159997Ssam if (u.u_error) 2167498Sroot return; 217*37578Smckusick gp = &u.u_groups[GRPSTART]; 218*37578Smckusick for (lp = groups; lp < &groups[uap->gidsetsize]; ) 21918362Skarels *gp++ = *lp++; 220*37578Smckusick u.u_ngroups = ngrp; 2217498Sroot } 2227498Sroot 2237498Sroot /* 224*37578Smckusick * Check if gid is a member of the group set. 22511810Ssam */ 226*37578Smckusick groupmember(gid, cred) 22726275Skarels gid_t gid; 228*37578Smckusick register struct ucred *cred; 2297866Sroot { 23018362Skarels register gid_t *gp; 231*37578Smckusick gid_t *egp; 2327866Sroot 233*37578Smckusick egp = &(cred->cr_groups[cred->cr_ngroups]); 234*37578Smckusick for (gp = cred->cr_groups; gp < egp; gp++) 2357866Sroot if (*gp == gid) 236*37578Smckusick return (1); 237*37578Smckusick return (0); 2387866Sroot } 2397866Sroot 24011810Ssam /* 241*37578Smckusick * Test if the current user is the super user. 24211810Ssam */ 243*37578Smckusick suser(cred, acflag) 244*37578Smckusick struct ucred *cred; 245*37578Smckusick short *acflag; 2467866Sroot { 2477866Sroot 248*37578Smckusick if (cred->cr_uid == 0) { 249*37578Smckusick if (acflag) 250*37578Smckusick *acflag |= ASU; 251*37578Smckusick return (0); 25218362Skarels } 253*37578Smckusick return (EPERM); 2547866Sroot } 25511810Ssam 25611810Ssam /* 257*37578Smckusick * Allocate a zeroed cred structure. 25811810Ssam */ 259*37578Smckusick struct ucred * 260*37578Smckusick crget() 26111810Ssam { 262*37578Smckusick register struct ucred *cr; 26311810Ssam 264*37578Smckusick MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 265*37578Smckusick bzero((caddr_t)cr, sizeof(*cr)); 266*37578Smckusick cr->cr_ref = 1; 267*37578Smckusick return(cr); 26811810Ssam } 26937085Skfall 27037085Skfall /* 271*37578Smckusick * Free a cred structure. 272*37578Smckusick * Throws away space when ref count gets to 0. 27337085Skfall */ 274*37578Smckusick crfree(cr) 275*37578Smckusick struct ucred *cr; 276*37578Smckusick { 277*37578Smckusick int s = splimp(); 27837085Skfall 279*37578Smckusick if (--cr->cr_ref != 0) { 280*37578Smckusick (void) splx(s); 281*37578Smckusick return; 282*37578Smckusick } 283*37578Smckusick FREE((caddr_t)cr, M_CRED); 284*37578Smckusick (void) splx(s); 285*37578Smckusick } 286*37578Smckusick 287*37578Smckusick /* 288*37578Smckusick * Copy cred structure to a new one and free the old one. 289*37578Smckusick */ 290*37578Smckusick struct ucred * 291*37578Smckusick crcopy(cr) 292*37578Smckusick struct ucred *cr; 29337085Skfall { 294*37578Smckusick struct ucred *newcr; 29537085Skfall 296*37578Smckusick newcr = crget(); 297*37578Smckusick *newcr = *cr; 298*37578Smckusick crfree(cr); 299*37578Smckusick newcr->cr_ref = 1; 300*37578Smckusick return(newcr); 30137085Skfall } 30237085Skfall 30337085Skfall /* 304*37578Smckusick * Dup cred struct to a new held one. 30537085Skfall */ 306*37578Smckusick struct ucred * 307*37578Smckusick crdup(cr) 308*37578Smckusick struct ucred *cr; 30937085Skfall { 310*37578Smckusick struct ucred *newcr; 31137085Skfall 312*37578Smckusick newcr = crget(); 313*37578Smckusick *newcr = *cr; 314*37578Smckusick newcr->cr_ref = 1; 315*37578Smckusick return(newcr); 31637085Skfall } 317