kern/54439: Protecting sysctls variables by given mutexes [PATCH].
Pawel Jakub Dawidek
nick at garage.freebsd.pl
Sun Jul 13 08:20:20 PDT 2003
>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:
More information about the freebsd-bugs
mailing list