1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Mike Karels at Berkeley Software Design, Inc.
9 *
10 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
11 * project, to make these variables more userfriendly.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
38 */
39
40 #include <sys/cdefs.h>
41 #include "opt_capsicum.h"
42 #include "opt_ddb.h"
43 #include "opt_ktrace.h"
44 #include "opt_sysctl.h"
45
46 #include <sys/param.h>
47 #include <sys/fail.h>
48 #include <sys/systm.h>
49 #include <sys/capsicum.h>
50 #include <sys/kernel.h>
51 #include <sys/limits.h>
52 #include <sys/sysctl.h>
53 #include <sys/malloc.h>
54 #include <sys/priv.h>
55 #include <sys/proc.h>
56 #include <sys/jail.h>
57 #include <sys/kdb.h>
58 #include <sys/lock.h>
59 #include <sys/mutex.h>
60 #include <sys/rmlock.h>
61 #include <sys/sbuf.h>
62 #include <sys/sx.h>
63 #include <sys/sysproto.h>
64 #include <sys/uio.h>
65 #ifdef KTRACE
66 #include <sys/ktrace.h>
67 #endif
68
69 #ifdef DDB
70 #include <ddb/ddb.h>
71 #include <ddb/db_lex.h>
72 #endif
73
74 #include <net/vnet.h>
75
76 #include <security/mac/mac_framework.h>
77
78 #include <vm/vm.h>
79 #include <vm/vm_extern.h>
80
81 static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic");
82 static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids");
83 static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer");
84
85 RB_GENERATE(sysctl_oid_list, sysctl_oid, oid_link, cmp_sysctl_oid);
86
87 /*
88 * The sysctllock protects the MIB tree. It also protects sysctl
89 * contexts used with dynamic sysctls. The sysctl_register_oid() and
90 * sysctl_unregister_oid() routines require the sysctllock to already
91 * be held, so the sysctl_wlock() and sysctl_wunlock() routines are
92 * provided for the few places in the kernel which need to use that
93 * API rather than using the dynamic API. Use of the dynamic API is
94 * strongly encouraged for most code.
95 *
96 * The sysctlmemlock is used to limit the amount of user memory wired for
97 * sysctl requests. This is implemented by serializing any userland
98 * sysctl requests larger than a single page via an exclusive lock.
99 *
100 * The sysctlstringlock is used to protect concurrent access to writable
101 * string nodes in sysctl_handle_string().
102 */
103 static struct rmlock sysctllock;
104 static struct sx __exclusive_cache_line sysctlmemlock;
105 static struct sx sysctlstringlock;
106
107 #define SYSCTL_WLOCK() rm_wlock(&sysctllock)
108 #define SYSCTL_WUNLOCK() rm_wunlock(&sysctllock)
109 #define SYSCTL_RLOCK(tracker) rm_rlock(&sysctllock, (tracker))
110 #define SYSCTL_RUNLOCK(tracker) rm_runlock(&sysctllock, (tracker))
111 #define SYSCTL_WLOCKED() rm_wowned(&sysctllock)
112 #define SYSCTL_ASSERT_LOCKED() rm_assert(&sysctllock, RA_LOCKED)
113 #define SYSCTL_ASSERT_WLOCKED() rm_assert(&sysctllock, RA_WLOCKED)
114 #define SYSCTL_ASSERT_RLOCKED() rm_assert(&sysctllock, RA_RLOCKED)
115 #define SYSCTL_INIT() rm_init_flags(&sysctllock, "sysctl lock", \
116 RM_SLEEPABLE)
117 #define SYSCTL_SLEEP(ch, wmesg, timo) \
118 rm_sleep(ch, &sysctllock, 0, wmesg, timo)
119
120 static int sysctl_root(SYSCTL_HANDLER_ARGS);
121
122 /* Root list */
123 struct sysctl_oid_list sysctl__children = RB_INITIALIZER(&sysctl__children);
124
125 static char* sysctl_escape_name(const char*);
126 static int sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del,
127 int recurse);
128 static int sysctl_old_kernel(struct sysctl_req *, const void *, size_t);
129 static int sysctl_new_kernel(struct sysctl_req *, void *, size_t);
130
131 static struct sysctl_oid *
sysctl_find_oidname(const char * name,struct sysctl_oid_list * list)132 sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)
133 {
134 struct sysctl_oid *oidp;
135
136 SYSCTL_ASSERT_LOCKED();
137 SYSCTL_FOREACH(oidp, list) {
138 if (strcmp(oidp->oid_name, name) == 0) {
139 return (oidp);
140 }
141 }
142 return (NULL);
143 }
144
145 /*
146 * Initialization of the MIB tree.
147 *
148 * Order by number in each list.
149 */
150 void
sysctl_wlock(void)151 sysctl_wlock(void)
152 {
153
154 SYSCTL_WLOCK();
155 }
156
157 void
sysctl_wunlock(void)158 sysctl_wunlock(void)
159 {
160
161 SYSCTL_WUNLOCK();
162 }
163
164 static int
sysctl_root_handler_locked(struct sysctl_oid * oid,void * arg1,intmax_t arg2,struct sysctl_req * req,struct rm_priotracker * tracker)165 sysctl_root_handler_locked(struct sysctl_oid *oid, void *arg1, intmax_t arg2,
166 struct sysctl_req *req, struct rm_priotracker *tracker)
167 {
168 int error;
169
170 if (oid->oid_kind & CTLFLAG_DYN)
171 atomic_add_int(&oid->oid_running, 1);
172
173 if (tracker != NULL)
174 SYSCTL_RUNLOCK(tracker);
175 else
176 SYSCTL_WUNLOCK();
177
178 /*
179 * Treat set CTLFLAG_NEEDGIANT and unset CTLFLAG_MPSAFE flags the same,
180 * untill we're ready to remove all traces of Giant from sysctl(9).
181 */
182 if ((oid->oid_kind & CTLFLAG_NEEDGIANT) ||
183 (!(oid->oid_kind & CTLFLAG_MPSAFE)))
184 mtx_lock(&Giant);
185 error = oid->oid_handler(oid, arg1, arg2, req);
186 if ((oid->oid_kind & CTLFLAG_NEEDGIANT) ||
187 (!(oid->oid_kind & CTLFLAG_MPSAFE)))
188 mtx_unlock(&Giant);
189
190 KFAIL_POINT_ERROR(_debug_fail_point, sysctl_running, error);
191
192 if (tracker != NULL)
193 SYSCTL_RLOCK(tracker);
194 else
195 SYSCTL_WLOCK();
196
197 if (oid->oid_kind & CTLFLAG_DYN) {
198 if (atomic_fetchadd_int(&oid->oid_running, -1) == 1 &&
199 (oid->oid_kind & CTLFLAG_DYING) != 0)
200 wakeup(&oid->oid_running);
201 }
202
203 return (error);
204 }
205
206 static void
sysctl_load_tunable_by_oid_locked(struct sysctl_oid * oidp)207 sysctl_load_tunable_by_oid_locked(struct sysctl_oid *oidp)
208 {
209 struct sysctl_req req;
210 struct sysctl_oid *curr;
211 char *penv = NULL;
212 char path[96];
213 ssize_t rem = sizeof(path);
214 ssize_t len;
215 uint8_t data[512] __aligned(sizeof(uint64_t));
216 int size;
217 int error;
218
219 path[--rem] = 0;
220
221 for (curr = oidp; curr != NULL; curr = SYSCTL_PARENT(curr)) {
222 len = strlen(curr->oid_name);
223 rem -= len;
224 if (curr != oidp)
225 rem -= 1;
226 if (rem < 0) {
227 printf("OID path exceeds %d bytes\n", (int)sizeof(path));
228 return;
229 }
230 memcpy(path + rem, curr->oid_name, len);
231 if (curr != oidp)
232 path[rem + len] = '.';
233 }
234
235 memset(&req, 0, sizeof(req));
236
237 req.td = curthread;
238 req.oldfunc = sysctl_old_kernel;
239 req.newfunc = sysctl_new_kernel;
240 req.lock = REQ_UNWIRED;
241
242 switch (oidp->oid_kind & CTLTYPE) {
243 case CTLTYPE_INT:
244 if (getenv_array(path + rem, data, sizeof(data), &size,
245 sizeof(int), GETENV_SIGNED) == 0)
246 return;
247 req.newlen = size;
248 req.newptr = data;
249 break;
250 case CTLTYPE_UINT:
251 if (getenv_array(path + rem, data, sizeof(data), &size,
252 sizeof(int), GETENV_UNSIGNED) == 0)
253 return;
254 req.newlen = size;
255 req.newptr = data;
256 break;
257 case CTLTYPE_LONG:
258 if (getenv_array(path + rem, data, sizeof(data), &size,
259 sizeof(long), GETENV_SIGNED) == 0)
260 return;
261 req.newlen = size;
262 req.newptr = data;
263 break;
264 case CTLTYPE_ULONG:
265 if (getenv_array(path + rem, data, sizeof(data), &size,
266 sizeof(long), GETENV_UNSIGNED) == 0)
267 return;
268 req.newlen = size;
269 req.newptr = data;
270 break;
271 case CTLTYPE_S8:
272 if (getenv_array(path + rem, data, sizeof(data), &size,
273 sizeof(int8_t), GETENV_SIGNED) == 0)
274 return;
275 req.newlen = size;
276 req.newptr = data;
277 break;
278 case CTLTYPE_S16:
279 if (getenv_array(path + rem, data, sizeof(data), &size,
280 sizeof(int16_t), GETENV_SIGNED) == 0)
281 return;
282 req.newlen = size;
283 req.newptr = data;
284 break;
285 case CTLTYPE_S32:
286 if (getenv_array(path + rem, data, sizeof(data), &size,
287 sizeof(int32_t), GETENV_SIGNED) == 0)
288 return;
289 req.newlen = size;
290 req.newptr = data;
291 break;
292 case CTLTYPE_S64:
293 if (getenv_array(path + rem, data, sizeof(data), &size,
294 sizeof(int64_t), GETENV_SIGNED) == 0)
295 return;
296 req.newlen = size;
297 req.newptr = data;
298 break;
299 case CTLTYPE_U8:
300 if (getenv_array(path + rem, data, sizeof(data), &size,
301 sizeof(uint8_t), GETENV_UNSIGNED) == 0)
302 return;
303 req.newlen = size;
304 req.newptr = data;
305 break;
306 case CTLTYPE_U16:
307 if (getenv_array(path + rem, data, sizeof(data), &size,
308 sizeof(uint16_t), GETENV_UNSIGNED) == 0)
309 return;
310 req.newlen = size;
311 req.newptr = data;
312 break;
313 case CTLTYPE_U32:
314 if (getenv_array(path + rem, data, sizeof(data), &size,
315 sizeof(uint32_t), GETENV_UNSIGNED) == 0)
316 return;
317 req.newlen = size;
318 req.newptr = data;
319 break;
320 case CTLTYPE_U64:
321 if (getenv_array(path + rem, data, sizeof(data), &size,
322 sizeof(uint64_t), GETENV_UNSIGNED) == 0)
323 return;
324 req.newlen = size;
325 req.newptr = data;
326 break;
327 case CTLTYPE_STRING:
328 penv = kern_getenv(path + rem);
329 if (penv == NULL)
330 return;
331 req.newlen = strlen(penv);
332 req.newptr = penv;
333 break;
334 default:
335 return;
336 }
337 error = sysctl_root_handler_locked(oidp, oidp->oid_arg1,
338 oidp->oid_arg2, &req, NULL);
339 if (error != 0)
340 printf("Setting sysctl %s failed: %d\n", path + rem, error);
341 if (penv != NULL)
342 freeenv(penv);
343 }
344
345 /*
346 * Locate the path to a given oid. Returns the length of the resulting path,
347 * or -1 if the oid was not found. nodes must have room for CTL_MAXNAME
348 * elements.
349 */
350 static int
sysctl_search_oid(struct sysctl_oid ** nodes,struct sysctl_oid * needle)351 sysctl_search_oid(struct sysctl_oid **nodes, struct sysctl_oid *needle)
352 {
353 int indx;
354
355 SYSCTL_ASSERT_LOCKED();
356 indx = 0;
357 /*
358 * Do a depth-first search of the oid tree, looking for 'needle'. Start
359 * with the first child of the root.
360 */
361 nodes[indx] = RB_MIN(sysctl_oid_list, &sysctl__children);
362 for (;;) {
363 if (nodes[indx] == needle)
364 return (indx + 1);
365
366 if (nodes[indx] == NULL) {
367 /* Node has no more siblings, so back up to parent. */
368 if (indx-- == 0) {
369 /* Retreat to root, so give up. */
370 break;
371 }
372 } else if ((nodes[indx]->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
373 /* Node has children. */
374 if (++indx == CTL_MAXNAME) {
375 /* Max search depth reached, so give up. */
376 break;
377 }
378 /* Start with the first child. */
379 nodes[indx] = RB_MIN(sysctl_oid_list,
380 &nodes[indx - 1]->oid_children);
381 continue;
382 }
383 /* Consider next sibling. */
384 nodes[indx] = RB_NEXT(sysctl_oid_list, NULL, nodes[indx]);
385 }
386 return (-1);
387 }
388
389 static void
sysctl_warn_reuse(const char * func,struct sysctl_oid * leaf)390 sysctl_warn_reuse(const char *func, struct sysctl_oid *leaf)
391 {
392 struct sysctl_oid *nodes[CTL_MAXNAME];
393 char buf[128];
394 struct sbuf sb;
395 int rc, i;
396
397 (void)sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN | SBUF_INCLUDENUL);
398 sbuf_set_drain(&sb, sbuf_printf_drain, NULL);
399
400 sbuf_printf(&sb, "%s: can't re-use a leaf (", __func__);
401
402 rc = sysctl_search_oid(nodes, leaf);
403 if (rc > 0) {
404 for (i = 0; i < rc; i++)
405 sbuf_printf(&sb, "%s%.*s", nodes[i]->oid_name,
406 i != (rc - 1), ".");
407 } else {
408 sbuf_printf(&sb, "%s", leaf->oid_name);
409 }
410 sbuf_printf(&sb, ")!\n");
411
412 (void)sbuf_finish(&sb);
413 }
414
415 #ifdef SYSCTL_DEBUG
416 static int
sysctl_reuse_test(SYSCTL_HANDLER_ARGS)417 sysctl_reuse_test(SYSCTL_HANDLER_ARGS)
418 {
419 struct rm_priotracker tracker;
420
421 SYSCTL_RLOCK(&tracker);
422 sysctl_warn_reuse(__func__, oidp);
423 SYSCTL_RUNLOCK(&tracker);
424 return (0);
425 }
426 SYSCTL_PROC(_sysctl, OID_AUTO, reuse_test,
427 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 0, sysctl_reuse_test, "-",
428 "");
429 #endif
430
431 void
sysctl_register_oid(struct sysctl_oid * oidp)432 sysctl_register_oid(struct sysctl_oid *oidp)
433 {
434 struct sysctl_oid_list *parent = oidp->oid_parent;
435 struct sysctl_oid *p, key;
436 int oid_number;
437 int timeout = 2;
438
439 /*
440 * First check if another oid with the same name already
441 * exists in the parent's list.
442 */
443 SYSCTL_ASSERT_WLOCKED();
444 p = sysctl_find_oidname(oidp->oid_name, parent);
445 if (p != NULL) {
446 if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
447 p->oid_refcnt++;
448 return;
449 } else {
450 sysctl_warn_reuse(__func__, p);
451 return;
452 }
453 }
454 /* get current OID number */
455 oid_number = oidp->oid_number;
456
457 #if (OID_AUTO >= 0)
458 #error "OID_AUTO is expected to be a negative value"
459 #endif
460 /*
461 * Any negative OID number qualifies as OID_AUTO. Valid OID
462 * numbers should always be positive.
463 *
464 * NOTE: DO NOT change the starting value here, change it in
465 * <sys/sysctl.h>, and make sure it is at least 256 to
466 * accommodate e.g. net.inet.raw as a static sysctl node.
467 */
468 if (oid_number < 0) {
469 static int newoid;
470
471 /*
472 * By decrementing the next OID number we spend less
473 * time inserting the OIDs into a sorted list.
474 */
475 if (--newoid < CTL_AUTO_START)
476 newoid = 0x7fffffff;
477
478 oid_number = newoid;
479 }
480
481 /*
482 * Insert the OID into the parent's list sorted by OID number.
483 */
484 key.oid_number = oid_number;
485 p = RB_NFIND(sysctl_oid_list, parent, &key);
486 while (p != NULL && oid_number == p->oid_number) {
487 /* get the next valid OID number */
488 if (oid_number < CTL_AUTO_START ||
489 oid_number == 0x7fffffff) {
490 /* wraparound - restart */
491 oid_number = CTL_AUTO_START;
492 /* don't loop forever */
493 if (!timeout--)
494 panic("sysctl: Out of OID numbers\n");
495 key.oid_number = oid_number;
496 p = RB_NFIND(sysctl_oid_list, parent, &key);
497 continue;
498 }
499 p = RB_NEXT(sysctl_oid_list, NULL, p);
500 oid_number++;
501 }
502 /* check for non-auto OID number collision */
503 if (oidp->oid_number >= 0 && oidp->oid_number < CTL_AUTO_START &&
504 oid_number >= CTL_AUTO_START) {
505 printf("sysctl: OID number(%d) is already in use for '%s'\n",
506 oidp->oid_number, oidp->oid_name);
507 }
508 /* update the OID number, if any */
509 oidp->oid_number = oid_number;
510 RB_INSERT(sysctl_oid_list, parent, oidp);
511
512 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE &&
513 #ifdef VIMAGE
514 (oidp->oid_kind & CTLFLAG_VNET) == 0 &&
515 #endif
516 (oidp->oid_kind & CTLFLAG_TUN) != 0 &&
517 (oidp->oid_kind & CTLFLAG_NOFETCH) == 0) {
518 /* only fetch value once */
519 oidp->oid_kind |= CTLFLAG_NOFETCH;
520 /* try to fetch value from kernel environment */
521 sysctl_load_tunable_by_oid_locked(oidp);
522 }
523 }
524
525 void
sysctl_register_disabled_oid(struct sysctl_oid * oidp)526 sysctl_register_disabled_oid(struct sysctl_oid *oidp)
527 {
528
529 /*
530 * Mark the leaf as dormant if it's not to be immediately enabled.
531 * We do not disable nodes as they can be shared between modules
532 * and it is always safe to access a node.
533 */
534 KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) == 0,
535 ("internal flag is set in oid_kind"));
536 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
537 oidp->oid_kind |= CTLFLAG_DORMANT;
538 sysctl_register_oid(oidp);
539 }
540
541 void
sysctl_enable_oid(struct sysctl_oid * oidp)542 sysctl_enable_oid(struct sysctl_oid *oidp)
543 {
544
545 SYSCTL_ASSERT_WLOCKED();
546 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
547 KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) == 0,
548 ("sysctl node is marked as dormant"));
549 return;
550 }
551 KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) != 0,
552 ("enabling already enabled sysctl oid"));
553 oidp->oid_kind &= ~CTLFLAG_DORMANT;
554 }
555
556 void
sysctl_unregister_oid(struct sysctl_oid * oidp)557 sysctl_unregister_oid(struct sysctl_oid *oidp)
558 {
559 int error;
560
561 SYSCTL_ASSERT_WLOCKED();
562 if (oidp->oid_number == OID_AUTO) {
563 error = EINVAL;
564 } else {
565 error = ENOENT;
566 if (RB_REMOVE(sysctl_oid_list, oidp->oid_parent, oidp))
567 error = 0;
568 }
569
570 /*
571 * This can happen when a module fails to register and is
572 * being unloaded afterwards. It should not be a panic()
573 * for normal use.
574 */
575 if (error) {
576 printf("%s: failed(%d) to unregister sysctl(%s)\n",
577 __func__, error, oidp->oid_name);
578 }
579 }
580
581 /* Initialize a new context to keep track of dynamically added sysctls. */
582 int
sysctl_ctx_init(struct sysctl_ctx_list * c)583 sysctl_ctx_init(struct sysctl_ctx_list *c)
584 {
585
586 if (c == NULL) {
587 return (EINVAL);
588 }
589
590 /*
591 * No locking here, the caller is responsible for not adding
592 * new nodes to a context until after this function has
593 * returned.
594 */
595 TAILQ_INIT(c);
596 return (0);
597 }
598
599 /* Free the context, and destroy all dynamic oids registered in this context */
600 int
sysctl_ctx_free(struct sysctl_ctx_list * clist)601 sysctl_ctx_free(struct sysctl_ctx_list *clist)
602 {
603 struct sysctl_ctx_entry *e, *e1;
604 int error;
605
606 error = 0;
607 /*
608 * First perform a "dry run" to check if it's ok to remove oids.
609 * XXX FIXME
610 * XXX This algorithm is a hack. But I don't know any
611 * XXX better solution for now...
612 */
613 SYSCTL_WLOCK();
614 TAILQ_FOREACH(e, clist, link) {
615 error = sysctl_remove_oid_locked(e->entry, 0, 0);
616 if (error)
617 break;
618 }
619 /*
620 * Restore deregistered entries, either from the end,
621 * or from the place where error occurred.
622 * e contains the entry that was not unregistered
623 */
624 if (error)
625 e1 = TAILQ_PREV(e, sysctl_ctx_list, link);
626 else
627 e1 = TAILQ_LAST(clist, sysctl_ctx_list);
628 while (e1 != NULL) {
629 sysctl_register_oid(e1->entry);
630 e1 = TAILQ_PREV(e1, sysctl_ctx_list, link);
631 }
632 if (error) {
633 SYSCTL_WUNLOCK();
634 return(EBUSY);
635 }
636 /* Now really delete the entries */
637 TAILQ_FOREACH_SAFE(e, clist, link, e1) {
638 error = sysctl_remove_oid_locked(e->entry, 1, 0);
639 if (error)
640 panic("sysctl_remove_oid: corrupt tree, entry: %s",
641 e->entry->oid_name);
642 free(e, M_SYSCTLOID);
643 }
644 SYSCTL_WUNLOCK();
645 TAILQ_INIT(clist);
646 return (error);
647 }
648
649 /* Add an entry to the context */
650 struct sysctl_ctx_entry *
sysctl_ctx_entry_add(struct sysctl_ctx_list * clist,struct sysctl_oid * oidp)651 sysctl_ctx_entry_add(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
652 {
653 struct sysctl_ctx_entry *e;
654
655 SYSCTL_ASSERT_WLOCKED();
656 if (clist == NULL || oidp == NULL)
657 return(NULL);
658 e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK);
659 e->entry = oidp;
660 TAILQ_INSERT_HEAD(clist, e, link);
661 return (e);
662 }
663
664 /* Find an entry in the context */
665 struct sysctl_ctx_entry *
sysctl_ctx_entry_find(struct sysctl_ctx_list * clist,struct sysctl_oid * oidp)666 sysctl_ctx_entry_find(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
667 {
668 struct sysctl_ctx_entry *e;
669
670 SYSCTL_ASSERT_WLOCKED();
671 if (clist == NULL || oidp == NULL)
672 return(NULL);
673 TAILQ_FOREACH(e, clist, link) {
674 if (e->entry == oidp)
675 return(e);
676 }
677 return (e);
678 }
679
680 /*
681 * Delete an entry from the context.
682 * NOTE: this function doesn't free oidp! You have to remove it
683 * with sysctl_remove_oid().
684 */
685 int
sysctl_ctx_entry_del(struct sysctl_ctx_list * clist,struct sysctl_oid * oidp)686 sysctl_ctx_entry_del(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
687 {
688 struct sysctl_ctx_entry *e;
689
690 if (clist == NULL || oidp == NULL)
691 return (EINVAL);
692 SYSCTL_WLOCK();
693 e = sysctl_ctx_entry_find(clist, oidp);
694 if (e != NULL) {
695 TAILQ_REMOVE(clist, e, link);
696 SYSCTL_WUNLOCK();
697 free(e, M_SYSCTLOID);
698 return (0);
699 } else {
700 SYSCTL_WUNLOCK();
701 return (ENOENT);
702 }
703 }
704
705 /*
706 * Remove dynamically created sysctl trees.
707 * oidp - top of the tree to be removed
708 * del - if 0 - just deregister, otherwise free up entries as well
709 * recurse - if != 0 traverse the subtree to be deleted
710 */
711 int
sysctl_remove_oid(struct sysctl_oid * oidp,int del,int recurse)712 sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse)
713 {
714 int error;
715
716 SYSCTL_WLOCK();
717 error = sysctl_remove_oid_locked(oidp, del, recurse);
718 SYSCTL_WUNLOCK();
719 return (error);
720 }
721
722 int
sysctl_remove_name(struct sysctl_oid * parent,const char * name,int del,int recurse)723 sysctl_remove_name(struct sysctl_oid *parent, const char *name,
724 int del, int recurse)
725 {
726 struct sysctl_oid *p;
727 int error;
728
729 error = ENOENT;
730 SYSCTL_WLOCK();
731 p = sysctl_find_oidname(name, &parent->oid_children);
732 if (p)
733 error = sysctl_remove_oid_locked(p, del, recurse);
734 SYSCTL_WUNLOCK();
735
736 return (error);
737 }
738
739 /*
740 * Duplicate the provided string, escaping any illegal characters. The result
741 * must be freed when no longer in use.
742 *
743 * The list of illegal characters is ".".
744 */
745 static char*
sysctl_escape_name(const char * orig)746 sysctl_escape_name(const char* orig)
747 {
748 int i, s = 0, d = 0, nillegals = 0;
749 char *new;
750
751 /* First count the number of illegal characters */
752 for (i = 0; orig[i] != '\0'; i++) {
753 if (orig[i] == '.')
754 nillegals++;
755 }
756
757 /* Allocate storage for new string */
758 new = malloc(i + 2 * nillegals + 1, M_SYSCTLOID, M_WAITOK);
759
760 /* Copy the name, escaping characters as we go */
761 while (orig[s] != '\0') {
762 if (orig[s] == '.') {
763 /* %25 is the hexadecimal representation of '.' */
764 new[d++] = '%';
765 new[d++] = '2';
766 new[d++] = '5';
767 s++;
768 } else {
769 new[d++] = orig[s++];
770 }
771 }
772
773 /* Finally, nul-terminate */
774 new[d] = '\0';
775
776 return (new);
777 }
778
779 static int
sysctl_remove_oid_locked(struct sysctl_oid * oidp,int del,int recurse)780 sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse)
781 {
782 struct sysctl_oid *p, *tmp;
783 int error;
784
785 SYSCTL_ASSERT_WLOCKED();
786 if (oidp == NULL)
787 return(EINVAL);
788 if ((oidp->oid_kind & CTLFLAG_DYN) == 0) {
789 printf("Warning: can't remove non-dynamic nodes (%s)!\n",
790 oidp->oid_name);
791 return (EINVAL);
792 }
793 /*
794 * WARNING: normal method to do this should be through
795 * sysctl_ctx_free(). Use recursing as the last resort
796 * method to purge your sysctl tree of leftovers...
797 * However, if some other code still references these nodes,
798 * it will panic.
799 */
800 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
801 if (oidp->oid_refcnt == 1) {
802 for(p = RB_MIN(sysctl_oid_list, &oidp->oid_children);
803 p != NULL; p = tmp) {
804 if (!recurse) {
805 printf("Warning: failed attempt to "
806 "remove oid %s with child %s\n",
807 oidp->oid_name, p->oid_name);
808 return (ENOTEMPTY);
809 }
810 tmp = RB_NEXT(sysctl_oid_list,
811 &oidp->oid_children, p);
812 error = sysctl_remove_oid_locked(p, del,
813 recurse);
814 if (error)
815 return (error);
816 }
817 }
818 }
819 if (oidp->oid_refcnt > 1 ) {
820 oidp->oid_refcnt--;
821 } else {
822 if (oidp->oid_refcnt == 0) {
823 printf("Warning: bad oid_refcnt=%u (%s)!\n",
824 oidp->oid_refcnt, oidp->oid_name);
825 return (EINVAL);
826 }
827 sysctl_unregister_oid(oidp);
828 if (del) {
829 /*
830 * Wait for all threads running the handler to drain.
831 * This preserves the previous behavior when the
832 * sysctl lock was held across a handler invocation,
833 * and is necessary for module unload correctness.
834 */
835 while (oidp->oid_running > 0) {
836 oidp->oid_kind |= CTLFLAG_DYING;
837 SYSCTL_SLEEP(&oidp->oid_running, "oidrm", 0);
838 }
839 if (oidp->oid_descr)
840 free(__DECONST(char *, oidp->oid_descr),
841 M_SYSCTLOID);
842 if (oidp->oid_label)
843 free(__DECONST(char *, oidp->oid_label),
844 M_SYSCTLOID);
845 free(__DECONST(char *, oidp->oid_name), M_SYSCTLOID);
846 free(oidp, M_SYSCTLOID);
847 }
848 }
849 return (0);
850 }
851 /*
852 * Create new sysctls at run time.
853 * clist may point to a valid context initialized with sysctl_ctx_init().
854 */
855 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,intmax_t arg2,int (* handler)(SYSCTL_HANDLER_ARGS),const char * fmt,const char * descr,const char * label)856 sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
857 int number, const char *name, int kind, void *arg1, intmax_t arg2,
858 int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr,
859 const char *label)
860 {
861 struct sysctl_oid *oidp;
862 char *escaped;
863
864 /* You have to hook up somewhere.. */
865 if (parent == NULL)
866 return(NULL);
867 escaped = sysctl_escape_name(name);
868 /* Check if the node already exists, otherwise create it */
869 SYSCTL_WLOCK();
870 oidp = sysctl_find_oidname(escaped, parent);
871 if (oidp != NULL) {
872 free(escaped, M_SYSCTLOID);
873 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
874 oidp->oid_refcnt++;
875 /* Update the context */
876 if (clist != NULL)
877 sysctl_ctx_entry_add(clist, oidp);
878 SYSCTL_WUNLOCK();
879 return (oidp);
880 } else {
881 sysctl_warn_reuse(__func__, oidp);
882 SYSCTL_WUNLOCK();
883 return (NULL);
884 }
885 }
886 oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK|M_ZERO);
887 oidp->oid_parent = parent;
888 RB_INIT(&oidp->oid_children);
889 oidp->oid_number = number;
890 oidp->oid_refcnt = 1;
891 oidp->oid_name = escaped;
892 oidp->oid_handler = handler;
893 oidp->oid_kind = CTLFLAG_DYN | kind;
894 oidp->oid_arg1 = arg1;
895 oidp->oid_arg2 = arg2;
896 oidp->oid_fmt = fmt;
897 if (descr != NULL)
898 oidp->oid_descr = strdup(descr, M_SYSCTLOID);
899 if (label != NULL)
900 oidp->oid_label = strdup(label, M_SYSCTLOID);
901 /* Update the context, if used */
902 if (clist != NULL)
903 sysctl_ctx_entry_add(clist, oidp);
904 /* Register this oid */
905 sysctl_register_oid(oidp);
906 SYSCTL_WUNLOCK();
907 return (oidp);
908 }
909
910 /*
911 * Rename an existing oid.
912 */
913 void
sysctl_rename_oid(struct sysctl_oid * oidp,const char * name)914 sysctl_rename_oid(struct sysctl_oid *oidp, const char *name)
915 {
916 char *newname;
917 char *oldname;
918
919 newname = strdup(name, M_SYSCTLOID);
920 SYSCTL_WLOCK();
921 oldname = __DECONST(char *, oidp->oid_name);
922 oidp->oid_name = newname;
923 SYSCTL_WUNLOCK();
924 free(oldname, M_SYSCTLOID);
925 }
926
927 /*
928 * Reparent an existing oid.
929 */
930 int
sysctl_move_oid(struct sysctl_oid * oid,struct sysctl_oid_list * parent)931 sysctl_move_oid(struct sysctl_oid *oid, struct sysctl_oid_list *parent)
932 {
933 struct sysctl_oid *oidp;
934
935 SYSCTL_WLOCK();
936 if (oid->oid_parent == parent) {
937 SYSCTL_WUNLOCK();
938 return (0);
939 }
940 oidp = sysctl_find_oidname(oid->oid_name, parent);
941 if (oidp != NULL) {
942 SYSCTL_WUNLOCK();
943 return (EEXIST);
944 }
945 sysctl_unregister_oid(oid);
946 oid->oid_parent = parent;
947 oid->oid_number = OID_AUTO;
948 sysctl_register_oid(oid);
949 SYSCTL_WUNLOCK();
950 return (0);
951 }
952
953 /*
954 * Register the kernel's oids on startup.
955 */
956 SET_DECLARE(sysctl_set, struct sysctl_oid);
957
958 static void
sysctl_register_all(void * arg)959 sysctl_register_all(void *arg)
960 {
961 struct sysctl_oid **oidp;
962
963 sx_init(&sysctlmemlock, "sysctl mem");
964 sx_init(&sysctlstringlock, "sysctl string handler");
965 SYSCTL_INIT();
966 SYSCTL_WLOCK();
967 SET_FOREACH(oidp, sysctl_set)
968 sysctl_register_oid(*oidp);
969 SYSCTL_WUNLOCK();
970 }
971 SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_register_all, NULL);
972
973 /*
974 * "Staff-functions"
975 *
976 * These functions implement a presently undocumented interface
977 * used by the sysctl program to walk the tree, and get the type
978 * so it can print the value.
979 * This interface is under work and consideration, and should probably
980 * be killed with a big axe by the first person who can find the time.
981 * (be aware though, that the proper interface isn't as obvious as it
982 * may seem, there are various conflicting requirements.
983 *
984 * {CTL_SYSCTL, CTL_SYSCTL_DEBUG} printf the entire MIB-tree.
985 * {CTL_SYSCTL, CTL_SYSCTL_NAME, ...} return the name of the "..."
986 * OID.
987 * {CTL_SYSCTL, CTL_SYSCTL_NEXT, ...} return the next OID, honoring
988 * CTLFLAG_SKIP.
989 * {CTL_SYSCTL, CTL_SYSCTL_NAME2OID} return the OID of the name in
990 * "new"
991 * {CTL_SYSCTL, CTL_SYSCTL_OIDFMT, ...} return the kind & format info
992 * for the "..." OID.
993 * {CTL_SYSCTL, CTL_SYSCTL_OIDDESCR, ...} return the description of the
994 * "..." OID.
995 * {CTL_SYSCTL, CTL_SYSCTL_OIDLABEL, ...} return the aggregation label of
996 * the "..." OID.
997 * {CTL_SYSCTL, CTL_SYSCTL_NEXTNOSKIP, ...} return the next OID, ignoring
998 * CTLFLAG_SKIP.
999 */
1000
1001 #ifdef SYSCTL_DEBUG
1002 static void
sysctl_sysctl_debug_dump_node(struct sysctl_oid_list * l,int i)1003 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i)
1004 {
1005 int k;
1006 struct sysctl_oid *oidp;
1007
1008 SYSCTL_ASSERT_LOCKED();
1009 SYSCTL_FOREACH(oidp, l) {
1010 for (k=0; k<i; k++)
1011 printf(" ");
1012
1013 printf("%d %s ", oidp->oid_number, oidp->oid_name);
1014
1015 printf("%c%c",
1016 oidp->oid_kind & CTLFLAG_RD ? 'R':' ',
1017 oidp->oid_kind & CTLFLAG_WR ? 'W':' ');
1018
1019 if (oidp->oid_handler)
1020 printf(" *Handler");
1021
1022 switch (oidp->oid_kind & CTLTYPE) {
1023 case CTLTYPE_NODE:
1024 printf(" Node\n");
1025 if (!oidp->oid_handler) {
1026 sysctl_sysctl_debug_dump_node(
1027 SYSCTL_CHILDREN(oidp), i + 2);
1028 }
1029 break;
1030 case CTLTYPE_INT: printf(" Int\n"); break;
1031 case CTLTYPE_UINT: printf(" u_int\n"); break;
1032 case CTLTYPE_LONG: printf(" Long\n"); break;
1033 case CTLTYPE_ULONG: printf(" u_long\n"); break;
1034 case CTLTYPE_STRING: printf(" String\n"); break;
1035 case CTLTYPE_S8: printf(" int8_t\n"); break;
1036 case CTLTYPE_S16: printf(" int16_t\n"); break;
1037 case CTLTYPE_S32: printf(" int32_t\n"); break;
1038 case CTLTYPE_S64: printf(" int64_t\n"); break;
1039 case CTLTYPE_U8: printf(" uint8_t\n"); break;
1040 case CTLTYPE_U16: printf(" uint16_t\n"); break;
1041 case CTLTYPE_U32: printf(" uint32_t\n"); break;
1042 case CTLTYPE_U64: printf(" uint64_t\n"); break;
1043 case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break;
1044 default: printf("\n");
1045 }
1046 }
1047 }
1048
1049 static int
sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS)1050 sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS)
1051 {
1052 struct rm_priotracker tracker;
1053 int error;
1054
1055 error = priv_check(req->td, PRIV_SYSCTL_DEBUG);
1056 if (error)
1057 return (error);
1058 SYSCTL_RLOCK(&tracker);
1059 sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
1060 SYSCTL_RUNLOCK(&tracker);
1061 return (ENOENT);
1062 }
1063
1064 SYSCTL_PROC(_sysctl, CTL_SYSCTL_DEBUG, debug, CTLTYPE_STRING | CTLFLAG_RD |
1065 CTLFLAG_MPSAFE, 0, 0, sysctl_sysctl_debug, "-", "");
1066 #endif
1067
1068 static int
sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)1069 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
1070 {
1071 int *name = (int *) arg1;
1072 u_int namelen = arg2;
1073 int error;
1074 struct sysctl_oid *oid, key;
1075 struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;
1076 struct rm_priotracker tracker;
1077 char buf[10];
1078
1079 error = sysctl_wire_old_buffer(req, 0);
1080 if (error)
1081 return (error);
1082
1083 SYSCTL_RLOCK(&tracker);
1084 while (namelen) {
1085 if (!lsp) {
1086 snprintf(buf,sizeof(buf),"%d",*name);
1087 if (req->oldidx)
1088 error = SYSCTL_OUT(req, ".", 1);
1089 if (!error)
1090 error = SYSCTL_OUT(req, buf, strlen(buf));
1091 if (error)
1092 goto out;
1093 namelen--;
1094 name++;
1095 continue;
1096 }
1097 lsp2 = NULL;
1098 key.oid_number = *name;
1099 oid = RB_FIND(sysctl_oid_list, lsp, &key);
1100 if (oid) {
1101 if (req->oldidx)
1102 error = SYSCTL_OUT(req, ".", 1);
1103 if (!error)
1104 error = SYSCTL_OUT(req, oid->oid_name,
1105 strlen(oid->oid_name));
1106 if (error)
1107 goto out;
1108
1109 namelen--;
1110 name++;
1111
1112 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE &&
1113 !oid->oid_handler)
1114 lsp2 = SYSCTL_CHILDREN(oid);
1115 }
1116 lsp = lsp2;
1117 }
1118 error = SYSCTL_OUT(req, "", 1);
1119 out:
1120 SYSCTL_RUNLOCK(&tracker);
1121 return (error);
1122 }
1123
1124 /*
1125 * XXXRW/JA: Shouldn't return name data for nodes that we don't permit in
1126 * capability mode.
1127 */
1128 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NAME, name, CTLFLAG_RD |
1129 CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_name, "");
1130
1131 enum sysctl_iter_action {
1132 ITER_SIBLINGS, /* Not matched, continue iterating siblings */
1133 ITER_CHILDREN, /* Node has children we need to iterate over them */
1134 ITER_FOUND, /* Matching node was found */
1135 };
1136
1137 /*
1138 * Tries to find the next node for @name and @namelen.
1139 *
1140 * Returns next action to take.
1141 */
1142 static enum sysctl_iter_action
sysctl_sysctl_next_node(struct sysctl_oid * oidp,int * name,unsigned int namelen,bool honor_skip)1143 sysctl_sysctl_next_node(struct sysctl_oid *oidp, int *name, unsigned int namelen,
1144 bool honor_skip)
1145 {
1146
1147 if ((oidp->oid_kind & CTLFLAG_DORMANT) != 0)
1148 return (ITER_SIBLINGS);
1149
1150 if (honor_skip && (oidp->oid_kind & CTLFLAG_SKIP) != 0)
1151 return (ITER_SIBLINGS);
1152
1153 if (namelen == 0) {
1154 /*
1155 * We have reached a node with a full name match and are
1156 * looking for the next oid in its children.
1157 *
1158 * For CTL_SYSCTL_NEXTNOSKIP we are done.
1159 *
1160 * For CTL_SYSCTL_NEXT we skip CTLTYPE_NODE (unless it
1161 * has a handler) and move on to the children.
1162 */
1163 if (!honor_skip)
1164 return (ITER_FOUND);
1165 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
1166 return (ITER_FOUND);
1167 /* If node does not have an iterator, treat it as leaf */
1168 if (oidp->oid_handler)
1169 return (ITER_FOUND);
1170
1171 /* Report oid as a node to iterate */
1172 return (ITER_CHILDREN);
1173 }
1174
1175 /*
1176 * No match yet. Continue seeking the given name.
1177 *
1178 * We are iterating in order by oid_number, so skip oids lower
1179 * than the one we are looking for.
1180 *
1181 * When the current oid_number is higher than the one we seek,
1182 * that means we have reached the next oid in the sequence and
1183 * should return it.
1184 *
1185 * If the oid_number matches the name at this level then we
1186 * have to find a node to continue searching at the next level.
1187 */
1188 if (oidp->oid_number < *name)
1189 return (ITER_SIBLINGS);
1190 if (oidp->oid_number > *name) {
1191 /*
1192 * We have reached the next oid.
1193 *
1194 * For CTL_SYSCTL_NEXTNOSKIP we are done.
1195 *
1196 * For CTL_SYSCTL_NEXT we skip CTLTYPE_NODE (unless it
1197 * has a handler) and move on to the children.
1198 */
1199 if (!honor_skip)
1200 return (ITER_FOUND);
1201 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
1202 return (ITER_FOUND);
1203 /* If node does not have an iterator, treat it as leaf */
1204 if (oidp->oid_handler)
1205 return (ITER_FOUND);
1206 return (ITER_CHILDREN);
1207 }
1208
1209 /* match at a current level */
1210 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
1211 return (ITER_SIBLINGS);
1212 if (oidp->oid_handler)
1213 return (ITER_SIBLINGS);
1214
1215 return (ITER_CHILDREN);
1216 }
1217
1218 /*
1219 * Recursively walk the sysctl subtree at lsp until we find the given name.
1220 * Returns true and fills in next oid data in @next and @len if oid is found.
1221 */
1222 static bool
sysctl_sysctl_next_action(struct sysctl_oid_list * lsp,int * name,u_int namelen,int * next,int * len,int level,bool honor_skip)1223 sysctl_sysctl_next_action(struct sysctl_oid_list *lsp, int *name, u_int namelen,
1224 int *next, int *len, int level, bool honor_skip)
1225 {
1226 struct sysctl_oid_list *next_lsp;
1227 struct sysctl_oid *oidp = NULL, key;
1228 bool success = false;
1229 enum sysctl_iter_action action;
1230
1231 SYSCTL_ASSERT_LOCKED();
1232 /*
1233 * Start the search at the requested oid. But if not found, then scan
1234 * through all children.
1235 */
1236 if (namelen > 0) {
1237 key.oid_number = *name;
1238 oidp = RB_FIND(sysctl_oid_list, lsp, &key);
1239 }
1240 if (!oidp)
1241 oidp = RB_MIN(sysctl_oid_list, lsp);
1242 for(; oidp != NULL; oidp = RB_NEXT(sysctl_oid_list, lsp, oidp)) {
1243 action = sysctl_sysctl_next_node(oidp, name, namelen,
1244 honor_skip);
1245 if (action == ITER_SIBLINGS)
1246 continue;
1247 if (action == ITER_FOUND) {
1248 success = true;
1249 break;
1250 }
1251 KASSERT((action== ITER_CHILDREN), ("ret(%d)!=ITER_CHILDREN", action));
1252
1253 next_lsp = SYSCTL_CHILDREN(oidp);
1254 if (namelen == 0) {
1255 success = sysctl_sysctl_next_action(next_lsp, NULL, 0,
1256 next + 1, len, level + 1, honor_skip);
1257 } else {
1258 success = sysctl_sysctl_next_action(next_lsp, name + 1,
1259 namelen - 1, next + 1, len, level + 1, honor_skip);
1260 if (!success) {
1261
1262 /*
1263 * We maintain the invariant that current node oid
1264 * is >= the oid provided in @name.
1265 * As there are no usable children at this node,
1266 * current node oid is strictly > than the requested
1267 * oid.
1268 * Hence, reduce namelen to 0 to allow for picking first
1269 * nodes/leafs in the next node in list.
1270 */
1271 namelen = 0;
1272 }
1273 }
1274 if (success)
1275 break;
1276 }
1277
1278 if (success) {
1279 *next = oidp->oid_number;
1280 if (level > *len)
1281 *len = level;
1282 }
1283
1284 return (success);
1285 }
1286
1287 static int
sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)1288 sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
1289 {
1290 int *name = (int *) arg1;
1291 u_int namelen = arg2;
1292 int len, error;
1293 bool success;
1294 struct sysctl_oid_list *lsp = &sysctl__children;
1295 struct rm_priotracker tracker;
1296 int next[CTL_MAXNAME];
1297
1298 len = 0;
1299 SYSCTL_RLOCK(&tracker);
1300 success = sysctl_sysctl_next_action(lsp, name, namelen, next, &len, 1,
1301 oidp->oid_number == CTL_SYSCTL_NEXT);
1302 SYSCTL_RUNLOCK(&tracker);
1303 if (!success)
1304 return (ENOENT);
1305 error = SYSCTL_OUT(req, next, len * sizeof (int));
1306 return (error);
1307 }
1308
1309 /*
1310 * XXXRW/JA: Shouldn't return next data for nodes that we don't permit in
1311 * capability mode.
1312 */
1313 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NEXT, next, CTLFLAG_RD |
1314 CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_next, "");
1315
1316 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_NEXTNOSKIP, nextnoskip, CTLFLAG_RD |
1317 CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_next, "");
1318
1319 static int
name2oid(char * name,int * oid,int * len,struct sysctl_oid ** oidpp)1320 name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp)
1321 {
1322 struct sysctl_oid *oidp;
1323 struct sysctl_oid_list *lsp = &sysctl__children;
1324
1325 SYSCTL_ASSERT_LOCKED();
1326
1327 for (*len = 0; *len < CTL_MAXNAME;) {
1328 oidp = sysctl_find_oidname(strsep(&name, "."), lsp);
1329 if (oidp == NULL)
1330 return (ENOENT);
1331 *oid++ = oidp->oid_number;
1332 (*len)++;
1333
1334 if (name == NULL || *name == '\0') {
1335 if (oidpp)
1336 *oidpp = oidp;
1337 return (0);
1338 }
1339
1340 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
1341 break;
1342
1343 if (oidp->oid_handler)
1344 break;
1345
1346 lsp = SYSCTL_CHILDREN(oidp);
1347 }
1348 return (ENOENT);
1349 }
1350
1351 static int
sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)1352 sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
1353 {
1354 char *p;
1355 int error, oid[CTL_MAXNAME], len = 0;
1356 struct sysctl_oid *op = NULL;
1357 struct rm_priotracker tracker;
1358 char buf[32];
1359
1360 if (!req->newlen)
1361 return (ENOENT);
1362 if (req->newlen >= MAXPATHLEN) /* XXX arbitrary, undocumented */
1363 return (ENAMETOOLONG);
1364
1365 p = buf;
1366 if (req->newlen >= sizeof(buf))
1367 p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK);
1368
1369 error = SYSCTL_IN(req, p, req->newlen);
1370 if (error) {
1371 if (p != buf)
1372 free(p, M_SYSCTL);
1373 return (error);
1374 }
1375
1376 p [req->newlen] = '\0';
1377
1378 SYSCTL_RLOCK(&tracker);
1379 error = name2oid(p, oid, &len, &op);
1380 SYSCTL_RUNLOCK(&tracker);
1381
1382 if (p != buf)
1383 free(p, M_SYSCTL);
1384
1385 if (error)
1386 return (error);
1387
1388 error = SYSCTL_OUT(req, oid, len * sizeof *oid);
1389 return (error);
1390 }
1391
1392 /*
1393 * XXXRW/JA: Shouldn't return name2oid data for nodes that we don't permit in
1394 * capability mode.
1395 */
1396 SYSCTL_PROC(_sysctl, CTL_SYSCTL_NAME2OID, name2oid, CTLTYPE_INT | CTLFLAG_RW |
1397 CTLFLAG_ANYBODY | CTLFLAG_MPSAFE | CTLFLAG_CAPRW, 0, 0,
1398 sysctl_sysctl_name2oid, "I", "");
1399
1400 static int
sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)1401 sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
1402 {
1403 struct sysctl_oid *oid;
1404 struct rm_priotracker tracker;
1405 int error;
1406
1407 error = sysctl_wire_old_buffer(req, 0);
1408 if (error)
1409 return (error);
1410
1411 SYSCTL_RLOCK(&tracker);
1412 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
1413 if (error)
1414 goto out;
1415
1416 if (oid->oid_fmt == NULL) {
1417 error = ENOENT;
1418 goto out;
1419 }
1420 error = SYSCTL_OUT(req, &oid->oid_kind, sizeof(oid->oid_kind));
1421 if (error)
1422 goto out;
1423 error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1);
1424 out:
1425 SYSCTL_RUNLOCK(&tracker);
1426 return (error);
1427 }
1428
1429 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_OIDFMT, oidfmt, CTLFLAG_RD |
1430 CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_oidfmt, "");
1431
1432 static int
sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)1433 sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)
1434 {
1435 struct sysctl_oid *oid;
1436 struct rm_priotracker tracker;
1437 int error;
1438
1439 error = sysctl_wire_old_buffer(req, 0);
1440 if (error)
1441 return (error);
1442
1443 SYSCTL_RLOCK(&tracker);
1444 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
1445 if (error)
1446 goto out;
1447
1448 if (oid->oid_descr == NULL) {
1449 error = ENOENT;
1450 goto out;
1451 }
1452 error = SYSCTL_OUT(req, oid->oid_descr, strlen(oid->oid_descr) + 1);
1453 out:
1454 SYSCTL_RUNLOCK(&tracker);
1455 return (error);
1456 }
1457
1458 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_OIDDESCR, oiddescr, CTLFLAG_RD |
1459 CTLFLAG_MPSAFE|CTLFLAG_CAPRD, sysctl_sysctl_oiddescr, "");
1460
1461 static int
sysctl_sysctl_oidlabel(SYSCTL_HANDLER_ARGS)1462 sysctl_sysctl_oidlabel(SYSCTL_HANDLER_ARGS)
1463 {
1464 struct sysctl_oid *oid;
1465 struct rm_priotracker tracker;
1466 int error;
1467
1468 error = sysctl_wire_old_buffer(req, 0);
1469 if (error)
1470 return (error);
1471
1472 SYSCTL_RLOCK(&tracker);
1473 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
1474 if (error)
1475 goto out;
1476
1477 if (oid->oid_label == NULL) {
1478 error = ENOENT;
1479 goto out;
1480 }
1481 error = SYSCTL_OUT(req, oid->oid_label, strlen(oid->oid_label) + 1);
1482 out:
1483 SYSCTL_RUNLOCK(&tracker);
1484 return (error);
1485 }
1486
1487 static SYSCTL_NODE(_sysctl, CTL_SYSCTL_OIDLABEL, oidlabel, CTLFLAG_RD |
1488 CTLFLAG_MPSAFE | CTLFLAG_CAPRD, sysctl_sysctl_oidlabel, "");
1489
1490 /*
1491 * Default "handler" functions.
1492 */
1493
1494 /*
1495 * Handle a bool.
1496 * Two cases:
1497 * a variable: point arg1 at it.
1498 * a constant: pass it in arg2.
1499 */
1500
1501 int
sysctl_handle_bool(SYSCTL_HANDLER_ARGS)1502 sysctl_handle_bool(SYSCTL_HANDLER_ARGS)
1503 {
1504 uint8_t temp;
1505 int error;
1506
1507 /*
1508 * Attempt to get a coherent snapshot by making a copy of the data.
1509 */
1510 if (arg1)
1511 temp = *(bool *)arg1 ? 1 : 0;
1512 else
1513 temp = arg2 ? 1 : 0;
1514
1515 error = SYSCTL_OUT(req, &temp, sizeof(temp));
1516 if (error || !req->newptr)
1517 return (error);
1518
1519 if (!arg1)
1520 error = EPERM;
1521 else {
1522 error = SYSCTL_IN(req, &temp, sizeof(temp));
1523 if (!error)
1524 *(bool *)arg1 = temp ? 1 : 0;
1525 }
1526 return (error);
1527 }
1528
1529 /*
1530 * Handle an int8_t, signed or unsigned.
1531 * Two cases:
1532 * a variable: point arg1 at it.
1533 * a constant: pass it in arg2.
1534 */
1535
1536 int
sysctl_handle_8(SYSCTL_HANDLER_ARGS)1537 sysctl_handle_8(SYSCTL_HANDLER_ARGS)
1538 {
1539 int8_t tmpout;
1540 int error = 0;
1541
1542 /*
1543 * Attempt to get a coherent snapshot by making a copy of the data.
1544 */
1545 if (arg1)
1546 tmpout = *(int8_t *)arg1;
1547 else
1548 tmpout = arg2;
1549 error = SYSCTL_OUT(req, &tmpout, sizeof(tmpout));
1550
1551 if (error || !req->newptr)
1552 return (error);
1553
1554 if (!arg1)
1555 error = EPERM;
1556 else
1557 error = SYSCTL_IN(req, arg1, sizeof(tmpout));
1558 return (error);
1559 }
1560
1561 /*
1562 * Handle an int16_t, signed or unsigned.
1563 * Two cases:
1564 * a variable: point arg1 at it.
1565 * a constant: pass it in arg2.
1566 */
1567
1568 int
sysctl_handle_16(SYSCTL_HANDLER_ARGS)1569 sysctl_handle_16(SYSCTL_HANDLER_ARGS)
1570 {
1571 int16_t tmpout;
1572 int error = 0;
1573
1574 /*
1575 * Attempt to get a coherent snapshot by making a copy of the data.
1576 */
1577 if (arg1)
1578 tmpout = *(int16_t *)arg1;
1579 else
1580 tmpout = arg2;
1581 error = SYSCTL_OUT(req, &tmpout, sizeof(tmpout));
1582
1583 if (error || !req->newptr)
1584 return (error);
1585
1586 if (!arg1)
1587 error = EPERM;
1588 else
1589 error = SYSCTL_IN(req, arg1, sizeof(tmpout));
1590 return (error);
1591 }
1592
1593 /*
1594 * Handle an int32_t, signed or unsigned.
1595 * Two cases:
1596 * a variable: point arg1 at it.
1597 * a constant: pass it in arg2.
1598 */
1599
1600 int
sysctl_handle_32(SYSCTL_HANDLER_ARGS)1601 sysctl_handle_32(SYSCTL_HANDLER_ARGS)
1602 {
1603 int32_t tmpout;
1604 int error = 0;
1605
1606 /*
1607 * Attempt to get a coherent snapshot by making a copy of the data.
1608 */
1609 if (arg1)
1610 tmpout = *(int32_t *)arg1;
1611 else
1612 tmpout = arg2;
1613 error = SYSCTL_OUT(req, &tmpout, sizeof(tmpout));
1614
1615 if (error || !req->newptr)
1616 return (error);
1617
1618 if (!arg1)
1619 error = EPERM;
1620 else
1621 error = SYSCTL_IN(req, arg1, sizeof(tmpout));
1622 return (error);
1623 }
1624
1625 /*
1626 * Handle an int, signed or unsigned.
1627 * Two cases:
1628 * a variable: point arg1 at it.
1629 * a constant: pass it in arg2.
1630 */
1631
1632 int
sysctl_handle_int(SYSCTL_HANDLER_ARGS)1633 sysctl_handle_int(SYSCTL_HANDLER_ARGS)
1634 {
1635 int tmpout, error = 0;
1636
1637 /*
1638 * Attempt to get a coherent snapshot by making a copy of the data.
1639 */
1640 if (arg1)
1641 tmpout = *(int *)arg1;
1642 else
1643 tmpout = arg2;
1644 error = SYSCTL_OUT(req, &tmpout, sizeof(int));
1645
1646 if (error || !req->newptr)
1647 return (error);
1648
1649 if (!arg1)
1650 error = EPERM;
1651 else
1652 error = SYSCTL_IN(req, arg1, sizeof(int));
1653 return (error);
1654 }
1655
1656 /*
1657 * Based on sysctl_handle_int() convert milliseconds into ticks.
1658 * Note: this is used by TCP.
1659 */
1660
1661 int
sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS)1662 sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS)
1663 {
1664 int error, s, tt;
1665
1666 tt = *(int *)arg1;
1667 s = (int)((int64_t)tt * 1000 / hz);
1668
1669 error = sysctl_handle_int(oidp, &s, 0, req);
1670 if (error || !req->newptr)
1671 return (error);
1672
1673 tt = (int)((int64_t)s * hz / 1000);
1674 if (tt < 1)
1675 return (EINVAL);
1676
1677 *(int *)arg1 = tt;
1678 return (0);
1679 }
1680
1681 /*
1682 * Handle a long, signed or unsigned.
1683 * Two cases:
1684 * a variable: point arg1 at it.
1685 * a constant: pass it in arg2.
1686 */
1687
1688 int
sysctl_handle_long(SYSCTL_HANDLER_ARGS)1689 sysctl_handle_long(SYSCTL_HANDLER_ARGS)
1690 {
1691 int error = 0;
1692 long tmplong;
1693 #ifdef SCTL_MASK32
1694 int tmpint;
1695 #endif
1696
1697 /*
1698 * Attempt to get a coherent snapshot by making a copy of the data.
1699 */
1700 if (arg1)
1701 tmplong = *(long *)arg1;
1702 else
1703 tmplong = arg2;
1704 #ifdef SCTL_MASK32
1705 if (req->flags & SCTL_MASK32) {
1706 tmpint = tmplong;
1707 error = SYSCTL_OUT(req, &tmpint, sizeof(int));
1708 } else
1709 #endif
1710 error = SYSCTL_OUT(req, &tmplong, sizeof(long));
1711
1712 if (error || !req->newptr)
1713 return (error);
1714
1715 if (!arg1)
1716 error = EPERM;
1717 #ifdef SCTL_MASK32
1718 else if (req->flags & SCTL_MASK32) {
1719 error = SYSCTL_IN(req, &tmpint, sizeof(int));
1720 *(long *)arg1 = (long)tmpint;
1721 }
1722 #endif
1723 else
1724 error = SYSCTL_IN(req, arg1, sizeof(long));
1725 return (error);
1726 }
1727
1728 /*
1729 * Handle a 64 bit int, signed or unsigned.
1730 * Two cases:
1731 * a variable: point arg1 at it.
1732 * a constant: pass it in arg2.
1733 */
1734 int
sysctl_handle_64(SYSCTL_HANDLER_ARGS)1735 sysctl_handle_64(SYSCTL_HANDLER_ARGS)
1736 {
1737 int error = 0;
1738 uint64_t tmpout;
1739
1740 /*
1741 * Attempt to get a coherent snapshot by making a copy of the data.
1742 */
1743 if (arg1)
1744 tmpout = *(uint64_t *)arg1;
1745 else
1746 tmpout = arg2;
1747 error = SYSCTL_OUT(req, &tmpout, sizeof(uint64_t));
1748
1749 if (error || !req->newptr)
1750 return (error);
1751
1752 if (!arg1)
1753 error = EPERM;
1754 else
1755 error = SYSCTL_IN(req, arg1, sizeof(uint64_t));
1756 return (error);
1757 }
1758
1759 /*
1760 * Handle our generic '\0' terminated 'C' string.
1761 * Two cases:
1762 * a variable string: point arg1 at it, arg2 is max length.
1763 * a constant string: point arg1 at it, arg2 is zero.
1764 */
1765
1766 int
sysctl_handle_string(SYSCTL_HANDLER_ARGS)1767 sysctl_handle_string(SYSCTL_HANDLER_ARGS)
1768 {
1769 char *tmparg;
1770 size_t outlen;
1771 int error = 0, ro_string = 0;
1772
1773 /*
1774 * If the sysctl isn't writable and isn't a preallocated tunable that
1775 * can be modified by kenv(2), microoptimise and treat it as a
1776 * read-only string.
1777 * A zero-length buffer indicates a fixed size read-only
1778 * string. In ddb, don't worry about trying to make a malloced
1779 * snapshot.
1780 */
1781 if ((oidp->oid_kind & (CTLFLAG_WR | CTLFLAG_TUN)) == 0 ||
1782 arg2 == 0 || kdb_active) {
1783 arg2 = strlen((char *)arg1) + 1;
1784 ro_string = 1;
1785 }
1786
1787 if (req->oldptr != NULL) {
1788 if (ro_string) {
1789 tmparg = arg1;
1790 outlen = strlen(tmparg) + 1;
1791 } else {
1792 tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK);
1793 sx_slock(&sysctlstringlock);
1794 memcpy(tmparg, arg1, arg2);
1795 sx_sunlock(&sysctlstringlock);
1796 outlen = strlen(tmparg) + 1;
1797 }
1798
1799 error = SYSCTL_OUT(req, tmparg, outlen);
1800
1801 if (!ro_string)
1802 free(tmparg, M_SYSCTLTMP);
1803 } else {
1804 if (!ro_string)
1805 sx_slock(&sysctlstringlock);
1806 outlen = strlen((char *)arg1) + 1;
1807 if (!ro_string)
1808 sx_sunlock(&sysctlstringlock);
1809 error = SYSCTL_OUT(req, NULL, outlen);
1810 }
1811 if (error || !req->newptr)
1812 return (error);
1813
1814 if (req->newlen - req->newidx >= arg2 ||
1815 req->newlen - req->newidx < 0) {
1816 error = EINVAL;
1817 } else if (req->newlen - req->newidx == 0) {
1818 sx_xlock(&sysctlstringlock);
1819 ((char *)arg1)[0] = '\0';
1820 sx_xunlock(&sysctlstringlock);
1821 } else if (req->newfunc == sysctl_new_kernel) {
1822 arg2 = req->newlen - req->newidx;
1823 sx_xlock(&sysctlstringlock);
1824 error = SYSCTL_IN(req, arg1, arg2);
1825 if (error == 0) {
1826 ((char *)arg1)[arg2] = '\0';
1827 req->newidx += arg2;
1828 }
1829 sx_xunlock(&sysctlstringlock);
1830 } else {
1831 arg2 = req->newlen - req->newidx;
1832 tmparg = malloc(arg2, M_SYSCTLTMP, M_WAITOK);
1833
1834 error = SYSCTL_IN(req, tmparg, arg2);
1835 if (error) {
1836 free(tmparg, M_SYSCTLTMP);
1837 return (error);
1838 }
1839
1840 sx_xlock(&sysctlstringlock);
1841 memcpy(arg1, tmparg, arg2);
1842 ((char *)arg1)[arg2] = '\0';
1843 sx_xunlock(&sysctlstringlock);
1844 free(tmparg, M_SYSCTLTMP);
1845 req->newidx += arg2;
1846 }
1847 return (error);
1848 }
1849
1850 /*
1851 * Handle any kind of opaque data.
1852 * arg1 points to it, arg2 is the size.
1853 */
1854
1855 int
sysctl_handle_opaque(SYSCTL_HANDLER_ARGS)1856 sysctl_handle_opaque(SYSCTL_HANDLER_ARGS)
1857 {
1858 int error, tries;
1859 u_int generation;
1860 struct sysctl_req req2;
1861
1862 /*
1863 * Attempt to get a coherent snapshot, by using the thread
1864 * pre-emption counter updated from within mi_switch() to
1865 * determine if we were pre-empted during a bcopy() or
1866 * copyout(). Make 3 attempts at doing this before giving up.
1867 * If we encounter an error, stop immediately.
1868 */
1869 tries = 0;
1870 req2 = *req;
1871 retry:
1872 generation = curthread->td_generation;
1873 error = SYSCTL_OUT(req, arg1, arg2);
1874 if (error)
1875 return (error);
1876 tries++;
1877 if (generation != curthread->td_generation && tries < 3) {
1878 *req = req2;
1879 goto retry;
1880 }
1881
1882 error = SYSCTL_IN(req, arg1, arg2);
1883
1884 return (error);
1885 }
1886
1887 /*
1888 * Based on sysctl_handle_64() convert microseconds to a sbintime.
1889 */
1890 int
sysctl_usec_to_sbintime(SYSCTL_HANDLER_ARGS)1891 sysctl_usec_to_sbintime(SYSCTL_HANDLER_ARGS)
1892 {
1893 int error;
1894 int64_t usec;
1895
1896 usec = sbttous(*(sbintime_t *)arg1);
1897
1898 error = sysctl_handle_64(oidp, &usec, 0, req);
1899 if (error || !req->newptr)
1900 return (error);
1901
1902 *(sbintime_t *)arg1 = ustosbt(usec);
1903
1904 return (0);
1905 }
1906
1907 /*
1908 * Based on sysctl_handle_64() convert milliseconds to a sbintime.
1909 */
1910 int
sysctl_msec_to_sbintime(SYSCTL_HANDLER_ARGS)1911 sysctl_msec_to_sbintime(SYSCTL_HANDLER_ARGS)
1912 {
1913 int error;
1914 int64_t msec;
1915
1916 msec = sbttoms(*(sbintime_t *)arg1);
1917
1918 error = sysctl_handle_64(oidp, &msec, 0, req);
1919 if (error || !req->newptr)
1920 return (error);
1921
1922 *(sbintime_t *)arg1 = mstosbt(msec);
1923
1924 return (0);
1925 }
1926
1927 /*
1928 * Convert seconds to a struct timeval. Intended for use with
1929 * intervals and thus does not permit negative seconds.
1930 */
1931 int
sysctl_sec_to_timeval(SYSCTL_HANDLER_ARGS)1932 sysctl_sec_to_timeval(SYSCTL_HANDLER_ARGS)
1933 {
1934 struct timeval *tv;
1935 int error, secs;
1936
1937 tv = arg1;
1938 secs = tv->tv_sec;
1939
1940 error = sysctl_handle_int(oidp, &secs, 0, req);
1941 if (error || req->newptr == NULL)
1942 return (error);
1943
1944 if (secs < 0)
1945 return (EINVAL);
1946 tv->tv_sec = secs;
1947
1948 return (0);
1949 }
1950
1951 /*
1952 * Transfer functions to/from kernel space.
1953 * XXX: rather untested at this point
1954 */
1955 static int
sysctl_old_kernel(struct sysctl_req * req,const void * p,size_t l)1956 sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l)
1957 {
1958 size_t i = 0;
1959
1960 if (req->oldptr) {
1961 i = l;
1962 if (req->oldlen <= req->oldidx)
1963 i = 0;
1964 else
1965 if (i > req->oldlen - req->oldidx)
1966 i = req->oldlen - req->oldidx;
1967 if (i > 0)
1968 bcopy(p, (char *)req->oldptr + req->oldidx, i);
1969 }
1970 req->oldidx += l;
1971 if (req->oldptr && i != l)
1972 return (ENOMEM);
1973 return (0);
1974 }
1975
1976 static int
sysctl_new_kernel(struct sysctl_req * req,void * p,size_t l)1977 sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l)
1978 {
1979 if (!req->newptr)
1980 return (0);
1981 if (req->newlen - req->newidx < l)
1982 return (EINVAL);
1983 bcopy((const char *)req->newptr + req->newidx, p, l);
1984 req->newidx += l;
1985 return (0);
1986 }
1987
1988 int
kernel_sysctl(struct thread * td,int * name,u_int namelen,void * old,size_t * oldlenp,void * new,size_t newlen,size_t * retval,int flags)1989 kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old,
1990 size_t *oldlenp, void *new, size_t newlen, size_t *retval, int flags)
1991 {
1992 int error = 0;
1993 struct sysctl_req req;
1994
1995 bzero(&req, sizeof req);
1996
1997 req.td = td;
1998 req.flags = flags;
1999
2000 if (oldlenp) {
2001 req.oldlen = *oldlenp;
2002 }
2003 req.validlen = req.oldlen;
2004
2005 if (old) {
2006 req.oldptr= old;
2007 }
2008
2009 if (new != NULL) {
2010 req.newlen = newlen;
2011 req.newptr = new;
2012 }
2013
2014 req.oldfunc = sysctl_old_kernel;
2015 req.newfunc = sysctl_new_kernel;
2016 req.lock = REQ_UNWIRED;
2017
2018 error = sysctl_root(0, name, namelen, &req);
2019
2020 if (req.lock == REQ_WIRED && req.validlen > 0)
2021 vsunlock(req.oldptr, req.validlen);
2022
2023 if (error && error != ENOMEM)
2024 return (error);
2025
2026 if (retval) {
2027 if (req.oldptr && req.oldidx > req.validlen)
2028 *retval = req.validlen;
2029 else
2030 *retval = req.oldidx;
2031 }
2032 return (error);
2033 }
2034
2035 int
kernel_sysctlbyname(struct thread * td,char * name,void * old,size_t * oldlenp,void * new,size_t newlen,size_t * retval,int flags)2036 kernel_sysctlbyname(struct thread *td, char *name, void *old, size_t *oldlenp,
2037 void *new, size_t newlen, size_t *retval, int flags)
2038 {
2039 int oid[CTL_MAXNAME];
2040 size_t oidlen, plen;
2041 int error;
2042
2043 oid[0] = CTL_SYSCTL;
2044 oid[1] = CTL_SYSCTL_NAME2OID;
2045 oidlen = sizeof(oid);
2046
2047 error = kernel_sysctl(td, oid, 2, oid, &oidlen,
2048 (void *)name, strlen(name), &plen, flags);
2049 if (error)
2050 return (error);
2051
2052 error = kernel_sysctl(td, oid, plen / sizeof(int), old, oldlenp,
2053 new, newlen, retval, flags);
2054 return (error);
2055 }
2056
2057 /*
2058 * Transfer function to/from user space.
2059 */
2060 static int
sysctl_old_user(struct sysctl_req * req,const void * p,size_t l)2061 sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
2062 {
2063 size_t i, len, origidx;
2064 int error;
2065
2066 origidx = req->oldidx;
2067 req->oldidx += l;
2068 if (req->oldptr == NULL)
2069 return (0);
2070 /*
2071 * If we have not wired the user supplied buffer and we are currently
2072 * holding locks, drop a witness warning, as it's possible that
2073 * write operations to the user page can sleep.
2074 */
2075 if (req->lock != REQ_WIRED)
2076 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
2077 "sysctl_old_user()");
2078 i = l;
2079 len = req->validlen;
2080 if (len <= origidx)
2081 i = 0;
2082 else {
2083 if (i > len - origidx)
2084 i = len - origidx;
2085 if (req->lock == REQ_WIRED) {
2086 error = copyout_nofault(p, (char *)req->oldptr +
2087 origidx, i);
2088 } else
2089 error = copyout(p, (char *)req->oldptr + origidx, i);
2090 if (error != 0)
2091 return (error);
2092 }
2093 if (i < l)
2094 return (ENOMEM);
2095 return (0);
2096 }
2097
2098 static int
sysctl_new_user(struct sysctl_req * req,void * p,size_t l)2099 sysctl_new_user(struct sysctl_req *req, void *p, size_t l)
2100 {
2101 int error;
2102
2103 if (!req->newptr)
2104 return (0);
2105 if (req->newlen - req->newidx < l)
2106 return (EINVAL);
2107 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
2108 "sysctl_new_user()");
2109 error = copyin((const char *)req->newptr + req->newidx, p, l);
2110 req->newidx += l;
2111 return (error);
2112 }
2113
2114 /*
2115 * Wire the user space destination buffer. If set to a value greater than
2116 * zero, the len parameter limits the maximum amount of wired memory.
2117 */
2118 int
sysctl_wire_old_buffer(struct sysctl_req * req,size_t len)2119 sysctl_wire_old_buffer(struct sysctl_req *req, size_t len)
2120 {
2121 int ret;
2122 size_t wiredlen;
2123
2124 wiredlen = (len > 0 && len < req->oldlen) ? len : req->oldlen;
2125 ret = 0;
2126 if (req->lock != REQ_WIRED && req->oldptr &&
2127 req->oldfunc == sysctl_old_user) {
2128 if (wiredlen != 0) {
2129 ret = vslock(req->oldptr, wiredlen);
2130 if (ret != 0) {
2131 if (ret != ENOMEM)
2132 return (ret);
2133 wiredlen = 0;
2134 }
2135 }
2136 req->lock = REQ_WIRED;
2137 req->validlen = wiredlen;
2138 }
2139 return (0);
2140 }
2141
2142 int
sysctl_find_oid(int * name,u_int namelen,struct sysctl_oid ** noid,int * nindx,struct sysctl_req * req)2143 sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid,
2144 int *nindx, struct sysctl_req *req)
2145 {
2146 struct sysctl_oid_list *lsp;
2147 struct sysctl_oid *oid;
2148 struct sysctl_oid key;
2149 int indx;
2150
2151 SYSCTL_ASSERT_LOCKED();
2152 lsp = &sysctl__children;
2153 indx = 0;
2154 while (indx < CTL_MAXNAME) {
2155 key.oid_number = name[indx];
2156 oid = RB_FIND(sysctl_oid_list, lsp, &key);
2157 if (oid == NULL)
2158 return (ENOENT);
2159
2160 indx++;
2161 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
2162 if (oid->oid_handler != NULL || indx == namelen) {
2163 *noid = oid;
2164 if (nindx != NULL)
2165 *nindx = indx;
2166 KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0,
2167 ("%s found DYING node %p", __func__, oid));
2168 return (0);
2169 }
2170 lsp = SYSCTL_CHILDREN(oid);
2171 } else if (indx == namelen) {
2172 if ((oid->oid_kind & CTLFLAG_DORMANT) != 0)
2173 return (ENOENT);
2174 *noid = oid;
2175 if (nindx != NULL)
2176 *nindx = indx;
2177 KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0,
2178 ("%s found DYING node %p", __func__, oid));
2179 return (0);
2180 } else {
2181 return (ENOTDIR);
2182 }
2183 }
2184 return (ENOENT);
2185 }
2186
2187 /*
2188 * Traverse our tree, and find the right node, execute whatever it points
2189 * to, and return the resulting error code.
2190 */
2191
2192 static int
sysctl_root(SYSCTL_HANDLER_ARGS)2193 sysctl_root(SYSCTL_HANDLER_ARGS)
2194 {
2195 struct sysctl_oid *oid;
2196 struct rm_priotracker tracker;
2197 int error, indx, lvl;
2198
2199 SYSCTL_RLOCK(&tracker);
2200
2201 error = sysctl_find_oid(arg1, arg2, &oid, &indx, req);
2202 if (error)
2203 goto out;
2204
2205 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
2206 /*
2207 * You can't call a sysctl when it's a node, but has
2208 * no handler. Inform the user that it's a node.
2209 * The indx may or may not be the same as namelen.
2210 */
2211 if (oid->oid_handler == NULL) {
2212 error = EISDIR;
2213 goto out;
2214 }
2215 }
2216
2217 /* Is this sysctl writable? */
2218 if (req->newptr && !(oid->oid_kind & CTLFLAG_WR)) {
2219 error = EPERM;
2220 goto out;
2221 }
2222
2223 KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL"));
2224
2225 #ifdef CAPABILITY_MODE
2226 /*
2227 * If the process is in capability mode, then don't permit reading or
2228 * writing unless specifically granted for the node.
2229 */
2230 if (IN_CAPABILITY_MODE(req->td)) {
2231 if ((req->oldptr && !(oid->oid_kind & CTLFLAG_CAPRD)) ||
2232 (req->newptr && !(oid->oid_kind & CTLFLAG_CAPWR))) {
2233 error = EPERM;
2234 goto out;
2235 }
2236 }
2237 #endif
2238
2239 /* Is this sysctl sensitive to securelevels? */
2240 if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) {
2241 lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE;
2242 error = securelevel_gt(req->td->td_ucred, lvl);
2243 if (error)
2244 goto out;
2245 }
2246
2247 /* Is this sysctl writable by only privileged users? */
2248 if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) {
2249 int priv;
2250
2251 if (oid->oid_kind & CTLFLAG_PRISON)
2252 priv = PRIV_SYSCTL_WRITEJAIL;
2253 #ifdef VIMAGE
2254 else if ((oid->oid_kind & CTLFLAG_VNET) &&
2255 prison_owns_vnet(req->td->td_ucred))
2256 priv = PRIV_SYSCTL_WRITEJAIL;
2257 #endif
2258 else
2259 priv = PRIV_SYSCTL_WRITE;
2260 error = priv_check(req->td, priv);
2261 if (error)
2262 goto out;
2263 }
2264
2265 if (!oid->oid_handler) {
2266 error = EINVAL;
2267 goto out;
2268 }
2269
2270 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
2271 arg1 = (int *)arg1 + indx;
2272 arg2 -= indx;
2273 } else {
2274 arg1 = oid->oid_arg1;
2275 arg2 = oid->oid_arg2;
2276 }
2277 #ifdef MAC
2278 error = mac_system_check_sysctl(req->td->td_ucred, oid, arg1, arg2,
2279 req);
2280 if (error != 0)
2281 goto out;
2282 #endif
2283 #ifdef VIMAGE
2284 if ((oid->oid_kind & CTLFLAG_VNET) && arg1 != NULL)
2285 arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1);
2286 #endif
2287 error = sysctl_root_handler_locked(oid, arg1, arg2, req, &tracker);
2288
2289 out:
2290 SYSCTL_RUNLOCK(&tracker);
2291 return (error);
2292 }
2293
2294 #ifndef _SYS_SYSPROTO_H_
2295 struct __sysctl_args {
2296 int *name;
2297 u_int namelen;
2298 void *old;
2299 size_t *oldlenp;
2300 void *new;
2301 size_t newlen;
2302 };
2303 #endif
2304 int
sys___sysctl(struct thread * td,struct __sysctl_args * uap)2305 sys___sysctl(struct thread *td, struct __sysctl_args *uap)
2306 {
2307 int error, i, name[CTL_MAXNAME];
2308 size_t j;
2309
2310 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
2311 return (EINVAL);
2312
2313 error = copyin(uap->name, &name, uap->namelen * sizeof(int));
2314 if (error)
2315 return (error);
2316
2317 error = userland_sysctl(td, name, uap->namelen,
2318 uap->old, uap->oldlenp, 0,
2319 uap->new, uap->newlen, &j, 0);
2320 if (error && error != ENOMEM)
2321 return (error);
2322 if (uap->oldlenp) {
2323 i = copyout(&j, uap->oldlenp, sizeof(j));
2324 if (i)
2325 return (i);
2326 }
2327 return (error);
2328 }
2329
2330 int
kern___sysctlbyname(struct thread * td,const char * oname,size_t namelen,void * old,size_t * oldlenp,void * new,size_t newlen,size_t * retval,int flags,bool inkernel)2331 kern___sysctlbyname(struct thread *td, const char *oname, size_t namelen,
2332 void *old, size_t *oldlenp, void *new, size_t newlen, size_t *retval,
2333 int flags, bool inkernel)
2334 {
2335 int oid[CTL_MAXNAME];
2336 char namebuf[16];
2337 char *name;
2338 size_t oidlen;
2339 int error;
2340
2341 if (namelen > MAXPATHLEN || namelen == 0)
2342 return (EINVAL);
2343 name = namebuf;
2344 if (namelen > sizeof(namebuf))
2345 name = malloc(namelen, M_SYSCTL, M_WAITOK);
2346 error = copyin(oname, name, namelen);
2347 if (error != 0)
2348 goto out;
2349
2350 oid[0] = CTL_SYSCTL;
2351 oid[1] = CTL_SYSCTL_NAME2OID;
2352 oidlen = sizeof(oid);
2353 error = kernel_sysctl(td, oid, 2, oid, &oidlen, (void *)name, namelen,
2354 retval, flags);
2355 if (error != 0)
2356 goto out;
2357 error = userland_sysctl(td, oid, *retval / sizeof(int), old, oldlenp,
2358 inkernel, new, newlen, retval, flags);
2359
2360 out:
2361 if (namelen > sizeof(namebuf))
2362 free(name, M_SYSCTL);
2363 return (error);
2364 }
2365
2366 #ifndef _SYS_SYSPROTO_H_
2367 struct __sysctlbyname_args {
2368 const char *name;
2369 size_t namelen;
2370 void *old;
2371 size_t *oldlenp;
2372 void *new;
2373 size_t newlen;
2374 };
2375 #endif
2376 int
sys___sysctlbyname(struct thread * td,struct __sysctlbyname_args * uap)2377 sys___sysctlbyname(struct thread *td, struct __sysctlbyname_args *uap)
2378 {
2379 size_t rv;
2380 int error;
2381
2382 error = kern___sysctlbyname(td, uap->name, uap->namelen, uap->old,
2383 uap->oldlenp, uap->new, uap->newlen, &rv, 0, 0);
2384 if (error != 0)
2385 return (error);
2386 if (uap->oldlenp != NULL)
2387 error = copyout(&rv, uap->oldlenp, sizeof(rv));
2388
2389 return (error);
2390 }
2391
2392 /*
2393 * This is used from various compatibility syscalls too. That's why name
2394 * must be in kernel space.
2395 */
2396 int
userland_sysctl(struct thread * td,int * name,u_int namelen,void * old,size_t * oldlenp,int inkernel,const void * new,size_t newlen,size_t * retval,int flags)2397 userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
2398 size_t *oldlenp, int inkernel, const void *new, size_t newlen,
2399 size_t *retval, int flags)
2400 {
2401 int error = 0, memlocked;
2402 struct sysctl_req req;
2403
2404 bzero(&req, sizeof req);
2405
2406 req.td = td;
2407 req.flags = flags;
2408
2409 if (oldlenp) {
2410 if (inkernel) {
2411 req.oldlen = *oldlenp;
2412 } else {
2413 error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp));
2414 if (error)
2415 return (error);
2416 }
2417 }
2418 req.validlen = req.oldlen;
2419 req.oldptr = old;
2420
2421 if (new != NULL) {
2422 req.newlen = newlen;
2423 req.newptr = new;
2424 }
2425
2426 req.oldfunc = sysctl_old_user;
2427 req.newfunc = sysctl_new_user;
2428 req.lock = REQ_UNWIRED;
2429
2430 #ifdef KTRACE
2431 if (KTRPOINT(curthread, KTR_SYSCTL))
2432 ktrsysctl(name, namelen);
2433 #endif
2434 memlocked = 0;
2435 if (req.oldptr && req.oldlen > 4 * PAGE_SIZE) {
2436 memlocked = 1;
2437 sx_xlock(&sysctlmemlock);
2438 }
2439 CURVNET_SET(TD_TO_VNET(td));
2440
2441 for (;;) {
2442 req.oldidx = 0;
2443 req.newidx = 0;
2444 error = sysctl_root(0, name, namelen, &req);
2445 if (error != EAGAIN)
2446 break;
2447 kern_yield(PRI_USER);
2448 }
2449
2450 CURVNET_RESTORE();
2451
2452 if (req.lock == REQ_WIRED && req.validlen > 0)
2453 vsunlock(req.oldptr, req.validlen);
2454 if (memlocked)
2455 sx_xunlock(&sysctlmemlock);
2456
2457 if (error && error != ENOMEM)
2458 return (error);
2459
2460 if (retval) {
2461 if (req.oldptr && req.oldidx > req.validlen)
2462 *retval = req.validlen;
2463 else
2464 *retval = req.oldidx;
2465 }
2466 return (error);
2467 }
2468
2469 /*
2470 * Drain into a sysctl struct. The user buffer should be wired if a page
2471 * fault would cause issue.
2472 */
2473 static int
sbuf_sysctl_drain(void * arg,const char * data,int len)2474 sbuf_sysctl_drain(void *arg, const char *data, int len)
2475 {
2476 struct sysctl_req *req = arg;
2477 int error;
2478
2479 error = SYSCTL_OUT(req, data, len);
2480 KASSERT(error >= 0, ("Got unexpected negative value %d", error));
2481 return (error == 0 ? len : -error);
2482 }
2483
2484 struct sbuf *
sbuf_new_for_sysctl(struct sbuf * s,char * buf,int length,struct sysctl_req * req)2485 sbuf_new_for_sysctl(struct sbuf *s, char *buf, int length,
2486 struct sysctl_req *req)
2487 {
2488
2489 /* Supply a default buffer size if none given. */
2490 if (buf == NULL && length == 0)
2491 length = 64;
2492 s = sbuf_new(s, buf, length, SBUF_FIXEDLEN | SBUF_INCLUDENUL);
2493 sbuf_set_drain(s, sbuf_sysctl_drain, req);
2494 return (s);
2495 }
2496
2497 #ifdef DDB
2498
2499 /* The current OID the debugger is working with */
2500 static struct sysctl_oid *g_ddb_oid;
2501
2502 /* The current flags specified by the user */
2503 static int g_ddb_sysctl_flags;
2504
2505 /* Check to see if the last sysctl printed */
2506 static int g_ddb_sysctl_printed;
2507
2508 static const int ctl_sign[CTLTYPE+1] = {
2509 [CTLTYPE_INT] = 1,
2510 [CTLTYPE_LONG] = 1,
2511 [CTLTYPE_S8] = 1,
2512 [CTLTYPE_S16] = 1,
2513 [CTLTYPE_S32] = 1,
2514 [CTLTYPE_S64] = 1,
2515 };
2516
2517 static const int ctl_size[CTLTYPE+1] = {
2518 [CTLTYPE_INT] = sizeof(int),
2519 [CTLTYPE_UINT] = sizeof(u_int),
2520 [CTLTYPE_LONG] = sizeof(long),
2521 [CTLTYPE_ULONG] = sizeof(u_long),
2522 [CTLTYPE_S8] = sizeof(int8_t),
2523 [CTLTYPE_S16] = sizeof(int16_t),
2524 [CTLTYPE_S32] = sizeof(int32_t),
2525 [CTLTYPE_S64] = sizeof(int64_t),
2526 [CTLTYPE_U8] = sizeof(uint8_t),
2527 [CTLTYPE_U16] = sizeof(uint16_t),
2528 [CTLTYPE_U32] = sizeof(uint32_t),
2529 [CTLTYPE_U64] = sizeof(uint64_t),
2530 };
2531
2532 #define DB_SYSCTL_NAME_ONLY 0x001 /* Compare with -N */
2533 #define DB_SYSCTL_VALUE_ONLY 0x002 /* Compare with -n */
2534 #define DB_SYSCTL_OPAQUE 0x004 /* Compare with -o */
2535 #define DB_SYSCTL_HEX 0x008 /* Compare with -x */
2536
2537 #define DB_SYSCTL_SAFE_ONLY 0x100 /* Only simple types */
2538
2539 static const char db_sysctl_modifs[] = {
2540 'N', 'n', 'o', 'x',
2541 };
2542
2543 static const int db_sysctl_modif_values[] = {
2544 DB_SYSCTL_NAME_ONLY, DB_SYSCTL_VALUE_ONLY,
2545 DB_SYSCTL_OPAQUE, DB_SYSCTL_HEX,
2546 };
2547
2548 /* Handlers considered safe to print while recursing */
2549 static int (* const db_safe_handlers[])(SYSCTL_HANDLER_ARGS) = {
2550 sysctl_handle_bool,
2551 sysctl_handle_8,
2552 sysctl_handle_16,
2553 sysctl_handle_32,
2554 sysctl_handle_64,
2555 sysctl_handle_int,
2556 sysctl_handle_long,
2557 sysctl_handle_string,
2558 sysctl_handle_opaque,
2559 };
2560
2561 /*
2562 * Use in place of sysctl_old_kernel to print sysctl values.
2563 *
2564 * Compare to the output handling in show_var from sbin/sysctl/sysctl.c
2565 */
2566 static int
sysctl_old_ddb(struct sysctl_req * req,const void * ptr,size_t len)2567 sysctl_old_ddb(struct sysctl_req *req, const void *ptr, size_t len)
2568 {
2569 const u_char *val, *p;
2570 const char *sep1;
2571 size_t intlen, slen;
2572 uintmax_t umv;
2573 intmax_t mv;
2574 int sign, ctltype, hexlen, xflag, error;
2575
2576 /* Suppress false-positive GCC uninitialized variable warnings */
2577 mv = 0;
2578 umv = 0;
2579
2580 slen = len;
2581 val = p = ptr;
2582
2583 if (ptr == NULL) {
2584 error = 0;
2585 goto out;
2586 }
2587
2588 /* We are going to print */
2589 g_ddb_sysctl_printed = 1;
2590
2591 xflag = g_ddb_sysctl_flags & DB_SYSCTL_HEX;
2592
2593 ctltype = (g_ddb_oid->oid_kind & CTLTYPE);
2594 sign = ctl_sign[ctltype];
2595 intlen = ctl_size[ctltype];
2596
2597 switch (ctltype) {
2598 case CTLTYPE_NODE:
2599 case CTLTYPE_STRING:
2600 db_printf("%.*s", (int) len, (const char *) p);
2601 error = 0;
2602 goto out;
2603
2604 case CTLTYPE_INT:
2605 case CTLTYPE_UINT:
2606 case CTLTYPE_LONG:
2607 case CTLTYPE_ULONG:
2608 case CTLTYPE_S8:
2609 case CTLTYPE_S16:
2610 case CTLTYPE_S32:
2611 case CTLTYPE_S64:
2612 case CTLTYPE_U8:
2613 case CTLTYPE_U16:
2614 case CTLTYPE_U32:
2615 case CTLTYPE_U64:
2616 hexlen = 2 + (intlen * CHAR_BIT + 3) / 4;
2617 sep1 = "";
2618 while (len >= intlen) {
2619 switch (ctltype) {
2620 case CTLTYPE_INT:
2621 case CTLTYPE_UINT:
2622 umv = *(const u_int *)p;
2623 mv = *(const int *)p;
2624 break;
2625 case CTLTYPE_LONG:
2626 case CTLTYPE_ULONG:
2627 umv = *(const u_long *)p;
2628 mv = *(const long *)p;
2629 break;
2630 case CTLTYPE_S8:
2631 case CTLTYPE_U8:
2632 umv = *(const uint8_t *)p;
2633 mv = *(const int8_t *)p;
2634 break;
2635 case CTLTYPE_S16:
2636 case CTLTYPE_U16:
2637 umv = *(const uint16_t *)p;
2638 mv = *(const int16_t *)p;
2639 break;
2640 case CTLTYPE_S32:
2641 case CTLTYPE_U32:
2642 umv = *(const uint32_t *)p;
2643 mv = *(const int32_t *)p;
2644 break;
2645 case CTLTYPE_S64:
2646 case CTLTYPE_U64:
2647 umv = *(const uint64_t *)p;
2648 mv = *(const int64_t *)p;
2649 break;
2650 }
2651
2652 db_printf("%s", sep1);
2653 if (xflag)
2654 db_printf("%#0*jx", hexlen, umv);
2655 else if (!sign)
2656 db_printf("%ju", umv);
2657 else if (g_ddb_oid->oid_fmt[1] == 'K') {
2658 /* Kelvins are currently unsupported. */
2659 error = EOPNOTSUPP;
2660 goto out;
2661 } else
2662 db_printf("%jd", mv);
2663
2664 sep1 = " ";
2665 len -= intlen;
2666 p += intlen;
2667 }
2668 error = 0;
2669 goto out;
2670
2671 case CTLTYPE_OPAQUE:
2672 /* TODO: Support struct functions. */
2673
2674 /* FALLTHROUGH */
2675 default:
2676 db_printf("Format:%s Length:%zu Dump:0x",
2677 g_ddb_oid->oid_fmt, len);
2678 while (len-- && (xflag || p < val + 16))
2679 db_printf("%02x", *p++);
2680 if (!xflag && len > 16)
2681 db_printf("...");
2682 error = 0;
2683 goto out;
2684 }
2685
2686 out:
2687 req->oldidx += slen;
2688 return (error);
2689 }
2690
2691 /*
2692 * Avoid setting new sysctl values from the debugger
2693 */
2694 static int
sysctl_new_ddb(struct sysctl_req * req,void * p,size_t l)2695 sysctl_new_ddb(struct sysctl_req *req, void *p, size_t l)
2696 {
2697
2698 if (!req->newptr)
2699 return (0);
2700
2701 /* Changing sysctls from the debugger is currently unsupported */
2702 return (EPERM);
2703 }
2704
2705 /*
2706 * Run a sysctl handler with the DDB oldfunc and newfunc attached.
2707 * Instead of copying any output to a buffer we'll dump it right to
2708 * the console.
2709 */
2710 static int
db_sysctl(struct sysctl_oid * oidp,int * name,u_int namelen,void * old,size_t * oldlenp,size_t * retval,int flags)2711 db_sysctl(struct sysctl_oid *oidp, int *name, u_int namelen,
2712 void *old, size_t *oldlenp, size_t *retval, int flags)
2713 {
2714 struct sysctl_req req;
2715 int error;
2716
2717 /* Setup the request */
2718 bzero(&req, sizeof req);
2719 req.td = kdb_thread;
2720 req.oldfunc = sysctl_old_ddb;
2721 req.newfunc = sysctl_new_ddb;
2722 req.lock = REQ_UNWIRED;
2723 if (oldlenp) {
2724 req.oldlen = *oldlenp;
2725 }
2726 req.validlen = req.oldlen;
2727 if (old) {
2728 req.oldptr = old;
2729 }
2730
2731 /* Setup our globals for sysctl_old_ddb */
2732 g_ddb_oid = oidp;
2733 g_ddb_sysctl_flags = flags;
2734 g_ddb_sysctl_printed = 0;
2735
2736 error = sysctl_root(0, name, namelen, &req);
2737
2738 /* Reset globals */
2739 g_ddb_oid = NULL;
2740 g_ddb_sysctl_flags = 0;
2741
2742 if (retval) {
2743 if (req.oldptr && req.oldidx > req.validlen)
2744 *retval = req.validlen;
2745 else
2746 *retval = req.oldidx;
2747 }
2748 return (error);
2749 }
2750
2751 /*
2752 * Show a sysctl's name
2753 */
2754 static void
db_show_oid_name(int * oid,size_t nlen)2755 db_show_oid_name(int *oid, size_t nlen)
2756 {
2757 struct sysctl_oid *oidp;
2758 int qoid[CTL_MAXNAME + 2];
2759 int error;
2760
2761 qoid[0] = CTL_SYSCTL;
2762 qoid[1] = CTL_SYSCTL_NAME;
2763 memcpy(qoid + 2, oid, nlen * sizeof(int));
2764
2765 error = sysctl_find_oid(qoid, nlen + 2, &oidp, NULL, NULL);
2766 if (error)
2767 db_error("sysctl name oid");
2768
2769 error = db_sysctl(oidp, qoid, nlen + 2, NULL, NULL, NULL, 0);
2770 if (error)
2771 db_error("sysctl name");
2772 }
2773
2774 /*
2775 * Check to see if an OID is safe to print from ddb.
2776 */
2777 static bool
db_oid_safe(const struct sysctl_oid * oidp)2778 db_oid_safe(const struct sysctl_oid *oidp)
2779 {
2780 for (unsigned int i = 0; i < nitems(db_safe_handlers); ++i) {
2781 if (oidp->oid_handler == db_safe_handlers[i])
2782 return (true);
2783 }
2784
2785 return (false);
2786 }
2787
2788 /*
2789 * Show a sysctl at a specific OID
2790 * Compare to the input handling in show_var from sbin/sysctl/sysctl.c
2791 */
2792 static int
db_show_oid(struct sysctl_oid * oidp,int * oid,size_t nlen,int flags)2793 db_show_oid(struct sysctl_oid *oidp, int *oid, size_t nlen, int flags)
2794 {
2795 int error, xflag, oflag, Nflag, nflag;
2796 size_t len;
2797
2798 xflag = flags & DB_SYSCTL_HEX;
2799 oflag = flags & DB_SYSCTL_OPAQUE;
2800 nflag = flags & DB_SYSCTL_VALUE_ONLY;
2801 Nflag = flags & DB_SYSCTL_NAME_ONLY;
2802
2803 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_OPAQUE &&
2804 (!xflag && !oflag))
2805 return (0);
2806
2807 if (Nflag) {
2808 db_show_oid_name(oid, nlen);
2809 error = 0;
2810 goto out;
2811 }
2812
2813 if (!nflag) {
2814 db_show_oid_name(oid, nlen);
2815 db_printf(": ");
2816 }
2817
2818 if ((flags & DB_SYSCTL_SAFE_ONLY) && !db_oid_safe(oidp)) {
2819 db_printf("Skipping, unsafe to print while recursing.");
2820 error = 0;
2821 goto out;
2822 }
2823
2824 /* Try once, and ask about the size */
2825 len = 0;
2826 error = db_sysctl(oidp, oid, nlen,
2827 NULL, NULL, &len, flags);
2828 if (error)
2829 goto out;
2830
2831 if (!g_ddb_sysctl_printed)
2832 /* Lie about the size */
2833 error = db_sysctl(oidp, oid, nlen,
2834 (void *) 1, &len, NULL, flags);
2835
2836 out:
2837 db_printf("\n");
2838 return (error);
2839 }
2840
2841 /*
2842 * Show all sysctls under a specific OID
2843 * Compare to sysctl_all from sbin/sysctl/sysctl.c
2844 */
2845 static int
db_show_sysctl_all(int * oid,size_t len,int flags)2846 db_show_sysctl_all(int *oid, size_t len, int flags)
2847 {
2848 struct sysctl_oid *oidp;
2849 int qoid[CTL_MAXNAME + 2], next[CTL_MAXNAME];
2850 size_t nlen;
2851
2852 qoid[0] = CTL_SYSCTL;
2853 qoid[1] = CTL_SYSCTL_NEXT;
2854 if (len) {
2855 nlen = len;
2856 memcpy(&qoid[2], oid, nlen * sizeof(int));
2857 } else {
2858 nlen = 1;
2859 qoid[2] = CTL_KERN;
2860 }
2861 for (;;) {
2862 int error;
2863 size_t nextsize = sizeof(next);
2864
2865 error = kernel_sysctl(kdb_thread, qoid, nlen + 2,
2866 next, &nextsize, NULL, 0, &nlen, 0);
2867 if (error != 0) {
2868 if (error == ENOENT)
2869 return (0);
2870 else
2871 db_error("sysctl(next)");
2872 }
2873
2874 nlen /= sizeof(int);
2875
2876 if (nlen < (unsigned int)len)
2877 return (0);
2878
2879 if (memcmp(&oid[0], &next[0], len * sizeof(int)) != 0)
2880 return (0);
2881
2882 /* Find the OID in question */
2883 error = sysctl_find_oid(next, nlen, &oidp, NULL, NULL);
2884 if (error)
2885 return (error);
2886
2887 (void)db_show_oid(oidp, next, nlen, flags | DB_SYSCTL_SAFE_ONLY);
2888
2889 if (db_pager_quit)
2890 return (0);
2891
2892 memcpy(&qoid[2 + len], &next[len], (nlen - len) * sizeof(int));
2893 }
2894 }
2895
2896 /*
2897 * Show a sysctl by its user facing string
2898 */
2899 static int
db_sysctlbyname(char * name,int flags)2900 db_sysctlbyname(char *name, int flags)
2901 {
2902 struct sysctl_oid *oidp;
2903 int oid[CTL_MAXNAME];
2904 int error, nlen;
2905
2906 error = name2oid(name, oid, &nlen, &oidp);
2907 if (error) {
2908 return (error);
2909 }
2910
2911 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
2912 db_show_sysctl_all(oid, nlen, flags);
2913 } else {
2914 error = db_show_oid(oidp, oid, nlen, flags);
2915 }
2916
2917 return (error);
2918 }
2919
2920 static void
db_sysctl_cmd_usage(void)2921 db_sysctl_cmd_usage(void)
2922 {
2923 db_printf(
2924 " sysctl [/Nnox] <sysctl> \n"
2925 " \n"
2926 " <sysctl> The name of the sysctl to show. \n"
2927 " \n"
2928 " Show a sysctl by hooking into SYSCTL_IN and SYSCTL_OUT. \n"
2929 " This will work for most sysctls, but should not be used \n"
2930 " with sysctls that are known to malloc. \n"
2931 " \n"
2932 " While recursing any \"unsafe\" sysctls will be skipped. \n"
2933 " Call sysctl directly on the sysctl to try printing the \n"
2934 " skipped sysctl. This is unsafe and may make the ddb \n"
2935 " session unusable. \n"
2936 " \n"
2937 " Arguments: \n"
2938 " /N Display only the name of the sysctl. \n"
2939 " /n Display only the value of the sysctl. \n"
2940 " /o Display opaque values. \n"
2941 " /x Display the sysctl in hex. \n"
2942 " \n"
2943 "For example: \n"
2944 "sysctl vm.v_free_min \n"
2945 "vn.v_free_min: 12669 \n"
2946 );
2947 }
2948
2949 /*
2950 * Show a specific sysctl similar to sysctl (8).
2951 */
DB_COMMAND_FLAGS(sysctl,db_sysctl_cmd,CS_OWN)2952 DB_COMMAND_FLAGS(sysctl, db_sysctl_cmd, CS_OWN)
2953 {
2954 char name[TOK_STRING_SIZE];
2955 int error, i, t, flags;
2956
2957 /* Parse the modifiers */
2958 t = db_read_token();
2959 if (t == tSLASH || t == tMINUS) {
2960 t = db_read_token();
2961 if (t != tIDENT) {
2962 db_printf("Bad modifier\n");
2963 error = EINVAL;
2964 goto out;
2965 }
2966 db_strcpy(modif, db_tok_string);
2967 }
2968 else {
2969 db_unread_token(t);
2970 modif[0] = '\0';
2971 }
2972
2973 flags = 0;
2974 for (i = 0; i < nitems(db_sysctl_modifs); i++) {
2975 if (strchr(modif, db_sysctl_modifs[i])) {
2976 flags |= db_sysctl_modif_values[i];
2977 }
2978 }
2979
2980 /* Parse the sysctl names */
2981 t = db_read_token();
2982 if (t != tIDENT) {
2983 db_printf("Need sysctl name\n");
2984 error = EINVAL;
2985 goto out;
2986 }
2987
2988 /* Copy the name into a temporary buffer */
2989 db_strcpy(name, db_tok_string);
2990
2991 /* Ensure there is no trailing cruft */
2992 t = db_read_token();
2993 if (t != tEOL) {
2994 db_printf("Unexpected sysctl argument\n");
2995 error = EINVAL;
2996 goto out;
2997 }
2998
2999 error = db_sysctlbyname(name, flags);
3000 if (error == ENOENT) {
3001 db_printf("unknown oid: '%s'\n", db_tok_string);
3002 goto out;
3003 } else if (error) {
3004 db_printf("%s: error: %d\n", db_tok_string, error);
3005 goto out;
3006 }
3007
3008 out:
3009 /* Ensure we eat all of our text */
3010 db_flush_lex();
3011
3012 if (error == EINVAL) {
3013 db_sysctl_cmd_usage();
3014 }
3015 }
3016
3017 #endif /* DDB */
3018