[Bug 246114] net.isr.dispatch can not be set via loader
bugzilla-noreply at freebsd.org
bugzilla-noreply at freebsd.org
Sat May 2 07:25:28 UTC 2020
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=246114
Bug ID: 246114
Summary: net.isr.dispatch can not be set via loader
Product: Base System
Version: CURRENT
Hardware: Any
OS: Any
Status: New
Severity: Affects Many People
Priority: ---
Component: kern
Assignee: bugs at FreeBSD.org
Reporter: delphij at FreeBSD.org
In r357614, sysctl_handle_string was refactored to protect against concurrent
writes to sysctl node, and as a result a temporary buffer is allocated via
malloc(9).
Unfortunately, netisr is initialized earlier than malloc(9), as the result,
setting net.isr.dispatch="deferred" in /boot/loader.conf would cause the kernel
to panic immediately:
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x47/frame 0xffffffff8228d560
vpanic() at vpanic+0x1c7/frame 0xffffffff8228d5c0
panic() at panic+0x43/frame 0xffffffff8228d620
trap_fatal() at trap_fatal+0x4ca/frame 0xffffffff8228d6a0
trap_pfault() at trap_pfault+0xdc/frame 0xffffffff8228d720
trap() at trap+0x3f8/frame 0xffffffff8228d840
calltrap() at calltrap+0x8/frame 0xffffffff8228d840
--- trap 0xc, rip = 0xffffffff8081a985, rsp = 0xffffffff8228d910, rbp =
0xffffffff8228d960 ---
malloc() at malloc+0x95/frame 0xffffffff8228d960
sysctl_handle_string() at sysctl_handle_string+0x215/frame 0xffffffff8228d9a0
sysctl_netisr_dispatch_policy() at sysctl_netisr_dispatch_policy+0x86/frame
0xffffffff8228d9f0
sysctl_root_handler_locked() at sysctl_root_handler_locked+0xf9/frame
0xffffffff8228da40
sysctl_register_oid() at sysctl_register_oid+0x9d1/frame 0xffffffff8228dd60
sysctl_register_all() at sysctl_register_all+0x89/frame 0xffffffff8228dd80
mi_startup() at mi_startup+0x3ac/frame 0xffffffff8228ddf0
btext() at btext+0x2c
KDB: enter: panic
[ thread pid 0 tid 0 ]
Stopped at kdb_enter+0x67: movq $0,0xa926e6(%rip)
db>
A very dirty (and wrong) hack would be to have a short string allocated in
stack buffer and fall back to malloc() only when the string is long, but I
don't like the approach as it's only papering out the actual issue.
svn diff sys/kern/kern_sysctl.c
Index: sys/kern/kern_sysctl.c
===================================================================
--- sys/kern/kern_sysctl.c (revision 360560)
+++ sys/kern/kern_sysctl.c (working copy)
@@ -1646,6 +1646,7 @@ sysctl_handle_string(SYSCTL_HANDLER_ARGS)
char *tmparg;
size_t outlen;
int error = 0, ro_string = 0;
+ char shortbuf[256];
/*
* If the sysctl isn't writable and isn't a preallocated tunable that
@@ -1666,7 +1667,11 @@ sysctl_handle_string(SYSCTL_HANDLER_ARGS)
tmparg = arg1;
outlen = strlen(tmparg) + 1;
} else {
- tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK);
+ if (arg2 <= sizeof(shortbuf)) {
+ tmparg = (char *)&shortbuf;
+ } else {
+ tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK);
+ }
sx_slock(&sysctlstringlock);
memcpy(tmparg, arg1, arg2);
sx_sunlock(&sysctlstringlock);
@@ -1675,7 +1680,7 @@ sysctl_handle_string(SYSCTL_HANDLER_ARGS)
error = SYSCTL_OUT(req, tmparg, outlen);
- if (!ro_string)
+ if (!ro_string && arg2 > sizeof(shortbuf))
free(tmparg, M_SYSCTLTMP);
} else {
if (!ro_string)
@@ -1697,11 +1702,16 @@ sysctl_handle_string(SYSCTL_HANDLER_ARGS)
sx_xunlock(&sysctlstringlock);
} else {
arg2 = req->newlen - req->newidx;
- tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK);
+ if (arg2 <= sizeof(shortbuf)) {
+ tmparg = (char *)&shortbuf;
+ } else {
+ tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK);
+ }
error = SYSCTL_IN(req, tmparg, arg2);
if (error) {
- free(tmparg, M_SYSCTLTMP);
+ if (arg2 > sizeof(shortbuf))
+ free(tmparg, M_SYSCTLTMP);
return (error);
}
@@ -1709,7 +1719,8 @@ sysctl_handle_string(SYSCTL_HANDLER_ARGS)
memcpy(arg1, tmparg, arg2);
((char *)arg1)[arg2] = '\0';
sx_xunlock(&sysctlstringlock);
- free(tmparg, M_SYSCTLTMP);
+ if (arg2 > sizeof(shortbuf))
+ free(tmparg, M_SYSCTLTMP);
req->newidx += arg2;
}
return (error);
--
You are receiving this mail because:
You are the assignee for the bug.
More information about the freebsd-bugs
mailing list