123372Smckusick /* 229092Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323372Smckusick * All rights reserved. The Berkeley software License Agreement 423372Smckusick * specifies the terms and conditions for redistribution. 523372Smckusick * 6*37553Smckusick * @(#)kern_prot.c 7.5 (Berkeley) 04/26/89 723372Smckusick */ 87420Sroot 97420Sroot /* 107498Sroot * System calls related to processes and protection 117420Sroot */ 127420Sroot 1317092Sbloom #include "param.h" 1417092Sbloom #include "systm.h" 1517092Sbloom #include "dir.h" 1617092Sbloom #include "user.h" 1717092Sbloom #include "inode.h" 1817092Sbloom #include "proc.h" 1917092Sbloom #include "timeb.h" 2017092Sbloom #include "times.h" 2117092Sbloom #include "reboot.h" 2217092Sbloom #include "fs.h" 2317092Sbloom #include "buf.h" 2417092Sbloom #include "mount.h" 2517092Sbloom #include "quota.h" 267420Sroot 2737520Smckusick #include "machine/reg.h" 2837520Smckusick 297498Sroot getpid() 307498Sroot { 317498Sroot 327498Sroot u.u_r.r_val1 = u.u_procp->p_pid; 337498Sroot u.u_r.r_val2 = u.u_procp->p_ppid; 347498Sroot } 357498Sroot 367498Sroot getpgrp() 377498Sroot { 387498Sroot register struct a { 397498Sroot int pid; 407498Sroot } *uap = (struct a *)u.u_ap; 417498Sroot register struct proc *p; 427498Sroot 437498Sroot if (uap->pid == 0) 4435810Smarc p = u.u_procp; 4535810Smarc else if ((p = pfind(uap->pid)) == 0) { 467498Sroot u.u_error = ESRCH; 477498Sroot return; 487498Sroot } 4935810Smarc u.u_r.r_val1 = p->p_pgrp->pg_id; 507498Sroot } 517498Sroot 527420Sroot getuid() 537420Sroot { 547420Sroot 557420Sroot u.u_r.r_val1 = u.u_ruid; 567420Sroot u.u_r.r_val2 = u.u_uid; 577420Sroot } 587420Sroot 597498Sroot getgid() 607498Sroot { 617498Sroot 627498Sroot u.u_r.r_val1 = u.u_rgid; 637498Sroot u.u_r.r_val2 = u.u_gid; 647498Sroot } 657498Sroot 667866Sroot getgroups() 677498Sroot { 687498Sroot register struct a { 698624Sroot u_int gidsetsize; 707498Sroot int *gidset; 717498Sroot } *uap = (struct a *)u.u_ap; 7218362Skarels register gid_t *gp; 7318362Skarels register int *lp; 7418362Skarels int groups[NGROUPS]; 757498Sroot 767866Sroot for (gp = &u.u_groups[NGROUPS]; gp > u.u_groups; gp--) 7718362Skarels if (gp[-1] != NOGROUP) 787866Sroot break; 797866Sroot if (uap->gidsetsize < gp - u.u_groups) { 807866Sroot u.u_error = EINVAL; 817866Sroot return; 827866Sroot } 837866Sroot uap->gidsetsize = gp - u.u_groups; 8418362Skarels for (lp = groups, gp = u.u_groups; lp < &groups[uap->gidsetsize]; ) 8518362Skarels *lp++ = *gp++; 8618362Skarels u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset, 8718362Skarels uap->gidsetsize * sizeof (groups[0])); 889997Ssam if (u.u_error) 897498Sroot return; 907866Sroot u.u_r.r_val1 = uap->gidsetsize; 917498Sroot } 927498Sroot 9335810Smarc setsid() 9435810Smarc { 9535810Smarc register struct proc *p = u.u_procp; 9635810Smarc 9735810Smarc if ((p->p_pgid == p->p_pid) || pgfind(p->p_pid)) 9835810Smarc u.u_error = EPERM; 9935810Smarc else { 10035810Smarc pgmv(p, p->p_pid, 1); 10135810Smarc u.u_r.r_val1 = p->p_pid; 10235810Smarc } 10335810Smarc return; 10435810Smarc } 10535810Smarc 10635810Smarc /* 10735810Smarc * set process group 10835810Smarc * 10935810Smarc * if target pid != caller's pid 11035810Smarc * pid must be an inferior 11135810Smarc * pid must be in same session 11235810Smarc * pid can't have done an exec 11335810Smarc * there must exist a pid with pgid in same session 11435810Smarc * pid must not be session leader 11535810Smarc */ 1167498Sroot setpgrp() 1177498Sroot { 1187498Sroot register struct a { 1197498Sroot int pid; 12035810Smarc int pgid; 1217498Sroot } *uap = (struct a *)u.u_ap; 12235810Smarc register struct proc *p; 12335810Smarc register struct pgrp *pgrp; 1247498Sroot 1257498Sroot if (uap->pid == 0) 12635810Smarc p = u.u_procp; 12735810Smarc else if ((p = pfind(uap->pid)) == 0 || !inferior(p)) { 1287498Sroot u.u_error = ESRCH; 1297498Sroot return; 1307498Sroot } 13135810Smarc else if (p != u.u_procp) { 13235810Smarc if (p->p_session != u.u_procp->p_session) { 13335810Smarc u.u_error = EPERM; 13435810Smarc return; 13535810Smarc } 13635810Smarc if (p->p_flag&SEXEC) { 13735810Smarc u.u_error = EACCES; 13835810Smarc return; 13935810Smarc } 14035810Smarc } 14135810Smarc if (SESS_LEADER(p)) { 1427498Sroot u.u_error = EPERM; 1437498Sroot return; 1447498Sroot } 14535810Smarc if (uap->pgid == 0) 14635810Smarc uap->pgid = p->p_pid; 14735810Smarc else if ((uap->pgid != p->p_pid) && 14835810Smarc (((pgrp = pgfind(uap->pgid)) == 0) || 14935810Smarc pgrp->pg_mem == NULL || 15035810Smarc pgrp->pg_session != u.u_procp->p_session)) { 15135810Smarc u.u_error = EPERM; 15235810Smarc return; 15335810Smarc } 15435810Smarc /* 15535810Smarc * done checking, now doit 15635810Smarc */ 15735810Smarc pgmv(p, uap->pgid, 0); 1587498Sroot } 1597498Sroot 1609160Ssam setreuid() 1617420Sroot { 1629160Ssam struct a { 1639160Ssam int ruid; 1649160Ssam int euid; 1659160Ssam } *uap; 1669160Ssam register int ruid, euid; 1679160Ssam 1689160Ssam uap = (struct a *)u.u_ap; 1699160Ssam ruid = uap->ruid; 1709160Ssam if (ruid == -1) 1719160Ssam ruid = u.u_ruid; 172*37553Smckusick if (u.u_ruid != ruid && u.u_uid != ruid && 173*37553Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 1749160Ssam return; 1759160Ssam euid = uap->euid; 1769160Ssam if (euid == -1) 1779160Ssam euid = u.u_uid; 178*37553Smckusick if (u.u_ruid != euid && u.u_uid != euid && 179*37553Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 1809160Ssam return; 1819160Ssam /* 1829160Ssam * Everything's okay, do it. 1839160Ssam */ 1849160Ssam #ifdef QUOTA 1859320Ssam if (u.u_quota->q_uid != ruid) { 1869320Ssam qclean(); 18726354Skarels qstart(getquota((uid_t)ruid, 0, 0)); 1889320Ssam } 1899160Ssam #endif 19025627Skarels u.u_procp->p_uid = euid; 1919320Ssam u.u_ruid = ruid; 1929160Ssam u.u_uid = euid; 1939160Ssam } 1949160Ssam 1959160Ssam setregid() 1967420Sroot { 1979160Ssam register struct a { 1989160Ssam int rgid; 1999160Ssam int egid; 2009160Ssam } *uap; 2019160Ssam register int rgid, egid; 2029160Ssam 2039160Ssam uap = (struct a *)u.u_ap; 2049160Ssam rgid = uap->rgid; 2059160Ssam if (rgid == -1) 2069160Ssam rgid = u.u_rgid; 207*37553Smckusick if (u.u_rgid != rgid && u.u_gid != rgid && 208*37553Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 2099160Ssam return; 2109160Ssam egid = uap->egid; 2119160Ssam if (egid == -1) 2129160Ssam egid = u.u_gid; 213*37553Smckusick if (u.u_rgid != egid && u.u_gid != egid && 214*37553Smckusick (u.u_error = suser(u.u_cred, &u.u_acflag))) 2159160Ssam return; 2169160Ssam if (u.u_rgid != rgid) { 2179160Ssam leavegroup(u.u_rgid); 21826275Skarels (void) entergroup((gid_t)rgid); 2199160Ssam u.u_rgid = rgid; 2209160Ssam } 22111164Ssam u.u_gid = egid; 2229160Ssam } 2239160Ssam 2247866Sroot setgroups() 2257498Sroot { 2267498Sroot register struct a { 2278624Sroot u_int gidsetsize; 2287498Sroot int *gidset; 2297498Sroot } *uap = (struct a *)u.u_ap; 23018362Skarels register gid_t *gp; 23118362Skarels register int *lp; 23218362Skarels int groups[NGROUPS]; 2337498Sroot 234*37553Smckusick if (u.u_error = suser(u.u_cred, &u.u_acflag)) 2357498Sroot return; 2367866Sroot if (uap->gidsetsize > sizeof (u.u_groups) / sizeof (u.u_groups[0])) { 2377866Sroot u.u_error = EINVAL; 2387498Sroot return; 2397498Sroot } 24018362Skarels u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups, 24118362Skarels uap->gidsetsize * sizeof (groups[0])); 2429997Ssam if (u.u_error) 2437498Sroot return; 24418362Skarels for (lp = groups, gp = u.u_groups; lp < &groups[uap->gidsetsize]; ) 24518362Skarels *gp++ = *lp++; 24618362Skarels for ( ; gp < &u.u_groups[NGROUPS]; gp++) 24711810Ssam *gp = NOGROUP; 2487498Sroot } 2497498Sroot 2507498Sroot /* 25111810Ssam * Group utility functions. 25211810Ssam */ 25311810Ssam 25411810Ssam /* 25511810Ssam * Delete gid from the group set. 25611810Ssam */ 2577866Sroot leavegroup(gid) 25826275Skarels gid_t gid; 2597866Sroot { 26018362Skarels register gid_t *gp; 2617866Sroot 2627866Sroot for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) 2637866Sroot if (*gp == gid) 2647866Sroot goto found; 2657866Sroot return; 2667866Sroot found: 2677866Sroot for (; gp < &u.u_groups[NGROUPS-1]; gp++) 2687866Sroot *gp = *(gp+1); 26911810Ssam *gp = NOGROUP; 2707866Sroot } 2717866Sroot 27211810Ssam /* 27311810Ssam * Add gid to the group set. 27411810Ssam */ 2757866Sroot entergroup(gid) 27626275Skarels gid_t gid; 2777866Sroot { 27818362Skarels register gid_t *gp; 2797866Sroot 28018362Skarels for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) { 2817866Sroot if (*gp == gid) 2827866Sroot return (0); 28318362Skarels if (*gp == NOGROUP) { 2847866Sroot *gp = gid; 2857866Sroot return (0); 2867866Sroot } 28718362Skarels } 2887866Sroot return (-1); 2897866Sroot } 29011810Ssam 29111810Ssam /* 29211810Ssam * Check if gid is a member of the group set. 29311810Ssam */ 29411810Ssam groupmember(gid) 29518362Skarels gid_t gid; 29611810Ssam { 29718362Skarels register gid_t *gp; 29811810Ssam 29911810Ssam if (u.u_gid == gid) 30011810Ssam return (1); 30111810Ssam for (gp = u.u_groups; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++) 30211810Ssam if (*gp == gid) 30311810Ssam return (1); 30411810Ssam return (0); 30511810Ssam } 30637085Skfall 30737085Skfall /* 30837085Skfall * Get login name of process owner, if available 30937085Skfall */ 31037085Skfall 31137085Skfall getlogname() 31237085Skfall { 31337085Skfall struct a { 31437085Skfall char *namebuf; 31537085Skfall u_int namelen; 31637085Skfall } *uap = (struct a *)u.u_ap; 31737085Skfall 31837085Skfall if (uap->namelen > sizeof (u.u_logname)) 31937085Skfall uap->namelen = sizeof (u.u_logname); 32037085Skfall u.u_error = copyout((caddr_t)u.u_logname, (caddr_t)uap->namebuf, 32137085Skfall uap->namelen); 32237085Skfall } 32337085Skfall 32437085Skfall /* 32537085Skfall * Set login name of process owner 32637085Skfall */ 32737085Skfall 32837085Skfall setlogname() 32937085Skfall { 33037085Skfall struct a { 33137085Skfall char *namebuf; 33237085Skfall u_int namelen; 33337085Skfall } *uap = (struct a *)u.u_ap; 33437085Skfall 335*37553Smckusick if (u.u_error = suser(u.u_cred, &u.u_acflag)) 336*37553Smckusick return; 337*37553Smckusick if (uap->namelen > sizeof (u.u_logname) - 1) 338*37553Smckusick u.u_error = EINVAL; 339*37553Smckusick else 340*37553Smckusick u.u_error = copyin((caddr_t)uap->namebuf, 341*37553Smckusick (caddr_t)u.u_logname, uap->namelen); 34237085Skfall } 343