summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/compat/svr4/svr4_misc.c2
-rw-r--r--sys/kern/init_main.c2
-rw-r--r--sys/kern/kern_exit.c2
-rw-r--r--sys/kern/kern_fork.c7
-rw-r--r--sys/kern/kern_proc.c146
-rw-r--r--sys/kern/kern_prot.c12
-rw-r--r--sys/kern/uipc_sockbuf.c8
-rw-r--r--sys/kern/uipc_socket.c4
-rw-r--r--sys/kern/uipc_socket2.c8
-rw-r--r--sys/kern/uipc_usrreq.c5
-rw-r--r--sys/svr4/svr4_misc.c2
-rw-r--r--sys/sys/proc.h4
12 files changed, 120 insertions, 82 deletions
diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c
index d06d4fc..81b7e65 100644
--- a/sys/compat/svr4/svr4_misc.c
+++ b/sys/compat/svr4/svr4_misc.c
@@ -1260,7 +1260,7 @@ loop:
/*
* Decrement the count of procs running with this uid.
*/
- (void)chgproccnt(q->p_cred->p_ruid, -1);
+ (void)chgproccnt(q->p_cred->p_ruid, -1, 0);
/*
* Free up credentials.
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index b732b90..442d266 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -387,7 +387,7 @@ proc0_init(dummy)
/*
* Charge root for one process.
*/
- (void)chgproccnt(0, 1);
+ (void)chgproccnt(0, 1, 0);
/*
* Initialize the current process pointer (curproc) before
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 9115f97..22e25b1 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);
+ (void)chgproccnt(p->p_cred->p_ruid, -1, 0);
/*
* Release reference to text vnode
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 62296b2..58e7ecc 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -183,7 +183,7 @@ fork1(p1, flags, procp)
struct proc *p2, *pptr;
uid_t uid;
struct proc *newproc;
- int count;
+ int ok;
static int pidchecked = 0;
struct forklist *ep;
@@ -245,9 +245,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.
*/
- count = chgproccnt(uid, 1);
- if (uid != 0 && count > p1->p_rlimit[RLIMIT_NPROC].rlim_cur) {
- (void)chgproccnt(uid, -1);
+ ok = chgproccnt(uid, 1, p1->p_rlimit[RLIMIT_NPROC].rlim_cur);
+ if (uid != 0 && !ok) {
/*
* Back out the process count
*/
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index df9f1c5..72069d0 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -72,6 +72,10 @@ 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
*/
@@ -99,85 +103,119 @@ procinit()
}
/*
- * Change the count associated with number of processes
- * a given user is using.
+ * find/create a uidinfo struct for the uid passed in
*/
-int
-chgproccnt(uid, diff)
- uid_t uid;
- int diff;
+static struct uidinfo *
+uifind(uid)
+ uid_t uid;
{
- register struct uidinfo *uip;
- register struct uihashhead *uipp;
+ struct uihashhead *uipp;
+ struct uidinfo *uip;
uipp = UIHASH(uid);
LIST_FOREACH(uip, uipp, ui_hash)
if (uip->ui_uid == uid)
break;
- if (uip) {
- uip->ui_proccnt += diff;
- if (uip->ui_proccnt < 0)
- panic("chgproccnt: procs < 0");
- if (uip->ui_proccnt > 0 || uip->ui_sbsize > 0)
- return (uip->ui_proccnt);
+
+ 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 (0);
+ return (1);
}
- if (diff <= 0) {
- if (diff == 0)
- return(0);
- panic("chgproccnt: lost user");
+ 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);
}
- MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK);
- LIST_INSERT_HEAD(uipp, uip, ui_hash);
- uip->ui_uid = uid;
- uip->ui_proccnt = diff;
- uip->ui_sbsize = 0;
- return (diff);
+ uip->ui_proccnt += diff;
+ (void)uifree(uip);
+ return (1);
}
/*
* Change the total socket buffer size a user has used.
*/
-rlim_t
-chgsbsize(uid, diff)
+int
+chgsbsize(uid, diff, max)
uid_t uid;
rlim_t diff;
+ rlim_t max;
{
- register struct uidinfo *uip;
- register struct uihashhead *uipp;
-
- uipp = UIHASH(uid);
- LIST_FOREACH(uip, uipp, ui_hash)
- if (uip->ui_uid == uid)
- break;
- if (diff <= 0) {
- if (diff == 0)
- return (uip ? uip->ui_sbsize : 0);
- KASSERT(uip != NULL, ("uidinfo (%d) gone", uid));
- }
- if (uip) {
- uip->ui_sbsize += diff;
- if (uip->ui_sbsize == 0 && uip->ui_proccnt == 0) {
- LIST_REMOVE(uip, ui_hash);
- FREE(uip, M_PROC);
- return (0);
- }
- return (uip->ui_sbsize);
+ struct uidinfo *uip;
+
+ uip = uifind(uid);
+ if (diff < 0)
+ KASSERT(uip != NULL, ("reducing sbsize: 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_sbsize + diff > max) {
+ (void)uifree(uip);
+ return (0);
}
- MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK);
- LIST_INSERT_HEAD(uipp, uip, ui_hash);
- uip->ui_uid = uid;
- uip->ui_proccnt = 0;
- uip->ui_sbsize = diff;
- return (diff);
+ uip->ui_sbsize += diff;
+ (void)uifree(uip);
+ return (1);
}
/*
* Is p an inferior of the current process?
*/
-int
+inT
inferior(p)
register struct proc *p;
{
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index e001e2e..0a8ae2c 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -430,8 +430,8 @@ setuid(p, uap)
* Transfer proc count to new user.
*/
if (uid != pc->p_ruid) {
- (void)chgproccnt(pc->p_ruid, -1);
- (void)chgproccnt(uid, 1);
+ (void)chgproccnt(pc->p_ruid, -1, 0);
+ (void)chgproccnt(uid, 1, 0);
}
/*
* Set real uid
@@ -679,8 +679,8 @@ setreuid(p, uap)
setsugid(p);
}
if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
- (void)chgproccnt(pc->p_ruid, -1);
- (void)chgproccnt(ruid, 1);
+ (void)chgproccnt(pc->p_ruid, -1, 0);
+ (void)chgproccnt(ruid, 1, 0);
pc->p_ruid = ruid;
setsugid(p);
}
@@ -772,8 +772,8 @@ setresuid(p, uap)
setsugid(p);
}
if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
- (void)chgproccnt(pc->p_ruid, -1);
- (void)chgproccnt(ruid, 1);
+ (void)chgproccnt(pc->p_ruid, -1, 0);
+ (void)chgproccnt(ruid, 1, 0);
pc->p_ruid = ruid;
setsugid(p);
}
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index 42e02a5..beb8fe5 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -432,10 +432,10 @@ sbreserve(sb, cc, so, p)
if ((u_quad_t)cc > (u_quad_t)sb_max * MCLBYTES / (MSIZE + MCLBYTES))
return (0);
delta = (rlim_t)cc - sb->sb_hiwat;
- if (p && delta >= 0 && chgsbsize(so->so_cred->cr_uid, 0) + delta >
- p->p_rlimit[RLIMIT_SBSIZE].rlim_cur)
+ if (p && !chgsbsize(so->so_cred->cr_uid, delta,
+ p->p_rlimit[RLIMIT_SBSIZE].rlim_cur)) {
return (0);
- (void)chgsbsize(so->so_cred->cr_uid, delta);
+ }
sb->sb_hiwat = cc;
sb->sb_mbmax = min(cc * sb_efficiency, sb_max);
if (sb->sb_lowat > sb->sb_hiwat)
@@ -453,7 +453,7 @@ sbrelease(sb, so)
{
sbflush(sb);
- (void)chgsbsize(so->so_cred->cr_uid, -(rlim_t)sb->sb_hiwat);
+ (void)chgsbsize(so->so_cred->cr_uid, -(rlim_t)sb->sb_hiwat, RLIM_INFINITY);
sb->sb_hiwat = sb->sb_mbmax = 0;
}
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index c2d0ad7..4dffd3a 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -191,10 +191,10 @@ sodealloc(so)
so->so_gencnt = ++so_gencnt;
if (so->so_rcv.sb_hiwat)
(void)chgsbsize(so->so_cred->cr_uid,
- -(rlim_t)so->so_rcv.sb_hiwat);
+ -(rlim_t)so->so_rcv.sb_hiwat, RLIM_INFINITY);
if (so->so_snd.sb_hiwat)
(void)chgsbsize(so->so_cred->cr_uid,
- -(rlim_t)so->so_snd.sb_hiwat);
+ -(rlim_t)so->so_snd.sb_hiwat, RLIM_INFINITY);
if (so->so_accf != NULL) {
if (so->so_accf->so_accept_filter != NULL &&
so->so_accf->so_accept_filter->accf_destroy != NULL) {
diff --git a/sys/kern/uipc_socket2.c b/sys/kern/uipc_socket2.c
index 42e02a5..beb8fe5 100644
--- a/sys/kern/uipc_socket2.c
+++ b/sys/kern/uipc_socket2.c
@@ -432,10 +432,10 @@ sbreserve(sb, cc, so, p)
if ((u_quad_t)cc > (u_quad_t)sb_max * MCLBYTES / (MSIZE + MCLBYTES))
return (0);
delta = (rlim_t)cc - sb->sb_hiwat;
- if (p && delta >= 0 && chgsbsize(so->so_cred->cr_uid, 0) + delta >
- p->p_rlimit[RLIMIT_SBSIZE].rlim_cur)
+ if (p && !chgsbsize(so->so_cred->cr_uid, delta,
+ p->p_rlimit[RLIMIT_SBSIZE].rlim_cur)) {
return (0);
- (void)chgsbsize(so->so_cred->cr_uid, delta);
+ }
sb->sb_hiwat = cc;
sb->sb_mbmax = min(cc * sb_efficiency, sb_max);
if (sb->sb_lowat > sb->sb_hiwat)
@@ -453,7 +453,7 @@ sbrelease(sb, so)
{
sbflush(sb);
- (void)chgsbsize(so->so_cred->cr_uid, -(rlim_t)sb->sb_hiwat);
+ (void)chgsbsize(so->so_cred->cr_uid, -(rlim_t)sb->sb_hiwat, RLIM_INFINITY);
sb->sb_hiwat = sb->sb_mbmax = 0;
}
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 5c0e8238..38ac3b0 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -48,6 +48,7 @@
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
+#include <sys/resourcevar.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/un.h>
@@ -236,7 +237,7 @@ uipc_rcvd(struct socket *so, int flags)
unp->unp_mbcnt = so->so_rcv.sb_mbcnt;
so2->so_snd.sb_hiwat += unp->unp_cc - so->so_rcv.sb_cc;
(void)chgsbsize(so2->so_cred->cr_uid,
- (rlim_t)unp->unp_cc - so->so_rcv.sb_cc);
+ (rlim_t)unp->unp_cc - so->so_rcv.sb_cc, RLIM_INFINITY);
unp->unp_cc = so->so_rcv.sb_cc;
sowwakeup(so2);
break;
@@ -344,7 +345,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
so->so_snd.sb_hiwat -=
so2->so_rcv.sb_cc - unp->unp_conn->unp_cc;
(void)chgsbsize(so->so_cred->cr_uid,
- (rlim_t)unp->unp_conn->unp_cc - so2->so_rcv.sb_cc);
+ (rlim_t)unp->unp_conn->unp_cc - so2->so_rcv.sb_cc, RLIM_INFINITY);
unp->unp_conn->unp_cc = so2->so_rcv.sb_cc;
sorwakeup(so2);
m = 0;
diff --git a/sys/svr4/svr4_misc.c b/sys/svr4/svr4_misc.c
index d06d4fc..81b7e65 100644
--- a/sys/svr4/svr4_misc.c
+++ b/sys/svr4/svr4_misc.c
@@ -1260,7 +1260,7 @@ loop:
/*
* Decrement the count of procs running with this uid.
*/
- (void)chgproccnt(q->p_cred->p_ruid, -1);
+ (void)chgproccnt(q->p_cred->p_ruid, -1, 0);
/*
* Free up credentials.
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index af7f110..d215351 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -420,8 +420,8 @@ 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));
-rlim_t chgsbsize __P((uid_t uid, rlim_t diff));
+int chgproccnt __P((uid_t uid, int diff, int max));
+int chgsbsize __P((uid_t uid, rlim_t diff, 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));
OpenPOWER on IntegriCloud