NFSv2/usr/src/sun/sys/sys/kern_prot.c
/* @(#)kern_prot.c 1.1 85/05/30 SMI; from UCB 5.17 83/05/27 */
/*
* System calls related to processes and protection
*/
#include "../machine/reg.h"
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/user.h"
#include "../h/vfs.h"
#include "../h/vnode.h"
#include "../h/proc.h"
#include "../h/timeb.h"
#include "../h/times.h"
#include "../h/reboot.h"
#include "../h/conf.h"
#include "../h/buf.h"
#include "../h/quota.h"
#include "../h/acct.h"
getpid()
{
u.u_r.r_val1 = u.u_procp->p_pid;
u.u_r.r_val2 = u.u_procp->p_ppid;
}
getpgrp()
{
register struct a {
int pid;
} *uap = (struct a *)u.u_ap;
register struct proc *p;
if (uap->pid == 0)
uap->pid = u.u_procp->p_pid;
p = pfind(uap->pid);
if (p == 0) {
u.u_error = ESRCH;
return;
}
u.u_r.r_val1 = p->p_pgrp;
}
getuid()
{
u.u_r.r_val1 = u.u_ruid;
u.u_r.r_val2 = u.u_uid;
}
getgid()
{
u.u_r.r_val1 = u.u_rgid;
u.u_r.r_val2 = u.u_gid;
}
getgroups()
{
register struct a {
u_int gidsetsize;
int *gidset;
} *uap = (struct a *)u.u_ap;
register int *gp;
for (gp = &u.u_groups[NGROUPS]; gp > u.u_groups; gp--)
if (gp[-1] >= 0)
break;
if (uap->gidsetsize < gp - u.u_groups) {
u.u_error = EINVAL;
return;
}
uap->gidsetsize = gp - u.u_groups;
u.u_error = copyout((caddr_t)u.u_groups, (caddr_t)uap->gidset,
uap->gidsetsize * sizeof (u.u_groups[0]));
if (u.u_error)
return;
u.u_r.r_val1 = uap->gidsetsize;
}
setpgrp()
{
register struct proc *p;
register struct a {
int pid;
int pgrp;
} *uap = (struct a *)u.u_ap;
if (uap->pid == 0)
uap->pid = u.u_procp->p_pid;
p = pfind(uap->pid);
if (p == 0) {
u.u_error = ESRCH;
return;
}
/* need better control mechanisms for process groups */
if (p->p_uid != u.u_uid && u.u_uid && !inferior(p)) {
u.u_error = EPERM;
return;
}
p->p_pgrp = uap->pgrp;
}
setreuid()
{
struct a {
int ruid;
int euid;
} *uap;
register int ruid, euid;
uap = (struct a *)u.u_ap;
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.
*/
u.u_cred = crcopy(u.u_cred);
#ifdef QUOTA
if (u.u_quota->q_uid != ruid) {
qclean();
qstart(getquota(ruid, 0, 0));
}
#endif
u.u_procp->p_uid = ruid;
u.u_ruid = ruid;
u.u_uid = euid;
}
setregid()
{
register struct a {
int rgid;
int egid;
} *uap;
register int rgid, egid;
uap = (struct a *)u.u_ap;
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;
u.u_cred = crcopy(u.u_cred);
if (u.u_rgid != rgid) {
leavegroup(u.u_rgid);
(void) entergroup(rgid);
u.u_rgid = rgid;
}
u.u_gid = egid;
}
setgroups()
{
register struct a {
u_int gidsetsize;
int *gidset;
} *uap = (struct a *)u.u_ap;
register int *gp;
struct ucred *newcr, *tmpcr;
if (!suser())
return;
if (uap->gidsetsize > sizeof (u.u_groups) / sizeof (u.u_groups[0])) {
u.u_error = EINVAL;
return;
}
newcr = crdup(u.u_cred);
u.u_error = copyin((caddr_t)uap->gidset, (caddr_t)newcr->cr_groups,
uap->gidsetsize * sizeof (newcr->cr_groups[0]));
if (u.u_error) {
crfree(newcr);
return;
}
tmpcr = u.u_cred;
u.u_cred = newcr;
crfree(tmpcr);
for (gp = &u.u_groups[uap->gidsetsize]; gp < &u.u_groups[NGROUPS]; gp++)
*gp = NOGROUP;
}
/*
* Group utility functions.
*/
/*
* Delete gid from the group set.
*/
leavegroup(gid)
int gid;
{
register int *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;
}
/*
* Add gid to the group set.
*/
entergroup(gid)
int gid;
{
register int *gp;
for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++)
if (*gp == gid)
return (0);
for (gp = u.u_groups; gp < &u.u_groups[NGROUPS]; gp++)
if (*gp < 0) {
*gp = gid;
return (0);
}
return (-1);
}
/*
* Check if gid is a member of the group set.
*/
groupmember(gid)
int gid;
{
register int *gp;
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);
}
/*
* Test if the current user is the super user.
*/
suser()
{
if (u.u_uid == 0) {
u.u_acflag |= ASU;
return (1);
}
u.u_error = EPERM;
return (0);
}
/*
* Routines to allocate and free credentials structures
*/
int crdebug = 0;
int cractive = 0;
/*
* Hold a cred structure.
*/
crhold(cr)
struct ucred *cr;
{
if (crdebug)
printf("crhold %x %d %d %x\n",
cr, cr->cr_uid, cr->cr_ref, caller());
cr->cr_ref++;
}
/*
* Allocate a zeroed cred structure and crhold it.
*/
struct ucred *
crget()
{
struct ucred *cr;
cr = (struct ucred *)kmem_alloc(sizeof(*cr));
bzero(cr, sizeof(*cr));
crhold(cr);
/* printf("crget: %x\n", cr);*/
cractive++;
return(cr);
}
/*
* Free a cred structure.
* Throws away space when ref count gets to 0.
*/
crfree(cr)
struct ucred *cr;
{
int s = spl6();
if (crdebug)
printf("crfree %x %d %d %x\n",
cr, cr->cr_uid, cr->cr_ref, caller());
if (--cr->cr_ref != 0) {
splx(s);
return;
}
kmem_free(cr, sizeof(*cr));
cractive--;
splx(s);
}
/*
* Copy cred structure to a new one and free the old one.
*/
struct ucred *
crcopy(cr)
struct ucred *cr;
{
struct ucred *newcr;
newcr = crget();
*newcr = *cr;
crfree(cr);
newcr->cr_ref = 1;
/* printf("crcopy: old %x %d %d new %x\n", cr, cr->cr_uid, cr->cr_ref, newcr);*/
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;
/* printf("crdup: old %x %d %d new %x\n", cr, cr->cr_uid, cr->cr_ref, newcr);*/
return(newcr);
}