123372Smckusick /* 237578Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337578Smckusick * All rights reserved. 423372Smckusick * 537578Smckusick * Redistribution and use in source and binary forms are permitted 637578Smckusick * provided that the above copyright notice and this paragraph are 737578Smckusick * duplicated in all such forms and that any documentation, 837578Smckusick * advertising materials, and other materials related to such 937578Smckusick * distribution and use acknowledge that the software was developed 1037578Smckusick * by the University of California, Berkeley. The name of the 1137578Smckusick * University may not be used to endorse or promote products derived 1237578Smckusick * from this software without specific prior written permission. 1337578Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437578Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537578Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637578Smckusick * 17*37579Smckusick * @(#)kern_prot.c 7.6 (Berkeley) 05/01/89 1823372Smckusick */ 197420Sroot 207420Sroot /* 217498Sroot * System calls related to processes and protection 227420Sroot */ 237420Sroot 2417092Sbloom #include "param.h" 2537578Smckusick #include "acct.h" 2617092Sbloom #include "systm.h" 2717092Sbloom #include "user.h" 2817092Sbloom #include "proc.h" 2917092Sbloom #include "timeb.h" 3017092Sbloom #include "times.h" 3117092Sbloom #include "reboot.h" 3237578Smckusick #include "mount.h" 3317092Sbloom #include "buf.h" 3437578Smckusick #include "../ufs/quota.h" 3537578Smckusick #include "malloc.h" 3637578Smckusick #define GRPSTART 0 377420Sroot 38*37579Smckusick #include "machine/reg.h" 39*37579Smckusick 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*37579Smckusick p = u.u_procp; 56*37579Smckusick else if ((p = pfind(uap->pid)) == 0) { 577498Sroot u.u_error = ESRCH; 587498Sroot return; 597498Sroot } 60*37579Smckusick u.u_r.r_val1 = p->p_pgrp->pg_id; 617498Sroot } 627498Sroot 637420Sroot getuid() 647420Sroot { 657420Sroot 667420Sroot u.u_r.r_val1 = u.u_ruid; 677420Sroot u.u_r.r_val2 = u.u_uid; 687420Sroot } 697420Sroot 707498Sroot getgid() 717498Sroot { 727498Sroot 737498Sroot u.u_r.r_val1 = u.u_rgid; 747498Sroot u.u_r.r_val2 = u.u_gid; 757498Sroot } 767498Sroot 777866Sroot getgroups() 787498Sroot { 797498Sroot register struct a { 808624Sroot u_int gidsetsize; 817498Sroot int *gidset; 827498Sroot } *uap = (struct a *)u.u_ap; 8318362Skarels register gid_t *gp; 8418362Skarels register int *lp; 8518362Skarels int groups[NGROUPS]; 867498Sroot 8737578Smckusick if (uap->gidsetsize == 0) { 8837578Smckusick u.u_r.r_val1 = u.u_ngroups - GRPSTART; 8937578Smckusick return; 9037578Smckusick } 9137578Smckusick if (uap->gidsetsize < u.u_ngroups - GRPSTART) { 927866Sroot u.u_error = EINVAL; 937866Sroot return; 947866Sroot } 9537578Smckusick uap->gidsetsize = u.u_ngroups - GRPSTART; 9637578Smckusick gp = &u.u_groups[GRPSTART]; 9737578Smckusick for (lp = groups; lp < &groups[uap->gidsetsize]; ) 9818362Skarels *lp++ = *gp++; 9918362Skarels u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset, 10018362Skarels uap->gidsetsize * sizeof (groups[0])); 1019997Ssam if (u.u_error) 1027498Sroot return; 1037866Sroot u.u_r.r_val1 = uap->gidsetsize; 1047498Sroot } 1057498Sroot 106*37579Smckusick setsid() 107*37579Smckusick { 108*37579Smckusick register struct proc *p = u.u_procp; 109*37579Smckusick 110*37579Smckusick if ((p->p_pgid == p->p_pid) || pgfind(p->p_pid)) 111*37579Smckusick u.u_error = EPERM; 112*37579Smckusick else { 113*37579Smckusick pgmv(p, p->p_pid, 1); 114*37579Smckusick u.u_r.r_val1 = p->p_pid; 115*37579Smckusick } 116*37579Smckusick return; 117*37579Smckusick } 118*37579Smckusick 119*37579Smckusick /* 120*37579Smckusick * set process group 121*37579Smckusick * 122*37579Smckusick * if target pid != caller's pid 123*37579Smckusick * pid must be an inferior 124*37579Smckusick * pid must be in same session 125*37579Smckusick * pid can't have done an exec 126*37579Smckusick * there must exist a pid with pgid in same session 127*37579Smckusick * pid must not be session leader 128*37579Smckusick */ 1297498Sroot setpgrp() 1307498Sroot { 1317498Sroot register struct a { 1327498Sroot int pid; 133*37579Smckusick int pgid; 1347498Sroot } *uap = (struct a *)u.u_ap; 135*37579Smckusick register struct proc *p; 136*37579Smckusick register struct pgrp *pgrp; 1377498Sroot 1387498Sroot if (uap->pid == 0) 139*37579Smckusick p = u.u_procp; 140*37579Smckusick else if ((p = pfind(uap->pid)) == 0 || !inferior(p)) { 1417498Sroot u.u_error = ESRCH; 1427498Sroot return; 1437498Sroot } 144*37579Smckusick else if (p != u.u_procp) { 145*37579Smckusick if (p->p_session != u.u_procp->p_session) { 146*37579Smckusick u.u_error = EPERM; 147*37579Smckusick return; 148*37579Smckusick } 149*37579Smckusick if (p->p_flag&SEXEC) { 150*37579Smckusick u.u_error = EACCES; 151*37579Smckusick return; 152*37579Smckusick } 153*37579Smckusick } 154*37579Smckusick if (SESS_LEADER(p)) { 1557498Sroot u.u_error = EPERM; 1567498Sroot return; 1577498Sroot } 158*37579Smckusick if (uap->pgid == 0) 159*37579Smckusick uap->pgid = p->p_pid; 160*37579Smckusick else if ((uap->pgid != p->p_pid) && 161*37579Smckusick (((pgrp = pgfind(uap->pgid)) == 0) || 162*37579Smckusick pgrp->pg_mem == NULL || 163*37579Smckusick pgrp->pg_session != u.u_procp->p_session)) { 164*37579Smckusick u.u_error = EPERM; 165*37579Smckusick return; 166*37579Smckusick } 167*37579Smckusick /* 168*37579Smckusick * done checking, now doit 169*37579Smckusick */ 170*37579Smckusick pgmv(p, uap->pgid, 0); 1717498Sroot } 1727498Sroot 1739160Ssam setreuid() 1747420Sroot { 1759160Ssam struct a { 1769160Ssam int ruid; 1779160Ssam int euid; 1789160Ssam } *uap; 1799160Ssam register int ruid, euid; 1809160Ssam 1819160Ssam uap = (struct a *)u.u_ap; 1829160Ssam ruid = uap->ruid; 1839160Ssam if (ruid == -1) 1849160Ssam ruid = u.u_ruid; 18537553Smckusick if (u.u_ruid != ruid && u.u_uid != ruid && 18637553Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 1879160Ssam return; 1889160Ssam euid = uap->euid; 1899160Ssam if (euid == -1) 1909160Ssam euid = u.u_uid; 19137553Smckusick if (u.u_ruid != euid && u.u_uid != euid && 19237553Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 1939160Ssam return; 1949160Ssam /* 1959160Ssam * Everything's okay, do it. 19637578Smckusick * Copy credentials so other references do not 19737578Smckusick * see our changes. 1989160Ssam */ 1999160Ssam #ifdef QUOTA 2009320Ssam if (u.u_quota->q_uid != ruid) { 2019320Ssam qclean(); 20226354Skarels qstart(getquota((uid_t)ruid, 0, 0)); 2039320Ssam } 2049160Ssam #endif 20537578Smckusick if (u.u_cred->cr_ref > 1) 20637578Smckusick u.u_cred = crcopy(u.u_cred); 20725627Skarels u.u_procp->p_uid = euid; 2089320Ssam u.u_ruid = ruid; 2099160Ssam u.u_uid = euid; 2109160Ssam } 2119160Ssam 2129160Ssam setregid() 2137420Sroot { 2149160Ssam register struct a { 2159160Ssam int rgid; 2169160Ssam int egid; 2179160Ssam } *uap; 2189160Ssam register int rgid, egid; 2199160Ssam 2209160Ssam uap = (struct a *)u.u_ap; 2219160Ssam rgid = uap->rgid; 2229160Ssam if (rgid == -1) 2239160Ssam rgid = u.u_rgid; 22437553Smckusick if (u.u_rgid != rgid && u.u_gid != rgid && 22537553Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 2269160Ssam return; 2279160Ssam egid = uap->egid; 2289160Ssam if (egid == -1) 2299160Ssam egid = u.u_gid; 23037553Smckusick if (u.u_rgid != egid && u.u_gid != egid && 23137553Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 2329160Ssam return; 23337578Smckusick if (u.u_cred->cr_ref > 1) 23437578Smckusick u.u_cred = crcopy(u.u_cred); 23537578Smckusick u.u_rgid = rgid; 23611164Ssam u.u_gid = egid; 2379160Ssam } 2389160Ssam 2397866Sroot setgroups() 2407498Sroot { 2417498Sroot register struct a { 2428624Sroot u_int gidsetsize; 2437498Sroot int *gidset; 2447498Sroot } *uap = (struct a *)u.u_ap; 24518362Skarels register gid_t *gp; 24618362Skarels register int *lp; 24737578Smckusick int ngrp, groups[NGROUPS]; 2487498Sroot 24937553Smckusick if (u.u_error = suser(u.u_cred, &u.u_acflag)) 2507498Sroot return; 25137578Smckusick ngrp = uap->gidsetsize + GRPSTART; 25237578Smckusick if (ngrp > sizeof (u.u_groups) / sizeof (u.u_groups[0])) { 2537866Sroot u.u_error = EINVAL; 2547498Sroot return; 2557498Sroot } 25618362Skarels u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups, 25718362Skarels uap->gidsetsize * sizeof (groups[0])); 2589997Ssam if (u.u_error) 2597498Sroot return; 26037578Smckusick gp = &u.u_groups[GRPSTART]; 26137578Smckusick for (lp = groups; lp < &groups[uap->gidsetsize]; ) 26218362Skarels *gp++ = *lp++; 26337578Smckusick u.u_ngroups = ngrp; 2647498Sroot } 2657498Sroot 2667498Sroot /* 26737578Smckusick * Check if gid is a member of the group set. 26811810Ssam */ 26937578Smckusick groupmember(gid, cred) 27026275Skarels gid_t gid; 27137578Smckusick register struct ucred *cred; 2727866Sroot { 27318362Skarels register gid_t *gp; 27437578Smckusick gid_t *egp; 2757866Sroot 27637578Smckusick egp = &(cred->cr_groups[cred->cr_ngroups]); 27737578Smckusick for (gp = cred->cr_groups; gp < egp; gp++) 2787866Sroot if (*gp == gid) 27937578Smckusick return (1); 28037578Smckusick return (0); 2817866Sroot } 2827866Sroot 28311810Ssam /* 28437578Smckusick * Test if the current user is the super user. 28511810Ssam */ 28637578Smckusick suser(cred, acflag) 28737578Smckusick struct ucred *cred; 28837578Smckusick short *acflag; 2897866Sroot { 2907866Sroot 29137578Smckusick if (cred->cr_uid == 0) { 29237578Smckusick if (acflag) 29337578Smckusick *acflag |= ASU; 29437578Smckusick return (0); 29518362Skarels } 29637578Smckusick return (EPERM); 2977866Sroot } 29811810Ssam 29911810Ssam /* 30037578Smckusick * Allocate a zeroed cred structure. 30111810Ssam */ 30237578Smckusick struct ucred * 30337578Smckusick crget() 30411810Ssam { 30537578Smckusick register struct ucred *cr; 30611810Ssam 30737578Smckusick MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 30837578Smckusick bzero((caddr_t)cr, sizeof(*cr)); 30937578Smckusick cr->cr_ref = 1; 31037578Smckusick return(cr); 31111810Ssam } 31237085Skfall 31337085Skfall /* 31437578Smckusick * Free a cred structure. 31537578Smckusick * Throws away space when ref count gets to 0. 31637085Skfall */ 31737578Smckusick crfree(cr) 31837578Smckusick struct ucred *cr; 31937578Smckusick { 32037578Smckusick int s = splimp(); 32137085Skfall 32237578Smckusick if (--cr->cr_ref != 0) { 32337578Smckusick (void) splx(s); 32437578Smckusick return; 32537578Smckusick } 32637578Smckusick FREE((caddr_t)cr, M_CRED); 32737578Smckusick (void) splx(s); 32837578Smckusick } 32937578Smckusick 33037578Smckusick /* 33137578Smckusick * Copy cred structure to a new one and free the old one. 33237578Smckusick */ 33337578Smckusick struct ucred * 33437578Smckusick crcopy(cr) 33537578Smckusick struct ucred *cr; 33637085Skfall { 33737578Smckusick struct ucred *newcr; 33837085Skfall 33937578Smckusick newcr = crget(); 34037578Smckusick *newcr = *cr; 34137578Smckusick crfree(cr); 34237578Smckusick newcr->cr_ref = 1; 34337578Smckusick return(newcr); 34437085Skfall } 34537085Skfall 34637085Skfall /* 34737578Smckusick * Dup cred struct to a new held one. 34837085Skfall */ 34937578Smckusick struct ucred * 35037578Smckusick crdup(cr) 35137578Smckusick struct ucred *cr; 35237085Skfall { 35337578Smckusick struct ucred *newcr; 35437085Skfall 35537578Smckusick newcr = crget(); 35637578Smckusick *newcr = *cr; 35737578Smckusick newcr->cr_ref = 1; 35837578Smckusick return(newcr); 35937085Skfall } 360*37579Smckusick 361*37579Smckusick /* 362*37579Smckusick * Get login name of process owner, if available 363*37579Smckusick */ 364*37579Smckusick 365*37579Smckusick getlogname() 366*37579Smckusick { 367*37579Smckusick struct a { 368*37579Smckusick char *namebuf; 369*37579Smckusick u_int namelen; 370*37579Smckusick } *uap = (struct a *)u.u_ap; 371*37579Smckusick 372*37579Smckusick if (uap->namelen > sizeof (u.u_logname)) 373*37579Smckusick uap->namelen = sizeof (u.u_logname); 374*37579Smckusick u.u_error = copyout((caddr_t)u.u_logname, (caddr_t)uap->namebuf, 375*37579Smckusick uap->namelen); 376*37579Smckusick } 377*37579Smckusick 378*37579Smckusick /* 379*37579Smckusick * Set login name of process owner 380*37579Smckusick */ 381*37579Smckusick 382*37579Smckusick setlogname() 383*37579Smckusick { 384*37579Smckusick struct a { 385*37579Smckusick char *namebuf; 386*37579Smckusick u_int namelen; 387*37579Smckusick } *uap = (struct a *)u.u_ap; 388*37579Smckusick 389*37579Smckusick if (u.u_error = suser(u.u_cred, &u.u_acflag)) 390*37579Smckusick return; 391*37579Smckusick if (uap->namelen > sizeof (u.u_logname) - 1) 392*37579Smckusick u.u_error = EINVAL; 393*37579Smckusick else 394*37579Smckusick u.u_error = copyin((caddr_t)uap->namebuf, 395*37579Smckusick (caddr_t)u.u_logname, uap->namelen); 396*37579Smckusick } 397