home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / kern_prot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-03  |  12.4 KB  |  585 lines

  1. /*
  2.  * Copyright (c) 1982, 1986, 1989, 1990, 1991 Regents of the University
  3.  * of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)kern_prot.c    7.21 (Berkeley) 5/3/91
  34.  */
  35.  
  36. /*
  37.  * System calls related to processes and protection
  38.  */
  39.  
  40. #include "param.h"
  41. #include "acct.h"
  42. #include "systm.h"
  43. #include "ucred.h"
  44. #include "proc.h"
  45. #include "timeb.h"
  46. #include "times.h"
  47. #include "malloc.h"
  48.  
  49. /* ARGSUSED */
  50. getpid(p, uap, retval)
  51.     struct proc *p;
  52.     void *uap;
  53.     int *retval;
  54. {
  55.  
  56.     *retval = p->p_pid;
  57. #ifdef COMPAT_43
  58.     retval[1] = p->p_pptr->p_pid;
  59. #endif
  60.     return (0);
  61. }
  62.  
  63. /* ARGSUSED */
  64. getppid(p, uap, retval)
  65.     struct proc *p;
  66.     void *uap;
  67.     int *retval;
  68. {
  69.  
  70.     *retval = p->p_pptr->p_pid;
  71.     return (0);
  72. }
  73.  
  74. /* Get process group ID; note that POSIX getpgrp takes no parameter */
  75. getpgrp(p, uap, retval)
  76.     struct proc *p;
  77.     void *uap;
  78.     int *retval;
  79. {
  80.  
  81.     *retval = p->p_pgrp->pg_id;
  82.     return (0);
  83. }
  84.  
  85. /* ARGSUSED */
  86. getuid(p, uap, retval)
  87.     struct proc *p;
  88.     void *uap;
  89.     int *retval;
  90. {
  91.  
  92.     *retval = p->p_cred->p_ruid;
  93. #ifdef COMPAT_43
  94.     retval[1] = p->p_ucred->cr_uid;
  95. #endif
  96.     return (0);
  97. }
  98.  
  99. /* ARGSUSED */
  100. geteuid(p, uap, retval)
  101.     struct proc *p;
  102.     void *uap;
  103.     int *retval;
  104. {
  105.  
  106.     *retval = p->p_ucred->cr_uid;
  107.     return (0);
  108. }
  109.  
  110. /* ARGSUSED */
  111. getgid(p, uap, retval)
  112.     struct proc *p;
  113.     void *uap;
  114.     int *retval;
  115. {
  116.  
  117.     *retval = p->p_cred->p_rgid;
  118. #ifdef COMPAT_43
  119.     retval[1] = p->p_ucred->cr_groups[0];
  120. #endif
  121.     return (0);
  122. }
  123.  
  124. /*
  125.  * Get effective group ID.  The "egid" is groups[0], and could be obtained
  126.  * via getgroups.  This syscall exists because it is somewhat painful to do
  127.  * correctly in a library function.
  128.  */
  129. /* ARGSUSED */
  130. getegid(p, uap, retval)
  131.     struct proc *p;
  132.     void *uap;
  133.     int *retval;
  134. {
  135.  
  136.     *retval = p->p_ucred->cr_groups[0];
  137.     return (0);
  138. }
  139.  
  140. getgroups(p, uap, retval)
  141.     struct proc *p;
  142.     register struct    arg {
  143.         u_int    gidsetsize;
  144.         int    *gidset;        /* XXX not yet POSIX */
  145.     } *uap;
  146.     int *retval;
  147. {
  148.     register struct pcred *pc = p->p_cred;
  149.     register gid_t *gp;
  150.     register int *lp;
  151.     register u_int ngrp;
  152.     int groups[NGROUPS];
  153.     int error;
  154.  
  155.     if ((ngrp = uap->gidsetsize) == 0) {
  156.         *retval = pc->pc_ucred->cr_ngroups;
  157.         return (0);
  158.     }
  159.     if (ngrp < pc->pc_ucred->cr_ngroups)
  160.         return (EINVAL);
  161.     ngrp = pc->pc_ucred->cr_ngroups;
  162.     for (gp = pc->pc_ucred->cr_groups, lp = groups; lp < &groups[ngrp]; )
  163.         *lp++ = *gp++;
  164.     if (error = copyout((caddr_t)groups, (caddr_t)uap->gidset,
  165.         ngrp * sizeof (groups[0])))
  166.         return (error);
  167.     *retval = ngrp;
  168.     return (0);
  169. }
  170.  
  171. /* ARGSUSED */
  172. setsid(p, uap, retval)
  173.     register struct proc *p;
  174.     void *uap;
  175.     int *retval;
  176. {
  177.  
  178.     if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
  179.         return (EPERM);
  180.     } else {
  181.         enterpgrp(p, p->p_pid, 1);
  182.         *retval = p->p_pid;
  183.         return (0);
  184.     }
  185. }
  186.  
  187. /*
  188.  * set process group (setpgid/old setpgrp)
  189.  *
  190.  * caller does setpgid(targpid, targpgid)
  191.  *
  192.  * pid must be caller or child of caller (ESRCH)
  193.  * if a child
  194.  *    pid must be in same session (EPERM)
  195.  *    pid can't have done an exec (EACCES)
  196.  * if pgid != pid
  197.  *     there must exist some pid in same session having pgid (EPERM)
  198.  * pid must not be session leader (EPERM)
  199.  */
  200. /* ARGSUSED */
  201. setpgid(curp, uap, retval)
  202.     struct proc *curp;
  203.     register struct args {
  204.         int    pid;    /* target process id */
  205.         int    pgid;    /* target pgrp id */
  206.     } *uap;
  207.     int *retval;
  208. {
  209.     register struct proc *targp;        /* target process */
  210.     register struct pgrp *pgrp;        /* target pgrp */
  211.  
  212.     if (uap->pid != 0 && uap->pid != curp->p_pid) {
  213.         if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
  214.             return (ESRCH);
  215.         if (targp->p_session != curp->p_session)
  216.             return (EPERM);
  217.         if (targp->p_flag&SEXEC)
  218.             return (EACCES);
  219.     } else
  220.         targp = curp;
  221.     if (SESS_LEADER(targp))
  222.         return (EPERM);
  223.     if (uap->pgid == 0)
  224.         uap->pgid = targp->p_pid;
  225.     else if (uap->pgid != targp->p_pid)
  226.         if ((pgrp = pgfind(uap->pgid)) == 0 ||
  227.                 pgrp->pg_session != curp->p_session)
  228.             return (EPERM);
  229.     enterpgrp(targp, uap->pgid, 0);
  230.     return (0);
  231. }
  232.  
  233. /* ARGSUSED */
  234. setuid(p, uap, retval)
  235.     struct proc *p;
  236.     struct args {
  237.         int    uid;
  238.     } *uap;
  239.     int *retval;
  240. {
  241.     register struct pcred *pc = p->p_cred;
  242.     register uid_t uid;
  243.     int error;
  244.  
  245.     uid = uap->uid;
  246.     if (uid != pc->p_ruid &&
  247.         (error = suser(pc->pc_ucred, &p->p_acflag)))
  248.         return (error);
  249.     /*
  250.      * Everything's okay, do it.  Copy credentials so other references do
  251.      * not see our changes.
  252.      */
  253.     pc->pc_ucred = crcopy(pc->pc_ucred);
  254.     pc->pc_ucred->cr_uid = uid;
  255.     pc->p_ruid = uid;
  256.     pc->p_svuid = uid;
  257.     return (0);
  258. }
  259.  
  260. /* ARGSUSED */
  261. seteuid(p, uap, retval)
  262.     struct proc *p;
  263.     struct args {
  264.         int    euid;
  265.     } *uap;
  266.     int *retval;
  267. {
  268.     register struct pcred *pc = p->p_cred;
  269.     register uid_t euid;
  270.     int error;
  271.  
  272.     euid = uap->euid;
  273.     if (euid != pc->p_ruid && euid != pc->p_svuid &&
  274.         (error = suser(pc->pc_ucred, &p->p_acflag)))
  275.         return (error);
  276.     /*
  277.      * Everything's okay, do it.  Copy credentials so other references do
  278.      * not see our changes.
  279.      */
  280.     pc->pc_ucred = crcopy(pc->pc_ucred);
  281.     pc->pc_ucred->cr_uid = euid;
  282.     return (0);
  283. }
  284.  
  285. /* ARGSUSED */
  286. setgid(p, uap, retval)
  287.     struct proc *p;
  288.     struct args {
  289.         int    gid;
  290.     } *uap;
  291.     int *retval;
  292. {
  293.     register struct pcred *pc = p->p_cred;
  294.     register gid_t gid;
  295.     int error;
  296.  
  297.     gid = uap->gid;
  298.     if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
  299.         return (error);
  300.     pc->pc_ucred = crcopy(pc->pc_ucred);
  301.     pc->pc_ucred->cr_groups[0] = gid;
  302.     pc->p_rgid = gid;
  303.     pc->p_svgid = gid;        /* ??? */
  304.     return (0);
  305. }
  306.  
  307. /* ARGSUSED */
  308. setegid(p, uap, retval)
  309.     struct proc *p;
  310.     struct args {
  311.         int    egid;
  312.     } *uap;
  313.     int *retval;
  314. {
  315.     register struct pcred *pc = p->p_cred;
  316.     register gid_t egid;
  317.     int error;
  318.  
  319.     egid = uap->egid;
  320.     if (egid != pc->p_rgid && egid != pc->p_svgid &&
  321.         (error = suser(pc->pc_ucred, &p->p_acflag)))
  322.         return (error);
  323.     pc->pc_ucred = crcopy(pc->pc_ucred);
  324.     pc->pc_ucred->cr_groups[0] = egid;
  325.     return (0);
  326. }
  327.  
  328. #ifdef COMPAT_43
  329. /* ARGSUSED */
  330. osetreuid(p, uap, retval)
  331.     register struct proc *p;
  332.     struct args {
  333.         int    ruid;
  334.         int    euid;
  335.     } *uap;
  336.     int *retval;
  337. {
  338.     register struct pcred *pc = p->p_cred;
  339.     register uid_t ruid, euid;
  340.     int error;
  341.  
  342.     if (uap->ruid == -1)
  343.         ruid = pc->p_ruid;
  344.     else
  345.         ruid = uap->ruid;
  346.     /*
  347.      * Allow setting real uid to previous effective, for swapping real and
  348.      * effective.  This should be:
  349.      *
  350.      * if (ruid != pc->p_ruid &&
  351.      *     (error = suser(pc->pc_ucred, &p->p_acflag)))
  352.      */
  353.     if (ruid != pc->p_ruid && ruid != pc->pc_ucred->cr_uid /* XXX */ &&
  354.         (error = suser(pc->pc_ucred, &p->p_acflag)))
  355.         return (error);
  356.     if (uap->euid == -1)
  357.         euid = pc->pc_ucred->cr_uid;
  358.     else
  359.         euid = uap->euid;
  360.     if (euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid &&
  361.         euid != pc->p_svuid && (error = suser(pc->pc_ucred, &p->p_acflag)))
  362.         return (error);
  363.     /*
  364.      * Everything's okay, do it.  Copy credentials so other references do
  365.      * not see our changes.
  366.      */
  367.     pc->pc_ucred = crcopy(pc->pc_ucred);
  368.     pc->pc_ucred->cr_uid = euid;
  369.     pc->p_ruid = ruid;
  370.     return (0);
  371. }
  372.  
  373. /* ARGSUSED */
  374. osetregid(p, uap, retval)
  375.     register struct proc *p;
  376.     struct args {
  377.         int    rgid;
  378.         int    egid;
  379.     } *uap;
  380.     int *retval;
  381. {
  382.     register struct pcred *pc = p->p_cred;
  383.     register gid_t rgid, egid;
  384.     int error;
  385.  
  386.     if (uap->rgid == -1)
  387.         rgid = pc->p_rgid;
  388.     else
  389.         rgid = uap->rgid;
  390.     /*
  391.      * Allow setting real gid to previous effective, for swapping real and
  392.      * effective.  This didn't really work correctly in 4.[23], but is
  393.      * preserved so old stuff doesn't fail.  This should be:
  394.      *
  395.      * if (rgid != pc->p_rgid &&
  396.      *     (error = suser(pc->pc_ucred, &p->p_acflag)))
  397.      */
  398.     if (rgid != pc->p_rgid && rgid != pc->pc_ucred->cr_groups[0] /* XXX */ &&
  399.         (error = suser(pc->pc_ucred, &p->p_acflag)))
  400.         return (error);
  401.     if (uap->egid == -1)
  402.         egid = pc->pc_ucred->cr_groups[0];
  403.     else
  404.         egid = uap->egid;
  405.     if (egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid &&
  406.         egid != pc->p_svgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
  407.         return (error);
  408.     pc->pc_ucred = crcopy(pc->pc_ucred);
  409.     pc->pc_ucred->cr_groups[0] = egid;
  410.     pc->p_rgid = rgid;
  411.     return (0);
  412. }
  413. #endif
  414.  
  415. /* ARGSUSED */
  416. setgroups(p, uap, retval)
  417.     struct proc *p;
  418.     struct args {
  419.         u_int    gidsetsize;
  420.         int    *gidset;
  421.     } *uap;
  422.     int *retval;
  423. {
  424.     register struct pcred *pc = p->p_cred;
  425.     register gid_t *gp;
  426.     register u_int ngrp;
  427.     register int *lp;
  428.     int error, groups[NGROUPS];
  429.  
  430.     if (error = suser(pc->pc_ucred, &p->p_acflag))
  431.         return (error);
  432.     if ((ngrp = uap->gidsetsize) > NGROUPS)
  433.         return (EINVAL);
  434.     if (error = copyin((caddr_t)uap->gidset, (caddr_t)groups,
  435.         ngrp * sizeof (groups[0])))
  436.         return (error);
  437.     pc->pc_ucred = crcopy(pc->pc_ucred);
  438.     pc->pc_ucred->cr_ngroups = ngrp;
  439.     /* convert from int's to gid_t's */
  440.     for (gp = pc->pc_ucred->cr_groups, lp = groups; ngrp--; )
  441.         *gp++ = *lp++;
  442.     return (0);
  443. }
  444.  
  445. /*
  446.  * Check if gid is a member of the group set.
  447.  */
  448. groupmember(gid, cred)
  449.     gid_t gid;
  450.     register struct ucred *cred;
  451. {
  452.     register gid_t *gp;
  453.     gid_t *egp;
  454.  
  455.     egp = &(cred->cr_groups[cred->cr_ngroups]);
  456.     for (gp = cred->cr_groups; gp < egp; gp++)
  457.         if (*gp == gid)
  458.             return (1);
  459.     return (0);
  460. }
  461.  
  462. /*
  463.  * Test whether the specified credentials imply "super-user"
  464.  * privilege; if so, and we have accounting info, set the flag
  465.  * indicating use of super-powers.
  466.  * Returns 0 or error.
  467.  */
  468. suser(cred, acflag)
  469.     struct ucred *cred;
  470.     short *acflag;
  471. {
  472.     if (cred->cr_uid == 0) {
  473.         if (acflag)
  474.             *acflag |= ASU;
  475.         return (0);
  476.     }
  477.     return (EPERM);
  478. }
  479.  
  480. /*
  481.  * Allocate a zeroed cred structure.
  482.  */
  483. struct ucred *
  484. crget()
  485. {
  486.     register struct ucred *cr;
  487.  
  488.     MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
  489.     bzero((caddr_t)cr, sizeof(*cr));
  490.     cr->cr_ref = 1;
  491.     return (cr);
  492. }
  493.  
  494. /*
  495.  * Free a cred structure.
  496.  * Throws away space when ref count gets to 0.
  497.  */
  498. crfree(cr)
  499.     struct ucred *cr;
  500. {
  501.     int s = splimp();            /* ??? */
  502.  
  503.     if (--cr->cr_ref != 0) {
  504.         (void) splx(s);
  505.         return;
  506.     }
  507.     FREE((caddr_t)cr, M_CRED);
  508.     (void) splx(s);
  509. }
  510.  
  511. /*
  512.  * Copy cred structure to a new one and free the old one.
  513.  */
  514. struct ucred *
  515. crcopy(cr)
  516.     struct ucred *cr;
  517. {
  518.     struct ucred *newcr;
  519.  
  520.     if (cr->cr_ref == 1)
  521.         return (cr);
  522.     newcr = crget();
  523.     *newcr = *cr;
  524.     crfree(cr);
  525.     newcr->cr_ref = 1;
  526.     return (newcr);
  527. }
  528.  
  529. /*
  530.  * Dup cred struct to a new held one.
  531.  */
  532. struct ucred *
  533. crdup(cr)
  534.     struct ucred *cr;
  535. {
  536.     struct ucred *newcr;
  537.  
  538.     newcr = crget();
  539.     *newcr = *cr;
  540.     newcr->cr_ref = 1;
  541.     return (newcr);
  542. }
  543.  
  544. /*
  545.  * Get login name, if available.
  546.  */
  547. /* ARGSUSED */
  548. getlogin(p, uap, retval)
  549.     struct proc *p;
  550.     struct args {
  551.         char    *namebuf;
  552.         u_int    namelen;
  553.     } *uap;
  554.     int *retval;
  555. {
  556.  
  557.     if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login))
  558.         uap->namelen = sizeof (p->p_pgrp->pg_session->s_login);
  559.     return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
  560.         (caddr_t) uap->namebuf, uap->namelen));
  561. }
  562.  
  563. /*
  564.  * Set login name.
  565.  */
  566. /* ARGSUSED */
  567. setlogin(p, uap, retval)
  568.     struct proc *p;
  569.     struct args {
  570.         char    *namebuf;
  571.     } *uap;
  572.     int *retval;
  573. {
  574.     int error;
  575.  
  576.     if (error = suser(p->p_ucred, &p->p_acflag))
  577.         return (error);
  578.     error = copyinstr((caddr_t) uap->namebuf,
  579.         (caddr_t) p->p_pgrp->pg_session->s_login,
  580.         sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0);
  581.     if (error == ENAMETOOLONG)
  582.         error = EINVAL;
  583.     return (error);
  584. }
  585.