diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 1a2644b44e6a..6d0d915ae54e 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -302,9 +302,11 @@ proc0_init(void *dummy __unused) /* Create credentials. */ cred0.p_refcnt = 1; + cred0.p_uidinfo = uifind(0); p->p_cred = &cred0; p->p_ucred = crget(); p->p_ucred->cr_ngroups = 1; /* group 0 */ + p->p_ucred->cr_uidinfo = uifind(0); /* Don't jail it */ p->p_prison = 0; @@ -360,7 +362,7 @@ proc0_init(void *dummy __unused) /* * Charge root for one process. */ - (void)chgproccnt(0, 1, 0); + (void)chgproccnt(cred0.p_uidinfo, 1, 0); /* * Initialize the current process pointer (curproc) before diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 67def009e54d..5f6d2be22d08 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -294,7 +295,7 @@ interpret: */ p->p_ucred = crcopy(p->p_ucred); if (attr.va_mode & VSUID) - p->p_ucred->cr_uid = attr.va_uid; + change_euid(p, attr.va_uid); if (attr.va_mode & VSGID) p->p_ucred->cr_gid = attr.va_gid; setsugid(p); diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 26e093bdcf4d..df71fe07bf45 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -472,7 +472,7 @@ loop: /* * Decrement the count of procs running with this uid. */ - (void)chgproccnt(p->p_cred->p_ruid, -1, 0); + (void)chgproccnt(p->p_cred->p_uidinfo, -1, 0); /* * Release reference to text vnode @@ -485,6 +485,7 @@ loop: */ if (--p->p_cred->p_refcnt == 0) { crfree(p->p_ucred); + uifree(p->p_cred->p_uidinfo); FREE(p->p_cred, M_SUBPROC); p->p_cred = NULL; } diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 9d3c68e97457..f24c97e9c4f4 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -246,7 +246,8 @@ fork1(p1, flags, procp) * Increment the count of procs running with this uid. Don't allow * a nonprivileged user to exceed their current limit. */ - ok = chgproccnt(uid, 1, p1->p_rlimit[RLIMIT_NPROC].rlim_cur); + ok = chgproccnt(p1->p_cred->p_uidinfo, 1, + p1->p_rlimit[RLIMIT_NPROC].rlim_cur); if (uid != 0 && !ok) { /* * Back out the process count @@ -359,6 +360,7 @@ again: bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred)); p2->p_cred->p_refcnt = 1; crhold(p1->p_ucred); + uihold(p1->p_cred->p_uidinfo); if (p2->p_prison) { p2->p_prison->pr_ref++; diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 6a94bf7ea146..7ec2628a187f 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -61,25 +61,8 @@ SYSCTL_INT(_kern, OID_AUTO, ps_showallprocs, CTLFLAG_RW, static void pgdelete __P((struct pgrp *)); -/* - * Structure associated with user cacheing. - */ -struct uidinfo { - LIST_ENTRY(uidinfo) ui_hash; - uid_t ui_uid; - long ui_proccnt; - rlim_t ui_sbsize; -}; -#define UIHASH(uid) (&uihashtbl[(uid) & uihash]) -static LIST_HEAD(uihashhead, uidinfo) *uihashtbl; -static u_long uihash; /* size of hash table - 1 */ - static void orphanpg __P((struct pgrp *pg)); -static struct uidinfo *uifind(uid_t uid); -static struct uidinfo *uicreate(uid_t uid); -static int uifree(struct uidinfo *uip); - /* * Other process lists */ @@ -102,126 +85,8 @@ procinit() LIST_INIT(&zombproc); pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash); pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash); - uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash); proc_zone = zinit("PROC", sizeof (struct proc), 0, 0, 5); -} - -/* - * find/create a uidinfo struct for the uid passed in - */ -static struct uidinfo * -uifind(uid) - uid_t uid; -{ - struct uihashhead *uipp; - struct uidinfo *uip; - - uipp = UIHASH(uid); - LIST_FOREACH(uip, uipp, ui_hash) - if (uip->ui_uid == uid) - break; - - return (uip); -} - -static struct uidinfo * -uicreate(uid) - uid_t uid; -{ - struct uidinfo *uip, *norace; - - MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_NOWAIT); - if (uip == NULL) { - MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); - /* - * if we M_WAITOK we must look afterwards or risk - * redundant entries - */ - norace = uifind(uid); - if (norace != NULL) { - FREE(uip, M_PROC); - return (norace); - } - } - LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash); - uip->ui_uid = uid; - uip->ui_proccnt = 0; - uip->ui_sbsize = 0; - return (uip); -} - -static int -uifree(uip) - struct uidinfo *uip; -{ - - if (uip->ui_sbsize == 0 && uip->ui_proccnt == 0) { - LIST_REMOVE(uip, ui_hash); - FREE(uip, M_PROC); - return (1); - } - return (0); -} - -/* - * Change the count associated with number of processes - * a given user is using. When 'max' is 0, don't enforce a limit - */ -int -chgproccnt(uid, diff, max) - uid_t uid; - int diff; - int max; -{ - struct uidinfo *uip; - - uip = uifind(uid); - if (diff < 0) - KASSERT(uip != NULL, ("reducing proccnt: lost count, uid = %d", uid)); - if (uip == NULL) - uip = uicreate(uid); - /* don't allow them to exceed max, but allow subtraction */ - if (diff > 0 && uip->ui_proccnt + diff > max && max != 0) { - (void)uifree(uip); - return (0); - } - uip->ui_proccnt += diff; - (void)uifree(uip); - return (1); -} - -/* - * Change the total socket buffer size a user has used. - */ -int -chgsbsize(uid, hiwat, to, max) - uid_t uid; - u_long *hiwat; - u_long to; - rlim_t max; -{ - struct uidinfo *uip; - rlim_t diff; - int s; - - uip = uifind(uid); - KASSERT(to >= *hiwat || uip != NULL, - ("reducing sbsize: lost count, uid = %d", uid)); - if (uip == NULL) - uip = uicreate(uid); - s = splnet(); - diff = (rlim_t)to - (rlim_t)*hiwat; - /* don't allow them to exceed max, but allow subtraction */ - if (diff > 0 && uip->ui_sbsize + diff > max) { - (void)uifree(uip); - splx(s); - return (0); - } - uip->ui_sbsize += diff; - *hiwat = to; - (void)uifree(uip); - splx(s); - return (1); + uihashinit(); } /* diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 4ce571db20fd..8c21107068f5 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -53,10 +53,13 @@ #include #include #include +#include #include static MALLOC_DEFINE(M_CRED, "cred", "credentials"); +static void change_ruid(struct proc *p, uid_t ruid); + #ifndef _SYS_SYSPROTO_H_ struct getpid_args { int dummy; @@ -427,18 +430,16 @@ setuid(p, uap) #endif { /* - * Transfer proc count to new user. + * Set the real uid and transfer proc count to new user. */ if (uid != pc->p_ruid) { - (void)chgproccnt(pc->p_ruid, -1, 0); - (void)chgproccnt(uid, 1, 0); + change_ruid(p, uid); + setsugid(p); } /* * Set real uid */ if (uid != pc->p_ruid) { - pc->p_ruid = uid; - setsugid(p); } /* * Set saved uid @@ -458,8 +459,7 @@ setuid(p, uap) * Copy credentials so other references do not see our changes. */ if (pc->pc_ucred->cr_uid != uid) { - pc->pc_ucred = crcopy(pc->pc_ucred); - pc->pc_ucred->cr_uid = uid; + change_euid(p, uid); setsugid(p); } return (0); @@ -490,8 +490,7 @@ seteuid(p, uap) * not see our changes. */ if (pc->pc_ucred->cr_uid != euid) { - pc->pc_ucred = crcopy(pc->pc_ucred); - pc->pc_ucred->cr_uid = euid; + change_euid(p, euid); setsugid(p); } return (0); @@ -674,14 +673,11 @@ setreuid(p, uap) return (error); if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { - pc->pc_ucred = crcopy(pc->pc_ucred); - pc->pc_ucred->cr_uid = euid; + change_euid(p, euid); setsugid(p); } if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { - (void)chgproccnt(pc->p_ruid, -1, 0); - (void)chgproccnt(ruid, 1, 0); - pc->p_ruid = ruid; + change_ruid(p, ruid); setsugid(p); } if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) && @@ -767,14 +763,11 @@ setresuid(p, uap) (error = suser_xxx(0, p, PRISON_ROOT)) != 0) return (error); if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { - pc->pc_ucred = crcopy(pc->pc_ucred); - pc->pc_ucred->cr_uid = euid; + change_euid(p, euid); setsugid(p); } if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { - (void)chgproccnt(pc->p_ruid, -1, 0); - (void)chgproccnt(ruid, 1, 0); - pc->p_ruid = ruid; + change_ruid(p, ruid); setsugid(p); } if (suid != (uid_t)-1 && pc->p_svuid != suid) { @@ -1157,8 +1150,16 @@ void crfree(cr) struct ucred *cr; { - if (--cr->cr_ref == 0) + if (--cr->cr_ref == 0) { + /* + * Some callers of crget(), such as nfs_statfs(), + * allocate a temporary credential, but don't + * allocate a uidinfo structure. + */ + if (cr->cr_uidinfo != NULL) + uifree(cr->cr_uidinfo); FREE((caddr_t)cr, M_CRED); + } } /* @@ -1174,6 +1175,7 @@ crcopy(cr) return (cr); newcr = crget(); *newcr = *cr; + uihold(newcr->cr_uidinfo); crfree(cr); newcr->cr_ref = 1; return (newcr); @@ -1190,6 +1192,7 @@ crdup(cr) newcr = crget(); *newcr = *cr; + uihold(newcr->cr_uidinfo); newcr->cr_ref = 1; return (newcr); } @@ -1253,3 +1256,50 @@ setsugid(p) if (!(p->p_pfsflags & PF_ISUGID)) p->p_stops = 0; } + +/* + * Helper function to change the effective uid of a process + */ +void +change_euid(p, euid) + struct proc *p; + uid_t euid; +{ + struct pcred *pc; + struct uidinfo *uip; + + pc = p->p_cred; + /* + * crcopy is essentially a NOP if ucred has a reference count + * of 1, which is true if it has already been copied. + */ + pc->pc_ucred = crcopy(pc->pc_ucred); + uip = pc->pc_ucred->cr_uidinfo; + pc->pc_ucred->cr_uid = euid; + pc->pc_ucred->cr_uidinfo = uifind(euid); + uifree(uip); +} + +/* + * Helper function to change the real uid of a process + * + * The per-uid process count for this process is transfered from + * the old uid to the new uid. + */ +static void +change_ruid(p, ruid) + struct proc *p; + uid_t ruid; +{ + struct pcred *pc; + struct uidinfo *uip; + + pc = p->p_cred; + (void)chgproccnt(pc->p_uidinfo, -1, 0); + uip = pc->p_uidinfo; + /* It is assumed that pcred is not shared between processes */ + pc->p_ruid = ruid; + pc->p_uidinfo = uifind(ruid); + (void)chgproccnt(pc->p_uidinfo, 1, 0); + uifree(uip); +} diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index b3c2ec6feb8b..4956e5188bf6 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,14 @@ static int donice __P((struct proc *curp, struct proc *chgp, int n)); /* dosetrlimit non-static: Needed by SysVR4 emulator */ int dosetrlimit __P((struct proc *p, u_int which, struct rlimit *limp)); +static MALLOC_DEFINE(M_UIDINFO, "uidinfo", "uidinfo structures"); +#define UIHASH(uid) (&uihashtbl[(uid) & uihash]) +static LIST_HEAD(uihashhead, uidinfo) *uihashtbl; +static u_long uihash; /* size of hash table - 1 */ + +static struct uidinfo *uicreate __P((uid_t uid)); +static struct uidinfo *uilookup __P((uid_t uid)); + /* * Resource controls and accounting. */ @@ -641,3 +650,136 @@ limcopy(lim) copy->p_refcnt = 1; return (copy); } + +/* + * Find the uidinfo structure for a uid. This structure is used to + * track the total resource consumption (process count, socket buffer + * size, etc.) for the uid and impose limits. + */ +void +uihashinit() +{ + uihashtbl = hashinit(maxproc / 16, M_UIDINFO, &uihash); +} + +static struct uidinfo * +uilookup(uid) + uid_t uid; +{ + struct uihashhead *uipp; + struct uidinfo *uip; + + uipp = UIHASH(uid); + LIST_FOREACH(uip, uipp, ui_hash) + if (uip->ui_uid == uid) + break; + + return (uip); +} + +static struct uidinfo * +uicreate(uid) + uid_t uid; +{ + struct uidinfo *uip, *norace; + + MALLOC(uip, struct uidinfo *, sizeof(*uip), M_UIDINFO, M_NOWAIT); + if (uip == NULL) { + MALLOC(uip, struct uidinfo *, sizeof(*uip), M_UIDINFO, M_WAITOK); + /* + * if we M_WAITOK we must look afterwards or risk + * redundant entries + */ + norace = uilookup(uid); + if (norace != NULL) { + FREE(uip, M_UIDINFO); + return (norace); + } + } + LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash); + uip->ui_uid = uid; + uip->ui_proccnt = 0; + uip->ui_sbsize = 0; + uip->ui_ref = 0; + return (uip); +} + +struct uidinfo * +uifind(uid) + uid_t uid; +{ + struct uidinfo *uip; + + uip = uilookup(uid); + if (uip == NULL) + uip = uicreate(uid); + uip->ui_ref++; + return (uip); +} + +int +uifree(uip) + struct uidinfo *uip; +{ + + if (--uip->ui_ref == 0) { + if (uip->ui_sbsize != 0) + /* XXX no %qd in kernel. Truncate. */ + panic("freeing uidinfo: uid = %d, sbsize = %ld", + uip->ui_uid, (long)uip->ui_sbsize); + if (uip->ui_proccnt != 0) + panic("freeing uidinfo: uid = %d, proccnt = %ld", + uip->ui_uid, uip->ui_proccnt); + LIST_REMOVE(uip, ui_hash); + FREE(uip, M_UIDINFO); + return (1); + } + return (0); +} + +/* + * Change the count associated with number of processes + * a given user is using. When 'max' is 0, don't enforce a limit + */ +int +chgproccnt(uip, diff, max) + struct uidinfo *uip; + int diff; + int max; +{ + /* don't allow them to exceed max, but allow subtraction */ + if (diff > 0 && uip->ui_proccnt + diff > max && max != 0) + return (0); + uip->ui_proccnt += diff; + if (uip->ui_proccnt < 0) + panic("negative proccnt for uid = %d", uip->ui_uid); + return (1); +} + +/* + * Change the total socket buffer size a user has used. + */ +int +chgsbsize(uip, hiwat, to, max) + struct uidinfo *uip; + u_long *hiwat; + u_long to; + rlim_t max; +{ + rlim_t new; + int s; + + s = splnet(); + new = uip->ui_sbsize + to - *hiwat; + /* don't allow them to exceed max, but allow subtraction */ + if (to > *hiwat && new > max) { + splx(s); + return (0); + } + uip->ui_sbsize = new; + *hiwat = to; + if (uip->ui_sbsize < 0) + panic("negative sbsize for uid = %d", uip->ui_uid); + splx(s); + return (1); +} diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index 80164366d232..4ed67e59d53d 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -427,7 +427,7 @@ sbreserve(sb, cc, so, p) */ if ((u_quad_t)cc > (u_quad_t)sb_max * MCLBYTES / (MSIZE + MCLBYTES)) return (0); - if (!chgsbsize(so->so_cred->cr_uid, &sb->sb_hiwat, cc, + if (!chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, cc, p ? p->p_rlimit[RLIMIT_SBSIZE].rlim_cur : RLIM_INFINITY)) { return (0); } @@ -447,7 +447,8 @@ sbrelease(sb, so) { sbflush(sb); - (void)chgsbsize(so->so_cred->cr_uid, &sb->sb_hiwat, 0, RLIM_INFINITY); + (void)chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, 0, + RLIM_INFINITY); sb->sb_mbmax = 0; } diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 7cd4ca759654..5d84d7eba5d4 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -190,10 +190,10 @@ sodealloc(so) so->so_gencnt = ++so_gencnt; if (so->so_rcv.sb_hiwat) - (void)chgsbsize(so->so_cred->cr_uid, + (void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_rcv.sb_hiwat, 0, RLIM_INFINITY); if (so->so_snd.sb_hiwat) - (void)chgsbsize(so->so_cred->cr_uid, + (void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat, 0, RLIM_INFINITY); if (so->so_accf != NULL) { if (so->so_accf->so_accept_filter != NULL && diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c index 80164366d232..4ed67e59d53d 100644 --- a/sys/kern/uipc_socket2.c +++ b/sys/kern/uipc_socket2.c @@ -427,7 +427,7 @@ sbreserve(sb, cc, so, p) */ if ((u_quad_t)cc > (u_quad_t)sb_max * MCLBYTES / (MSIZE + MCLBYTES)) return (0); - if (!chgsbsize(so->so_cred->cr_uid, &sb->sb_hiwat, cc, + if (!chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, cc, p ? p->p_rlimit[RLIMIT_SBSIZE].rlim_cur : RLIM_INFINITY)) { return (0); } @@ -447,7 +447,8 @@ sbrelease(sb, so) { sbflush(sb); - (void)chgsbsize(so->so_cred->cr_uid, &sb->sb_hiwat, 0, RLIM_INFINITY); + (void)chgsbsize(so->so_cred->cr_uidinfo, &sb->sb_hiwat, 0, + RLIM_INFINITY); sb->sb_mbmax = 0; } diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index c4a332671413..0e028e763036 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -238,7 +238,7 @@ uipc_rcvd(struct socket *so, int flags) unp->unp_mbcnt = so->so_rcv.sb_mbcnt; newhiwat = so2->so_snd.sb_hiwat + unp->unp_cc - so->so_rcv.sb_cc; - (void)chgsbsize(so2->so_cred->cr_uid, &so2->so_snd.sb_hiwat, + (void)chgsbsize(so2->so_cred->cr_uidinfo, &so2->so_snd.sb_hiwat, newhiwat, RLIM_INFINITY); unp->unp_cc = so->so_rcv.sb_cc; sowwakeup(so2); @@ -347,7 +347,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, unp->unp_conn->unp_mbcnt = so2->so_rcv.sb_mbcnt; newhiwat = so->so_snd.sb_hiwat - (so2->so_rcv.sb_cc - unp->unp_conn->unp_cc); - (void)chgsbsize(so->so_cred->cr_uid, &so->so_snd.sb_hiwat, + (void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat, newhiwat, RLIM_INFINITY); unp->unp_conn->unp_cc = so2->so_rcv.sb_cc; sorwakeup(so2); diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index ea26dbd21705..861e7e376239 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -673,6 +673,8 @@ aio_daemon(void *uproc) mycp->p_fd = NULL; mycp->p_ucred = crcopy(mycp->p_ucred); mycp->p_ucred->cr_uid = 0; + uifree(mycp->p_ucred->cr_uidinfo); + mycp->p_ucred->cr_uidinfo = uifind(0); mycp->p_ucred->cr_ngroups = 1; mycp->p_ucred->cr_groups[0] = 1; diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 9865d97244ae..4173fea63a58 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -312,6 +312,7 @@ struct pcred { gid_t p_rgid; /* Real group id. */ gid_t p_svgid; /* Saved effective group id. */ int p_refcnt; /* Number of references. */ + struct uidinfo *p_uidinfo; /* Per uid resource consumption */ }; @@ -427,8 +428,6 @@ struct pgrp *pgfind __P((pid_t)); /* Find process group by id. */ struct vm_zone; extern struct vm_zone *proc_zone; -int chgproccnt __P((uid_t uid, int diff, int max)); -int chgsbsize __P((uid_t uid, u_long *hiwat, u_long to, rlim_t max)); int enterpgrp __P((struct proc *p, pid_t pgid, int mksess)); void fixjobc __P((struct proc *p, struct pgrp *pgrp, int entering)); int inferior __P((struct proc *p)); diff --git a/sys/sys/resourcevar.h b/sys/sys/resourcevar.h index 75a8f53994be..8931f749bed3 100644 --- a/sys/sys/resourcevar.h +++ b/sys/sys/resourcevar.h @@ -38,6 +38,7 @@ #define _SYS_RESOURCEVAR_H_ #include +#include /* * Kernel per-process accounting / statistics @@ -80,18 +81,37 @@ struct plimit { rlim_t p_cpulimit; /* current cpu limit in usec */ }; +/* + * Per uid resource consumption + */ +struct uidinfo { + LIST_ENTRY(uidinfo) ui_hash; + rlim_t ui_sbsize; /* socket buffer space consumed */ + long ui_proccnt; /* number of processes */ + uid_t ui_uid; /* uid */ + u_short ui_ref; /* reference count */ +}; + #ifdef _KERNEL +#define uihold(uip) (uip)->ui_ref++ struct proc; void addupc_intr __P((struct proc *p, u_long pc, u_int ticks)); void addupc_task __P((struct proc *p, u_long pc, u_int ticks)); void calcru __P((struct proc *p, struct timeval *up, struct timeval *sp, struct timeval *ip)); +int chgproccnt __P((struct uidinfo *uip, int diff, int max)); +int chgsbsize __P((struct uidinfo *uip, u_long *hiwat, u_long to, + rlim_t max)); int fuswintr __P((void *base)); struct plimit *limcopy __P((struct plimit *lim)); void ruadd __P((struct rusage *ru, struct rusage *ru2)); int suswintr __P((void *base, int word)); +struct uidinfo + *uifind __P((uid_t uid)); +int uifree __P((struct uidinfo *uip)); +void uihashinit __P((void)); #endif #endif /* !_SYS_RESOURCEVAR_H_ */ diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h index 256119ce2757..e667dbe476b4 100644 --- a/sys/sys/ucred.h +++ b/sys/sys/ucred.h @@ -48,6 +48,7 @@ struct ucred { uid_t cr_uid; /* effective user id */ short cr_ngroups; /* number of groups */ gid_t cr_groups[NGROUPS]; /* groups */ + struct uidinfo *cr_uidinfo; /* per uid resource consumption */ }; #define cr_gid cr_groups[0] #define NOCRED ((struct ucred *)0) /* no credential available */ @@ -56,6 +57,7 @@ struct ucred { #ifdef _KERNEL #define crhold(cr) (cr)->cr_ref++ +void change_euid __P((struct proc *p, uid_t euid)); struct ucred *crcopy __P((struct ucred *cr)); struct ucred *crdup __P((struct ucred *cr)); void crfree __P((struct ucred *cr));