diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1886,7 +1886,8 @@ { char *tmparg; size_t outlen; - int error = 0, ro_string = 0; + int error = 0; + bool ro_string = false; /* * If the sysctl isn't writable and isn't a preallocated tunable that @@ -1898,20 +1899,22 @@ */ if ((oidp->oid_kind & (CTLFLAG_WR | CTLFLAG_TUN)) == 0 || arg2 == 0 || kdb_active) { - arg2 = strlen((char *)arg1) + 1; - ro_string = 1; + ro_string = true; + if (arg2 == 0) + outlen = arg2 = strlen(arg1) + 1; + else + outlen = strnlen(arg1, arg2 - 1) + 1; } if (req->oldptr != NULL) { - if (ro_string) { + if (ro_string) tmparg = arg1; - outlen = strlen(tmparg) + 1; - } else { + else { tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK); sx_slock(&sysctlstringlock); memcpy(tmparg, arg1, arg2); sx_sunlock(&sysctlstringlock); - outlen = strlen(tmparg) + 1; + outlen = strnlen(tmparg, arg2 - 1) + 1; } error = SYSCTL_OUT(req, tmparg, outlen); @@ -1919,11 +1922,11 @@ if (!ro_string) free(tmparg, M_SYSCTLTMP); } else { - if (!ro_string) + if (!ro_string) { sx_slock(&sysctlstringlock); - outlen = strlen((char *)arg1) + 1; - if (!ro_string) + outlen = strnlen(arg1, arg2 - 1) + 1; sx_sunlock(&sysctlstringlock); + } error = SYSCTL_OUT(req, NULL, outlen); } if (error || !req->newptr)