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*37085Skfall * @(#)kern_prot.c 7.3 (Berkeley) 03/07/89 723372Smckusick */ 87420Sroot 97420Sroot /* 107498Sroot * System calls related to processes and protection 117420Sroot */ 127420Sroot 139754Ssam #include "../machine/reg.h" 149754Ssam 1517092Sbloom #include "param.h" 1617092Sbloom #include "systm.h" 1717092Sbloom #include "dir.h" 1817092Sbloom #include "user.h" 1917092Sbloom #include "inode.h" 2017092Sbloom #include "proc.h" 2117092Sbloom #include "timeb.h" 2217092Sbloom #include "times.h" 2317092Sbloom #include "reboot.h" 2417092Sbloom #include "fs.h" 2517092Sbloom #include "buf.h" 2617092Sbloom #include "mount.h" 2717092Sbloom #include "quota.h" 287420Sroot 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; 1729160Ssam if (u.u_ruid != ruid && u.u_uid != ruid && !suser()) 1739160Ssam return; 1749160Ssam euid = uap->euid; 1759160Ssam if (euid == -1) 1769160Ssam euid = u.u_uid; 1779160Ssam if (u.u_ruid != euid && u.u_uid != euid && !suser()) 1789160Ssam return; 1799160Ssam /* 1809160Ssam * Everything's okay, do it. 1819160Ssam */ 1829160Ssam #ifdef QUOTA 1839320Ssam if (u.u_quota->q_uid != ruid) { 1849320Ssam qclean(); 18526354Skarels qstart(getquota((uid_t)ruid, 0, 0)); 1869320Ssam } 1879160Ssam #endif 18825627Skarels u.u_procp->p_uid = euid; 1899320Ssam u.u_ruid = ruid; 1909160Ssam u.u_uid = euid; 1919160Ssam } 1929160Ssam 1939160Ssam setregid() 1947420Sroot { 1959160Ssam register struct a { 1969160Ssam int rgid; 1979160Ssam int egid; 1989160Ssam } *uap; 1999160Ssam register int rgid, egid; 2009160Ssam 2019160Ssam uap = (struct a *)u.u_ap; 2029160Ssam rgid = uap->rgid; 2039160Ssam if (rgid == -1) 2049160Ssam rgid = u.u_rgid; 2059160Ssam if (u.u_rgid != rgid && u.u_gid != rgid && !suser()) 2069160Ssam return; 2079160Ssam egid = uap->egid; 2089160Ssam if (egid == -1) 2099160Ssam egid = u.u_gid; 2109160Ssam if (u.u_rgid != egid && u.u_gid != egid && !suser()) 2119160Ssam return; 2129160Ssam if (u.u_rgid != rgid) { 2139160Ssam leavegroup(u.u_rgid); 21426275Skarels (void) entergroup((gid_t)rgid); 2159160Ssam u.u_rgid = rgid; 2169160Ssam } 21711164Ssam u.u_gid = egid; 2189160Ssam } 2199160Ssam 2207866Sroot setgroups() 2217498Sroot { 2227498Sroot register struct a { 2238624Sroot u_int gidsetsize; 2247498Sroot int *gidset; 2257498Sroot } *uap = (struct a *)u.u_ap; 22618362Skarels register gid_t *gp; 22718362Skarels register int *lp; 22818362Skarels int groups[NGROUPS]; 2297498Sroot 2308100Sroot if (!suser()) 2317498Sroot return; 2327866Sroot if (uap->gidsetsize > sizeof (u.u_groups) / sizeof (u.u_groups[0])) { 2337866Sroot u.u_error = EINVAL; 2347498Sroot return; 2357498Sroot } 23618362Skarels u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)groups, 23718362Skarels uap->gidsetsize * sizeof (groups[0])); 2389997Ssam if (u.u_error) 2397498Sroot return; 24018362Skarels for (lp = groups, gp = u.u_groups; lp < &groups[uap->gidsetsize]; ) 24118362Skarels *gp++ = *lp++; 24218362Skarels for ( ; gp < &u.u_groups[NGROUPS]; gp++) 24311810Ssam *gp = NOGROUP; 2447498Sroot } 2457498Sroot 2467498Sroot /* 24711810Ssam * Group utility functions. 24811810Ssam */ 24911810Ssam 25011810Ssam /* 25111810Ssam * Delete gid from the group set. 25211810Ssam */ 2537866Sroot leavegroup(gid) 25426275Skarels gid_t gid; 2557866Sroot { 25618362Skarels register gid_t *gp; 2577866Sroot 2587866Sroot for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) 2597866Sroot if (*gp == gid) 2607866Sroot goto found; 2617866Sroot return; 2627866Sroot found: 2637866Sroot for (; gp < &u.u_groups[NGROUPS-1]; gp++) 2647866Sroot *gp = *(gp+1); 26511810Ssam *gp = NOGROUP; 2667866Sroot } 2677866Sroot 26811810Ssam /* 26911810Ssam * Add gid to the group set. 27011810Ssam */ 2717866Sroot entergroup(gid) 27226275Skarels gid_t gid; 2737866Sroot { 27418362Skarels register gid_t *gp; 2757866Sroot 27618362Skarels for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) { 2777866Sroot if (*gp == gid) 2787866Sroot return (0); 27918362Skarels if (*gp == NOGROUP) { 2807866Sroot *gp = gid; 2817866Sroot return (0); 2827866Sroot } 28318362Skarels } 2847866Sroot return (-1); 2857866Sroot } 28611810Ssam 28711810Ssam /* 28811810Ssam * Check if gid is a member of the group set. 28911810Ssam */ 29011810Ssam groupmember(gid) 29118362Skarels gid_t gid; 29211810Ssam { 29318362Skarels register gid_t *gp; 29411810Ssam 29511810Ssam if (u.u_gid == gid) 29611810Ssam return (1); 29711810Ssam for (gp = u.u_groups; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++) 29811810Ssam if (*gp == gid) 29911810Ssam return (1); 30011810Ssam return (0); 30111810Ssam } 302*37085Skfall 303*37085Skfall /* 304*37085Skfall * Get login name of process owner, if available 305*37085Skfall */ 306*37085Skfall 307*37085Skfall getlogname() 308*37085Skfall { 309*37085Skfall struct a { 310*37085Skfall char *namebuf; 311*37085Skfall u_int namelen; 312*37085Skfall } *uap = (struct a *)u.u_ap; 313*37085Skfall 314*37085Skfall if (uap->namelen > sizeof (u.u_logname)) 315*37085Skfall uap->namelen = sizeof (u.u_logname); 316*37085Skfall u.u_error = copyout((caddr_t)u.u_logname, (caddr_t)uap->namebuf, 317*37085Skfall uap->namelen); 318*37085Skfall } 319*37085Skfall 320*37085Skfall /* 321*37085Skfall * Set login name of process owner 322*37085Skfall */ 323*37085Skfall 324*37085Skfall setlogname() 325*37085Skfall { 326*37085Skfall struct a { 327*37085Skfall char *namebuf; 328*37085Skfall u_int namelen; 329*37085Skfall } *uap = (struct a *)u.u_ap; 330*37085Skfall 331*37085Skfall if(suser()) { 332*37085Skfall if(uap->namelen > sizeof (u.u_logname) - 1) 333*37085Skfall u.u_error = EINVAL; 334*37085Skfall else 335*37085Skfall u.u_error = copyin((caddr_t)uap->namebuf, 336*37085Skfall (caddr_t)u.u_logname, uap->namelen); 337*37085Skfall } 338*37085Skfall } 339