Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Jul 2003 17:20:10 +0200 (CEST)
From:      Pawel Jakub Dawidek <nick@garage.freebsd.pl>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/54439: Protecting sysctls variables by given mutexes [PATCH].
Message-ID:  <20030713152010.ED4423ABB4C@milla.ask33.net>
Resent-Message-ID: <200307131520.h6DFKIgT079339@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         54439
>Category:       kern
>Synopsis:       Protecting sysctls variables by given mutexes [PATCH].
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jul 13 08:20:18 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator:     Pawel Jakub Dawidek
>Release:        FreeBSD 5.1-CURRENT i386
>Organization:
Pawel Jakub Dawidek
>Environment:
System: FreeBSD 5.1-CURRENT

>Description:
	For now variables used by sysctls cannot by protected with mutexes.
	Some variables in source are marked that they should be (for example
	security.jail.* from kern_jail.c).
>How-To-Repeat:

>Fix:
 	This patch adds code that will handle protecting selected sysctl
	variables with given mutexes. It also contains usage example for
	sysctls from security.jail.* node (kern_jail.c).
	New macros:
	- SYSCTL_OID_MTX(),
	- SYSCTL_ADD_OID_MTX(),
	- SYSCTL_STRING_MTX(),
	- SYSCTL_ADD_STRING_MTX(),
	- SYSCTL_INT_MTX(),
	- SYSCTL_ADD_INT_MTX(),
	- SYSCTL_UINT_MTX(),
	- SYSCTL_ADD_UINT_MTX(),
	- SYSCTL_LONG_MTX(),
	- SYSCTL_ADD_LONG_MTX(),
	- SYSCTL_ULONG_MTX(),
	- SYSCTL_ADD_ULONG_MTX(),
	- SYSCTL_OPAQUE_MTX(),
	- SYSCTL_ADD_OPAQUE_MTX(),
	- SYSCTL_STRUCT_MTX(),
	- SYSCTL_ADD_STRUCT_MTX(),
	- SYSCTL_OUT_MTX(),
	- OID_LOCK(),
	- OID_UNLOCK().

	Patch against FreeBSD 5.1-CURRENT, kern.osreldate: 501102.

diff -upr /usr/src/sys/kern/kern_jail.c src/sys/kern/kern_jail.c
--- /usr/src/sys/kern/kern_jail.c	Tue Jul  1 11:29:30 2003
+++ src/sys/kern/kern_jail.c	Sun Jul 13 15:24:05 2003
@@ -32,32 +32,33 @@ __FBSDID("$FreeBSD: src/sys/kern/kern_ja
 
 MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
 
+
+/* allprison, lastprid, and prisoncount are protected by allprison_mtx. */
+struct	prisonlist allprison;
+struct	mtx allprison_mtx;
+int	lastprid = 0;
+int	prisoncount = 0;
+
+
 SYSCTL_DECL(_security);
 SYSCTL_NODE(_security, OID_AUTO, jail, CTLFLAG_RW, 0,
     "Jail rules");
 
-mp_fixme("these variables need a lock")
-
+/* Those variables are protected by allprison_mtx mutex. */
 int	jail_set_hostname_allowed = 1;
-SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
-    &jail_set_hostname_allowed, 0,
+SYSCTL_INT_MTX(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
+    &jail_set_hostname_allowed, 0, &allprison_mtx,
     "Processes in jail can set their hostnames");
 
 int	jail_socket_unixiproute_only = 1;
-SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
-    &jail_socket_unixiproute_only, 0,
+SYSCTL_INT_MTX(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
+    &jail_socket_unixiproute_only, 0, &allprison_mtx,
     "Processes in jail are limited to creating UNIX/IPv4/route sockets only");
 
 int	jail_sysvipc_allowed = 0;
-SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
-    &jail_sysvipc_allowed, 0,
+SYSCTL_INT_MTX(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
+    &jail_sysvipc_allowed, 0, &allprison_mtx,
     "Processes in jail can use System V IPC primitives");
-
-/* allprison, lastprid, and prisoncount are protected by allprison_mtx. */
-struct	prisonlist allprison;
-struct	mtx allprison_mtx;
-int	lastprid = 0;
-int	prisoncount = 0;
 
 static void		 init_prison(void *);
 static struct prison	*prison_find(int);
diff -upr /usr/src/sys/kern/kern_sysctl.c src/sys/kern/kern_sysctl.c
--- /usr/src/sys/kern/kern_sysctl.c	Tue Jul  1 11:29:30 2003
+++ src/sys/kern/kern_sysctl.c	Sun Jul 13 16:30:02 2003
@@ -356,7 +356,8 @@ sysctl_remove_oid(struct sysctl_oid *oid
 struct sysctl_oid *
 sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
 	int number, const char *name, int kind, void *arg1, int arg2,
-	int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr)
+	int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, struct mtx *mtx,
+	const char *descr)
 {
 	struct sysctl_oid *oidp;
 	ssize_t len;
@@ -391,6 +392,7 @@ sysctl_add_oid(struct sysctl_ctx_list *c
 	oidp->oid_name = newname;
 	oidp->oid_handler = handler;
 	oidp->oid_kind = CTLFLAG_DYN | kind;
+	oidp->oid_mtx = mtx;
 	if ((kind & CTLTYPE) == CTLTYPE_NODE) {
 		/* Allocate space for children */
 		SYSCTL_CHILDREN(oidp) = malloc(sizeof(struct sysctl_oid_list),
@@ -788,19 +790,24 @@ sysctl_handle_int(SYSCTL_HANDLER_ARGS)
 	/*
 	 * Attempt to get a coherent snapshot by making a copy of the data.
 	 */
+	OID_LOCK(oidp);
 	if (arg1)
 		tmpout = *(int *)arg1;
 	else
 		tmpout = arg2;
-	error = SYSCTL_OUT(req, &tmpout, sizeof(int));
+	error = SYSCTL_OUT_MTX(req, &tmpout, sizeof(int),
+	    oidp->oid_mtx != NULL);
 
-	if (error || !req->newptr)
+	if (error || !req->newptr) {
+		OID_UNLOCK(oidp);
 		return (error);
+	}
 
 	if (!arg1)
 		error = EPERM;
 	else
 		error = SYSCTL_IN(req, arg1, sizeof(int));
+	OID_UNLOCK(oidp);
 	return (error);
 }
 
@@ -817,15 +824,22 @@ sysctl_handle_long(SYSCTL_HANDLER_ARGS)
 	/*
 	 * Attempt to get a coherent snapshot by making a copy of the data.
 	 */
-	if (!arg1)
+	OID_LOCK(oidp);
+	if (!arg1) {
+		OID_UNLOCK(oidp);
 		return (EINVAL);
+	}
 	tmpout = *(long *)arg1;
-	error = SYSCTL_OUT(req, &tmpout, sizeof(long));
+	error = SYSCTL_OUT_MTX(req, &tmpout, sizeof(long),
+	    oidp->oid_mtx != NULL);
 
-	if (error || !req->newptr)
+	if (error || !req->newptr) {
+		OID_UNLOCK(oidp);
 		return (error);
+	}
 
 	error = SYSCTL_IN(req, arg1, sizeof(long));
+	OID_UNLOCK(oidp);
 	return (error);
 }
 
@@ -847,20 +861,27 @@ sysctl_handle_string(SYSCTL_HANDLER_ARGS
 	 * Attempt to get a coherent snapshot by copying to a
 	 * temporary kernel buffer.
 	 */
+	OID_LOCK(oidp);
 retry:
 	outlen = strlen((char *)arg1)+1;
-	tmparg = malloc(outlen, M_SYSCTLTMP, M_WAITOK);
+	tmparg = malloc(outlen, M_SYSCTLTMP, M_NOWAIT);
+	if (tmparg == NULL) {
+		OID_UNLOCK(oidp);
+		return (ENOMEM);
+	}
 
 	if (strlcpy(tmparg, (char *)arg1, outlen) >= outlen) {
 		free(tmparg, M_SYSCTLTMP);
 		goto retry;
 	}
 
-	error = SYSCTL_OUT(req, tmparg, outlen);
+	error = SYSCTL_OUT_MTX(req, tmparg, outlen, oidp->oid_mtx != NULL);
 	free(tmparg, M_SYSCTLTMP);
 
-	if (error || !req->newptr)
+	if (error || !req->newptr) {
+		OID_UNLOCK(oidp);
 		return (error);
+	}
 
 	if ((req->newlen - req->newidx) >= arg2) {
 		error = EINVAL;
@@ -870,6 +891,7 @@ retry:
 		((char *)arg1)[arg2] = '\0';
 	}
 
+	OID_UNLOCK(oidp);
 	return (error);
 }
 
@@ -889,21 +911,26 @@ sysctl_handle_opaque(SYSCTL_HANDLER_ARGS
 	 * user space buffer or copying to a temporary kernel buffer
 	 * depending on the size of the data.
 	 */
+	OID_LOCK(oidp);
 	if (arg2 > PAGE_SIZE) {
 		sysctl_wire_old_buffer(req, arg2);
 		error = SYSCTL_OUT(req, arg1, arg2);
 	} else {
 		tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK);
 		bcopy(arg1, tmparg, arg2);
-		error = SYSCTL_OUT(req, tmparg, arg2);
+		error = SYSCTL_OUT_MTX(req, tmparg, arg2,
+		    oidp->oid_mtx != NULL);
 		free(tmparg, M_SYSCTLTMP);
 	}
 
-	if (error || !req->newptr)
+	if (error || !req->newptr) {
+		OID_UNLOCK(oidp);
 		return (error);
+	}
 
 	error = SYSCTL_IN(req, arg1, arg2);
 
+	OID_UNLOCK(oidp);
 	return (error);
 }
 
@@ -912,7 +939,8 @@ sysctl_handle_opaque(SYSCTL_HANDLER_ARGS
  * XXX: rather untested at this point
  */
 static int
-sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l)
+sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l,
+    int locked __unused)
 {
 	size_t i = 0;
 
@@ -1019,12 +1047,12 @@ kernel_sysctlbyname(struct thread *td, c
  * Transfer function to/from user space.
  */
 static int
-sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
+sysctl_old_user(struct sysctl_req *req, const void *p, size_t l, int locked)
 {
 	int error = 0;
 	size_t i = 0;
 
-	if (req->lock == 1 && req->oldptr)
+	if (req->lock == 1 && req->oldptr && !locked)
 		WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
 		    "sysctl_old_user()");
 	if (req->oldptr) {
diff -upr /usr/src/sys/sys/sysctl.h src/sys/sys/sysctl.h
--- /usr/src/sys/sys/sysctl.h	Tue Jul  1 11:30:18 2003
+++ src/sys/sys/sysctl.h	Sun Jul 13 16:37:28 2003
@@ -127,7 +127,8 @@ struct sysctl_req {
 	void		*oldptr;
 	size_t		oldlen;
 	size_t		oldidx;
-	int		(*oldfunc)(struct sysctl_req *, const void *, size_t);
+	int		(*oldfunc)(struct sysctl_req *, const void *, size_t,
+			    int);
 	void		*newptr;
 	size_t		newlen;
 	size_t		newidx;
@@ -140,6 +141,7 @@ SLIST_HEAD(sysctl_oid_list, sysctl_oid);
  * This describes one "oid" in the MIB tree.  Potentially more nodes can
  * be hidden behind it, expanded by the handler.
  */
+struct mtx;
 struct sysctl_oid {
 	struct sysctl_oid_list *oid_parent;
 	SLIST_ENTRY(sysctl_oid) oid_link;
@@ -151,11 +153,13 @@ struct sysctl_oid {
 	int 		(*oid_handler)(SYSCTL_HANDLER_ARGS);
 	const char	*oid_fmt;
 	int		oid_refcnt;
+	struct mtx	*oid_mtx;
 	const char	*descr;
 };
 
 #define SYSCTL_IN(r, p, l) (r->newfunc)(r, p, l)
-#define SYSCTL_OUT(r, p, l) (r->oldfunc)(r, p, l)
+#define SYSCTL_OUT(r, p, l) SYSCTL_OUT_MTX(r, p, l, 0)
+#define SYSCTL_OUT_MTX(r, p, l, m) (r->oldfunc)(r, p, l, m)
 
 int sysctl_handle_int(SYSCTL_HANDLER_ARGS);
 int sysctl_handle_long(SYSCTL_HANDLER_ARGS);
@@ -194,88 +198,129 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_e
 
 /* This constructs a "raw" MIB oid. */
 #define SYSCTL_OID(parent, nbr, name, kind, a1, a2, handler, fmt, descr) \
-	static struct sysctl_oid sysctl__##parent##_##name = {		 \
-		&sysctl_##parent##_children, { 0 },			 \
-		nbr, kind, a1, a2, #name, handler, fmt, 0, descr };	 \
+	SYSCTL_OID_MTX(parent, nbr, name, kind, a1, a2, handler, fmt,	\
+	    NULL, descr)
+/* Mutex that protects its value have to be given. */
+#define SYSCTL_OID_MTX(parent, nbr, name, kind, a1, a2, handler, fmt, mtx, descr) \
+	static struct sysctl_oid sysctl__##parent##_##name = {		\
+	    &sysctl_##parent##_children, { 0 }, nbr, kind, a1, a2,	\
+	    #name, handler, fmt, 0, mtx, descr };			\
 	DATA_SET(sysctl_set, sysctl__##parent##_##name)
 
 #define SYSCTL_ADD_OID(ctx, parent, nbr, name, kind, a1, a2, handler, fmt, descr) \
-	sysctl_add_oid(ctx, parent, nbr, name, kind, a1, a2, handler, fmt, descr)
+	SYSCTL_ADD_OID_MTX(ctx, parent, nbr, name, kind, a1, a2,	\
+	    handler, fmt, NULL, descr)
+#define SYSCTL_ADD_OID_MTX(ctx, parent, nbr, name, kind, a1, a2, handler, fmt, mtx, descr) \
+	sysctl_add_oid(ctx, parent, nbr, name, kind, a1, a2, handler,	\
+	    fmt, mtx, descr)
 
 /* This constructs a node from which other oids can hang. */
-#define SYSCTL_NODE(parent, nbr, name, access, handler, descr)		    \
-	struct sysctl_oid_list SYSCTL_NODE_CHILDREN(parent, name);	    \
-	SYSCTL_OID(parent, nbr, name, CTLTYPE_NODE|(access),		    \
-		   (void*)&SYSCTL_NODE_CHILDREN(parent, name), 0, handler, \
-		   "N", descr)
-
-#define SYSCTL_ADD_NODE(ctx, parent, nbr, name, access, handler, descr)	    \
-	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_NODE|(access),	    \
-	0, 0, handler, "N", descr)
+#define SYSCTL_NODE(parent, nbr, name, access, handler, descr)		\
+	struct sysctl_oid_list SYSCTL_NODE_CHILDREN(parent, name);	\
+	SYSCTL_OID(parent, nbr, name, CTLTYPE_NODE|(access),		\
+	    (void*)&SYSCTL_NODE_CHILDREN(parent, name), 0, handler, "N", descr)
+
+#define SYSCTL_ADD_NODE(ctx, parent, nbr, name, access, handler, descr)	\
+	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_NODE|(access), 0,\
+	    0, handler, "N", NULL, descr)
 
 /* Oid for a string.  len can be 0 to indicate '\0' termination. */
-#define SYSCTL_STRING(parent, nbr, name, access, arg, len, descr) \
-	SYSCTL_OID(parent, nbr, name, CTLTYPE_STRING|(access), \
-		arg, len, sysctl_handle_string, "A", descr)
+#define SYSCTL_STRING(parent, nbr, name, access, arg, len, descr)	\
+	SYSCTL_STRING_MTX(parent, nbr, name, access, arg, len, NULL, descr)
+#define SYSCTL_STRING_MTX(parent, nbr, name, access, arg, len, mtx, descr) \
+	SYSCTL_OID_MTX(parent, nbr, name, CTLTYPE_STRING|(access), arg,	\
+	    len, sysctl_handle_string, "A", mtx, descr)
 
 #define SYSCTL_ADD_STRING(ctx, parent, nbr, name, access, arg, len, descr)  \
-	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_STRING|(access),	    \
-	arg, len, sysctl_handle_string, "A", descr)
+	SYSCTL_ADD_STRING_MTX(ctx, parent, nbr, name, access, arg, len,	\
+	    NULL, descr)
+#define SYSCTL_ADD_STRING_MTX(ctx, parent, nbr, name, access, arg, len, mtx, descr)  \
+	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_STRING|(access),	\
+	    arg, len, sysctl_handle_string, "A", mtx, descr)
 
 /* Oid for an int.  If ptr is NULL, val is returned. */
 #define SYSCTL_INT(parent, nbr, name, access, ptr, val, descr) \
-	SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|(access), \
-		ptr, val, sysctl_handle_int, "I", descr)
-
-#define SYSCTL_ADD_INT(ctx, parent, nbr, name, access, ptr, val, descr)	    \
-	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_INT|(access),	    \
-	ptr, val, sysctl_handle_int, "I", descr)
+	SYSCTL_INT_MTX(parent, nbr, name, access, ptr, val, NULL, descr)
+#define SYSCTL_INT_MTX(parent, nbr, name, access, ptr, val, mtx, descr) \
+	SYSCTL_OID_MTX(parent, nbr, name, CTLTYPE_INT|(access), ptr,	\
+	    val, sysctl_handle_int, "I", mtx, descr)
+
+#define SYSCTL_ADD_INT(ctx, parent, nbr, name, access, ptr, val, descr)	\
+	SYSCTL_ADD_INT_MTX(ctx, parent, nbr, name, access, ptr, val,	\
+	    NULL, descr)
+#define SYSCTL_ADD_INT_MTX(ctx, parent, nbr, name, access, ptr, val, mtx, descr) \
+	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_INT|(access),	\
+	    ptr, val, sysctl_handle_int, "I", mtx, descr)
 
 /* Oid for an unsigned int.  If ptr is NULL, val is returned. */
-#define SYSCTL_UINT(parent, nbr, name, access, ptr, val, descr) \
-	SYSCTL_OID(parent, nbr, name, CTLTYPE_UINT|(access), \
-		ptr, val, sysctl_handle_int, "IU", descr)
-
-#define SYSCTL_ADD_UINT(ctx, parent, nbr, name, access, ptr, val, descr)    \
-	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_UINT|(access),	    \
-	ptr, val, sysctl_handle_int, "IU", descr)
+#define SYSCTL_UINT(parent, nbr, name, access, ptr, val, descr)		\
+	SYSCTL_UINT_MTX(parent, nbr, name, access, ptr, val, NULL, descr)
+#define SYSCTL_UINT_MTX(parent, nbr, name, access, ptr, val, mtx, descr) \
+	SYSCTL_OID_MTX(parent, nbr, name, CTLTYPE_UINT|(access), ptr,	\
+	    val, sysctl_handle_int, "IU", mtx, descr)
+
+#define SYSCTL_ADD_UINT(ctx, parent, nbr, name, access, ptr, val, descr) \
+	SYSCTL_ADD_UINT_MTX(ctx, parent, nbr, name, access, ptr, val,	\
+	    NULL, descr)
+#define SYSCTL_ADD_UINT_MTX(ctx, parent, nbr, name, access, ptr, val, mtx, descr) \
+	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_UINT|(access),	\
+	    ptr, val, sysctl_handle_int, "IU", mtx, descr)
 
 /* Oid for a long.  The pointer must be non NULL. */
 #define SYSCTL_LONG(parent, nbr, name, access, ptr, val, descr) \
-	SYSCTL_OID(parent, nbr, name, CTLTYPE_LONG|(access), \
-		ptr, val, sysctl_handle_long, "L", descr)
-
-#define SYSCTL_ADD_LONG(ctx, parent, nbr, name, access, ptr, descr)	    \
-	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_LONG|(access),	    \
-	ptr, 0, sysctl_handle_long, "L", descr)
+	SYSCTL_LONG_MTX(parent, nbr, name, access, ptr, val, NULL, descr)
+#define SYSCTL_LONG_MTX(parent, nbr, name, access, ptr, val, mtx, descr) \
+	SYSCTL_OID_MTX(parent, nbr, name, CTLTYPE_LONG|(access), ptr,	\
+	    val, sysctl_handle_long, "L", mtx, descr)
+
+#define SYSCTL_ADD_LONG(ctx, parent, nbr, name, access, ptr, descr)	\
+	SYSCTL_ADD_LONG_MTX(ctx, parent, nbr, name, access, ptr, NULL, descr)
+#define SYSCTL_ADD_LONG_MTX(ctx, parent, nbr, name, access, ptr, mtx, descr) \
+	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_LONG|(access),	\
+	    ptr, 0, sysctl_handle_long, "L", mtx, descr)
 
 /* Oid for an unsigned long.  The pointer must be non NULL. */
 #define SYSCTL_ULONG(parent, nbr, name, access, ptr, val, descr) \
-	SYSCTL_OID(parent, nbr, name, CTLTYPE_ULONG|(access), \
-		ptr, val, sysctl_handle_long, "LU", descr)
-
-#define SYSCTL_ADD_ULONG(ctx, parent, nbr, name, access, ptr, descr)	    \
-	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_ULONG|(access),	    \
-	ptr, 0, sysctl_handle_long, "LU", descr)
+	SYSCTL_ULONG_MTX(parent, nbr, name, access, ptr, val, NULL, descr)
+#define SYSCTL_ULONG_MTX(parent, nbr, name, access, ptr, val, mtx, descr) \
+	SYSCTL_OID_MTX(parent, nbr, name, CTLTYPE_ULONG|(access), ptr,	\
+	    val, sysctl_handle_long, "LU", mtx, descr)
+
+#define SYSCTL_ADD_ULONG(ctx, parent, nbr, name, access, ptr, descr)	\
+	SYSCTL_ADD_ULONG_MTX(ctx, parent, nbr, name, access, ptr, NULL, descr)
+#define SYSCTL_ADD_ULONG_MTX(ctx, parent, nbr, name, access, ptr, mtx, descr) \
+	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_ULONG|(access),	\
+	    ptr, 0, sysctl_handle_long, "LU", mtx, descr)
 
 /* Oid for an opaque object.  Specified by a pointer and a length. */
-#define SYSCTL_OPAQUE(parent, nbr, name, access, ptr, len, fmt, descr) \
-	SYSCTL_OID(parent, nbr, name, CTLTYPE_OPAQUE|(access), \
-		ptr, len, sysctl_handle_opaque, fmt, descr)
-
-#define SYSCTL_ADD_OPAQUE(ctx, parent, nbr, name, access, ptr, len, fmt, descr)\
-	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_OPAQUE|(access),	    \
-	ptr, len, sysctl_handle_opaque, fmt, descr)
+#define SYSCTL_OPAQUE(parent, nbr, name, access, ptr, len, fmt, descr)	\
+	SYSCTL_OPAQUE_MTX(parent, nbr, name, access, ptr, len, fmt, NULL, descr)
+#define SYSCTL_OPAQUE_MTX(parent, nbr, name, access, ptr, len, fmt, mtx, descr) \
+	SYSCTL_OID_MTX(parent, nbr, name, CTLTYPE_OPAQUE|(access), ptr,	\
+	    len, sysctl_handle_opaque, fmt, mtx, descr)
+
+#define SYSCTL_ADD_OPAQUE(ctx, parent, nbr, name, access, ptr, len, fmt, descr) \
+	SYSCTL_ADD_OPAQUE_MTX(ctx, parent, nbr, name, access, ptr, len,	\
+	    fmt, NULL, descr)
+#define SYSCTL_ADD_OPAQUE_MTX(ctx, parent, nbr, name, access, ptr, len, fmt, mtx, descr) \
+	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_OPAQUE|(access),	\
+	    ptr, len, sysctl_handle_opaque, fmt, mtx, descr)
 
 /* Oid for a struct.  Specified by a pointer and a type. */
-#define SYSCTL_STRUCT(parent, nbr, name, access, ptr, type, descr) \
-	SYSCTL_OID(parent, nbr, name, CTLTYPE_OPAQUE|(access), \
-		ptr, sizeof(struct type), sysctl_handle_opaque, \
-		"S," #type, descr)
+#define SYSCTL_STRUCT(parent, nbr, name, access, ptr, type, descr)	\
+	SYSCTL_STRUCT_MTX(parent, nbr, name, access, ptr, type, NULL, descr)
+#define SYSCTL_STRUCT_MTX(parent, nbr, name, access, ptr, type, mtx, descr) \
+	SYSCTL_OID_MTX(parent, nbr, name, CTLTYPE_OPAQUE|(access), ptr,	\
+	    sizeof(struct type), sysctl_handle_opaque, "S," #type, mtx,	\
+	    descr)
 
 #define SYSCTL_ADD_STRUCT(ctx, parent, nbr, name, access, ptr, type, descr) \
-	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_OPAQUE|(access),	    \
-	ptr, sizeof(struct type), sysctl_handle_opaque, "S," #type, descr)
+	SYSCTL_ADD_STRUCT_MTX(ctx, parent, nbr, name, access, ptr,	\
+	    type, NULL, descr)
+#define SYSCTL_ADD_STRUCT_MTX(ctx, parent, nbr, name, access, ptr, type, mtx, descr) \
+	sysctl_add_oid(ctx, parent, nbr, name, CTLTYPE_OPAQUE|(access),	\
+	    ptr, sizeof(struct type), sysctl_handle_opaque, "S," #type,	\
+	    mtx, descr)
 
 /* Oid for a procedure.  Specified by a pointer and an arg. */
 #define SYSCTL_PROC(parent, nbr, name, access, ptr, arg, handler, fmt, descr) \
@@ -284,8 +329,12 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_e
 
 #define SYSCTL_ADD_PROC(ctx, parent, nbr, name, access, ptr, arg, handler, fmt, descr) \
 	sysctl_add_oid(ctx, parent, nbr, name, (access),			    \
-	ptr, arg, handler, fmt, descr)
+	ptr, arg, handler, fmt, NULL, descr)
 
+#define	OID_LOCK(oidp)		if ((oidp)->oid_mtx != NULL)		\
+					mtx_lock((oidp)->oid_mtx)
+#define	OID_UNLOCK(oidp)	if ((oidp)->oid_mtx != NULL)		\
+					mtx_unlock((oidp)->oid_mtx)
 #endif /* _KERNEL */
 
 /*
@@ -589,7 +638,7 @@ struct sysctl_oid *sysctl_add_oid(struct
 		struct sysctl_oid_list *parent, int nbr, const char *name,
 		int kind, void *arg1, int arg2,
 		int (*handler) (SYSCTL_HANDLER_ARGS),
-		const char *fmt, const char *descr);
+		const char *fmt, struct mtx *mtx, const char *descr);
 int	sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse);
 int	sysctl_ctx_init(struct sysctl_ctx_list *clist);
 int	sysctl_ctx_free(struct sysctl_ctx_list *clist);
>Release-Note:
>Audit-Trail:
>Unformatted:



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