Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 25 Nov 2000 04:17:47 -0800
From:      Alfred Perlstein <bright@wintelcom.net>
To:        smp@freebsd.org
Subject:   uidinfo patches, review please.
Message-ID:  <20001125041747.I8051@fw.wintelcom.net>

next in thread | raw e-mail | index | archive | help
Protect the uidinfo structures.

My only concern is that I must now include sys/mutex.h in
sys/resourcevar.h, I didn't notice any userland utils using
this file, I'm going to try to do a buildworld.

A kernel with this patch boots and seems to run multiuser
fine.


Index: kern/kern_resource.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_resource.c,v
retrieving revision 1.65
diff -u -r1.65 kern_resource.c
--- kern/kern_resource.c	2000/11/22 07:41:58	1.65
+++ kern/kern_resource.c	2000/11/25 12:16:02
@@ -64,6 +64,7 @@
 
 static MALLOC_DEFINE(M_UIDINFO, "uidinfo", "uidinfo structures");
 #define	UIHASH(uid)	(&uihashtbl[(uid) & uihash])
+static struct mtx uidhash_mtx;
 static LIST_HEAD(uihashhead, uidinfo) *uihashtbl;
 static u_long uihash;		/* size of hash table - 1 */
 
@@ -663,9 +664,15 @@
 void
 uihashinit()
 {
+
 	uihashtbl = hashinit(maxproc / 16, M_UIDINFO, &uihash);
+	mtx_init(&uidhash_mtx, "uidinfo hash", MTX_DEF);
 }
 
+/*
+ * lookup a uidinfo struct for the parameter uid.
+ * uidhash_mtx must be locked.
+ */
 static struct uidinfo *
 uilookup(uid)
 	uid_t uid;
@@ -673,6 +680,7 @@
 	struct	uihashhead *uipp;
 	struct	uidinfo *uip;
 
+	mtx_assert(&uidhash_mtx, MA_OWNED);
 	uipp = UIHASH(uid);
 	LIST_FOREACH(uip, uipp, ui_hash)
 		if (uip->ui_uid == uid)
@@ -681,43 +689,42 @@
 	return (uip);
 }
 
+/*
+ * Create a uidinfo struct for the parameter uid.
+ * uidhash_mtx must be locked.
+ */
 static struct uidinfo *
 uicreate(uid)
 	uid_t uid;
 {
-	struct	uidinfo *uip, *norace;
+	struct	uidinfo *uip;
 
-	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);
-		}
-	}
+	mtx_assert(&uidhash_mtx, MA_OWNED);
+	MALLOC(uip, struct uidinfo *, sizeof(*uip), M_UIDINFO, M_WAITOK);
 	LIST_INSERT_HEAD(UIHASH(uid), uip, ui_hash);
 	uip->ui_uid = uid;
 	uip->ui_proccnt = 0;
 	uip->ui_sbsize = 0;
 	uip->ui_ref = 0;
+	mtx_init(&uip->ui_mtx, "uidinfo struct", MTX_DEF);
 	return (uip);
 }
 
+/*
+ * find or allocate a struct uidinfo for a particular uid
+ */
 struct uidinfo *
 uifind(uid)
 	uid_t uid;
 {
 	struct	uidinfo *uip;
 
+	mtx_enter(&uidhash_mtx, MTX_DEF);
 	uip = uilookup(uid);
 	if (uip == NULL)
 		uip = uicreate(uid);
-	uip->ui_ref++;
+	uihold(uip);
+	mtx_exit(&uidhash_mtx, MTX_DEF);
 	return (uip);
 }
 
@@ -726,6 +733,8 @@
 	struct	uidinfo *uip;
 {
 
+	mtx_enter(&uidhash_mtx, MTX_DEF);
+	mtx_enter(&uip->ui_mtx, MTX_DEF);
 	if (--uip->ui_ref == 0) {
 		if (uip->ui_sbsize != 0)
 			/* XXX no %qd in kernel.  Truncate. */
@@ -735,9 +744,13 @@
 			printf("freeing uidinfo: uid = %d, proccnt = %ld\n",
 			    uip->ui_uid, uip->ui_proccnt);
 		LIST_REMOVE(uip, ui_hash);
+		mtx_destroy(&uip->ui_mtx);
+		mtx_exit(&uidhash_mtx, MTX_DEF);
 		FREE(uip, M_UIDINFO);
 		return (1);
 	}
+	mtx_exit(&uip->ui_mtx, MTX_DEF);
+	mtx_exit(&uidhash_mtx, MTX_DEF);
 	return (0);
 }
 
@@ -751,12 +764,17 @@
 	int	diff;
 	int	max;
 {
+
+	mtx_enter(&uip->ui_mtx, MTX_DEF);
 	/* don't allow them to exceed max, but allow subtraction */
-	if (diff > 0 && uip->ui_proccnt + diff > max && max != 0)
+	if (diff > 0 && uip->ui_proccnt + diff > max && max != 0) {
+		mtx_exit(&uip->ui_mtx, MTX_DEF);
 		return (0);
+	}
 	uip->ui_proccnt += diff;
 	if (uip->ui_proccnt < 0)
 		printf("negative proccnt for uid = %d\n", uip->ui_uid);
+	mtx_exit(&uip->ui_mtx, MTX_DEF);
 	return (1);
 }
 
@@ -773,11 +791,14 @@
 	rlim_t new;
 	int s;
 
+	mtx_enter(&uip->ui_mtx, MTX_DEF);
+
 	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);
+		mtx_exit(&uip->ui_mtx, MTX_DEF);
 		return (0);
 	}
 	uip->ui_sbsize = new;
@@ -785,5 +806,6 @@
 	if (uip->ui_sbsize < 0)
 		printf("negative sbsize for uid = %d\n", uip->ui_uid);
 	splx(s);
+	mtx_exit(&uip->ui_mtx, MTX_DEF);
 	return (1);
 }
Index: sys/resourcevar.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/resourcevar.h,v
retrieving revision 1.17
diff -u -r1.17 resourcevar.h
--- sys/resourcevar.h	2000/09/05 22:11:12	1.17
+++ sys/resourcevar.h	2000/11/25 12:16:03
@@ -40,6 +40,9 @@
 #include <sys/resource.h>
 #include <sys/queue.h>
 
+#include <sys/mutex.h>	/* XXX */
+
+
 /*
  * Kernel per-process accounting / statistics
  * (not necessarily resident except when running).
@@ -90,10 +93,17 @@
 	long	ui_proccnt;		/* number of processes */
 	uid_t	ui_uid;			/* uid */
 	u_short	ui_ref;			/* reference count */
+	struct mtx	ui_mtx;		/* protect counts */
 };
 
 #ifdef _KERNEL
-#define uihold(uip)	(uip)->ui_ref++
+#define uihold(uip)	\
+	do {			\
+		mtx_enter(&(uip)->ui_mtx, MTX_DEF);	\
+		(uip)->ui_ref++;					\
+		mtx_exit(&(uip)->ui_mtx, MTX_DEF);	\
+	} while(0)
+
 struct proc;
 
 void	 addupc_intr __P((struct proc *p, u_long pc, u_int ticks));

-- 
-Alfred Perlstein - [bright@wintelcom.net|alfred@freebsd.org]
"I have the heart of a child; I keep it in a jar on my desk."


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-smp" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001125041747.I8051>