X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/38b6104cbeb1de7fc36bc2a9b4b78e55168a98e2..a2f658f997662926f2a54d337f2ed9abde78f991:/usr/src/sys/kern/kern_prot.c diff --git a/usr/src/sys/kern/kern_prot.c b/usr/src/sys/kern/kern_prot.c index 3d376fd0fc..4ccfd65783 100644 --- a/usr/src/sys/kern/kern_prot.c +++ b/usr/src/sys/kern/kern_prot.c @@ -1,25 +1,41 @@ -/* kern_prot.c 6.3 85/03/18 */ +/* + * Copyright (c) 1982, 1986, 1989 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)kern_prot.c 7.7 (Berkeley) %G% + */ /* * System calls related to processes and protection */ -#include "../machine/reg.h" - #include "param.h" +#include "acct.h" #include "systm.h" -#include "dir.h" #include "user.h" -#include "inode.h" #include "proc.h" #include "timeb.h" #include "times.h" #include "reboot.h" -#include "fs.h" -#include "conf.h" -#include "buf.h" #include "mount.h" -#include "quota.h" +#include "buf.h" +#include "../ufs/quota.h" +#include "malloc.h" +#define GRPSTART 0 + +#include "machine/reg.h" getpid() { @@ -36,13 +52,12 @@ getpgrp() register struct proc *p; if (uap->pid == 0) - uap->pid = u.u_procp->p_pid; - p = pfind(uap->pid); - if (p == 0) { + p = u.u_procp; + else if ((p = pfind(uap->pid)) == 0) { u.u_error = ESRCH; return; } - u.u_r.r_val1 = p->p_pgrp; + u.u_r.r_val1 = p->p_pgrp->pg_id; } getuid() @@ -69,15 +84,17 @@ getgroups() register int *lp; int groups[NGROUPS]; - for (gp = &u.u_groups[NGROUPS]; gp > u.u_groups; gp--) - if (gp[-1] != NOGROUP) - break; - if (uap->gidsetsize < gp - u.u_groups) { + if (uap->gidsetsize == 0) { + u.u_r.r_val1 = u.u_ngroups - GRPSTART; + return; + } + if (uap->gidsetsize < u.u_ngroups - GRPSTART) { u.u_error = EINVAL; return; } - uap->gidsetsize = gp - u.u_groups; - for (lp = groups, gp = u.u_groups; lp < &groups[uap->gidsetsize]; ) + uap->gidsetsize = u.u_ngroups - GRPSTART; + gp = &u.u_groups[GRPSTART]; + for (lp = groups; lp < &groups[uap->gidsetsize]; ) *lp++ = *gp++; u.u_error = copyout((caddr_t)groups, (caddr_t)uap->gidset, uap->gidsetsize * sizeof (groups[0])); @@ -86,27 +103,71 @@ getgroups() u.u_r.r_val1 = uap->gidsetsize; } +setsid() +{ + register struct proc *p = u.u_procp; + + if ((p->p_pgid == p->p_pid) || pgfind(p->p_pid)) + u.u_error = EPERM; + else { + pgmv(p, p->p_pid, 1); + u.u_r.r_val1 = p->p_pid; + } + return; +} + +/* + * set process group + * + * if target pid != caller's pid + * pid must be an inferior + * pid must be in same session + * pid can't have done an exec + * there must exist a pid with pgid in same session + * pid must not be session leader + */ setpgrp() { - register struct proc *p; register struct a { int pid; - int pgrp; + int pgid; } *uap = (struct a *)u.u_ap; + register struct proc *p; + register struct pgrp *pgrp; if (uap->pid == 0) - uap->pid = u.u_procp->p_pid; - p = pfind(uap->pid); - if (p == 0) { + p = u.u_procp; + else if ((p = pfind(uap->pid)) == 0 || !inferior(p)) { u.u_error = ESRCH; return; } -/* need better control mechanisms for process groups */ - if (p->p_uid != u.u_uid && u.u_uid && !inferior(p)) { + else if (p != u.u_procp) { + if (p->p_session != u.u_procp->p_session) { + u.u_error = EPERM; + return; + } + if (p->p_flag&SEXEC) { + u.u_error = EACCES; + return; + } + } + if (SESS_LEADER(p)) { u.u_error = EPERM; return; } - p->p_pgrp = uap->pgrp; + if (uap->pgid == 0) + uap->pgid = p->p_pid; + else if ((uap->pgid != p->p_pid) && + (((pgrp = pgfind(uap->pgid)) == 0) || + pgrp->pg_mem == NULL || + pgrp->pg_session != u.u_procp->p_session)) { + u.u_error = EPERM; + return; + } + /* + * done checking, now doit + */ + pgmv(p, uap->pgid, 0); } setreuid() @@ -121,23 +182,25 @@ setreuid() ruid = uap->ruid; if (ruid == -1) ruid = u.u_ruid; - if (u.u_ruid != ruid && u.u_uid != ruid && !suser()) return; euid = uap->euid; if (euid == -1) euid = u.u_uid; - if (u.u_ruid != euid && u.u_uid != euid && !suser()) return; /* * Everything's okay, do it. + * Copy credentials so other references do not + * see our changes. */ #ifdef QUOTA if (u.u_quota->q_uid != ruid) { qclean(); - qstart(getquota(ruid, 0, 0)); + qstart(getquota((uid_t)ruid, 0, 0)); } #endif - u.u_procp->p_uid = ruid; + if (u.u_cred->cr_ref > 1) + u.u_cred = crcopy(u.u_cred); + u.u_procp->p_uid = euid; u.u_ruid = ruid; u.u_uid = euid; } @@ -154,18 +217,14 @@ setregid() rgid = uap->rgid; if (rgid == -1) rgid = u.u_rgid; - if (u.u_rgid != rgid && u.u_gid != rgid && !suser()) return; egid = uap->egid; if (egid == -1) egid = u.u_gid; - if (u.u_rgid != egid && u.u_gid != egid && !suser()) return; - if (u.u_rgid != rgid) { - leavegroup(u.u_rgid); - (void) entergroup(rgid); - u.u_rgid = rgid; - } + if (u.u_cred->cr_ref > 1) + u.u_cred = crcopy(u.u_cred); + u.u_rgid = rgid; u.u_gid = egid; } @@ -177,11 +236,12 @@ setgroups() } *uap = (struct a *)u.u_ap; register gid_t *gp; register int *lp; - int groups[NGROUPS]; + int ngrp, groups[NGROUPS]; - if (!suser()) + if (u.u_error = suser(u.u_cred, &u.u_acflag)) return; - if (uap->gidsetsize > sizeof (u.u_groups) / sizeof (u.u_groups[0])) { + ngrp = uap->gidsetsize + GRPSTART; + if (ngrp > sizeof (u.u_groups) / sizeof (u.u_groups[0])) { u.u_error = EINVAL; return; } @@ -189,65 +249,142 @@ setgroups() uap->gidsetsize * sizeof (groups[0])); if (u.u_error) return; - for (lp = groups, gp = u.u_groups; lp < &groups[uap->gidsetsize]; ) + gp = &u.u_groups[GRPSTART]; + for (lp = groups; lp < &groups[uap->gidsetsize]; ) *gp++ = *lp++; - for ( ; gp < &u.u_groups[NGROUPS]; gp++) - *gp = NOGROUP; + u.u_ngroups = ngrp; } /* - * Group utility functions. + * Check if gid is a member of the group set. */ +groupmember(gid, cred) + gid_t gid; + register struct ucred *cred; +{ + register gid_t *gp; + gid_t *egp; + + egp = &(cred->cr_groups[cred->cr_ngroups]); + for (gp = cred->cr_groups; gp < egp; gp++) + if (*gp == gid) + return (1); + return (0); +} /* - * Delete gid from the group set. + * Test if the current user is the super user. */ -leavegroup(gid) - int gid; +suser(cred, acflag) + struct ucred *cred; + short *acflag; { - register gid_t *gp; - for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) - if (*gp == gid) - goto found; - return; -found: - for (; gp < &u.u_groups[NGROUPS-1]; gp++) - *gp = *(gp+1); - *gp = NOGROUP; + if (cred->cr_uid == 0) { + if (acflag) + *acflag |= ASU; + return (0); + } + return (EPERM); } /* - * Add gid to the group set. + * Allocate a zeroed cred structure. */ -entergroup(gid) - int gid; +struct ucred * +crget() { - register gid_t *gp; + register struct ucred *cr; - for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++) { - if (*gp == gid) - return (0); - if (*gp == NOGROUP) { - *gp = gid; - return (0); - } + MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); + bzero((caddr_t)cr, sizeof(*cr)); + cr->cr_ref = 1; + return(cr); +} + +/* + * Free a cred structure. + * Throws away space when ref count gets to 0. + */ +crfree(cr) + struct ucred *cr; +{ + int s = splimp(); + + if (--cr->cr_ref != 0) { + (void) splx(s); + return; } - return (-1); + FREE((caddr_t)cr, M_CRED); + (void) splx(s); } /* - * Check if gid is a member of the group set. + * Copy cred structure to a new one and free the old one. */ -groupmember(gid) - gid_t gid; +struct ucred * +crcopy(cr) + struct ucred *cr; { - register gid_t *gp; + struct ucred *newcr; - if (u.u_gid == gid) - return (1); - for (gp = u.u_groups; gp < &u.u_groups[NGROUPS] && *gp != NOGROUP; gp++) - if (*gp == gid) - return (1); - return (0); + newcr = crget(); + *newcr = *cr; + crfree(cr); + newcr->cr_ref = 1; + return(newcr); +} + +/* + * Dup cred struct to a new held one. + */ +struct ucred * +crdup(cr) + struct ucred *cr; +{ + struct ucred *newcr; + + newcr = crget(); + *newcr = *cr; + newcr->cr_ref = 1; + return(newcr); +} + +/* + * Get login name of process owner, if available + */ + +getlogname() +{ + struct a { + char *namebuf; + u_int namelen; + } *uap = (struct a *)u.u_ap; + + if (uap->namelen > sizeof (u.u_logname)) + uap->namelen = sizeof (u.u_logname); + u.u_error = copyout((caddr_t)u.u_logname, (caddr_t)uap->namebuf, + uap->namelen); +} + +/* + * Set login name of process owner + */ + +setlogname() +{ + struct a { + char *namebuf; + u_int namelen; + } *uap = (struct a *)u.u_ap; + + if (u.u_error = suser(u.u_cred, &u.u_acflag)) + return; + if (uap->namelen > sizeof (u.u_logname) - 1) + u.u_error = EINVAL; + else { + u.u_logname[uap->namelen] = NULL; + u.u_error = copyin((caddr_t)uap->namebuf, + (caddr_t)u.u_logname, uap->namelen); + } }