summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/init_main.c4
-rw-r--r--sys/kern/kern_exec.c3
-rw-r--r--sys/kern/kern_exit.c3
-rw-r--r--sys/kern/kern_fork.c4
-rw-r--r--sys/kern/kern_proc.c137
-rw-r--r--sys/kern/kern_prot.c90
-rw-r--r--sys/kern/kern_resource.c142
-rw-r--r--sys/kern/uipc_sockbuf.c5
-rw-r--r--sys/kern/uipc_socket.c4
-rw-r--r--sys/kern/uipc_socket2.c5
-rw-r--r--sys/kern/uipc_usrreq.c4
-rw-r--r--sys/kern/vfs_aio.c2
-rw-r--r--sys/sys/proc.h3
-rw-r--r--sys/sys/resourcevar.h20
-rw-r--r--sys/sys/ucred.h2
15 files changed, 258 insertions, 170 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 1a2644b..6d0d915 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 67def00..5f6d2be 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -43,6 +43,7 @@
#include <sys/pioctl.h>
#include <sys/malloc.h>
#include <sys/namei.h>
+#include <sys/resourcevar.h>
#include <sys/sysent.h>
#include <sys/shm.h>
#include <sys/sysctl.h>
@@ -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 26e093b..df71fe0 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 9d3c68e..f24c97e 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 6a94bf7..7ec2628 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 4ce571d..8c21107 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -53,10 +53,13 @@
#include <sys/proc.h>
#include <sys/malloc.h>
#include <sys/pioctl.h>
+#include <sys/resourcevar.h>
#include <sys/sysctl.h>
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 b3c2ec6..4956e51 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -46,6 +46,7 @@
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/file.h>
+#include <sys/kernel.h>
#include <sys/resourcevar.h>
#include <sys/malloc.h>
#include <sys/proc.h>
@@ -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 8016436..4ed67e5 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 7cd4ca7..5d84d7e 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 8016436..4ed67e5 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 c4a3326..0e028e7 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 ea26dbd..861e7e3 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 9865d97..4173fea 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 75a8f53..8931f74 100644
--- a/sys/sys/resourcevar.h
+++ b/sys/sys/resourcevar.h
@@ -38,6 +38,7 @@
#define _SYS_RESOURCEVAR_H_
#include <sys/resource.h>
+#include <sys/queue.h>
/*
* 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 256119c..e667dbe 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));
OpenPOWER on IntegriCloud