Date: Mon, 27 Sep 1999 20:12:19 GMT From: abb@zenon.net To: FreeBSD-gnats-submit@freebsd.org Subject: kern/13997: RLIMIT_NPROC works unadequately for jails (patch included) Message-ID: <199909272012.UAA13312@abb.zenon.net>
index | next in thread | raw e-mail
>Number: 13997
>Category: kern
>Synopsis: RLIMIT_NPROC works unadequately for jails (patch included)
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Mon Sep 27 09:20:01 PDT 1999
>Closed-Date:
>Last-Modified:
>Originator: Alexander Bezroutchko <abb@zenon.net>
>Release: FreeBSD 4.0-CURRENT i386
>Organization:
Zenon NSP
>Environment:
4.0-19990918-CURRENT
>Description:
The fork() syscall checks RLIMIT_NPROC resource limit using system-wide
table `uihashtbl'. So limitation on number of running processes will work
unadequately if processes run in different jails but have equal uids.
>How-To-Repeat:
Run two shells with equal uids (not root) in different jails with
RLIMIT_NPROC set to 5. Invoke 3 subshells in one jail. Now it is
impossible to run any subprocess in shell in another jail because
fork fails.
>Fix:
Create private `uihashtbl' for each jail.
diff -c -r sys/jail.h.orig sys/jail.h
*** sys/jail.h.orig Mon Sep 27 11:57:59 1999
--- sys/jail.h Mon Sep 27 14:00:18 1999
***************
*** 29,34 ****
--- 29,36 ----
MALLOC_DECLARE(M_PRISON);
#endif
+ #include <sys/proc.h>
+
/*
* This structure describes a prison. It is pointed to by all struct
* proc's of the inmates. pr_ref keeps track of them and is used to
***************
*** 40,45 ****
--- 42,49 ----
char pr_host[MAXHOSTNAMELEN];
u_int32_t pr_ip;
void *pr_linux;
+ struct uihashhead *pr_uihashtbl;
+ u_long pr_uihash;
};
#endif /* !KERNEL */
diff -c -r sys/proc.h.orig sys/proc.h
*** sys/proc.h.orig Mon Sep 27 11:58:00 1999
--- sys/proc.h Mon Sep 27 12:21:24 1999
***************
*** 107,112 ****
--- 107,116 ----
*/
struct jail;
+ struct prison;
+
+ struct uidinfo;
+ LIST_HEAD(uihashhead, uidinfo);
struct proc {
TAILQ_ENTRY(proc) p_procq; /* run/sleep queue. */
***************
*** 373,379 ****
struct vm_zone;
extern struct vm_zone *proc_zone;
! int chgproccnt __P((uid_t uid, int diff));
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));
--- 377,383 ----
struct vm_zone;
extern struct vm_zone *proc_zone;
! int chgproccnt __P((const struct prison *prison, uid_t uid, int diff));
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 -c -r kern/init_main.c.orig kern/init_main.c
*** kern/init_main.c.orig Mon Sep 27 11:57:11 1999
--- kern/init_main.c Mon Sep 27 12:05:39 1999
***************
*** 396,402 ****
/*
* Charge root for one process.
*/
! (void)chgproccnt(0, 1);
/*
* Initialize the current process pointer (curproc) before
--- 396,402 ----
/*
* Charge root for one process.
*/
! (void)chgproccnt(NULL, 0, 1);
/*
* Initialize the current process pointer (curproc) before
diff -c -r kern/kern_exit.c.orig kern/kern_exit.c
*** kern/kern_exit.c.orig Mon Sep 27 11:57:11 1999
--- kern/kern_exit.c Mon Sep 27 12:57:55 1999
***************
*** 488,494 ****
/*
* Decrement the count of procs running with this uid.
*/
! (void)chgproccnt(p->p_cred->p_ruid, -1);
/*
* Release reference to text vnode
--- 488,494 ----
/*
* Decrement the count of procs running with this uid.
*/
! (void)chgproccnt(p->p_prison, p->p_cred->p_ruid, -1);
/*
* Release reference to text vnode
***************
*** 509,514 ****
--- 509,524 ----
* Destroy empty prisons
*/
if (p->p_prison && !--p->p_prison->pr_ref) {
+ #ifdef DIAGNOSTIC
+ u_long i;
+ struct prison *pr = p->p_prison;
+ for(i = 0; i <= pr->pr_uihash; i++) {
+ if (!LIST_EMPTY(&pr->pr_uihashtbl[i])) {
+ panic("pr_uihashtbl not empty");
+ }
+ }
+ #endif
+ FREE(p->p_prison->pr_uihashtbl, M_PRISON);
if (p->p_prison->pr_linux != NULL)
FREE(p->p_prison->pr_linux, M_PRISON);
FREE(p->p_prison, M_PRISON);
diff -c -r kern/kern_fork.c.orig kern/kern_fork.c
*** kern/kern_fork.c.orig Mon Sep 27 11:57:11 1999
--- kern/kern_fork.c Mon Sep 27 15:06:34 1999
***************
*** 222,230 ****
* 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);
/*
* Back out the process count
*/
--- 222,230 ----
* Increment the count of procs running with this uid. Don't allow
* a nonprivileged user to exceed their current limit.
*/
! count = chgproccnt(p1->p_prison, uid, 1);
if (uid != 0 && count > p1->p_rlimit[RLIMIT_NPROC].rlim_cur) {
! (void)chgproccnt(p1->p_prison, uid, -1);
/*
* Back out the process count
*/
diff -c -r kern/kern_jail.c.orig kern/kern_jail.c
*** kern/kern_jail.c.orig Mon Sep 27 11:57:11 1999
--- kern/kern_jail.c Mon Sep 27 12:52:01 1999
***************
*** 58,63 ****
--- 58,69 ----
pr->pr_ref++;
p->p_prison = pr;
p->p_flag |= P_JAILED;
+
+ /* The process is being jailed. Assume nested jails are not allowed. */
+ /* XXX Perhaps the size of pr_uihashtbl should be decreased */
+ pr->pr_uihashtbl = hashinit(maxproc / 16, M_PRISON, &pr->pr_uihash);
+ chgproccnt(NULL, p->p_cred->p_ruid, -1);
+ chgproccnt(pr, p->p_cred->p_ruid, 1);
return (0);
bail:
diff -c -r kern/kern_proc.c.orig kern/kern_proc.c
*** kern/kern_proc.c.orig Mon Sep 27 11:57:12 1999
--- kern/kern_proc.c Mon Sep 27 13:10:02 1999
***************
*** 49,54 ****
--- 49,55 ----
#include <vm/vm_map.h>
#include <sys/user.h>
#include <vm/vm_zone.h>
+ #include <sys/jail.h>
static MALLOC_DEFINE(M_PGRP, "pgrp", "process group header");
MALLOC_DEFINE(M_SESSION, "session", "session header");
***************
*** 65,72 ****
uid_t ui_uid;
long ui_proccnt;
};
! #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));
--- 66,73 ----
uid_t ui_uid;
long ui_proccnt;
};
! #define UIHASH(uihashtbl, uihash, uid) (&uihashtbl[(uid) & uihash])
! static struct uihashhead *uihashtbl;
static u_long uihash; /* size of hash table - 1 */
static void orphanpg __P((struct pgrp *pg));
***************
*** 102,115 ****
* a given user is using.
*/
int
! chgproccnt(uid, diff)
uid_t uid;
int diff;
{
register struct uidinfo *uip;
register struct uihashhead *uipp;
! uipp = UIHASH(uid);
for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next)
if (uip->ui_uid == uid)
break;
--- 103,120 ----
* a given user is using.
*/
int
! chgproccnt(prison, uid, diff)
! const struct prison *prison;
uid_t uid;
int diff;
{
register struct uidinfo *uip;
register struct uihashhead *uipp;
! if (prison)
! uipp = UIHASH(prison->pr_uihashtbl, prison->pr_uihash, uid);
! else
! uipp = UIHASH(uihashtbl, uihash, uid);
for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next)
if (uip->ui_uid == uid)
break;
diff -c -r kern/kern_prot.c.orig kern/kern_prot.c
*** kern/kern_prot.c.orig Mon Sep 27 11:57:12 1999
--- kern/kern_prot.c Mon Sep 27 12:08:19 1999
***************
*** 414,421 ****
* Transfer proc count to new user.
*/
if (uid != pc->p_ruid) {
! (void)chgproccnt(pc->p_ruid, -1);
! (void)chgproccnt(uid, 1);
}
/*
* Set real uid
--- 414,421 ----
* Transfer proc count to new user.
*/
if (uid != pc->p_ruid) {
! (void)chgproccnt(p->p_prison, pc->p_ruid, -1);
! (void)chgproccnt(p->p_prison, uid, 1);
}
/*
* Set real uid
***************
*** 663,670 ****
setsugid(p);
}
if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
! (void)chgproccnt(pc->p_ruid, -1);
! (void)chgproccnt(ruid, 1);
pc->p_ruid = ruid;
setsugid(p);
}
--- 663,670 ----
setsugid(p);
}
if (ruid != (uid_t)-1 && pc->p_ruid != ruid) {
! (void)chgproccnt(p->p_prison, pc->p_ruid, -1);
! (void)chgproccnt(p->p_prison, ruid, 1);
pc->p_ruid = ruid;
setsugid(p);
}
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199909272012.UAA13312>
