1 /*-
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Mike Karels at Berkeley Software Design, Inc.
7 *
8 * Quite extensively rewritten by Poul-Henning Kamp of the FreeBSD
9 * project, to make these variables more userfriendly.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
36 */
37
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40
41 #include "opt_compat.h"
42 #include "opt_ktrace.h"
43 #include "opt_mac.h"
44
45 #include <sys/param.h>
46 #include <sys/fail.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
49 #include <sys/sysctl.h>
50 #include <sys/malloc.h>
51 #include <sys/priv.h>
52 #include <sys/proc.h>
53 #include <sys/lock.h>
54 #include <sys/mutex.h>
55 #include <sys/sbuf.h>
56 #include <sys/sx.h>
57 #include <sys/sysproto.h>
58 #include <sys/uio.h>
59 #ifdef KTRACE
60 #include <sys/ktrace.h>
61 #endif
62
63 #include <security/mac/mac_framework.h>
64
65 #include <vm/vm.h>
66 #include <vm/vm_extern.h>
67
68 static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic");
69 static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids");
70 static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer");
71
72 /*
73 * The sysctllock protects the MIB tree. It also protects sysctl
74 * contexts used with dynamic sysctls. The sysctl_register_oid() and
75 * sysctl_unregister_oid() routines require the sysctllock to already
76 * be held, so the sysctl_lock() and sysctl_unlock() routines are
77 * provided for the few places in the kernel which need to use that
78 * API rather than using the dynamic API. Use of the dynamic API is
79 * strongly encouraged for most code.
80 *
81 * The sysctlmemlock is used to limit the amount of user memory wired for
82 * sysctl requests. This is implemented by serializing any userland
83 * sysctl requests larger than a single page via an exclusive lock.
84 */
85 static struct sx sysctllock;
86 static struct sx sysctlmemlock;
87
88 #define SYSCTL_XLOCK() sx_xlock(&sysctllock)
89 #define SYSCTL_XUNLOCK() sx_xunlock(&sysctllock)
90 #define SYSCTL_ASSERT_XLOCKED() sx_assert(&sysctllock, SA_XLOCKED)
91 #define SYSCTL_INIT() sx_init(&sysctllock, "sysctl lock")
92 #define SYSCTL_SLEEP(ch, wmesg, timo) \
93 sx_sleep(ch, &sysctllock, 0, wmesg, timo)
94
95 static int sysctl_root(SYSCTL_HANDLER_ARGS);
96
97 struct sysctl_oid_list sysctl__children; /* root list */
98
99 static int sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del,
100 int recurse);
101
102 static struct sysctl_oid *
103 sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)
104 {
105 struct sysctl_oid *oidp;
106
107 SYSCTL_ASSERT_XLOCKED();
108 SLIST_FOREACH(oidp, list, oid_link) {
109 if (strcmp(oidp->oid_name, name) == 0) {
110 return (oidp);
111 }
112 }
113 return (NULL);
114 }
115
116 /*
117 * Initialization of the MIB tree.
118 *
119 * Order by number in each list.
120 */
121 void
122 sysctl_lock(void)
123 {
124
125 SYSCTL_XLOCK();
126 }
127
128 void
129 sysctl_unlock(void)
130 {
131
132 SYSCTL_XUNLOCK();
133 }
134
135 void
136 sysctl_register_oid(struct sysctl_oid *oidp)
137 {
138 struct sysctl_oid_list *parent = oidp->oid_parent;
139 struct sysctl_oid *p;
140 struct sysctl_oid *q;
141
142 /*
143 * First check if another oid with the same name already
144 * exists in the parent's list.
145 */
146 SYSCTL_ASSERT_XLOCKED();
147 p = sysctl_find_oidname(oidp->oid_name, parent);
148 if (p != NULL) {
149 if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
150 p->oid_refcnt++;
151 return;
152 } else {
153 printf("can't re-use a leaf (%s)!\n", p->oid_name);
154 return;
155 }
156 }
157 /*
158 * If this oid has a number OID_AUTO, give it a number which
159 * is greater than any current oid.
160 * NOTE: DO NOT change the starting value here, change it in
161 * <sys/sysctl.h>, and make sure it is at least 256 to
162 * accomodate e.g. net.inet.raw as a static sysctl node.
163 */
164 if (oidp->oid_number == OID_AUTO) {
165 static int newoid = CTL_AUTO_START;
166
167 oidp->oid_number = newoid++;
168 if (newoid == 0x7fffffff)
169 panic("out of oids");
170 }
171 #if 0
172 else if (oidp->oid_number >= CTL_AUTO_START) {
173 /* do not panic; this happens when unregistering sysctl sets */
174 printf("static sysctl oid too high: %d", oidp->oid_number);
175 }
176 #endif
177
178 /*
179 * Insert the oid into the parent's list in order.
180 */
181 q = NULL;
182 SLIST_FOREACH(p, parent, oid_link) {
183 if (oidp->oid_number < p->oid_number)
184 break;
185 q = p;
186 }
187 if (q)
188 SLIST_INSERT_AFTER(q, oidp, oid_link);
189 else
190 SLIST_INSERT_HEAD(parent, oidp, oid_link);
191 }
192
193 void
194 sysctl_unregister_oid(struct sysctl_oid *oidp)
195 {
196 struct sysctl_oid *p;
197 int error;
198
199 SYSCTL_ASSERT_XLOCKED();
200 error = ENOENT;
201 if (oidp->oid_number == OID_AUTO) {
202 error = EINVAL;
203 } else {
204 SLIST_FOREACH(p, oidp->oid_parent, oid_link) {
205 if (p == oidp) {
206 SLIST_REMOVE(oidp->oid_parent, oidp,
207 sysctl_oid, oid_link);
208 error = 0;
209 break;
210 }
211 }
212 }
213
214 /*
215 * This can happen when a module fails to register and is
216 * being unloaded afterwards. It should not be a panic()
217 * for normal use.
218 */
219 if (error)
220 printf("%s: failed to unregister sysctl\n", __func__);
221 }
222
223 /* Initialize a new context to keep track of dynamically added sysctls. */
224 int
225 sysctl_ctx_init(struct sysctl_ctx_list *c)
226 {
227
228 if (c == NULL) {
229 return (EINVAL);
230 }
231
232 /*
233 * No locking here, the caller is responsible for not adding
234 * new nodes to a context until after this function has
235 * returned.
236 */
237 TAILQ_INIT(c);
238 return (0);
239 }
240
241 /* Free the context, and destroy all dynamic oids registered in this context */
242 int
243 sysctl_ctx_free(struct sysctl_ctx_list *clist)
244 {
245 struct sysctl_ctx_entry *e, *e1;
246 int error;
247
248 error = 0;
249 /*
250 * First perform a "dry run" to check if it's ok to remove oids.
251 * XXX FIXME
252 * XXX This algorithm is a hack. But I don't know any
253 * XXX better solution for now...
254 */
255 SYSCTL_XLOCK();
256 TAILQ_FOREACH(e, clist, link) {
257 error = sysctl_remove_oid_locked(e->entry, 0, 0);
258 if (error)
259 break;
260 }
261 /*
262 * Restore deregistered entries, either from the end,
263 * or from the place where error occured.
264 * e contains the entry that was not unregistered
265 */
266 if (error)
267 e1 = TAILQ_PREV(e, sysctl_ctx_list, link);
268 else
269 e1 = TAILQ_LAST(clist, sysctl_ctx_list);
270 while (e1 != NULL) {
271 sysctl_register_oid(e1->entry);
272 e1 = TAILQ_PREV(e1, sysctl_ctx_list, link);
273 }
274 if (error) {
275 SYSCTL_XUNLOCK();
276 return(EBUSY);
277 }
278 /* Now really delete the entries */
279 e = TAILQ_FIRST(clist);
280 while (e != NULL) {
281 e1 = TAILQ_NEXT(e, link);
282 error = sysctl_remove_oid_locked(e->entry, 1, 0);
283 if (error)
284 panic("sysctl_remove_oid: corrupt tree, entry: %s",
285 e->entry->oid_name);
286 free(e, M_SYSCTLOID);
287 e = e1;
288 }
289 SYSCTL_XUNLOCK();
290 return (error);
291 }
292
293 /* Add an entry to the context */
294 struct sysctl_ctx_entry *
295 sysctl_ctx_entry_add(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
296 {
297 struct sysctl_ctx_entry *e;
298
299 SYSCTL_ASSERT_XLOCKED();
300 if (clist == NULL || oidp == NULL)
301 return(NULL);
302 e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK);
303 e->entry = oidp;
304 TAILQ_INSERT_HEAD(clist, e, link);
305 return (e);
306 }
307
308 /* Find an entry in the context */
309 struct sysctl_ctx_entry *
310 sysctl_ctx_entry_find(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
311 {
312 struct sysctl_ctx_entry *e;
313
314 SYSCTL_ASSERT_XLOCKED();
315 if (clist == NULL || oidp == NULL)
316 return(NULL);
317 TAILQ_FOREACH(e, clist, link) {
318 if(e->entry == oidp)
319 return(e);
320 }
321 return (e);
322 }
323
324 /*
325 * Delete an entry from the context.
326 * NOTE: this function doesn't free oidp! You have to remove it
327 * with sysctl_remove_oid().
328 */
329 int
330 sysctl_ctx_entry_del(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
331 {
332 struct sysctl_ctx_entry *e;
333
334 if (clist == NULL || oidp == NULL)
335 return (EINVAL);
336 SYSCTL_XLOCK();
337 e = sysctl_ctx_entry_find(clist, oidp);
338 if (e != NULL) {
339 TAILQ_REMOVE(clist, e, link);
340 SYSCTL_XUNLOCK();
341 free(e, M_SYSCTLOID);
342 return (0);
343 } else {
344 SYSCTL_XUNLOCK();
345 return (ENOENT);
346 }
347 }
348
349 /*
350 * Remove dynamically created sysctl trees.
351 * oidp - top of the tree to be removed
352 * del - if 0 - just deregister, otherwise free up entries as well
353 * recurse - if != 0 traverse the subtree to be deleted
354 */
355 int
356 sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse)
357 {
358 int error;
359
360 SYSCTL_XLOCK();
361 error = sysctl_remove_oid_locked(oidp, del, recurse);
362 SYSCTL_XUNLOCK();
363 return (error);
364 }
365
366 static int
367 sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse)
368 {
369 struct sysctl_oid *p;
370 int error;
371
372 SYSCTL_ASSERT_XLOCKED();
373 if (oidp == NULL)
374 return(EINVAL);
375 if ((oidp->oid_kind & CTLFLAG_DYN) == 0) {
376 printf("can't remove non-dynamic nodes!\n");
377 return (EINVAL);
378 }
379 /*
380 * WARNING: normal method to do this should be through
381 * sysctl_ctx_free(). Use recursing as the last resort
382 * method to purge your sysctl tree of leftovers...
383 * However, if some other code still references these nodes,
384 * it will panic.
385 */
386 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
387 if (oidp->oid_refcnt == 1) {
388 SLIST_FOREACH(p, SYSCTL_CHILDREN(oidp), oid_link) {
389 if (!recurse)
390 return (ENOTEMPTY);
391 error = sysctl_remove_oid_locked(p, del,
392 recurse);
393 if (error)
394 return (error);
395 }
396 if (del)
397 free(SYSCTL_CHILDREN(oidp), M_SYSCTLOID);
398 }
399 }
400 if (oidp->oid_refcnt > 1 ) {
401 oidp->oid_refcnt--;
402 } else {
403 if (oidp->oid_refcnt == 0) {
404 printf("Warning: bad oid_refcnt=%u (%s)!\n",
405 oidp->oid_refcnt, oidp->oid_name);
406 return (EINVAL);
407 }
408 sysctl_unregister_oid(oidp);
409 if (del) {
410 /*
411 * Wait for all threads running the handler to drain.
412 * This preserves the previous behavior when the
413 * sysctl lock was held across a handler invocation,
414 * and is necessary for module unload correctness.
415 */
416 while (oidp->oid_running > 0) {
417 oidp->oid_kind |= CTLFLAG_DYING;
418 SYSCTL_SLEEP(&oidp->oid_running, "oidrm", 0);
419 }
420 if (oidp->oid_descr)
421 free((void *)(uintptr_t)(const void *)oidp->oid_descr, M_SYSCTLOID);
422 free((void *)(uintptr_t)(const void *)oidp->oid_name,
423 M_SYSCTLOID);
424 free(oidp, M_SYSCTLOID);
425 }
426 }
427 return (0);
428 }
429
430 /*
431 * Create new sysctls at run time.
432 * clist may point to a valid context initialized with sysctl_ctx_init().
433 */
434 struct sysctl_oid *
435 sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
436 int number, const char *name, int kind, void *arg1, int arg2,
437 int (*handler)(SYSCTL_HANDLER_ARGS), const char *fmt, const char *descr)
438 {
439 struct sysctl_oid *oidp;
440 ssize_t len;
441 char *newname;
442
443 /* You have to hook up somewhere.. */
444 if (parent == NULL)
445 return(NULL);
446 /* Check if the node already exists, otherwise create it */
447 SYSCTL_XLOCK();
448 oidp = sysctl_find_oidname(name, parent);
449 if (oidp != NULL) {
450 if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
451 oidp->oid_refcnt++;
452 /* Update the context */
453 if (clist != NULL)
454 sysctl_ctx_entry_add(clist, oidp);
455 SYSCTL_XUNLOCK();
456 return (oidp);
457 } else {
458 SYSCTL_XUNLOCK();
459 printf("can't re-use a leaf (%s)!\n", name);
460 return (NULL);
461 }
462 }
463 oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK|M_ZERO);
464 oidp->oid_parent = parent;
465 SLIST_NEXT(oidp, oid_link) = NULL;
466 oidp->oid_number = number;
467 oidp->oid_refcnt = 1;
468 len = strlen(name);
469 newname = malloc(len + 1, M_SYSCTLOID, M_WAITOK);
470 bcopy(name, newname, len + 1);
471 newname[len] = '\0';
472 oidp->oid_name = newname;
473 oidp->oid_handler = handler;
474 oidp->oid_kind = CTLFLAG_DYN | kind;
475 if ((kind & CTLTYPE) == CTLTYPE_NODE) {
476 /* Allocate space for children */
477 SYSCTL_CHILDREN_SET(oidp, malloc(sizeof(struct sysctl_oid_list),
478 M_SYSCTLOID, M_WAITOK));
479 SLIST_INIT(SYSCTL_CHILDREN(oidp));
480 } else {
481 oidp->oid_arg1 = arg1;
482 oidp->oid_arg2 = arg2;
483 }
484 oidp->oid_fmt = fmt;
485 if (descr) {
486 int len = strlen(descr) + 1;
487 oidp->oid_descr = malloc(len, M_SYSCTLOID, M_WAITOK);
488 if (oidp->oid_descr)
489 strcpy((char *)(uintptr_t)(const void *)oidp->oid_descr, descr);
490 }
491 /* Update the context, if used */
492 if (clist != NULL)
493 sysctl_ctx_entry_add(clist, oidp);
494 /* Register this oid */
495 sysctl_register_oid(oidp);
496 SYSCTL_XUNLOCK();
497 return (oidp);
498 }
499
500 /*
501 * Rename an existing oid.
502 */
503 void
504 sysctl_rename_oid(struct sysctl_oid *oidp, const char *name)
505 {
506 ssize_t len;
507 char *newname;
508 void *oldname;
509
510 len = strlen(name);
511 newname = malloc(len + 1, M_SYSCTLOID, M_WAITOK);
512 bcopy(name, newname, len + 1);
513 newname[len] = '\0';
514 SYSCTL_XLOCK();
515 oldname = (void *)(uintptr_t)(const void *)oidp->oid_name;
516 oidp->oid_name = newname;
517 SYSCTL_XUNLOCK();
518 free(oldname, M_SYSCTLOID);
519 }
520
521 /*
522 * Reparent an existing oid.
523 */
524 int
525 sysctl_move_oid(struct sysctl_oid *oid, struct sysctl_oid_list *parent)
526 {
527 struct sysctl_oid *oidp;
528
529 SYSCTL_XLOCK();
530 if (oid->oid_parent == parent) {
531 SYSCTL_XUNLOCK();
532 return (0);
533 }
534 oidp = sysctl_find_oidname(oid->oid_name, parent);
535 if (oidp != NULL) {
536 SYSCTL_XUNLOCK();
537 return (EEXIST);
538 }
539 sysctl_unregister_oid(oid);
540 oid->oid_parent = parent;
541 oid->oid_number = OID_AUTO;
542 sysctl_register_oid(oid);
543 SYSCTL_XUNLOCK();
544 return (0);
545 }
546
547 /*
548 * Register the kernel's oids on startup.
549 */
550 SET_DECLARE(sysctl_set, struct sysctl_oid);
551
552 static void
553 sysctl_register_all(void *arg)
554 {
555 struct sysctl_oid **oidp;
556
557 sx_init(&sysctlmemlock, "sysctl mem");
558 SYSCTL_INIT();
559 SYSCTL_XLOCK();
560 SET_FOREACH(oidp, sysctl_set)
561 sysctl_register_oid(*oidp);
562 SYSCTL_XUNLOCK();
563 }
564 SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_register_all, 0);
565
566 /*
567 * "Staff-functions"
568 *
569 * These functions implement a presently undocumented interface
570 * used by the sysctl program to walk the tree, and get the type
571 * so it can print the value.
572 * This interface is under work and consideration, and should probably
573 * be killed with a big axe by the first person who can find the time.
574 * (be aware though, that the proper interface isn't as obvious as it
575 * may seem, there are various conflicting requirements.
576 *
577 * {0,0} printf the entire MIB-tree.
578 * {0,1,...} return the name of the "..." OID.
579 * {0,2,...} return the next OID.
580 * {0,3} return the OID of the name in "new"
581 * {0,4,...} return the kind & format info for the "..." OID.
582 * {0,5,...} return the description the "..." OID.
583 */
584
585 #ifdef SYSCTL_DEBUG
586 static void
587 sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i)
588 {
589 int k;
590 struct sysctl_oid *oidp;
591
592 SYSCTL_ASSERT_XLOCKED();
593 SLIST_FOREACH(oidp, l, oid_link) {
594
595 for (k=0; k<i; k++)
596 printf(" ");
597
598 printf("%d %s ", oidp->oid_number, oidp->oid_name);
599
600 printf("%c%c",
601 oidp->oid_kind & CTLFLAG_RD ? 'R':' ',
602 oidp->oid_kind & CTLFLAG_WR ? 'W':' ');
603
604 if (oidp->oid_handler)
605 printf(" *Handler");
606
607 switch (oidp->oid_kind & CTLTYPE) {
608 case CTLTYPE_NODE:
609 printf(" Node\n");
610 if (!oidp->oid_handler) {
611 sysctl_sysctl_debug_dump_node(
612 oidp->oid_arg1, i+2);
613 }
614 break;
615 case CTLTYPE_INT: printf(" Int\n"); break;
616 case CTLTYPE_STRING: printf(" String\n"); break;
617 case CTLTYPE_QUAD: printf(" Quad\n"); break;
618 case CTLTYPE_OPAQUE: printf(" Opaque/struct\n"); break;
619 default: printf("\n");
620 }
621
622 }
623 }
624
625 static int
626 sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS)
627 {
628 int error;
629
630 error = priv_check(req->td, PRIV_SYSCTL_DEBUG);
631 if (error)
632 return (error);
633 SYSCTL_XLOCK();
634 sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
635 SYSCTL_XUNLOCK();
636 return (ENOENT);
637 }
638
639 SYSCTL_PROC(_sysctl, 0, debug, CTLTYPE_STRING|CTLFLAG_RD,
640 0, 0, sysctl_sysctl_debug, "-", "");
641 #endif
642
643 static int
644 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
645 {
646 int *name = (int *) arg1;
647 u_int namelen = arg2;
648 int error = 0;
649 struct sysctl_oid *oid;
650 struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;
651 char buf[10];
652
653 SYSCTL_XLOCK();
654 while (namelen) {
655 if (!lsp) {
656 snprintf(buf,sizeof(buf),"%d",*name);
657 if (req->oldidx)
658 error = SYSCTL_OUT(req, ".", 1);
659 if (!error)
660 error = SYSCTL_OUT(req, buf, strlen(buf));
661 if (error)
662 goto out;
663 namelen--;
664 name++;
665 continue;
666 }
667 lsp2 = 0;
668 SLIST_FOREACH(oid, lsp, oid_link) {
669 if (oid->oid_number != *name)
670 continue;
671
672 if (req->oldidx)
673 error = SYSCTL_OUT(req, ".", 1);
674 if (!error)
675 error = SYSCTL_OUT(req, oid->oid_name,
676 strlen(oid->oid_name));
677 if (error)
678 goto out;
679
680 namelen--;
681 name++;
682
683 if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE)
684 break;
685
686 if (oid->oid_handler)
687 break;
688
689 lsp2 = SYSCTL_CHILDREN(oid);
690 break;
691 }
692 lsp = lsp2;
693 }
694 error = SYSCTL_OUT(req, "", 1);
695 out:
696 SYSCTL_XUNLOCK();
697 return (error);
698 }
699
700 static SYSCTL_NODE(_sysctl, 1, name, CTLFLAG_RD, sysctl_sysctl_name, "");
701
702 static int
703 sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int *name, u_int namelen,
704 int *next, int *len, int level, struct sysctl_oid **oidpp)
705 {
706 struct sysctl_oid *oidp;
707
708 SYSCTL_ASSERT_XLOCKED();
709 *len = level;
710 SLIST_FOREACH(oidp, lsp, oid_link) {
711 *next = oidp->oid_number;
712 *oidpp = oidp;
713
714 if (oidp->oid_kind & CTLFLAG_SKIP)
715 continue;
716
717 if (!namelen) {
718 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
719 return (0);
720 if (oidp->oid_handler)
721 /* We really should call the handler here...*/
722 return (0);
723 lsp = SYSCTL_CHILDREN(oidp);
724 if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1,
725 len, level+1, oidpp))
726 return (0);
727 goto emptynode;
728 }
729
730 if (oidp->oid_number < *name)
731 continue;
732
733 if (oidp->oid_number > *name) {
734 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
735 return (0);
736 if (oidp->oid_handler)
737 return (0);
738 lsp = SYSCTL_CHILDREN(oidp);
739 if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1,
740 next+1, len, level+1, oidpp))
741 return (0);
742 goto next;
743 }
744 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
745 continue;
746
747 if (oidp->oid_handler)
748 continue;
749
750 lsp = SYSCTL_CHILDREN(oidp);
751 if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1,
752 len, level+1, oidpp))
753 return (0);
754 next:
755 namelen = 1;
756 emptynode:
757 *len = level;
758 }
759 return (1);
760 }
761
762 static int
763 sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
764 {
765 int *name = (int *) arg1;
766 u_int namelen = arg2;
767 int i, j, error;
768 struct sysctl_oid *oid;
769 struct sysctl_oid_list *lsp = &sysctl__children;
770 int newoid[CTL_MAXNAME];
771
772 SYSCTL_XLOCK();
773 i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid);
774 SYSCTL_XUNLOCK();
775 if (i)
776 return (ENOENT);
777 error = SYSCTL_OUT(req, newoid, j * sizeof (int));
778 return (error);
779 }
780
781 static SYSCTL_NODE(_sysctl, 2, next, CTLFLAG_RD, sysctl_sysctl_next, "");
782
783 static int
784 name2oid(char *name, int *oid, int *len, struct sysctl_oid **oidpp)
785 {
786 int i;
787 struct sysctl_oid *oidp;
788 struct sysctl_oid_list *lsp = &sysctl__children;
789 char *p;
790
791 SYSCTL_ASSERT_XLOCKED();
792
793 if (!*name)
794 return (ENOENT);
795
796 p = name + strlen(name) - 1 ;
797 if (*p == '.')
798 *p = '\0';
799
800 *len = 0;
801
802 for (p = name; *p && *p != '.'; p++)
803 ;
804 i = *p;
805 if (i == '.')
806 *p = '\0';
807
808 oidp = SLIST_FIRST(lsp);
809
810 while (oidp && *len < CTL_MAXNAME) {
811 if (strcmp(name, oidp->oid_name)) {
812 oidp = SLIST_NEXT(oidp, oid_link);
813 continue;
814 }
815 *oid++ = oidp->oid_number;
816 (*len)++;
817
818 if (!i) {
819 if (oidpp)
820 *oidpp = oidp;
821 return (0);
822 }
823
824 if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
825 break;
826
827 if (oidp->oid_handler)
828 break;
829
830 lsp = SYSCTL_CHILDREN(oidp);
831 oidp = SLIST_FIRST(lsp);
832 name = p+1;
833 for (p = name; *p && *p != '.'; p++)
834 ;
835 i = *p;
836 if (i == '.')
837 *p = '\0';
838 }
839 return (ENOENT);
840 }
841
842 static int
843 sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
844 {
845 char *p;
846 int error, oid[CTL_MAXNAME], len;
847 struct sysctl_oid *op = 0;
848
849 if (!req->newlen)
850 return (ENOENT);
851 if (req->newlen >= MAXPATHLEN) /* XXX arbitrary, undocumented */
852 return (ENAMETOOLONG);
853
854 p = malloc(req->newlen+1, M_SYSCTL, M_WAITOK);
855
856 error = SYSCTL_IN(req, p, req->newlen);
857 if (error) {
858 free(p, M_SYSCTL);
859 return (error);
860 }
861
862 p [req->newlen] = '\0';
863 len = 0;
864 SYSCTL_XLOCK();
865 error = name2oid(p, oid, &len, &op);
866 SYSCTL_XUNLOCK();
867
868 free(p, M_SYSCTL);
869
870 if (error)
871 return (error);
872
873 error = SYSCTL_OUT(req, oid, len * sizeof *oid);
874 return (error);
875 }
876
877 SYSCTL_PROC(_sysctl, 3, name2oid, CTLFLAG_RW|CTLFLAG_ANYBODY|CTLFLAG_MPSAFE,
878 0, 0, sysctl_sysctl_name2oid, "I", "");
879
880 static int
881 sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
882 {
883 struct sysctl_oid *oid;
884 int error;
885
886 SYSCTL_XLOCK();
887 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
888 if (error)
889 goto out;
890
891 if (oid->oid_fmt == NULL) {
892 error = ENOENT;
893 goto out;
894 }
895 error = SYSCTL_OUT(req, &oid->oid_kind, sizeof(oid->oid_kind));
896 if (error)
897 goto out;
898 error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1);
899 out:
900 SYSCTL_XUNLOCK();
901 return (error);
902 }
903
904
905 static SYSCTL_NODE(_sysctl, 4, oidfmt, CTLFLAG_RD|CTLFLAG_MPSAFE,
906 sysctl_sysctl_oidfmt, "");
907
908 static int
909 sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)
910 {
911 struct sysctl_oid *oid;
912 int error;
913
914 SYSCTL_XLOCK();
915 error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
916 if (error)
917 goto out;
918
919 if (oid->oid_descr == NULL) {
920 error = ENOENT;
921 goto out;
922 }
923 error = SYSCTL_OUT(req, oid->oid_descr, strlen(oid->oid_descr) + 1);
924 out:
925 SYSCTL_XUNLOCK();
926 return (error);
927 }
928
929 static SYSCTL_NODE(_sysctl, 5, oiddescr, CTLFLAG_RD, sysctl_sysctl_oiddescr, "");
930
931 /*
932 * Default "handler" functions.
933 */
934
935 /*
936 * Handle an int, signed or unsigned.
937 * Two cases:
938 * a variable: point arg1 at it.
939 * a constant: pass it in arg2.
940 */
941
942 int
943 sysctl_handle_int(SYSCTL_HANDLER_ARGS)
944 {
945 int tmpout, error = 0;
946
947 /*
948 * Attempt to get a coherent snapshot by making a copy of the data.
949 */
950 if (arg1)
951 tmpout = *(int *)arg1;
952 else
953 tmpout = arg2;
954 error = SYSCTL_OUT(req, &tmpout, sizeof(int));
955
956 if (error || !req->newptr)
957 return (error);
958
959 if (!arg1)
960 error = EPERM;
961 else
962 error = SYSCTL_IN(req, arg1, sizeof(int));
963 return (error);
964 }
965
966
967 /*
968 * Based on on sysctl_handle_int() convert milliseconds into ticks.
969 */
970
971 int
972 sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS)
973 {
974 int error, s, tt;
975
976 tt = *(int *)oidp->oid_arg1;
977 s = (int)((int64_t)tt * 1000 / hz);
978
979 error = sysctl_handle_int(oidp, &s, 0, req);
980 if (error || !req->newptr)
981 return (error);
982
983 tt = (int)((int64_t)s * hz / 1000);
984 if (tt < 1)
985 return (EINVAL);
986
987 *(int *)oidp->oid_arg1 = tt;
988 return (0);
989 }
990
991
992 /*
993 * Handle a long, signed or unsigned. arg1 points to it.
994 */
995
996 int
997 sysctl_handle_long(SYSCTL_HANDLER_ARGS)
998 {
999 int error = 0;
1000 long tmplong;
1001 #ifdef SCTL_MASK32
1002 int tmpint;
1003 #endif
1004
1005 /*
1006 * Attempt to get a coherent snapshot by making a copy of the data.
1007 */
1008 if (!arg1)
1009 return (EINVAL);
1010 tmplong = *(long *)arg1;
1011 #ifdef SCTL_MASK32
1012 if (req->flags & SCTL_MASK32) {
1013 tmpint = tmplong;
1014 error = SYSCTL_OUT(req, &tmpint, sizeof(int));
1015 } else
1016 #endif
1017 error = SYSCTL_OUT(req, &tmplong, sizeof(long));
1018
1019 if (error || !req->newptr)
1020 return (error);
1021
1022 #ifdef SCTL_MASK32
1023 if (req->flags & SCTL_MASK32) {
1024 error = SYSCTL_IN(req, &tmpint, sizeof(int));
1025 *(long *)arg1 = (long)tmpint;
1026 } else
1027 #endif
1028 error = SYSCTL_IN(req, arg1, sizeof(long));
1029 return (error);
1030 }
1031
1032 /*
1033 * Handle a 64 bit int, signed or unsigned. arg1 points to it.
1034 */
1035
1036 int
1037 sysctl_handle_quad(SYSCTL_HANDLER_ARGS)
1038 {
1039 int error = 0;
1040 uint64_t tmpout;
1041
1042 /*
1043 * Attempt to get a coherent snapshot by making a copy of the data.
1044 */
1045 if (!arg1)
1046 return (EINVAL);
1047 tmpout = *(uint64_t *)arg1;
1048 error = SYSCTL_OUT(req, &tmpout, sizeof(uint64_t));
1049
1050 if (error || !req->newptr)
1051 return (error);
1052
1053 error = SYSCTL_IN(req, arg1, sizeof(uint64_t));
1054 return (error);
1055 }
1056
1057 /*
1058 * Handle our generic '\0' terminated 'C' string.
1059 * Two cases:
1060 * a variable string: point arg1 at it, arg2 is max length.
1061 * a constant string: point arg1 at it, arg2 is zero.
1062 */
1063
1064 int
1065 sysctl_handle_string(SYSCTL_HANDLER_ARGS)
1066 {
1067 int error=0;
1068 char *tmparg;
1069 size_t outlen;
1070
1071 /*
1072 * Attempt to get a coherent snapshot by copying to a
1073 * temporary kernel buffer.
1074 */
1075 retry:
1076 outlen = strlen((char *)arg1)+1;
1077 tmparg = malloc(outlen, M_SYSCTLTMP, M_WAITOK);
1078
1079 if (strlcpy(tmparg, (char *)arg1, outlen) >= outlen) {
1080 free(tmparg, M_SYSCTLTMP);
1081 goto retry;
1082 }
1083
1084 error = SYSCTL_OUT(req, tmparg, outlen);
1085 free(tmparg, M_SYSCTLTMP);
1086
1087 if (error || !req->newptr)
1088 return (error);
1089
1090 if ((req->newlen - req->newidx) >= arg2) {
1091 error = EINVAL;
1092 } else {
1093 arg2 = (req->newlen - req->newidx);
1094 error = SYSCTL_IN(req, arg1, arg2);
1095 ((char *)arg1)[arg2] = '\0';
1096 }
1097
1098 return (error);
1099 }
1100
1101 /*
1102 * Handle any kind of opaque data.
1103 * arg1 points to it, arg2 is the size.
1104 */
1105
1106 int
1107 sysctl_handle_opaque(SYSCTL_HANDLER_ARGS)
1108 {
1109 int error, tries;
1110 u_int generation;
1111 struct sysctl_req req2;
1112
1113 /*
1114 * Attempt to get a coherent snapshot, by using the thread
1115 * pre-emption counter updated from within mi_switch() to
1116 * determine if we were pre-empted during a bcopy() or
1117 * copyout(). Make 3 attempts at doing this before giving up.
1118 * If we encounter an error, stop immediately.
1119 */
1120 tries = 0;
1121 req2 = *req;
1122 retry:
1123 generation = curthread->td_generation;
1124 error = SYSCTL_OUT(req, arg1, arg2);
1125 if (error)
1126 return (error);
1127 tries++;
1128 if (generation != curthread->td_generation && tries < 3) {
1129 *req = req2;
1130 goto retry;
1131 }
1132
1133 error = SYSCTL_IN(req, arg1, arg2);
1134
1135 return (error);
1136 }
1137
1138 /*
1139 * Transfer functions to/from kernel space.
1140 * XXX: rather untested at this point
1141 */
1142 static int
1143 sysctl_old_kernel(struct sysctl_req *req, const void *p, size_t l)
1144 {
1145 size_t i = 0;
1146
1147 if (req->oldptr) {
1148 i = l;
1149 if (req->oldlen <= req->oldidx)
1150 i = 0;
1151 else
1152 if (i > req->oldlen - req->oldidx)
1153 i = req->oldlen - req->oldidx;
1154 if (i > 0)
1155 bcopy(p, (char *)req->oldptr + req->oldidx, i);
1156 }
1157 req->oldidx += l;
1158 if (req->oldptr && i != l)
1159 return (ENOMEM);
1160 return (0);
1161 }
1162
1163 static int
1164 sysctl_new_kernel(struct sysctl_req *req, void *p, size_t l)
1165 {
1166 if (!req->newptr)
1167 return (0);
1168 if (req->newlen - req->newidx < l)
1169 return (EINVAL);
1170 bcopy((char *)req->newptr + req->newidx, p, l);
1171 req->newidx += l;
1172 return (0);
1173 }
1174
1175 int
1176 kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old,
1177 size_t *oldlenp, void *new, size_t newlen, size_t *retval, int flags)
1178 {
1179 int error = 0;
1180 struct sysctl_req req;
1181
1182 bzero(&req, sizeof req);
1183
1184 req.td = td;
1185 req.flags = flags;
1186
1187 if (oldlenp) {
1188 req.oldlen = *oldlenp;
1189 }
1190 req.validlen = req.oldlen;
1191
1192 if (old) {
1193 req.oldptr= old;
1194 }
1195
1196 if (new != NULL) {
1197 req.newlen = newlen;
1198 req.newptr = new;
1199 }
1200
1201 req.oldfunc = sysctl_old_kernel;
1202 req.newfunc = sysctl_new_kernel;
1203 req.lock = REQ_LOCKED;
1204
1205 SYSCTL_XLOCK();
1206 error = sysctl_root(0, name, namelen, &req);
1207 SYSCTL_XUNLOCK();
1208
1209 if (req.lock == REQ_WIRED && req.validlen > 0)
1210 vsunlock(req.oldptr, req.validlen);
1211
1212 if (error && error != ENOMEM)
1213 return (error);
1214
1215 if (retval) {
1216 if (req.oldptr && req.oldidx > req.validlen)
1217 *retval = req.validlen;
1218 else
1219 *retval = req.oldidx;
1220 }
1221 return (error);
1222 }
1223
1224 int
1225 kernel_sysctlbyname(struct thread *td, char *name, void *old, size_t *oldlenp,
1226 void *new, size_t newlen, size_t *retval, int flags)
1227 {
1228 int oid[CTL_MAXNAME];
1229 size_t oidlen, plen;
1230 int error;
1231
1232 oid[0] = 0; /* sysctl internal magic */
1233 oid[1] = 3; /* name2oid */
1234 oidlen = sizeof(oid);
1235
1236 error = kernel_sysctl(td, oid, 2, oid, &oidlen,
1237 (void *)name, strlen(name), &plen, flags);
1238 if (error)
1239 return (error);
1240
1241 error = kernel_sysctl(td, oid, plen / sizeof(int), old, oldlenp,
1242 new, newlen, retval, flags);
1243 return (error);
1244 }
1245
1246 /*
1247 * Transfer function to/from user space.
1248 */
1249 static int
1250 sysctl_old_user(struct sysctl_req *req, const void *p, size_t l)
1251 {
1252 int error = 0;
1253 size_t i, len, origidx;
1254
1255 origidx = req->oldidx;
1256 req->oldidx += l;
1257 if (req->oldptr == NULL)
1258 return (0);
1259 /*
1260 * If we have not wired the user supplied buffer and we are currently
1261 * holding locks, drop a witness warning, as it's possible that
1262 * write operations to the user page can sleep.
1263 */
1264 if (req->lock != REQ_WIRED)
1265 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
1266 "sysctl_old_user()");
1267 i = l;
1268 len = req->validlen;
1269 if (len <= origidx)
1270 i = 0;
1271 else {
1272 if (i > len - origidx)
1273 i = len - origidx;
1274 error = copyout(p, (char *)req->oldptr + origidx, i);
1275 }
1276 if (error)
1277 return (error);
1278 if (i < l)
1279 return (ENOMEM);
1280 return (0);
1281 }
1282
1283 static int
1284 sysctl_new_user(struct sysctl_req *req, void *p, size_t l)
1285 {
1286 int error;
1287
1288 if (!req->newptr)
1289 return (0);
1290 if (req->newlen - req->newidx < l)
1291 return (EINVAL);
1292 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
1293 "sysctl_new_user()");
1294 error = copyin((char *)req->newptr + req->newidx, p, l);
1295 req->newidx += l;
1296 return (error);
1297 }
1298
1299 /*
1300 * Wire the user space destination buffer. If set to a value greater than
1301 * zero, the len parameter limits the maximum amount of wired memory.
1302 */
1303 int
1304 sysctl_wire_old_buffer(struct sysctl_req *req, size_t len)
1305 {
1306 int ret;
1307 size_t i, wiredlen;
1308 char *cp, dummy;
1309
1310 wiredlen = (len > 0 && len < req->oldlen) ? len : req->oldlen;
1311 ret = 0;
1312 if (req->lock == REQ_LOCKED && req->oldptr &&
1313 req->oldfunc == sysctl_old_user) {
1314 if (wiredlen != 0) {
1315 ret = vslock(req->oldptr, wiredlen);
1316 if (ret != 0) {
1317 if (ret != ENOMEM)
1318 return (ret);
1319 wiredlen = 0;
1320 }
1321 /*
1322 * Touch all the wired pages to avoid PTE modified
1323 * bit emulation traps on Alpha while holding locks
1324 * in the sysctl handler.
1325 */
1326 for (i = (wiredlen + PAGE_SIZE - 1) / PAGE_SIZE,
1327 cp = req->oldptr; i > 0; i--, cp += PAGE_SIZE) {
1328 copyin(cp, &dummy, 1);
1329 copyout(&dummy, cp, 1);
1330 }
1331 }
1332 req->lock = REQ_WIRED;
1333 req->validlen = wiredlen;
1334 }
1335 return (0);
1336 }
1337
1338 int
1339 sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid,
1340 int *nindx, struct sysctl_req *req)
1341 {
1342 struct sysctl_oid_list *lsp;
1343 struct sysctl_oid *oid;
1344 int indx;
1345
1346 SYSCTL_ASSERT_XLOCKED();
1347 lsp = &sysctl__children;
1348 indx = 0;
1349 while (indx < CTL_MAXNAME) {
1350 SLIST_FOREACH(oid, lsp, oid_link) {
1351 if (oid->oid_number == name[indx])
1352 break;
1353 }
1354 if (oid == NULL)
1355 return (ENOENT);
1356
1357 indx++;
1358 if (oid->oid_kind & CTLFLAG_NOLOCK)
1359 req->lock = REQ_UNLOCKED;
1360 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
1361 if (oid->oid_handler != NULL || indx == namelen) {
1362 *noid = oid;
1363 if (nindx != NULL)
1364 *nindx = indx;
1365 KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0,
1366 ("%s found DYING node %p", __func__, oid));
1367 return (0);
1368 }
1369 lsp = SYSCTL_CHILDREN(oid);
1370 } else if (indx == namelen) {
1371 *noid = oid;
1372 if (nindx != NULL)
1373 *nindx = indx;
1374 KASSERT((oid->oid_kind & CTLFLAG_DYING) == 0,
1375 ("%s found DYING node %p", __func__, oid));
1376 return (0);
1377 } else {
1378 return (ENOTDIR);
1379 }
1380 }
1381 return (ENOENT);
1382 }
1383
1384 /*
1385 * Traverse our tree, and find the right node, execute whatever it points
1386 * to, and return the resulting error code.
1387 */
1388
1389 static int
1390 sysctl_root(SYSCTL_HANDLER_ARGS)
1391 {
1392 struct sysctl_oid *oid;
1393 int error, indx, lvl;
1394
1395 SYSCTL_ASSERT_XLOCKED();
1396
1397 error = sysctl_find_oid(arg1, arg2, &oid, &indx, req);
1398 if (error)
1399 return (error);
1400
1401 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
1402 /*
1403 * You can't call a sysctl when it's a node, but has
1404 * no handler. Inform the user that it's a node.
1405 * The indx may or may not be the same as namelen.
1406 */
1407 if (oid->oid_handler == NULL)
1408 return (EISDIR);
1409 }
1410
1411 /* Is this sysctl writable? */
1412 if (req->newptr && !(oid->oid_kind & CTLFLAG_WR))
1413 return (EPERM);
1414
1415 KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL"));
1416
1417 /* Is this sysctl sensitive to securelevels? */
1418 if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) {
1419 lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE;
1420 error = securelevel_gt(req->td->td_ucred, lvl);
1421 if (error)
1422 return (error);
1423 }
1424
1425 /* Is this sysctl writable by only privileged users? */
1426 if (req->newptr && !(oid->oid_kind & CTLFLAG_ANYBODY)) {
1427 if (oid->oid_kind & CTLFLAG_PRISON)
1428 error = priv_check(req->td, PRIV_SYSCTL_WRITEJAIL);
1429 else
1430 error = priv_check(req->td, PRIV_SYSCTL_WRITE);
1431 if (error)
1432 return (error);
1433 }
1434
1435 if (!oid->oid_handler)
1436 return (EINVAL);
1437
1438 if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
1439 arg1 = (int *)arg1 + indx;
1440 arg2 -= indx;
1441 } else {
1442 arg1 = oid->oid_arg1;
1443 arg2 = oid->oid_arg2;
1444 }
1445 #ifdef MAC
1446 error = mac_check_system_sysctl(req->td->td_ucred, oid, arg1, arg2,
1447 req);
1448 if (error != 0)
1449 return (error);
1450 #endif
1451 oid->oid_running++;
1452 SYSCTL_XUNLOCK();
1453
1454 if (!(oid->oid_kind & CTLFLAG_MPSAFE))
1455 mtx_lock(&Giant);
1456 error = oid->oid_handler(oid, arg1, arg2, req);
1457 if (!(oid->oid_kind & CTLFLAG_MPSAFE))
1458 mtx_unlock(&Giant);
1459
1460 KFAIL_POINT_ERROR(_debug_fail_point, sysctl_running, error);
1461
1462 SYSCTL_XLOCK();
1463 oid->oid_running--;
1464 if (oid->oid_running == 0 && (oid->oid_kind & CTLFLAG_DYING) != 0)
1465 wakeup(&oid->oid_running);
1466 return (error);
1467 }
1468
1469 #ifndef _SYS_SYSPROTO_H_
1470 struct sysctl_args {
1471 int *name;
1472 u_int namelen;
1473 void *old;
1474 size_t *oldlenp;
1475 void *new;
1476 size_t newlen;
1477 };
1478 #endif
1479 int
1480 __sysctl(struct thread *td, struct sysctl_args *uap)
1481 {
1482 int error, i, name[CTL_MAXNAME];
1483 size_t j;
1484
1485 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
1486 return (EINVAL);
1487
1488 error = copyin(uap->name, &name, uap->namelen * sizeof(int));
1489 if (error)
1490 return (error);
1491
1492 error = userland_sysctl(td, name, uap->namelen,
1493 uap->old, uap->oldlenp, 0,
1494 uap->new, uap->newlen, &j, 0);
1495 if (error && error != ENOMEM)
1496 return (error);
1497 if (uap->oldlenp) {
1498 i = copyout(&j, uap->oldlenp, sizeof(j));
1499 if (i)
1500 return (i);
1501 }
1502 return (error);
1503 }
1504
1505 /*
1506 * This is used from various compatibility syscalls too. That's why name
1507 * must be in kernel space.
1508 */
1509 int
1510 userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
1511 size_t *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval,
1512 int flags)
1513 {
1514 int error = 0, memlocked;
1515 struct sysctl_req req;
1516
1517 bzero(&req, sizeof req);
1518
1519 req.td = td;
1520 req.flags = flags;
1521
1522 if (oldlenp) {
1523 if (inkernel) {
1524 req.oldlen = *oldlenp;
1525 } else {
1526 error = copyin(oldlenp, &req.oldlen, sizeof(*oldlenp));
1527 if (error)
1528 return (error);
1529 }
1530 }
1531 req.validlen = req.oldlen;
1532
1533 if (old) {
1534 if (!useracc(old, req.oldlen, VM_PROT_WRITE))
1535 return (EFAULT);
1536 req.oldptr= old;
1537 }
1538
1539 if (new != NULL) {
1540 if (!useracc(new, newlen, VM_PROT_READ))
1541 return (EFAULT);
1542 req.newlen = newlen;
1543 req.newptr = new;
1544 }
1545
1546 req.oldfunc = sysctl_old_user;
1547 req.newfunc = sysctl_new_user;
1548 req.lock = REQ_LOCKED;
1549
1550 #ifdef KTRACE
1551 if (KTRPOINT(curthread, KTR_SYSCTL))
1552 ktrsysctl(name, namelen);
1553 #endif
1554
1555 if (req.oldlen > PAGE_SIZE) {
1556 memlocked = 1;
1557 sx_xlock(&sysctlmemlock);
1558 } else
1559 memlocked = 0;
1560
1561 for (;;) {
1562 req.oldidx = 0;
1563 req.newidx = 0;
1564 SYSCTL_XLOCK();
1565 error = sysctl_root(0, name, namelen, &req);
1566 SYSCTL_XUNLOCK();
1567 if (error != EAGAIN)
1568 break;
1569 uio_yield();
1570 }
1571
1572
1573 if (req.lock == REQ_WIRED && req.validlen > 0)
1574 vsunlock(req.oldptr, req.validlen);
1575 if (memlocked)
1576 sx_xunlock(&sysctlmemlock);
1577
1578 if (error && error != ENOMEM)
1579 return (error);
1580
1581 if (retval) {
1582 if (req.oldptr && req.oldidx > req.validlen)
1583 *retval = req.validlen;
1584 else
1585 *retval = req.oldidx;
1586 }
1587 return (error);
1588 }
1589
1590 /*
1591 * Drain into a sysctl struct. The user buffer should be wired if a page
1592 * fault would cause issue.
1593 */
1594 static int
1595 sbuf_sysctl_drain(void *arg, const char *data, int len)
1596 {
1597 struct sysctl_req *req = arg;
1598 int error;
1599
1600 error = SYSCTL_OUT(req, data, len);
1601 KASSERT(error >= 0, ("Got unexpected negative value %d", error));
1602 return (error == 0 ? len : -error);
1603 }
1604
1605 struct sbuf *
1606 sbuf_new_for_sysctl(struct sbuf *s, char *buf, int length,
1607 struct sysctl_req *req)
1608 {
1609
1610 s = sbuf_new(s, buf, length, SBUF_FIXEDLEN);
1611 sbuf_set_drain(s, sbuf_sysctl_drain, req);
1612 return (s);
1613 }
Cache object: 6bcdfcd2202094680247f37c0322520b
|