init_sysctl.c revision 1.81.4.6 1 /* $NetBSD: init_sysctl.c,v 1.81.4.6 2006/12/29 20:27:43 ad Exp $ */
2
3 /*-
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Brown.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.81.4.6 2006/12/29 20:27:43 ad Exp $");
41
42 #include "opt_sysv.h"
43 #include "opt_multiprocessor.h"
44 #include "opt_posix.h"
45 #include "opt_compat_netbsd32.h"
46 #include "opt_ktrace.h"
47 #include "veriexec.h"
48 #include "pty.h"
49 #include "rnd.h"
50
51 #include <sys/types.h>
52 #include <sys/param.h>
53 #include <sys/sysctl.h>
54 #include <sys/errno.h>
55 #include <sys/systm.h>
56 #include <sys/kernel.h>
57 #include <sys/unistd.h>
58 #include <sys/disklabel.h>
59 #include <sys/rnd.h>
60 #include <sys/vnode.h>
61 #include <sys/mount.h>
62 #include <sys/namei.h>
63 #include <sys/msgbuf.h>
64 #include <dev/cons.h>
65 #include <sys/socketvar.h>
66 #include <sys/file.h>
67 #include <sys/filedesc.h>
68 #include <sys/tty.h>
69 #include <sys/malloc.h>
70 #include <sys/resource.h>
71 #include <sys/resourcevar.h>
72 #include <sys/exec.h>
73 #include <sys/conf.h>
74 #include <sys/device.h>
75 #if NVERIEXEC > 0
76 #define VERIEXEC_NEED_NODE
77 #include <sys/verified_exec.h>
78 #endif /* NVERIEXEC > 0 */
79 #include <sys/stat.h>
80 #include <sys/kauth.h>
81 #ifdef KTRACE
82 #include <sys/ktrace.h>
83 #endif
84
85 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
86 #include <sys/ipc.h>
87 #endif
88 #ifdef SYSVMSG
89 #include <sys/msg.h>
90 #endif
91 #ifdef SYSVSEM
92 #include <sys/sem.h>
93 #endif
94 #ifdef SYSVSHM
95 #include <sys/shm.h>
96 #endif
97
98 #ifdef COMPAT_NETBSD32
99 #include <compat/netbsd32/netbsd32.h>
100 #endif
101
102 #include <machine/cpu.h>
103
104 /* XXX this should not be here */
105 int security_setidcore_dump;
106 char security_setidcore_path[MAXPATHLEN] = "/var/crash/%n.core";
107 uid_t security_setidcore_owner = 0;
108 gid_t security_setidcore_group = 0;
109 mode_t security_setidcore_mode = (S_IRUSR|S_IWUSR);
110
111 static const u_int sysctl_flagmap[] = {
112 P_ADVLOCK, KP_ADVLOCK,
113 P_EXEC, KP_EXEC,
114 P_NOCLDWAIT, KP_NOCLDWAIT,
115 P_32, KP_32,
116 P_CLDSIGIGN, KP_CLDSIGIGN,
117 P_PAXMPROTECT, KP_PAXMPROTECT,
118 P_PAXNOMPROTECT, KP_PAXNOMPROTECT,
119 P_SYSTRACE, KP_SYSTRACE,
120 P_SUGID, KP_SUGID,
121 0
122 };
123
124 static const u_int sysctl_sflagmap[] = {
125 PS_NOCLDSTOP, KP_NOCLDSTOP,
126 PS_PPWAIT, KP_PPWAIT,
127 PS_WEXIT, KP_WEXIT,
128 PS_STOPFORK, KP_STOPFORK,
129 PS_STOPEXEC, KP_STOPEXEC,
130 PS_STOPEXIT, KP_STOPEXIT,
131 0
132 };
133
134 static const u_int sysctl_slflagmap[] = {
135 PSL_TRACED, KP_TRACED,
136 PSL_FSTRACE, KP_FSTRACE,
137 PSL_CHTRACED, KP_CHTRACED,
138 PSL_SYSCALL, KP_SYSCALL,
139 0
140 };
141
142 static const u_int sysctl_lflagmap[] = {
143 PL_CONTROLT, KP_CONTROLT,
144 0
145 };
146
147 static const u_int sysctl_stflagmap[] = {
148 PST_PROFIL, KP_PROFIL,
149 0
150
151 };
152
153 static const u_int sysctl_lwpflagmap[] = {
154 L_INMEM, KP_INMEM,
155 L_SELECT, KP_SELECT,
156 L_SINTR, KP_SINTR,
157 L_SYSTEM, KP_SYSTEM,
158 L_SA, KP_SA,
159 0
160 };
161
162
163 /*
164 * try over estimating by 5 procs/lwps
165 */
166 #define KERN_PROCSLOP (5 * sizeof(struct kinfo_proc))
167 #define KERN_LWPSLOP (5 * sizeof(struct kinfo_lwp))
168
169 #ifdef KTRACE
170 int dcopyout(struct lwp *, const void *, void *, size_t);
171
172 int
173 dcopyout(l, kaddr, uaddr, len)
174 struct lwp *l;
175 const void *kaddr;
176 void *uaddr;
177 size_t len;
178 {
179 int error;
180
181 error = copyout(kaddr, uaddr, len);
182 if (!error && KTRPOINT(l->l_proc, KTR_MIB)) {
183 struct iovec iov;
184
185 iov.iov_base = uaddr;
186 iov.iov_len = len;
187 ktrgenio(l, -1, UIO_READ, &iov, len, 0);
188 }
189 return error;
190 }
191 #else /* !KTRACE */
192 #define dcopyout(l, kaddr, uaddr, len) copyout(kaddr, uaddr, len)
193 #endif /* KTRACE */
194 #ifndef MULTIPROCESSOR
195 #define sysctl_ncpus() (1)
196 #else /* MULTIPROCESSOR */
197 #ifndef CPU_INFO_FOREACH
198 #define CPU_INFO_ITERATOR int
199 #define CPU_INFO_FOREACH(cii, ci) cii = 0, ci = curcpu(); ci != NULL; ci = NULL
200 #endif
201 static int
202 sysctl_ncpus(void)
203 {
204 struct cpu_info *ci;
205 CPU_INFO_ITERATOR cii;
206
207 int ncpus = 0;
208 for (CPU_INFO_FOREACH(cii, ci))
209 ncpus++;
210 return (ncpus);
211 }
212 #endif /* MULTIPROCESSOR */
213
214 #ifdef DIAGNOSTIC
215 static int sysctl_kern_trigger_panic(SYSCTLFN_PROTO);
216 #endif
217 static int sysctl_kern_maxvnodes(SYSCTLFN_PROTO);
218 static int sysctl_kern_rtc_offset(SYSCTLFN_PROTO);
219 static int sysctl_kern_maxproc(SYSCTLFN_PROTO);
220 static int sysctl_kern_hostid(SYSCTLFN_PROTO);
221 static int sysctl_setlen(SYSCTLFN_PROTO);
222 static int sysctl_kern_clockrate(SYSCTLFN_PROTO);
223 static int sysctl_kern_file(SYSCTLFN_PROTO);
224 static int sysctl_kern_autonice(SYSCTLFN_PROTO);
225 static int sysctl_msgbuf(SYSCTLFN_PROTO);
226 static int sysctl_kern_defcorename(SYSCTLFN_PROTO);
227 static int sysctl_kern_cptime(SYSCTLFN_PROTO);
228 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
229 static int sysctl_kern_sysvipc(SYSCTLFN_PROTO);
230 #endif /* defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) */
231 #if NPTY > 0
232 static int sysctl_kern_maxptys(SYSCTLFN_PROTO);
233 #endif /* NPTY > 0 */
234 static int sysctl_kern_sbmax(SYSCTLFN_PROTO);
235 static int sysctl_kern_urnd(SYSCTLFN_PROTO);
236 static int sysctl_kern_arnd(SYSCTLFN_PROTO);
237 static int sysctl_kern_lwp(SYSCTLFN_PROTO);
238 static int sysctl_kern_forkfsleep(SYSCTLFN_PROTO);
239 static int sysctl_kern_root_partition(SYSCTLFN_PROTO);
240 static int sysctl_kern_drivers(SYSCTLFN_PROTO);
241 static int sysctl_kern_file2(SYSCTLFN_PROTO);
242 #if NVERIEXEC > 0
243 static int sysctl_kern_veriexec(SYSCTLFN_PROTO);
244 #endif /* NVERIEXEC > 0 */
245 static int sysctl_security_setidcore(SYSCTLFN_PROTO);
246 static int sysctl_security_setidcorename(SYSCTLFN_PROTO);
247 static int sysctl_kern_cpid(SYSCTLFN_PROTO);
248 static int sysctl_doeproc(SYSCTLFN_PROTO);
249 static int sysctl_kern_proc_args(SYSCTLFN_PROTO);
250 static int sysctl_hw_usermem(SYSCTLFN_PROTO);
251 static int sysctl_hw_cnmagic(SYSCTLFN_PROTO);
252 static int sysctl_hw_ncpu(SYSCTLFN_PROTO);
253
254 static u_int sysctl_map_flags(const u_int *, u_int);
255 static void fill_kproc2(struct proc *, struct kinfo_proc2 *);
256 static void fill_lwp(struct lwp *l, struct kinfo_lwp *kl);
257 static void fill_file(struct kinfo_file *, const struct file *, struct proc *,
258 int);
259
260 /*
261 * ********************************************************************
262 * section 1: setup routines
263 * ********************************************************************
264 * these functions are stuffed into a link set for sysctl setup
265 * functions. they're never called or referenced from anywhere else.
266 * ********************************************************************
267 */
268
269 /*
270 * sets up the base nodes...
271 */
272 SYSCTL_SETUP(sysctl_root_setup, "sysctl base setup")
273 {
274
275 sysctl_createv(clog, 0, NULL, NULL,
276 CTLFLAG_PERMANENT,
277 CTLTYPE_NODE, "kern",
278 SYSCTL_DESCR("High kernel"),
279 NULL, 0, NULL, 0,
280 CTL_KERN, CTL_EOL);
281 sysctl_createv(clog, 0, NULL, NULL,
282 CTLFLAG_PERMANENT,
283 CTLTYPE_NODE, "vm",
284 SYSCTL_DESCR("Virtual memory"),
285 NULL, 0, NULL, 0,
286 CTL_VM, CTL_EOL);
287 sysctl_createv(clog, 0, NULL, NULL,
288 CTLFLAG_PERMANENT,
289 CTLTYPE_NODE, "vfs",
290 SYSCTL_DESCR("Filesystem"),
291 NULL, 0, NULL, 0,
292 CTL_VFS, CTL_EOL);
293 sysctl_createv(clog, 0, NULL, NULL,
294 CTLFLAG_PERMANENT,
295 CTLTYPE_NODE, "net",
296 SYSCTL_DESCR("Networking"),
297 NULL, 0, NULL, 0,
298 CTL_NET, CTL_EOL);
299 sysctl_createv(clog, 0, NULL, NULL,
300 CTLFLAG_PERMANENT,
301 CTLTYPE_NODE, "debug",
302 SYSCTL_DESCR("Debugging"),
303 NULL, 0, NULL, 0,
304 CTL_DEBUG, CTL_EOL);
305 sysctl_createv(clog, 0, NULL, NULL,
306 CTLFLAG_PERMANENT,
307 CTLTYPE_NODE, "hw",
308 SYSCTL_DESCR("Generic CPU, I/O"),
309 NULL, 0, NULL, 0,
310 CTL_HW, CTL_EOL);
311 sysctl_createv(clog, 0, NULL, NULL,
312 CTLFLAG_PERMANENT,
313 CTLTYPE_NODE, "machdep",
314 SYSCTL_DESCR("Machine dependent"),
315 NULL, 0, NULL, 0,
316 CTL_MACHDEP, CTL_EOL);
317 /*
318 * this node is inserted so that the sysctl nodes in libc can
319 * operate.
320 */
321 sysctl_createv(clog, 0, NULL, NULL,
322 CTLFLAG_PERMANENT,
323 CTLTYPE_NODE, "user",
324 SYSCTL_DESCR("User-level"),
325 NULL, 0, NULL, 0,
326 CTL_USER, CTL_EOL);
327 sysctl_createv(clog, 0, NULL, NULL,
328 CTLFLAG_PERMANENT,
329 CTLTYPE_NODE, "ddb",
330 SYSCTL_DESCR("In-kernel debugger"),
331 NULL, 0, NULL, 0,
332 CTL_DDB, CTL_EOL);
333 sysctl_createv(clog, 0, NULL, NULL,
334 CTLFLAG_PERMANENT,
335 CTLTYPE_NODE, "proc",
336 SYSCTL_DESCR("Per-process"),
337 NULL, 0, NULL, 0,
338 CTL_PROC, CTL_EOL);
339 sysctl_createv(clog, 0, NULL, NULL,
340 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
341 CTLTYPE_NODE, "vendor",
342 SYSCTL_DESCR("Vendor specific"),
343 NULL, 0, NULL, 0,
344 CTL_VENDOR, CTL_EOL);
345 sysctl_createv(clog, 0, NULL, NULL,
346 CTLFLAG_PERMANENT,
347 CTLTYPE_NODE, "emul",
348 SYSCTL_DESCR("Emulation settings"),
349 NULL, 0, NULL, 0,
350 CTL_EMUL, CTL_EOL);
351 sysctl_createv(clog, 0, NULL, NULL,
352 CTLFLAG_PERMANENT,
353 CTLTYPE_NODE, "security",
354 SYSCTL_DESCR("Security"),
355 NULL, 0, NULL, 0,
356 CTL_SECURITY, CTL_EOL);
357 }
358
359 /*
360 * this setup routine is a replacement for kern_sysctl()
361 */
362 SYSCTL_SETUP(sysctl_kern_setup, "sysctl kern subtree setup")
363 {
364 extern int kern_logsigexit; /* defined in kern/kern_sig.c */
365 extern fixpt_t ccpu; /* defined in kern/kern_synch.c */
366 extern int dumponpanic; /* defined in kern/subr_prf.c */
367 const struct sysctlnode *rnode;
368
369 sysctl_createv(clog, 0, NULL, NULL,
370 CTLFLAG_PERMANENT,
371 CTLTYPE_NODE, "kern", NULL,
372 NULL, 0, NULL, 0,
373 CTL_KERN, CTL_EOL);
374
375 sysctl_createv(clog, 0, NULL, NULL,
376 CTLFLAG_PERMANENT,
377 CTLTYPE_STRING, "ostype",
378 SYSCTL_DESCR("Operating system type"),
379 NULL, 0, &ostype, 0,
380 CTL_KERN, KERN_OSTYPE, CTL_EOL);
381 sysctl_createv(clog, 0, NULL, NULL,
382 CTLFLAG_PERMANENT,
383 CTLTYPE_STRING, "osrelease",
384 SYSCTL_DESCR("Operating system release"),
385 NULL, 0, &osrelease, 0,
386 CTL_KERN, KERN_OSRELEASE, CTL_EOL);
387 sysctl_createv(clog, 0, NULL, NULL,
388 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
389 CTLTYPE_INT, "osrevision",
390 SYSCTL_DESCR("Operating system revision"),
391 NULL, __NetBSD_Version__, NULL, 0,
392 CTL_KERN, KERN_OSREV, CTL_EOL);
393 sysctl_createv(clog, 0, NULL, NULL,
394 CTLFLAG_PERMANENT,
395 CTLTYPE_STRING, "version",
396 SYSCTL_DESCR("Kernel version"),
397 NULL, 0, &version, 0,
398 CTL_KERN, KERN_VERSION, CTL_EOL);
399 sysctl_createv(clog, 0, NULL, NULL,
400 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
401 CTLTYPE_INT, "maxvnodes",
402 SYSCTL_DESCR("Maximum number of vnodes"),
403 sysctl_kern_maxvnodes, 0, NULL, 0,
404 CTL_KERN, KERN_MAXVNODES, CTL_EOL);
405 sysctl_createv(clog, 0, NULL, NULL,
406 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
407 CTLTYPE_INT, "maxproc",
408 SYSCTL_DESCR("Maximum number of simultaneous processes"),
409 sysctl_kern_maxproc, 0, NULL, 0,
410 CTL_KERN, KERN_MAXPROC, CTL_EOL);
411 sysctl_createv(clog, 0, NULL, NULL,
412 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
413 CTLTYPE_INT, "maxfiles",
414 SYSCTL_DESCR("Maximum number of open files"),
415 NULL, 0, &maxfiles, 0,
416 CTL_KERN, KERN_MAXFILES, CTL_EOL);
417 sysctl_createv(clog, 0, NULL, NULL,
418 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
419 CTLTYPE_INT, "argmax",
420 SYSCTL_DESCR("Maximum number of bytes of arguments to "
421 "execve(2)"),
422 NULL, ARG_MAX, NULL, 0,
423 CTL_KERN, KERN_ARGMAX, CTL_EOL);
424 sysctl_createv(clog, 0, NULL, NULL,
425 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
426 CTLTYPE_STRING, "hostname",
427 SYSCTL_DESCR("System hostname"),
428 sysctl_setlen, 0, &hostname, MAXHOSTNAMELEN,
429 CTL_KERN, KERN_HOSTNAME, CTL_EOL);
430 sysctl_createv(clog, 0, NULL, NULL,
431 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_HEX,
432 CTLTYPE_INT, "hostid",
433 SYSCTL_DESCR("System host ID number"),
434 sysctl_kern_hostid, 0, NULL, 0,
435 CTL_KERN, KERN_HOSTID, CTL_EOL);
436 sysctl_createv(clog, 0, NULL, NULL,
437 CTLFLAG_PERMANENT,
438 CTLTYPE_STRUCT, "clockrate",
439 SYSCTL_DESCR("Kernel clock rates"),
440 sysctl_kern_clockrate, 0, NULL,
441 sizeof(struct clockinfo),
442 CTL_KERN, KERN_CLOCKRATE, CTL_EOL);
443 sysctl_createv(clog, 0, NULL, NULL,
444 CTLFLAG_PERMANENT,
445 CTLTYPE_INT, "hardclock_ticks",
446 SYSCTL_DESCR("Number of hardclock ticks"),
447 NULL, 0, &hardclock_ticks, sizeof(hardclock_ticks),
448 CTL_KERN, KERN_HARDCLOCK_TICKS, CTL_EOL);
449 sysctl_createv(clog, 0, NULL, NULL,
450 CTLFLAG_PERMANENT,
451 CTLTYPE_STRUCT, "vnode",
452 SYSCTL_DESCR("System vnode table"),
453 sysctl_kern_vnode, 0, NULL, 0,
454 CTL_KERN, KERN_VNODE, CTL_EOL);
455 sysctl_createv(clog, 0, NULL, NULL,
456 CTLFLAG_PERMANENT,
457 CTLTYPE_STRUCT, "file",
458 SYSCTL_DESCR("System open file table"),
459 sysctl_kern_file, 0, NULL, 0,
460 CTL_KERN, KERN_FILE, CTL_EOL);
461 #ifndef GPROF
462 sysctl_createv(clog, 0, NULL, NULL,
463 CTLFLAG_PERMANENT,
464 CTLTYPE_NODE, "profiling",
465 SYSCTL_DESCR("Profiling information (not available)"),
466 sysctl_notavail, 0, NULL, 0,
467 CTL_KERN, KERN_PROF, CTL_EOL);
468 #endif
469 sysctl_createv(clog, 0, NULL, NULL,
470 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
471 CTLTYPE_INT, "posix1version",
472 SYSCTL_DESCR("Version of ISO/IEC 9945 (POSIX 1003.1) "
473 "with which the operating system attempts "
474 "to comply"),
475 NULL, _POSIX_VERSION, NULL, 0,
476 CTL_KERN, KERN_POSIX1, CTL_EOL);
477 sysctl_createv(clog, 0, NULL, NULL,
478 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
479 CTLTYPE_INT, "ngroups",
480 SYSCTL_DESCR("Maximum number of supplemental groups"),
481 NULL, NGROUPS_MAX, NULL, 0,
482 CTL_KERN, KERN_NGROUPS, CTL_EOL);
483 sysctl_createv(clog, 0, NULL, NULL,
484 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
485 CTLTYPE_INT, "job_control",
486 SYSCTL_DESCR("Whether job control is available"),
487 NULL, 1, NULL, 0,
488 CTL_KERN, KERN_JOB_CONTROL, CTL_EOL);
489 sysctl_createv(clog, 0, NULL, NULL,
490 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
491 CTLTYPE_INT, "saved_ids",
492 SYSCTL_DESCR("Whether POSIX saved set-group/user ID is "
493 "available"), NULL,
494 #ifdef _POSIX_SAVED_IDS
495 1,
496 #else /* _POSIX_SAVED_IDS */
497 0,
498 #endif /* _POSIX_SAVED_IDS */
499 NULL, 0, CTL_KERN, KERN_SAVED_IDS, CTL_EOL);
500 sysctl_createv(clog, 0, NULL, NULL,
501 CTLFLAG_PERMANENT,
502 CTLTYPE_STRUCT, "boottime",
503 SYSCTL_DESCR("System boot time"),
504 NULL, 0, &boottime, sizeof(boottime),
505 CTL_KERN, KERN_BOOTTIME, CTL_EOL);
506 sysctl_createv(clog, 0, NULL, NULL,
507 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
508 CTLTYPE_STRING, "domainname",
509 SYSCTL_DESCR("YP domain name"),
510 sysctl_setlen, 0, &domainname, MAXHOSTNAMELEN,
511 CTL_KERN, KERN_DOMAINNAME, CTL_EOL);
512 sysctl_createv(clog, 0, NULL, NULL,
513 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
514 CTLTYPE_INT, "maxpartitions",
515 SYSCTL_DESCR("Maximum number of partitions allowed per "
516 "disk"),
517 NULL, MAXPARTITIONS, NULL, 0,
518 CTL_KERN, KERN_MAXPARTITIONS, CTL_EOL);
519 sysctl_createv(clog, 0, NULL, NULL,
520 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
521 CTLTYPE_INT, "rawpartition",
522 SYSCTL_DESCR("Raw partition of a disk"),
523 NULL, RAW_PART, NULL, 0,
524 CTL_KERN, KERN_RAWPARTITION, CTL_EOL);
525 sysctl_createv(clog, 0, NULL, NULL,
526 CTLFLAG_PERMANENT,
527 CTLTYPE_STRUCT, "timex", NULL,
528 sysctl_notavail, 0, NULL, 0,
529 CTL_KERN, KERN_TIMEX, CTL_EOL);
530 sysctl_createv(clog, 0, NULL, NULL,
531 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
532 CTLTYPE_INT, "autonicetime",
533 SYSCTL_DESCR("CPU clock seconds before non-root "
534 "process priority is lowered"),
535 sysctl_kern_autonice, 0, &autonicetime, 0,
536 CTL_KERN, KERN_AUTONICETIME, CTL_EOL);
537 sysctl_createv(clog, 0, NULL, NULL,
538 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
539 CTLTYPE_INT, "autoniceval",
540 SYSCTL_DESCR("Automatic reniced non-root process "
541 "priority"),
542 sysctl_kern_autonice, 0, &autoniceval, 0,
543 CTL_KERN, KERN_AUTONICEVAL, CTL_EOL);
544 sysctl_createv(clog, 0, NULL, NULL,
545 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
546 CTLTYPE_INT, "rtc_offset",
547 SYSCTL_DESCR("Offset of real time clock from UTC in "
548 "minutes"),
549 sysctl_kern_rtc_offset, 0, &rtc_offset, 0,
550 CTL_KERN, KERN_RTC_OFFSET, CTL_EOL);
551 sysctl_createv(clog, 0, NULL, NULL,
552 CTLFLAG_PERMANENT,
553 CTLTYPE_STRING, "root_device",
554 SYSCTL_DESCR("Name of the root device"),
555 sysctl_root_device, 0, NULL, 0,
556 CTL_KERN, KERN_ROOT_DEVICE, CTL_EOL);
557 sysctl_createv(clog, 0, NULL, NULL,
558 CTLFLAG_PERMANENT,
559 CTLTYPE_INT, "msgbufsize",
560 SYSCTL_DESCR("Size of the kernel message buffer"),
561 sysctl_msgbuf, 0, NULL, 0,
562 CTL_KERN, KERN_MSGBUFSIZE, CTL_EOL);
563 sysctl_createv(clog, 0, NULL, NULL,
564 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
565 CTLTYPE_INT, "fsync",
566 SYSCTL_DESCR("Whether the POSIX 1003.1b File "
567 "Synchronization Option is available on "
568 "this system"),
569 NULL, 1, NULL, 0,
570 CTL_KERN, KERN_FSYNC, CTL_EOL);
571 sysctl_createv(clog, 0, NULL, NULL,
572 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
573 CTLTYPE_INT, "sysvmsg",
574 SYSCTL_DESCR("System V style message support available"),
575 NULL,
576 #ifdef SYSVMSG
577 1,
578 #else /* SYSVMSG */
579 0,
580 #endif /* SYSVMSG */
581 NULL, 0, CTL_KERN, KERN_SYSVMSG, CTL_EOL);
582 sysctl_createv(clog, 0, NULL, NULL,
583 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
584 CTLTYPE_INT, "sysvsem",
585 SYSCTL_DESCR("System V style semaphore support "
586 "available"), NULL,
587 #ifdef SYSVSEM
588 1,
589 #else /* SYSVSEM */
590 0,
591 #endif /* SYSVSEM */
592 NULL, 0, CTL_KERN, KERN_SYSVSEM, CTL_EOL);
593 sysctl_createv(clog, 0, NULL, NULL,
594 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
595 CTLTYPE_INT, "sysvshm",
596 SYSCTL_DESCR("System V style shared memory support "
597 "available"), NULL,
598 #ifdef SYSVSHM
599 1,
600 #else /* SYSVSHM */
601 0,
602 #endif /* SYSVSHM */
603 NULL, 0, CTL_KERN, KERN_SYSVSHM, CTL_EOL);
604 sysctl_createv(clog, 0, NULL, NULL,
605 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
606 CTLTYPE_INT, "synchronized_io",
607 SYSCTL_DESCR("Whether the POSIX 1003.1b Synchronized "
608 "I/O Option is available on this system"),
609 NULL, 1, NULL, 0,
610 CTL_KERN, KERN_SYNCHRONIZED_IO, CTL_EOL);
611 sysctl_createv(clog, 0, NULL, NULL,
612 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
613 CTLTYPE_INT, "iov_max",
614 SYSCTL_DESCR("Maximum number of iovec structures per "
615 "process"),
616 NULL, IOV_MAX, NULL, 0,
617 CTL_KERN, KERN_IOV_MAX, CTL_EOL);
618 sysctl_createv(clog, 0, NULL, NULL,
619 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
620 CTLTYPE_INT, "mapped_files",
621 SYSCTL_DESCR("Whether the POSIX 1003.1b Memory Mapped "
622 "Files Option is available on this system"),
623 NULL, 1, NULL, 0,
624 CTL_KERN, KERN_MAPPED_FILES, CTL_EOL);
625 sysctl_createv(clog, 0, NULL, NULL,
626 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
627 CTLTYPE_INT, "memlock",
628 SYSCTL_DESCR("Whether the POSIX 1003.1b Process Memory "
629 "Locking Option is available on this "
630 "system"),
631 NULL, 1, NULL, 0,
632 CTL_KERN, KERN_MEMLOCK, CTL_EOL);
633 sysctl_createv(clog, 0, NULL, NULL,
634 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
635 CTLTYPE_INT, "memlock_range",
636 SYSCTL_DESCR("Whether the POSIX 1003.1b Range Memory "
637 "Locking Option is available on this "
638 "system"),
639 NULL, 1, NULL, 0,
640 CTL_KERN, KERN_MEMLOCK_RANGE, CTL_EOL);
641 sysctl_createv(clog, 0, NULL, NULL,
642 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
643 CTLTYPE_INT, "memory_protection",
644 SYSCTL_DESCR("Whether the POSIX 1003.1b Memory "
645 "Protection Option is available on this "
646 "system"),
647 NULL, 1, NULL, 0,
648 CTL_KERN, KERN_MEMORY_PROTECTION, CTL_EOL);
649 sysctl_createv(clog, 0, NULL, NULL,
650 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
651 CTLTYPE_INT, "login_name_max",
652 SYSCTL_DESCR("Maximum login name length"),
653 NULL, LOGIN_NAME_MAX, NULL, 0,
654 CTL_KERN, KERN_LOGIN_NAME_MAX, CTL_EOL);
655 sysctl_createv(clog, 0, NULL, NULL,
656 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
657 CTLTYPE_STRING, "defcorename",
658 SYSCTL_DESCR("Default core file name"),
659 sysctl_kern_defcorename, 0, defcorename, MAXPATHLEN,
660 CTL_KERN, KERN_DEFCORENAME, CTL_EOL);
661 sysctl_createv(clog, 0, NULL, NULL,
662 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
663 CTLTYPE_INT, "logsigexit",
664 SYSCTL_DESCR("Log process exit when caused by signals"),
665 NULL, 0, &kern_logsigexit, 0,
666 CTL_KERN, KERN_LOGSIGEXIT, CTL_EOL);
667 sysctl_createv(clog, 0, NULL, NULL,
668 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
669 CTLTYPE_INT, "fscale",
670 SYSCTL_DESCR("Kernel fixed-point scale factor"),
671 NULL, FSCALE, NULL, 0,
672 CTL_KERN, KERN_FSCALE, CTL_EOL);
673 sysctl_createv(clog, 0, NULL, NULL,
674 CTLFLAG_PERMANENT,
675 CTLTYPE_INT, "ccpu",
676 SYSCTL_DESCR("Scheduler exponential decay value"),
677 NULL, 0, &ccpu, 0,
678 CTL_KERN, KERN_CCPU, CTL_EOL);
679 sysctl_createv(clog, 0, NULL, NULL,
680 CTLFLAG_PERMANENT,
681 CTLTYPE_STRUCT, "cp_time",
682 SYSCTL_DESCR("Clock ticks spent in different CPU states"),
683 sysctl_kern_cptime, 0, NULL, 0,
684 CTL_KERN, KERN_CP_TIME, CTL_EOL);
685 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
686 sysctl_createv(clog, 0, NULL, NULL,
687 CTLFLAG_PERMANENT,
688 CTLTYPE_STRUCT, "sysvipc_info",
689 SYSCTL_DESCR("System V style IPC information"),
690 sysctl_kern_sysvipc, 0, NULL, 0,
691 CTL_KERN, KERN_SYSVIPC_INFO, CTL_EOL);
692 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */
693 sysctl_createv(clog, 0, NULL, NULL,
694 CTLFLAG_PERMANENT,
695 CTLTYPE_INT, "msgbuf",
696 SYSCTL_DESCR("Kernel message buffer"),
697 sysctl_msgbuf, 0, NULL, 0,
698 CTL_KERN, KERN_MSGBUF, CTL_EOL);
699 sysctl_createv(clog, 0, NULL, NULL,
700 CTLFLAG_PERMANENT,
701 CTLTYPE_STRUCT, "consdev",
702 SYSCTL_DESCR("Console device"),
703 sysctl_consdev, 0, NULL, sizeof(dev_t),
704 CTL_KERN, KERN_CONSDEV, CTL_EOL);
705 #if NPTY > 0
706 sysctl_createv(clog, 0, NULL, NULL,
707 CTLFLAG_PERMANENT,
708 CTLTYPE_INT, "maxptys",
709 SYSCTL_DESCR("Maximum number of pseudo-ttys"),
710 sysctl_kern_maxptys, 0, NULL, 0,
711 CTL_KERN, KERN_MAXPTYS, CTL_EOL);
712 #endif /* NPTY > 0 */
713 sysctl_createv(clog, 0, NULL, NULL,
714 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
715 CTLTYPE_INT, "maxphys",
716 SYSCTL_DESCR("Maximum raw I/O transfer size"),
717 NULL, MAXPHYS, NULL, 0,
718 CTL_KERN, KERN_MAXPHYS, CTL_EOL);
719 sysctl_createv(clog, 0, NULL, NULL,
720 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
721 CTLTYPE_INT, "sbmax",
722 SYSCTL_DESCR("Maximum socket buffer size"),
723 sysctl_kern_sbmax, 0, NULL, 0,
724 CTL_KERN, KERN_SBMAX, CTL_EOL);
725 sysctl_createv(clog, 0, NULL, NULL,
726 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
727 CTLTYPE_INT, "monotonic_clock",
728 SYSCTL_DESCR("Implementation version of the POSIX "
729 "1003.1b Monotonic Clock Option"),
730 /* XXX _POSIX_VERSION */
731 NULL, _POSIX_MONOTONIC_CLOCK, NULL, 0,
732 CTL_KERN, KERN_MONOTONIC_CLOCK, CTL_EOL);
733 sysctl_createv(clog, 0, NULL, NULL,
734 CTLFLAG_PERMANENT,
735 CTLTYPE_INT, "urandom",
736 SYSCTL_DESCR("Random integer value"),
737 sysctl_kern_urnd, 0, NULL, 0,
738 CTL_KERN, KERN_URND, CTL_EOL);
739 sysctl_createv(clog, 0, NULL, NULL,
740 CTLFLAG_PERMANENT,
741 CTLTYPE_INT, "arandom",
742 SYSCTL_DESCR("n bytes of random data"),
743 sysctl_kern_arnd, 0, NULL, 0,
744 CTL_KERN, KERN_ARND, CTL_EOL);
745 sysctl_createv(clog, 0, NULL, NULL,
746 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
747 CTLTYPE_INT, "labelsector",
748 SYSCTL_DESCR("Sector number containing the disklabel"),
749 NULL, LABELSECTOR, NULL, 0,
750 CTL_KERN, KERN_LABELSECTOR, CTL_EOL);
751 sysctl_createv(clog, 0, NULL, NULL,
752 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
753 CTLTYPE_INT, "labeloffset",
754 SYSCTL_DESCR("Offset of the disklabel within the "
755 "sector"),
756 NULL, LABELOFFSET, NULL, 0,
757 CTL_KERN, KERN_LABELOFFSET, CTL_EOL);
758 sysctl_createv(clog, 0, NULL, NULL,
759 CTLFLAG_PERMANENT,
760 CTLTYPE_NODE, "lwp",
761 SYSCTL_DESCR("System-wide LWP information"),
762 sysctl_kern_lwp, 0, NULL, 0,
763 CTL_KERN, KERN_LWP, CTL_EOL);
764 sysctl_createv(clog, 0, NULL, NULL,
765 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
766 CTLTYPE_INT, "forkfsleep",
767 SYSCTL_DESCR("Milliseconds to sleep on fork failure due "
768 "to process limits"),
769 sysctl_kern_forkfsleep, 0, NULL, 0,
770 CTL_KERN, KERN_FORKFSLEEP, CTL_EOL);
771 sysctl_createv(clog, 0, NULL, NULL,
772 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
773 CTLTYPE_INT, "posix_threads",
774 SYSCTL_DESCR("Version of IEEE Std 1003.1 and its "
775 "Threads option to which the system "
776 "attempts to conform"),
777 /* XXX _POSIX_VERSION */
778 NULL, _POSIX_THREADS, NULL, 0,
779 CTL_KERN, KERN_POSIX_THREADS, CTL_EOL);
780 sysctl_createv(clog, 0, NULL, NULL,
781 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
782 CTLTYPE_INT, "posix_semaphores",
783 SYSCTL_DESCR("Version of IEEE Std 1003.1 and its "
784 "Semaphores option to which the system "
785 "attempts to conform"), NULL,
786 #ifdef P1003_1B_SEMAPHORE
787 200112,
788 #else /* P1003_1B_SEMAPHORE */
789 0,
790 #endif /* P1003_1B_SEMAPHORE */
791 NULL, 0, CTL_KERN, KERN_POSIX_SEMAPHORES, CTL_EOL);
792 sysctl_createv(clog, 0, NULL, NULL,
793 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
794 CTLTYPE_INT, "posix_barriers",
795 SYSCTL_DESCR("Version of IEEE Std 1003.1 and its "
796 "Barriers option to which the system "
797 "attempts to conform"),
798 /* XXX _POSIX_VERSION */
799 NULL, _POSIX_BARRIERS, NULL, 0,
800 CTL_KERN, KERN_POSIX_BARRIERS, CTL_EOL);
801 sysctl_createv(clog, 0, NULL, NULL,
802 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
803 CTLTYPE_INT, "posix_timers",
804 SYSCTL_DESCR("Version of IEEE Std 1003.1 and its "
805 "Timers option to which the system "
806 "attempts to conform"),
807 /* XXX _POSIX_VERSION */
808 NULL, _POSIX_TIMERS, NULL, 0,
809 CTL_KERN, KERN_POSIX_TIMERS, CTL_EOL);
810 sysctl_createv(clog, 0, NULL, NULL,
811 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
812 CTLTYPE_INT, "posix_spin_locks",
813 SYSCTL_DESCR("Version of IEEE Std 1003.1 and its Spin "
814 "Locks option to which the system attempts "
815 "to conform"),
816 /* XXX _POSIX_VERSION */
817 NULL, _POSIX_SPIN_LOCKS, NULL, 0,
818 CTL_KERN, KERN_POSIX_SPIN_LOCKS, CTL_EOL);
819 sysctl_createv(clog, 0, NULL, NULL,
820 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
821 CTLTYPE_INT, "posix_reader_writer_locks",
822 SYSCTL_DESCR("Version of IEEE Std 1003.1 and its "
823 "Read-Write Locks option to which the "
824 "system attempts to conform"),
825 /* XXX _POSIX_VERSION */
826 NULL, _POSIX_READER_WRITER_LOCKS, NULL, 0,
827 CTL_KERN, KERN_POSIX_READER_WRITER_LOCKS, CTL_EOL);
828 sysctl_createv(clog, 0, NULL, NULL,
829 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
830 CTLTYPE_INT, "dump_on_panic",
831 SYSCTL_DESCR("Perform a crash dump on system panic"),
832 NULL, 0, &dumponpanic, 0,
833 CTL_KERN, KERN_DUMP_ON_PANIC, CTL_EOL);
834 #ifdef DIAGNOSTIC
835 sysctl_createv(clog, 0, NULL, NULL,
836 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
837 CTLTYPE_INT, "panic_now",
838 SYSCTL_DESCR("Trigger a panic"),
839 sysctl_kern_trigger_panic, 0, NULL, 0,
840 CTL_KERN, CTL_CREATE, CTL_EOL);
841 #endif
842 sysctl_createv(clog, 0, NULL, NULL,
843 CTLFLAG_PERMANENT,
844 CTLTYPE_INT, "root_partition",
845 SYSCTL_DESCR("Root partition on the root device"),
846 sysctl_kern_root_partition, 0, NULL, 0,
847 CTL_KERN, KERN_ROOT_PARTITION, CTL_EOL);
848 sysctl_createv(clog, 0, NULL, NULL,
849 CTLFLAG_PERMANENT,
850 CTLTYPE_STRUCT, "drivers",
851 SYSCTL_DESCR("List of all drivers with block and "
852 "character device numbers"),
853 sysctl_kern_drivers, 0, NULL, 0,
854 CTL_KERN, KERN_DRIVERS, CTL_EOL);
855 sysctl_createv(clog, 0, NULL, NULL,
856 CTLFLAG_PERMANENT,
857 CTLTYPE_STRUCT, "file2",
858 SYSCTL_DESCR("System open file table"),
859 sysctl_kern_file2, 0, NULL, 0,
860 CTL_KERN, KERN_FILE2, CTL_EOL);
861 #if NVERIEXEC > 0
862 sysctl_createv(clog, 0, NULL, NULL,
863 CTLFLAG_PERMANENT,
864 CTLTYPE_NODE, "veriexec",
865 SYSCTL_DESCR("Verified Exec"),
866 NULL, 0, NULL, 0,
867 CTL_KERN, KERN_VERIEXEC, CTL_EOL);
868 sysctl_createv(clog, 0, NULL, NULL,
869 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
870 CTLTYPE_INT, "verbose",
871 SYSCTL_DESCR("Verified Exec verbose level"),
872 NULL, 0, &veriexec_verbose, 0,
873 CTL_KERN, KERN_VERIEXEC, VERIEXEC_VERBOSE,
874 CTL_EOL);
875 sysctl_createv(clog, 0, NULL, NULL,
876 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
877 CTLTYPE_INT, "strict",
878 SYSCTL_DESCR("Verified Exec strict level"),
879 sysctl_kern_veriexec, 0, NULL, 0,
880 CTL_KERN, KERN_VERIEXEC, VERIEXEC_STRICT, CTL_EOL);
881 sysctl_createv(clog, 0, NULL, NULL,
882 CTLFLAG_PERMANENT,
883 CTLTYPE_STRING, "algorithms",
884 SYSCTL_DESCR("Verified Exec supported hashing "
885 "algorithms"),
886 sysctl_kern_veriexec, 0, NULL, 0,
887 CTL_KERN, KERN_VERIEXEC, VERIEXEC_ALGORITHMS, CTL_EOL);
888 sysctl_createv(clog, 0, NULL, &veriexec_count_node,
889 CTLFLAG_PERMANENT,
890 CTLTYPE_NODE, "count",
891 SYSCTL_DESCR("Number of fingerprints on device(s)"),
892 NULL, 0, NULL, 0,
893 CTL_KERN, KERN_VERIEXEC, VERIEXEC_COUNT, CTL_EOL);
894 #endif /* NVERIEXEC > 0 */
895 sysctl_createv(clog, 0, NULL, NULL,
896 CTLFLAG_PERMANENT,
897 CTLTYPE_STRUCT, "cp_id",
898 SYSCTL_DESCR("Mapping of CPU number to CPU id"),
899 sysctl_kern_cpid, 0, NULL, 0,
900 CTL_KERN, KERN_CP_ID, CTL_EOL);
901
902 sysctl_createv(clog, 0, NULL, &rnode,
903 CTLFLAG_PERMANENT,
904 CTLTYPE_NODE, "coredump",
905 SYSCTL_DESCR("Coredump settings."),
906 NULL, 0, NULL, 0,
907 CTL_KERN, CTL_CREATE, CTL_EOL);
908 sysctl_createv(clog, 0, &rnode, &rnode,
909 CTLFLAG_PERMANENT,
910 CTLTYPE_NODE, "setid",
911 SYSCTL_DESCR("Set-id processes' coredump settings."),
912 NULL, 0, NULL, 0,
913 CTL_CREATE, CTL_EOL);
914 sysctl_createv(clog, 0, &rnode, NULL,
915 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
916 CTLTYPE_INT, "dump",
917 SYSCTL_DESCR("Allow set-id processes to dump core."),
918 sysctl_security_setidcore, 0, &security_setidcore_dump,
919 sizeof(security_setidcore_dump),
920 CTL_CREATE, CTL_EOL);
921 sysctl_createv(clog, 0, &rnode, NULL,
922 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
923 CTLTYPE_STRING, "path",
924 SYSCTL_DESCR("Path pattern for set-id coredumps."),
925 sysctl_security_setidcorename, 0,
926 &security_setidcore_path,
927 sizeof(security_setidcore_path),
928 CTL_CREATE, CTL_EOL);
929 sysctl_createv(clog, 0, &rnode, NULL,
930 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
931 CTLTYPE_INT, "owner",
932 SYSCTL_DESCR("Owner id for set-id processes' cores."),
933 sysctl_security_setidcore, 0, &security_setidcore_owner,
934 0,
935 CTL_CREATE, CTL_EOL);
936 sysctl_createv(clog, 0, &rnode, NULL,
937 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
938 CTLTYPE_INT, "group",
939 SYSCTL_DESCR("Group id for set-id processes' cores."),
940 sysctl_security_setidcore, 0, &security_setidcore_group,
941 0,
942 CTL_CREATE, CTL_EOL);
943 sysctl_createv(clog, 0, &rnode, NULL,
944 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
945 CTLTYPE_INT, "mode",
946 SYSCTL_DESCR("Mode for set-id processes' cores."),
947 sysctl_security_setidcore, 0, &security_setidcore_mode,
948 0,
949 CTL_CREATE, CTL_EOL);
950 }
951
952 SYSCTL_SETUP(sysctl_kern_proc_setup,
953 "sysctl kern.proc/proc2/proc_args subtree setup")
954 {
955
956 sysctl_createv(clog, 0, NULL, NULL,
957 CTLFLAG_PERMANENT,
958 CTLTYPE_NODE, "kern", NULL,
959 NULL, 0, NULL, 0,
960 CTL_KERN, CTL_EOL);
961
962 sysctl_createv(clog, 0, NULL, NULL,
963 CTLFLAG_PERMANENT,
964 CTLTYPE_NODE, "proc",
965 SYSCTL_DESCR("System-wide process information"),
966 sysctl_doeproc, 0, NULL, 0,
967 CTL_KERN, KERN_PROC, CTL_EOL);
968 sysctl_createv(clog, 0, NULL, NULL,
969 CTLFLAG_PERMANENT,
970 CTLTYPE_NODE, "proc2",
971 SYSCTL_DESCR("Machine-independent process information"),
972 sysctl_doeproc, 0, NULL, 0,
973 CTL_KERN, KERN_PROC2, CTL_EOL);
974 sysctl_createv(clog, 0, NULL, NULL,
975 CTLFLAG_PERMANENT,
976 CTLTYPE_NODE, "proc_args",
977 SYSCTL_DESCR("Process argument information"),
978 sysctl_kern_proc_args, 0, NULL, 0,
979 CTL_KERN, KERN_PROC_ARGS, CTL_EOL);
980
981 /*
982 "nodes" under these:
983
984 KERN_PROC_ALL
985 KERN_PROC_PID pid
986 KERN_PROC_PGRP pgrp
987 KERN_PROC_SESSION sess
988 KERN_PROC_TTY tty
989 KERN_PROC_UID uid
990 KERN_PROC_RUID uid
991 KERN_PROC_GID gid
992 KERN_PROC_RGID gid
993
994 all in all, probably not worth the effort...
995 */
996 }
997
998 SYSCTL_SETUP(sysctl_hw_setup, "sysctl hw subtree setup")
999 {
1000 u_int u;
1001 u_quad_t q;
1002
1003 sysctl_createv(clog, 0, NULL, NULL,
1004 CTLFLAG_PERMANENT,
1005 CTLTYPE_NODE, "hw", NULL,
1006 NULL, 0, NULL, 0,
1007 CTL_HW, CTL_EOL);
1008
1009 sysctl_createv(clog, 0, NULL, NULL,
1010 CTLFLAG_PERMANENT,
1011 CTLTYPE_STRING, "machine",
1012 SYSCTL_DESCR("Machine class"),
1013 NULL, 0, machine, 0,
1014 CTL_HW, HW_MACHINE, CTL_EOL);
1015 sysctl_createv(clog, 0, NULL, NULL,
1016 CTLFLAG_PERMANENT,
1017 CTLTYPE_STRING, "model",
1018 SYSCTL_DESCR("Machine model"),
1019 NULL, 0, cpu_model, 0,
1020 CTL_HW, HW_MODEL, CTL_EOL);
1021 sysctl_createv(clog, 0, NULL, NULL,
1022 CTLFLAG_PERMANENT,
1023 CTLTYPE_INT, "ncpu",
1024 SYSCTL_DESCR("Number of active CPUs"),
1025 sysctl_hw_ncpu, 0, NULL, 0,
1026 CTL_HW, HW_NCPU, CTL_EOL);
1027 sysctl_createv(clog, 0, NULL, NULL,
1028 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
1029 CTLTYPE_INT, "byteorder",
1030 SYSCTL_DESCR("System byte order"),
1031 NULL, BYTE_ORDER, NULL, 0,
1032 CTL_HW, HW_BYTEORDER, CTL_EOL);
1033 u = ((u_int)physmem > (UINT_MAX / PAGE_SIZE)) ?
1034 UINT_MAX : physmem * PAGE_SIZE;
1035 sysctl_createv(clog, 0, NULL, NULL,
1036 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
1037 CTLTYPE_INT, "physmem",
1038 SYSCTL_DESCR("Bytes of physical memory"),
1039 NULL, u, NULL, 0,
1040 CTL_HW, HW_PHYSMEM, CTL_EOL);
1041 sysctl_createv(clog, 0, NULL, NULL,
1042 CTLFLAG_PERMANENT,
1043 CTLTYPE_INT, "usermem",
1044 SYSCTL_DESCR("Bytes of non-kernel memory"),
1045 sysctl_hw_usermem, 0, NULL, 0,
1046 CTL_HW, HW_USERMEM, CTL_EOL);
1047 sysctl_createv(clog, 0, NULL, NULL,
1048 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
1049 CTLTYPE_INT, "pagesize",
1050 SYSCTL_DESCR("Software page size"),
1051 NULL, PAGE_SIZE, NULL, 0,
1052 CTL_HW, HW_PAGESIZE, CTL_EOL);
1053 sysctl_createv(clog, 0, NULL, NULL,
1054 CTLFLAG_PERMANENT,
1055 CTLTYPE_STRING, "machine_arch",
1056 SYSCTL_DESCR("Machine CPU class"),
1057 NULL, 0, machine_arch, 0,
1058 CTL_HW, HW_MACHINE_ARCH, CTL_EOL);
1059 sysctl_createv(clog, 0, NULL, NULL,
1060 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
1061 CTLTYPE_INT, "alignbytes",
1062 SYSCTL_DESCR("Alignment constraint for all possible "
1063 "data types"),
1064 NULL, ALIGNBYTES, NULL, 0,
1065 CTL_HW, HW_ALIGNBYTES, CTL_EOL);
1066 sysctl_createv(clog, 0, NULL, NULL,
1067 CTLFLAG_PERMANENT|CTLFLAG_READWRITE|CTLFLAG_HEX,
1068 CTLTYPE_STRING, "cnmagic",
1069 SYSCTL_DESCR("Console magic key sequence"),
1070 sysctl_hw_cnmagic, 0, NULL, CNS_LEN,
1071 CTL_HW, HW_CNMAGIC, CTL_EOL);
1072 q = (u_quad_t)physmem * PAGE_SIZE;
1073 sysctl_createv(clog, 0, NULL, NULL,
1074 CTLFLAG_PERMANENT|CTLFLAG_IMMEDIATE,
1075 CTLTYPE_QUAD, "physmem64",
1076 SYSCTL_DESCR("Bytes of physical memory"),
1077 NULL, q, NULL, 0,
1078 CTL_HW, HW_PHYSMEM64, CTL_EOL);
1079 sysctl_createv(clog, 0, NULL, NULL,
1080 CTLFLAG_PERMANENT,
1081 CTLTYPE_QUAD, "usermem64",
1082 SYSCTL_DESCR("Bytes of non-kernel memory"),
1083 sysctl_hw_usermem, 0, NULL, 0,
1084 CTL_HW, HW_USERMEM64, CTL_EOL);
1085 }
1086
1087 #ifdef DEBUG
1088 /*
1089 * Debugging related system variables.
1090 */
1091 struct ctldebug /* debug0, */ /* debug1, */ debug2, debug3, debug4;
1092 struct ctldebug debug5, debug6, debug7, debug8, debug9;
1093 struct ctldebug debug10, debug11, debug12, debug13, debug14;
1094 struct ctldebug debug15, debug16, debug17, debug18, debug19;
1095 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
1096 &debug0, &debug1, &debug2, &debug3, &debug4,
1097 &debug5, &debug6, &debug7, &debug8, &debug9,
1098 &debug10, &debug11, &debug12, &debug13, &debug14,
1099 &debug15, &debug16, &debug17, &debug18, &debug19,
1100 };
1101
1102 /*
1103 * this setup routine is a replacement for debug_sysctl()
1104 *
1105 * note that it creates several nodes per defined debug variable
1106 */
1107 SYSCTL_SETUP(sysctl_debug_setup, "sysctl debug subtree setup")
1108 {
1109 struct ctldebug *cdp;
1110 char nodename[20];
1111 int i;
1112
1113 /*
1114 * two ways here:
1115 *
1116 * the "old" way (debug.name -> value) which was emulated by
1117 * the sysctl(8) binary
1118 *
1119 * the new way, which the sysctl(8) binary was actually using
1120
1121 node debug
1122 node debug.0
1123 string debug.0.name
1124 int debug.0.value
1125 int debug.name
1126
1127 */
1128
1129 sysctl_createv(clog, 0, NULL, NULL,
1130 CTLFLAG_PERMANENT,
1131 CTLTYPE_NODE, "debug", NULL,
1132 NULL, 0, NULL, 0,
1133 CTL_DEBUG, CTL_EOL);
1134
1135 for (i = 0; i < CTL_DEBUG_MAXID; i++) {
1136 cdp = debugvars[i];
1137 if (cdp->debugname == NULL || cdp->debugvar == NULL)
1138 continue;
1139
1140 snprintf(nodename, sizeof(nodename), "debug%d", i);
1141 sysctl_createv(clog, 0, NULL, NULL,
1142 CTLFLAG_PERMANENT|CTLFLAG_HIDDEN,
1143 CTLTYPE_NODE, nodename, NULL,
1144 NULL, 0, NULL, 0,
1145 CTL_DEBUG, i, CTL_EOL);
1146 sysctl_createv(clog, 0, NULL, NULL,
1147 CTLFLAG_PERMANENT|CTLFLAG_HIDDEN,
1148 CTLTYPE_STRING, "name", NULL,
1149 /*XXXUNCONST*/
1150 NULL, 0, __UNCONST(cdp->debugname), 0,
1151 CTL_DEBUG, i, CTL_DEBUG_NAME, CTL_EOL);
1152 sysctl_createv(clog, 0, NULL, NULL,
1153 CTLFLAG_PERMANENT|CTLFLAG_HIDDEN,
1154 CTLTYPE_INT, "value", NULL,
1155 NULL, 0, cdp->debugvar, 0,
1156 CTL_DEBUG, i, CTL_DEBUG_VALUE, CTL_EOL);
1157 sysctl_createv(clog, 0, NULL, NULL,
1158 CTLFLAG_PERMANENT,
1159 CTLTYPE_INT, cdp->debugname, NULL,
1160 NULL, 0, cdp->debugvar, 0,
1161 CTL_DEBUG, CTL_CREATE, CTL_EOL);
1162 }
1163 }
1164 #endif /* DEBUG */
1165
1166 /*
1167 * ********************************************************************
1168 * section 2: private node-specific helper routines.
1169 * ********************************************************************
1170 */
1171
1172 #ifdef DIAGNOSTIC
1173 static int
1174 sysctl_kern_trigger_panic(SYSCTLFN_ARGS)
1175 {
1176 int newtrig, error;
1177 struct sysctlnode node;
1178
1179 newtrig = 0;
1180 node = *rnode;
1181 node.sysctl_data = &newtrig;
1182 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1183 if (error || newp == NULL)
1184 return (error);
1185
1186 if (newtrig != 0)
1187 panic("Panic triggered");
1188
1189 return (error);
1190 }
1191 #endif
1192
1193 /*
1194 * sysctl helper routine for kern.maxvnodes. drain vnodes if
1195 * new value is lower than desiredvnodes and then calls reinit
1196 * routines that needs to adjust to the new value.
1197 */
1198 static int
1199 sysctl_kern_maxvnodes(SYSCTLFN_ARGS)
1200 {
1201 int error, new_vnodes, old_vnodes;
1202 struct sysctlnode node;
1203
1204 new_vnodes = desiredvnodes;
1205 node = *rnode;
1206 node.sysctl_data = &new_vnodes;
1207 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1208 if (error || newp == NULL)
1209 return (error);
1210
1211 old_vnodes = desiredvnodes;
1212 desiredvnodes = new_vnodes;
1213 if (new_vnodes < old_vnodes) {
1214 error = vfs_drainvnodes(new_vnodes, l);
1215 if (error) {
1216 desiredvnodes = old_vnodes;
1217 return (error);
1218 }
1219 }
1220 vfs_reinit();
1221 nchreinit();
1222
1223 return (0);
1224 }
1225
1226 /*
1227 * sysctl helper routine for rtc_offset - set time after changes
1228 */
1229 static int
1230 sysctl_kern_rtc_offset(SYSCTLFN_ARGS)
1231 {
1232 struct timespec ts, delta;
1233 int error, new_rtc_offset;
1234 struct sysctlnode node;
1235
1236 new_rtc_offset = rtc_offset;
1237 node = *rnode;
1238 node.sysctl_data = &new_rtc_offset;
1239 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1240 if (error || newp == NULL)
1241 return (error);
1242
1243 if (kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME,
1244 KAUTH_REQ_SYSTEM_TIME_RTCOFFSET,
1245 (void *)(u_long)new_rtc_offset, NULL, NULL))
1246 return (EPERM);
1247 if (rtc_offset == new_rtc_offset)
1248 return (0);
1249
1250 /* if we change the offset, adjust the time */
1251 nanotime(&ts);
1252 delta.tv_sec = 60 * (new_rtc_offset - rtc_offset);
1253 delta.tv_nsec = 0;
1254 timespecadd(&ts, &delta, &ts);
1255 rtc_offset = new_rtc_offset;
1256 settime(l->l_proc, &ts);
1257
1258 return (0);
1259 }
1260
1261 /*
1262 * sysctl helper routine for kern.maxproc. ensures that the new
1263 * values are not too low or too high.
1264 */
1265 static int
1266 sysctl_kern_maxproc(SYSCTLFN_ARGS)
1267 {
1268 int error, nmaxproc;
1269 struct sysctlnode node;
1270
1271 nmaxproc = maxproc;
1272 node = *rnode;
1273 node.sysctl_data = &nmaxproc;
1274 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1275 if (error || newp == NULL)
1276 return (error);
1277
1278 if (nmaxproc < 0 || nmaxproc >= PID_MAX)
1279 return (EINVAL);
1280 #ifdef __HAVE_CPU_MAXPROC
1281 if (nmaxproc > cpu_maxproc())
1282 return (EINVAL);
1283 #endif
1284 maxproc = nmaxproc;
1285
1286 return (0);
1287 }
1288
1289 /*
1290 * sysctl helper function for kern.hostid. the hostid is a long, but
1291 * we export it as an int, so we need to give it a little help.
1292 */
1293 static int
1294 sysctl_kern_hostid(SYSCTLFN_ARGS)
1295 {
1296 int error, inthostid;
1297 struct sysctlnode node;
1298
1299 inthostid = hostid; /* XXX assumes sizeof int <= sizeof long */
1300 node = *rnode;
1301 node.sysctl_data = &inthostid;
1302 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1303 if (error || newp == NULL)
1304 return (error);
1305
1306 hostid = (unsigned)inthostid;
1307
1308 return (0);
1309 }
1310
1311 /*
1312 * sysctl helper function for kern.hostname and kern.domainnname.
1313 * resets the relevant recorded length when the underlying name is
1314 * changed.
1315 */
1316 static int
1317 sysctl_setlen(SYSCTLFN_ARGS)
1318 {
1319 int error;
1320
1321 error = sysctl_lookup(SYSCTLFN_CALL(rnode));
1322 if (error || newp == NULL)
1323 return (error);
1324
1325 switch (rnode->sysctl_num) {
1326 case KERN_HOSTNAME:
1327 hostnamelen = strlen((const char*)rnode->sysctl_data);
1328 break;
1329 case KERN_DOMAINNAME:
1330 domainnamelen = strlen((const char*)rnode->sysctl_data);
1331 break;
1332 }
1333
1334 return (0);
1335 }
1336
1337 /*
1338 * sysctl helper routine for kern.clockrate. assembles a struct on
1339 * the fly to be returned to the caller.
1340 */
1341 static int
1342 sysctl_kern_clockrate(SYSCTLFN_ARGS)
1343 {
1344 struct clockinfo clkinfo;
1345 struct sysctlnode node;
1346
1347 clkinfo.tick = tick;
1348 clkinfo.tickadj = tickadj;
1349 clkinfo.hz = hz;
1350 clkinfo.profhz = profhz;
1351 clkinfo.stathz = stathz ? stathz : hz;
1352
1353 node = *rnode;
1354 node.sysctl_data = &clkinfo;
1355 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
1356 }
1357
1358
1359 /*
1360 * sysctl helper routine for kern.file pseudo-subtree.
1361 */
1362 static int
1363 sysctl_kern_file(SYSCTLFN_ARGS)
1364 {
1365 int error;
1366 size_t buflen;
1367 struct file *fp;
1368 char *start, *where;
1369
1370 start = where = oldp;
1371 buflen = *oldlenp;
1372 if (where == NULL) {
1373 /*
1374 * overestimate by 10 files
1375 */
1376 *oldlenp = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
1377 return (0);
1378 }
1379
1380 /*
1381 * first dcopyout filehead
1382 */
1383 if (buflen < sizeof(filehead)) {
1384 *oldlenp = 0;
1385 return (0);
1386 }
1387 error = dcopyout(l, &filehead, where, sizeof(filehead));
1388 if (error)
1389 return (error);
1390 buflen -= sizeof(filehead);
1391 where += sizeof(filehead);
1392
1393 /*
1394 * followed by an array of file structures
1395 */
1396 LIST_FOREACH(fp, &filehead, f_list) {
1397 if (kauth_authorize_generic(l->l_cred,
1398 KAUTH_GENERIC_CANSEE, fp->f_cred) != 0)
1399 continue;
1400 if (buflen < sizeof(struct file)) {
1401 *oldlenp = where - start;
1402 return (ENOMEM);
1403 }
1404 error = dcopyout(l, fp, where, sizeof(struct file));
1405 if (error)
1406 return (error);
1407 buflen -= sizeof(struct file);
1408 where += sizeof(struct file);
1409 }
1410 *oldlenp = where - start;
1411 return (0);
1412 }
1413
1414 /*
1415 * sysctl helper routine for kern.autonicetime and kern.autoniceval.
1416 * asserts that the assigned value is in the correct range.
1417 */
1418 static int
1419 sysctl_kern_autonice(SYSCTLFN_ARGS)
1420 {
1421 int error, t = 0;
1422 struct sysctlnode node;
1423
1424 node = *rnode;
1425 t = *(int*)node.sysctl_data;
1426 node.sysctl_data = &t;
1427 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1428 if (error || newp == NULL)
1429 return (error);
1430
1431 switch (node.sysctl_num) {
1432 case KERN_AUTONICETIME:
1433 if (t >= 0)
1434 autonicetime = t;
1435 break;
1436 case KERN_AUTONICEVAL:
1437 if (t < PRIO_MIN)
1438 t = PRIO_MIN;
1439 else if (t > PRIO_MAX)
1440 t = PRIO_MAX;
1441 autoniceval = t;
1442 break;
1443 }
1444
1445 return (0);
1446 }
1447
1448 /*
1449 * sysctl helper routine for kern.msgbufsize and kern.msgbuf. for the
1450 * former it merely checks the message buffer is set up. for the latter,
1451 * it also copies out the data if necessary.
1452 */
1453 static int
1454 sysctl_msgbuf(SYSCTLFN_ARGS)
1455 {
1456 char *where = oldp;
1457 size_t len, maxlen;
1458 long beg, end;
1459 int error;
1460
1461 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
1462 msgbufenabled = 0;
1463 return (ENXIO);
1464 }
1465
1466 switch (rnode->sysctl_num) {
1467 case KERN_MSGBUFSIZE: {
1468 struct sysctlnode node = *rnode;
1469 int msg_bufs = (int)msgbufp->msg_bufs;
1470 node.sysctl_data = &msg_bufs;
1471 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
1472 }
1473 case KERN_MSGBUF:
1474 break;
1475 default:
1476 return (EOPNOTSUPP);
1477 }
1478
1479 if (newp != NULL)
1480 return (EPERM);
1481
1482 if (oldp == NULL) {
1483 /* always return full buffer size */
1484 *oldlenp = msgbufp->msg_bufs;
1485 return (0);
1486 }
1487
1488 error = 0;
1489 maxlen = MIN(msgbufp->msg_bufs, *oldlenp);
1490
1491 /*
1492 * First, copy from the write pointer to the end of
1493 * message buffer.
1494 */
1495 beg = msgbufp->msg_bufx;
1496 end = msgbufp->msg_bufs;
1497 while (maxlen > 0) {
1498 len = MIN(end - beg, maxlen);
1499 if (len == 0)
1500 break;
1501 error = dcopyout(l, &msgbufp->msg_bufc[beg], where, len);
1502 if (error)
1503 break;
1504 where += len;
1505 maxlen -= len;
1506
1507 /*
1508 * ... then, copy from the beginning of message buffer to
1509 * the write pointer.
1510 */
1511 beg = 0;
1512 end = msgbufp->msg_bufx;
1513 }
1514
1515 return (error);
1516 }
1517
1518 /*
1519 * sysctl helper routine for kern.defcorename. in the case of a new
1520 * string being assigned, check that it's not a zero-length string.
1521 * (XXX the check in -current doesn't work, but do we really care?)
1522 */
1523 static int
1524 sysctl_kern_defcorename(SYSCTLFN_ARGS)
1525 {
1526 int error;
1527 char *newcorename;
1528 struct sysctlnode node;
1529
1530 newcorename = PNBUF_GET();
1531 node = *rnode;
1532 node.sysctl_data = &newcorename[0];
1533 memcpy(node.sysctl_data, rnode->sysctl_data, MAXPATHLEN);
1534 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1535 if (error || newp == NULL) {
1536 goto done;
1537 }
1538
1539 /*
1540 * when sysctl_lookup() deals with a string, it's guaranteed
1541 * to come back nul terminated. so there. :)
1542 */
1543 if (strlen(newcorename) == 0) {
1544 error = EINVAL;
1545 } else {
1546 memcpy(rnode->sysctl_data, node.sysctl_data, MAXPATHLEN);
1547 error = 0;
1548 }
1549 done:
1550 PNBUF_PUT(newcorename);
1551 return error;
1552 }
1553
1554 /*
1555 * sysctl helper routine for kern.cp_time node. adds up cpu time
1556 * across all cpus.
1557 */
1558 static int
1559 sysctl_kern_cptime(SYSCTLFN_ARGS)
1560 {
1561 struct sysctlnode node = *rnode;
1562
1563 #ifndef MULTIPROCESSOR
1564
1565 if (namelen == 1) {
1566 if (name[0] != 0)
1567 return (ENOENT);
1568 /*
1569 * you're allowed to ask for the zero'th processor
1570 */
1571 name++;
1572 namelen--;
1573 }
1574 node.sysctl_data = curcpu()->ci_schedstate.spc_cp_time;
1575 node.sysctl_size = sizeof(curcpu()->ci_schedstate.spc_cp_time);
1576 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
1577
1578 #else /* MULTIPROCESSOR */
1579
1580 uint64_t *cp_time = NULL;
1581 int error, n = sysctl_ncpus(), i;
1582 struct cpu_info *ci;
1583 CPU_INFO_ITERATOR cii;
1584
1585 /*
1586 * if you specifically pass a buffer that is the size of the
1587 * sum, or if you are probing for the size, you get the "sum"
1588 * of cp_time (and the size thereof) across all processors.
1589 *
1590 * alternately, you can pass an additional mib number and get
1591 * cp_time for that particular processor.
1592 */
1593 switch (namelen) {
1594 case 0:
1595 if (*oldlenp == sizeof(uint64_t) * CPUSTATES || oldp == NULL) {
1596 node.sysctl_size = sizeof(uint64_t) * CPUSTATES;
1597 n = -1; /* SUM */
1598 }
1599 else {
1600 node.sysctl_size = n * sizeof(uint64_t) * CPUSTATES;
1601 n = -2; /* ALL */
1602 }
1603 break;
1604 case 1:
1605 if (name[0] < 0 || name[0] >= n)
1606 return (ENOENT); /* ENOSUCHPROCESSOR */
1607 node.sysctl_size = sizeof(uint64_t) * CPUSTATES;
1608 n = name[0];
1609 /*
1610 * adjust these so that sysctl_lookup() will be happy
1611 */
1612 name++;
1613 namelen--;
1614 break;
1615 default:
1616 return (EINVAL);
1617 }
1618
1619 cp_time = malloc(node.sysctl_size, M_TEMP, M_WAITOK|M_CANFAIL);
1620 if (cp_time == NULL)
1621 return (ENOMEM);
1622 node.sysctl_data = cp_time;
1623 memset(cp_time, 0, node.sysctl_size);
1624
1625 for (CPU_INFO_FOREACH(cii, ci)) {
1626 if (n <= 0)
1627 for (i = 0; i < CPUSTATES; i++)
1628 cp_time[i] += ci->ci_schedstate.spc_cp_time[i];
1629 /*
1630 * if a specific processor was requested and we just
1631 * did it, we're done here
1632 */
1633 if (n == 0)
1634 break;
1635 /*
1636 * if doing "all", skip to next cp_time set for next processor
1637 */
1638 if (n == -2)
1639 cp_time += CPUSTATES;
1640 /*
1641 * if we're doing a specific processor, we're one
1642 * processor closer
1643 */
1644 if (n > 0)
1645 n--;
1646 }
1647
1648 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1649 free(node.sysctl_data, M_TEMP);
1650 return (error);
1651
1652 #endif /* MULTIPROCESSOR */
1653 }
1654
1655 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
1656 /*
1657 * sysctl helper routine for kern.sysvipc_info subtree.
1658 */
1659
1660 #define FILL_PERM(src, dst) do { \
1661 (dst)._key = (src)._key; \
1662 (dst).uid = (src).uid; \
1663 (dst).gid = (src).gid; \
1664 (dst).cuid = (src).cuid; \
1665 (dst).cgid = (src).cgid; \
1666 (dst).mode = (src).mode; \
1667 (dst)._seq = (src)._seq; \
1668 } while (/*CONSTCOND*/ 0);
1669 #define FILL_MSG(src, dst) do { \
1670 FILL_PERM((src).msg_perm, (dst).msg_perm); \
1671 (dst).msg_qnum = (src).msg_qnum; \
1672 (dst).msg_qbytes = (src).msg_qbytes; \
1673 (dst)._msg_cbytes = (src)._msg_cbytes; \
1674 (dst).msg_lspid = (src).msg_lspid; \
1675 (dst).msg_lrpid = (src).msg_lrpid; \
1676 (dst).msg_stime = (src).msg_stime; \
1677 (dst).msg_rtime = (src).msg_rtime; \
1678 (dst).msg_ctime = (src).msg_ctime; \
1679 } while (/*CONSTCOND*/ 0)
1680 #define FILL_SEM(src, dst) do { \
1681 FILL_PERM((src).sem_perm, (dst).sem_perm); \
1682 (dst).sem_nsems = (src).sem_nsems; \
1683 (dst).sem_otime = (src).sem_otime; \
1684 (dst).sem_ctime = (src).sem_ctime; \
1685 } while (/*CONSTCOND*/ 0)
1686 #define FILL_SHM(src, dst) do { \
1687 FILL_PERM((src).shm_perm, (dst).shm_perm); \
1688 (dst).shm_segsz = (src).shm_segsz; \
1689 (dst).shm_lpid = (src).shm_lpid; \
1690 (dst).shm_cpid = (src).shm_cpid; \
1691 (dst).shm_atime = (src).shm_atime; \
1692 (dst).shm_dtime = (src).shm_dtime; \
1693 (dst).shm_ctime = (src).shm_ctime; \
1694 (dst).shm_nattch = (src).shm_nattch; \
1695 } while (/*CONSTCOND*/ 0)
1696
1697 static int
1698 sysctl_kern_sysvipc(SYSCTLFN_ARGS)
1699 {
1700 void *where = oldp;
1701 size_t *sizep = oldlenp;
1702 #ifdef SYSVMSG
1703 struct msg_sysctl_info *msgsi = NULL;
1704 #endif
1705 #ifdef SYSVSEM
1706 struct sem_sysctl_info *semsi = NULL;
1707 #endif
1708 #ifdef SYSVSHM
1709 struct shm_sysctl_info *shmsi = NULL;
1710 #endif
1711 size_t infosize, dssize, tsize, buflen;
1712 void *bf = NULL;
1713 char *start;
1714 int32_t nds;
1715 int i, error, ret;
1716
1717 if (namelen != 1)
1718 return (EINVAL);
1719
1720 start = where;
1721 buflen = *sizep;
1722
1723 switch (*name) {
1724 case KERN_SYSVIPC_MSG_INFO:
1725 #ifdef SYSVMSG
1726 infosize = sizeof(msgsi->msginfo);
1727 nds = msginfo.msgmni;
1728 dssize = sizeof(msgsi->msgids[0]);
1729 break;
1730 #else
1731 return (EINVAL);
1732 #endif
1733 case KERN_SYSVIPC_SEM_INFO:
1734 #ifdef SYSVSEM
1735 infosize = sizeof(semsi->seminfo);
1736 nds = seminfo.semmni;
1737 dssize = sizeof(semsi->semids[0]);
1738 break;
1739 #else
1740 return (EINVAL);
1741 #endif
1742 case KERN_SYSVIPC_SHM_INFO:
1743 #ifdef SYSVSHM
1744 infosize = sizeof(shmsi->shminfo);
1745 nds = shminfo.shmmni;
1746 dssize = sizeof(shmsi->shmids[0]);
1747 break;
1748 #else
1749 return (EINVAL);
1750 #endif
1751 default:
1752 return (EINVAL);
1753 }
1754 /*
1755 * Round infosize to 64 bit boundary if requesting more than just
1756 * the info structure or getting the total data size.
1757 */
1758 if (where == NULL || *sizep > infosize)
1759 infosize = ((infosize + 7) / 8) * 8;
1760 tsize = infosize + nds * dssize;
1761
1762 /* Return just the total size required. */
1763 if (where == NULL) {
1764 *sizep = tsize;
1765 return (0);
1766 }
1767
1768 /* Not enough room for even the info struct. */
1769 if (buflen < infosize) {
1770 *sizep = 0;
1771 return (ENOMEM);
1772 }
1773 bf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK);
1774 memset(bf, 0, min(tsize, buflen));
1775
1776 switch (*name) {
1777 #ifdef SYSVMSG
1778 case KERN_SYSVIPC_MSG_INFO:
1779 msgsi = (struct msg_sysctl_info *)bf;
1780 msgsi->msginfo = msginfo;
1781 break;
1782 #endif
1783 #ifdef SYSVSEM
1784 case KERN_SYSVIPC_SEM_INFO:
1785 semsi = (struct sem_sysctl_info *)bf;
1786 semsi->seminfo = seminfo;
1787 break;
1788 #endif
1789 #ifdef SYSVSHM
1790 case KERN_SYSVIPC_SHM_INFO:
1791 shmsi = (struct shm_sysctl_info *)bf;
1792 shmsi->shminfo = shminfo;
1793 break;
1794 #endif
1795 }
1796 buflen -= infosize;
1797
1798 ret = 0;
1799 if (buflen > 0) {
1800 /* Fill in the IPC data structures. */
1801 for (i = 0; i < nds; i++) {
1802 if (buflen < dssize) {
1803 ret = ENOMEM;
1804 break;
1805 }
1806 switch (*name) {
1807 #ifdef SYSVMSG
1808 case KERN_SYSVIPC_MSG_INFO:
1809 FILL_MSG(msqids[i], msgsi->msgids[i]);
1810 break;
1811 #endif
1812 #ifdef SYSVSEM
1813 case KERN_SYSVIPC_SEM_INFO:
1814 FILL_SEM(sema[i], semsi->semids[i]);
1815 break;
1816 #endif
1817 #ifdef SYSVSHM
1818 case KERN_SYSVIPC_SHM_INFO:
1819 FILL_SHM(shmsegs[i], shmsi->shmids[i]);
1820 break;
1821 #endif
1822 }
1823 buflen -= dssize;
1824 }
1825 }
1826 *sizep -= buflen;
1827 error = dcopyout(l, bf, start, *sizep);
1828 /* If dcopyout succeeded, use return code set earlier. */
1829 if (error == 0)
1830 error = ret;
1831 if (bf)
1832 free(bf, M_TEMP);
1833 return (error);
1834 }
1835
1836 #undef FILL_PERM
1837 #undef FILL_MSG
1838 #undef FILL_SEM
1839 #undef FILL_SHM
1840
1841 #endif /* defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) */
1842
1843 #if NPTY > 0
1844 /*
1845 * sysctl helper routine for kern.maxptys. ensures that any new value
1846 * is acceptable to the pty subsystem.
1847 */
1848 static int
1849 sysctl_kern_maxptys(SYSCTLFN_ARGS)
1850 {
1851 int pty_maxptys(int, int); /* defined in kern/tty_pty.c */
1852 int error, xmax;
1853 struct sysctlnode node;
1854
1855 /* get current value of maxptys */
1856 xmax = pty_maxptys(0, 0);
1857
1858 node = *rnode;
1859 node.sysctl_data = &xmax;
1860 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1861 if (error || newp == NULL)
1862 return (error);
1863
1864 if (xmax != pty_maxptys(xmax, 1))
1865 return (EINVAL);
1866
1867 return (0);
1868 }
1869 #endif /* NPTY > 0 */
1870
1871 /*
1872 * sysctl helper routine for kern.sbmax. basically just ensures that
1873 * any new value is not too small.
1874 */
1875 static int
1876 sysctl_kern_sbmax(SYSCTLFN_ARGS)
1877 {
1878 int error, new_sbmax;
1879 struct sysctlnode node;
1880
1881 new_sbmax = sb_max;
1882 node = *rnode;
1883 node.sysctl_data = &new_sbmax;
1884 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1885 if (error || newp == NULL)
1886 return (error);
1887
1888 error = sb_max_set(new_sbmax);
1889
1890 return (error);
1891 }
1892
1893 /*
1894 * sysctl helper routine for kern.urandom node. picks a random number
1895 * for you.
1896 */
1897 static int
1898 sysctl_kern_urnd(SYSCTLFN_ARGS)
1899 {
1900 #if NRND > 0
1901 int v;
1902
1903 if (rnd_extract_data(&v, sizeof(v), RND_EXTRACT_ANY) == sizeof(v)) {
1904 struct sysctlnode node = *rnode;
1905 node.sysctl_data = &v;
1906 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
1907 }
1908 else
1909 return (EIO); /*XXX*/
1910 #else
1911 return (EOPNOTSUPP);
1912 #endif
1913 }
1914
1915 /*
1916 * sysctl helper routine for kern.arandom node. picks a random number
1917 * for you.
1918 */
1919 static int
1920 sysctl_kern_arnd(SYSCTLFN_ARGS)
1921 {
1922 #if NRND > 0
1923 int error;
1924 void *v;
1925 struct sysctlnode node = *rnode;
1926
1927 if (*oldlenp == 0)
1928 return 0;
1929 if (*oldlenp > 8192)
1930 return E2BIG;
1931
1932 v = malloc(*oldlenp, M_TEMP, M_WAITOK);
1933
1934 arc4randbytes(v, *oldlenp);
1935 node.sysctl_data = v;
1936 node.sysctl_size = *oldlenp;
1937 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1938 free(v, M_TEMP);
1939 return error;
1940 #else
1941 return (EOPNOTSUPP);
1942 #endif
1943 }
1944 /*
1945 * sysctl helper routine to do kern.lwp.* work.
1946 */
1947 static int
1948 sysctl_kern_lwp(SYSCTLFN_ARGS)
1949 {
1950 struct kinfo_lwp klwp;
1951 struct proc *p;
1952 struct lwp *l2;
1953 char *where, *dp;
1954 int pid, elem_size, elem_count;
1955 int buflen, needed, error;
1956
1957 if (namelen == 1 && name[0] == CTL_QUERY)
1958 return (sysctl_query(SYSCTLFN_CALL(rnode)));
1959
1960 dp = where = oldp;
1961 buflen = where != NULL ? *oldlenp : 0;
1962 error = needed = 0;
1963
1964 if (newp != NULL || namelen != 3)
1965 return (EINVAL);
1966 pid = name[0];
1967 elem_size = name[1];
1968 elem_count = name[2];
1969
1970 p = p_find(pid, PFIND_UNLOCK_FAIL);
1971 if (p == NULL)
1972 return (ESRCH);
1973 mutex_enter(&p->p_smutex);
1974 LIST_FOREACH(l2, &p->p_lwps, l_sibling) {
1975 if (buflen >= elem_size && elem_count > 0) {
1976 lwp_lock(l2);
1977 fill_lwp(l2, &klwp);
1978 lwp_unlock(l2);
1979
1980 /*
1981 * Copy out elem_size, but not larger than
1982 * the size of a struct kinfo_proc2.
1983 *
1984 * XXX We should not be holding p_smutex, but
1985 * for now, the buffer is wired. Fix later.
1986 */
1987 error = dcopyout(l, &klwp, dp,
1988 min(sizeof(klwp), elem_size));
1989 if (error)
1990 goto cleanup;
1991 dp += elem_size;
1992 buflen -= elem_size;
1993 elem_count--;
1994 }
1995 needed += elem_size;
1996 }
1997 mutex_exit(&p->p_smutex);
1998 rw_exit(&proclist_lock);
1999
2000 if (where != NULL) {
2001 *oldlenp = dp - where;
2002 if (needed > *oldlenp)
2003 return (ENOMEM);
2004 } else {
2005 needed += KERN_LWPSLOP;
2006 *oldlenp = needed;
2007 }
2008 return (0);
2009 cleanup:
2010 return (error);
2011 }
2012
2013 /*
2014 * sysctl helper routine for kern.forkfsleep node. ensures that the
2015 * given value is not too large or two small, and is at least one
2016 * timer tick if not zero.
2017 */
2018 static int
2019 sysctl_kern_forkfsleep(SYSCTLFN_ARGS)
2020 {
2021 /* userland sees value in ms, internally is in ticks */
2022 extern int forkfsleep; /* defined in kern/kern_fork.c */
2023 int error, timo, lsleep;
2024 struct sysctlnode node;
2025
2026 lsleep = forkfsleep * 1000 / hz;
2027 node = *rnode;
2028 node.sysctl_data = &lsleep;
2029 error = sysctl_lookup(SYSCTLFN_CALL(&node));
2030 if (error || newp == NULL)
2031 return (error);
2032
2033 /* refuse negative values, and overly 'long time' */
2034 if (lsleep < 0 || lsleep > MAXSLP * 1000)
2035 return (EINVAL);
2036
2037 timo = mstohz(lsleep);
2038
2039 /* if the interval is >0 ms && <1 tick, use 1 tick */
2040 if (lsleep != 0 && timo == 0)
2041 forkfsleep = 1;
2042 else
2043 forkfsleep = timo;
2044
2045 return (0);
2046 }
2047
2048 /*
2049 * sysctl helper routine for kern.root_partition
2050 */
2051 static int
2052 sysctl_kern_root_partition(SYSCTLFN_ARGS)
2053 {
2054 int rootpart = DISKPART(rootdev);
2055 struct sysctlnode node = *rnode;
2056
2057 node.sysctl_data = &rootpart;
2058 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
2059 }
2060
2061 /*
2062 * sysctl helper function for kern.drivers
2063 */
2064 static int
2065 sysctl_kern_drivers(SYSCTLFN_ARGS)
2066 {
2067 int error;
2068 size_t buflen;
2069 struct kinfo_drivers kd;
2070 char *start, *where;
2071 const char *dname;
2072 int i;
2073 extern struct devsw_conv *devsw_conv;
2074 extern int max_devsw_convs;
2075
2076 if (newp != NULL || namelen != 0)
2077 return (EINVAL);
2078
2079 start = where = oldp;
2080 buflen = *oldlenp;
2081 if (where == NULL) {
2082 *oldlenp = max_devsw_convs * sizeof kd;
2083 return 0;
2084 }
2085
2086 /*
2087 * An array of kinfo_drivers structures
2088 */
2089 error = 0;
2090 for (i = 0; i < max_devsw_convs; i++) {
2091 dname = devsw_conv[i].d_name;
2092 if (dname == NULL)
2093 continue;
2094 if (buflen < sizeof kd) {
2095 error = ENOMEM;
2096 break;
2097 }
2098 memset(&kd, 0, sizeof(kd));
2099 kd.d_bmajor = devsw_conv[i].d_bmajor;
2100 kd.d_cmajor = devsw_conv[i].d_cmajor;
2101 strlcpy(kd.d_name, dname, sizeof kd.d_name);
2102 error = dcopyout(l, &kd, where, sizeof kd);
2103 if (error != 0)
2104 break;
2105 buflen -= sizeof kd;
2106 where += sizeof kd;
2107 }
2108 *oldlenp = where - start;
2109 return error;
2110 }
2111
2112 /*
2113 * sysctl helper function for kern.file2
2114 */
2115 static int
2116 sysctl_kern_file2(SYSCTLFN_ARGS)
2117 {
2118 struct proc *p;
2119 struct file *fp;
2120 struct filedesc *fd;
2121 struct kinfo_file kf;
2122 char *dp;
2123 u_int i, op;
2124 size_t len, needed, elem_size, out_size;
2125 int error, arg, elem_count;
2126
2127 if (namelen == 1 && name[0] == CTL_QUERY)
2128 return (sysctl_query(SYSCTLFN_CALL(rnode)));
2129
2130 if (namelen != 4)
2131 return (EINVAL);
2132
2133 error = 0;
2134 dp = oldp;
2135 len = (oldp != NULL) ? *oldlenp : 0;
2136 op = name[0];
2137 arg = name[1];
2138 elem_size = name[2];
2139 elem_count = name[3];
2140 out_size = MIN(sizeof(kf), elem_size);
2141 needed = 0;
2142
2143 if (elem_size < 1 || elem_count < 0)
2144 return (EINVAL);
2145
2146 switch (op) {
2147 case KERN_FILE_BYFILE:
2148 /*
2149 * doesn't use arg so it must be zero
2150 */
2151 if (arg != 0)
2152 return (EINVAL);
2153 LIST_FOREACH(fp, &filehead, f_list) {
2154 if (kauth_authorize_generic(l->l_cred,
2155 KAUTH_GENERIC_CANSEE, fp->f_cred) != 0)
2156 continue;
2157 if (len >= elem_size && elem_count > 0) {
2158 fill_file(&kf, fp, NULL, 0);
2159 error = dcopyout(l, &kf, dp, out_size);
2160 if (error)
2161 break;
2162 dp += elem_size;
2163 len -= elem_size;
2164 }
2165 if (elem_count > 0) {
2166 needed += elem_size;
2167 if (elem_count != INT_MAX)
2168 elem_count--;
2169 }
2170 }
2171 break;
2172 case KERN_FILE_BYPID:
2173 if (arg < -1)
2174 /* -1 means all processes */
2175 return (EINVAL);
2176 rw_enter(&proclist_lock, RW_READER);
2177 PROCLIST_FOREACH(p, &allproc) {
2178 if (p->p_stat == SIDL)
2179 /* skip embryonic processes */
2180 continue;
2181 if (kauth_authorize_process(l->l_cred,
2182 KAUTH_PROCESS_CANSEE, p, NULL, NULL, NULL) != 0)
2183 continue;
2184 if (arg > 0 && p->p_pid != arg)
2185 /* pick only the one we want */
2186 /* XXX want 0 to mean "kernel files" */
2187 continue;
2188 fd = p->p_fd;
2189 for (i = 0; i < fd->fd_nfiles; i++) {
2190 fp = fd->fd_ofiles[i];
2191 if (fp == NULL || !FILE_IS_USABLE(fp))
2192 continue;
2193 if (len >= elem_size && elem_count > 0) {
2194 fill_file(&kf, fd->fd_ofiles[i],
2195 p, i);
2196 error = dcopyout(l, &kf, dp, out_size);
2197 if (error)
2198 break;
2199 dp += elem_size;
2200 len -= elem_size;
2201 }
2202 if (elem_count > 0) {
2203 needed += elem_size;
2204 if (elem_count != INT_MAX)
2205 elem_count--;
2206 }
2207 }
2208 }
2209 rw_exit(&proclist_lock);
2210 break;
2211 default:
2212 return (EINVAL);
2213 }
2214
2215 if (oldp == NULL)
2216 needed += KERN_FILESLOP * elem_size;
2217 *oldlenp = needed;
2218
2219 return (error);
2220 }
2221
2222 static void
2223 fill_file(struct kinfo_file *kp, const struct file *fp, struct proc *p, int i)
2224 {
2225
2226 memset(kp, 0, sizeof(*kp));
2227
2228 kp->ki_fileaddr = PTRTOUINT64(fp);
2229 kp->ki_flag = fp->f_flag;
2230 kp->ki_iflags = fp->f_iflags;
2231 kp->ki_ftype = fp->f_type;
2232 kp->ki_count = fp->f_count;
2233 kp->ki_msgcount = fp->f_msgcount;
2234 kp->ki_usecount = fp->f_usecount;
2235 kp->ki_fucred = PTRTOUINT64(fp->f_cred);
2236 kp->ki_fuid = kauth_cred_geteuid(fp->f_cred);
2237 kp->ki_fgid = kauth_cred_getegid(fp->f_cred);
2238 kp->ki_fops = PTRTOUINT64(fp->f_ops);
2239 kp->ki_foffset = fp->f_offset;
2240 kp->ki_fdata = PTRTOUINT64(fp->f_data);
2241
2242 /* vnode information to glue this file to something */
2243 if (fp->f_type == DTYPE_VNODE) {
2244 struct vnode *vp = (struct vnode *)fp->f_data;
2245
2246 kp->ki_vun = PTRTOUINT64(vp->v_un.vu_socket);
2247 kp->ki_vsize = vp->v_size;
2248 kp->ki_vtype = vp->v_type;
2249 kp->ki_vtag = vp->v_tag;
2250 kp->ki_vdata = PTRTOUINT64(vp->v_data);
2251 }
2252
2253 /* process information when retrieved via KERN_FILE_BYPID */
2254 if (p) {
2255 kp->ki_pid = p->p_pid;
2256 kp->ki_fd = i;
2257 kp->ki_ofileflags = p->p_fd->fd_ofileflags[i];
2258 }
2259 }
2260
2261 static int
2262 sysctl_doeproc(SYSCTLFN_ARGS)
2263 {
2264 struct eproc *eproc;
2265 struct kinfo_proc2 *kproc2;
2266 struct kinfo_proc *dp;
2267 struct proc *p;
2268 const struct proclist_desc *pd;
2269 char *where, *dp2;
2270 int type, op, arg;
2271 u_int elem_size, elem_count;
2272 size_t buflen, needed;
2273 int error;
2274
2275 if (namelen == 1 && name[0] == CTL_QUERY)
2276 return (sysctl_query(SYSCTLFN_CALL(rnode)));
2277
2278 dp = oldp;
2279 dp2 = where = oldp;
2280 buflen = where != NULL ? *oldlenp : 0;
2281 error = 0;
2282 needed = 0;
2283 type = rnode->sysctl_num;
2284
2285 if (type == KERN_PROC) {
2286 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
2287 return (EINVAL);
2288 op = name[0];
2289 if (op != KERN_PROC_ALL)
2290 arg = name[1];
2291 else
2292 arg = 0; /* Quell compiler warning */
2293 elem_size = elem_count = 0; /* Ditto */
2294 } else {
2295 if (namelen != 4)
2296 return (EINVAL);
2297 op = name[0];
2298 arg = name[1];
2299 elem_size = name[2];
2300 elem_count = name[3];
2301 }
2302
2303 if (type == KERN_PROC) {
2304 eproc = malloc(sizeof(*eproc), M_TEMP, M_WAITOK);
2305 kproc2 = NULL;
2306 } else {
2307 eproc = NULL;
2308 kproc2 = malloc(sizeof(*kproc2), M_TEMP, M_WAITOK);
2309 }
2310 rw_enter(&proclist_lock, RW_READER);
2311
2312 pd = proclists;
2313 again:
2314 PROCLIST_FOREACH(p, pd->pd_list) {
2315 /*
2316 * Skip embryonic processes.
2317 */
2318 if (p->p_stat == SIDL)
2319 continue;
2320
2321 if (kauth_authorize_process(l->l_cred,
2322 KAUTH_PROCESS_CANSEE, p, NULL, NULL, NULL) != 0)
2323 continue;
2324
2325 /*
2326 * TODO - make more efficient (see notes below).
2327 * do by session.
2328 */
2329 switch (op) {
2330
2331 case KERN_PROC_PID:
2332 /* could do this with just a lookup */
2333 if (p->p_pid != (pid_t)arg)
2334 continue;
2335 break;
2336
2337 case KERN_PROC_PGRP:
2338 /* could do this by traversing pgrp */
2339 if (p->p_pgrp->pg_id != (pid_t)arg)
2340 continue;
2341 break;
2342
2343 case KERN_PROC_SESSION:
2344 if (p->p_session->s_sid != (pid_t)arg)
2345 continue;
2346 break;
2347
2348 case KERN_PROC_TTY:
2349 if (arg == (int) KERN_PROC_TTY_REVOKE) {
2350 if ((p->p_lflag & PL_CONTROLT) == 0 ||
2351 p->p_session->s_ttyp == NULL ||
2352 p->p_session->s_ttyvp != NULL)
2353 continue;
2354 } else if ((p->p_lflag & PL_CONTROLT) == 0 ||
2355 p->p_session->s_ttyp == NULL) {
2356 if ((dev_t)arg != KERN_PROC_TTY_NODEV)
2357 continue;
2358 } else if (p->p_session->s_ttyp->t_dev != (dev_t)arg)
2359 continue;
2360 break;
2361
2362 case KERN_PROC_UID:
2363 if (kauth_cred_geteuid(p->p_cred) != (uid_t)arg)
2364 continue;
2365 break;
2366
2367 case KERN_PROC_RUID:
2368 if (kauth_cred_getuid(p->p_cred) != (uid_t)arg)
2369 continue;
2370 break;
2371
2372 case KERN_PROC_GID:
2373 if (kauth_cred_getegid(p->p_cred) != (uid_t)arg)
2374 continue;
2375 break;
2376
2377 case KERN_PROC_RGID:
2378 if (kauth_cred_getgid(p->p_cred) != (uid_t)arg)
2379 continue;
2380 break;
2381
2382 case KERN_PROC_ALL:
2383 /* allow everything */
2384 break;
2385
2386 default:
2387 error = EINVAL;
2388 goto cleanup;
2389 }
2390 if (type == KERN_PROC) {
2391 if (buflen >= sizeof(struct kinfo_proc)) {
2392 fill_eproc(p, eproc);
2393 error = dcopyout(l, p, &dp->kp_proc,
2394 sizeof(struct proc));
2395 if (error)
2396 goto cleanup;
2397 error = dcopyout(l, eproc, &dp->kp_eproc,
2398 sizeof(*eproc));
2399 if (error)
2400 goto cleanup;
2401 dp++;
2402 buflen -= sizeof(struct kinfo_proc);
2403 }
2404 needed += sizeof(struct kinfo_proc);
2405 } else { /* KERN_PROC2 */
2406 if (buflen >= elem_size && elem_count > 0) {
2407 fill_kproc2(p, kproc2);
2408 /*
2409 * Copy out elem_size, but not larger than
2410 * the size of a struct kinfo_proc2.
2411 */
2412 error = dcopyout(l, kproc2, dp2,
2413 min(sizeof(*kproc2), elem_size));
2414 if (error)
2415 goto cleanup;
2416 dp2 += elem_size;
2417 buflen -= elem_size;
2418 elem_count--;
2419 }
2420 needed += elem_size;
2421 }
2422 }
2423 pd++;
2424 if (pd->pd_list != NULL)
2425 goto again;
2426 rw_exit(&proclist_lock);
2427
2428 if (where != NULL) {
2429 if (type == KERN_PROC)
2430 *oldlenp = (char *)dp - where;
2431 else
2432 *oldlenp = dp2 - where;
2433 if (needed > *oldlenp) {
2434 error = ENOMEM;
2435 goto out;
2436 }
2437 } else {
2438 needed += KERN_PROCSLOP;
2439 *oldlenp = needed;
2440 }
2441 if (kproc2)
2442 free(kproc2, M_TEMP);
2443 if (eproc)
2444 free(eproc, M_TEMP);
2445 return 0;
2446 cleanup:
2447 rw_exit(&proclist_lock);
2448 out:
2449 if (kproc2)
2450 free(kproc2, M_TEMP);
2451 if (eproc)
2452 free(eproc, M_TEMP);
2453 return error;
2454 }
2455
2456 /*
2457 * sysctl helper routine for kern.proc_args pseudo-subtree.
2458 */
2459 static int
2460 sysctl_kern_proc_args(SYSCTLFN_ARGS)
2461 {
2462 struct ps_strings pss;
2463 struct proc *p;
2464 size_t len, i;
2465 struct uio auio;
2466 struct iovec aiov;
2467 pid_t pid;
2468 int nargv, type, error;
2469 char *arg;
2470 char **argv = NULL;
2471 char *tmp;
2472 struct vmspace *vmspace;
2473 vaddr_t psstr_addr;
2474 vaddr_t offsetn;
2475 vaddr_t offsetv;
2476
2477 if (namelen == 1 && name[0] == CTL_QUERY)
2478 return (sysctl_query(SYSCTLFN_CALL(rnode)));
2479
2480 if (newp != NULL || namelen != 2)
2481 return (EINVAL);
2482 pid = name[0];
2483 type = name[1];
2484
2485 switch (type) {
2486 case KERN_PROC_ARGV:
2487 case KERN_PROC_NARGV:
2488 case KERN_PROC_ENV:
2489 case KERN_PROC_NENV:
2490 /* ok */
2491 break;
2492 default:
2493 return (EINVAL);
2494 }
2495
2496 rw_enter(&proclist_lock, RW_READER);
2497
2498 /* check pid */
2499 if ((p = p_find(pid, PFIND_LOCKED)) == NULL) {
2500 error = EINVAL;
2501 goto out_locked;
2502 }
2503
2504 error = kauth_authorize_process(l->l_cred,
2505 KAUTH_PROCESS_CANSEE, p, NULL, NULL, NULL);
2506 if (error) {
2507 goto out_locked;
2508 }
2509
2510 /* only root or same user change look at the environment */
2511 if (type == KERN_PROC_ENV || type == KERN_PROC_NENV) {
2512 if (kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE,
2513 p, NULL, NULL, NULL)) {
2514 error = EPERM;
2515 goto out_locked;
2516 }
2517 }
2518
2519 if (oldp == NULL) {
2520 if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV)
2521 *oldlenp = sizeof (int);
2522 else
2523 *oldlenp = ARG_MAX; /* XXX XXX XXX */
2524 error = 0;
2525 goto out_locked;
2526 }
2527
2528 /*
2529 * Zombies don't have a stack, so we can't read their psstrings.
2530 * System processes also don't have a user stack.
2531 */
2532 if (P_ZOMBIE(p) || (p->p_flag & P_SYSTEM) != 0) {
2533 error = EINVAL;
2534 goto out_locked;
2535 }
2536
2537 /*
2538 * Lock the process down in memory.
2539 */
2540 /* XXXCDC: how should locking work here? */
2541 if ((l->l_flag & L_WEXIT) || (p->p_vmspace->vm_refcnt < 1)) {
2542 error = EFAULT;
2543 goto out_locked;
2544 }
2545
2546 psstr_addr = (vaddr_t)p->p_psstr;
2547 if (type == KERN_PROC_ARGV || type == KERN_PROC_NARGV) {
2548 offsetn = p->p_psnargv;
2549 offsetv = p->p_psargv;
2550 } else {
2551 offsetn = p->p_psnenv;
2552 offsetv = p->p_psenv;
2553 }
2554 vmspace = p->p_vmspace;
2555 vmspace->vm_refcnt++; /* XXX */
2556
2557 rw_exit(&proclist_lock);
2558
2559 /*
2560 * Allocate a temporary buffer to hold the arguments.
2561 */
2562 arg = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
2563
2564 /*
2565 * Read in the ps_strings structure.
2566 */
2567 aiov.iov_base = &pss;
2568 aiov.iov_len = sizeof(pss);
2569 auio.uio_iov = &aiov;
2570 auio.uio_iovcnt = 1;
2571 auio.uio_offset = psstr_addr;
2572 auio.uio_resid = sizeof(pss);
2573 auio.uio_rw = UIO_READ;
2574 UIO_SETUP_SYSSPACE(&auio);
2575 error = uvm_io(&vmspace->vm_map, &auio);
2576 if (error)
2577 goto done;
2578
2579 memcpy(&nargv, (char *)&pss + offsetn, sizeof(nargv));
2580 if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV) {
2581 error = dcopyout(l, &nargv, oldp, sizeof(nargv));
2582 *oldlenp = sizeof(nargv);
2583 goto done;
2584 }
2585 /*
2586 * Now read the address of the argument vector.
2587 */
2588 switch (type) {
2589 case KERN_PROC_ARGV:
2590 /* FALLTHROUGH */
2591 case KERN_PROC_ENV:
2592 memcpy(&tmp, (char *)&pss + offsetv, sizeof(tmp));
2593 break;
2594 default:
2595 return (EINVAL);
2596 }
2597
2598 #ifdef COMPAT_NETBSD32
2599 if (p->p_flag & P_32)
2600 len = sizeof(netbsd32_charp) * nargv;
2601 else
2602 #endif
2603 len = sizeof(char *) * nargv;
2604
2605 argv = malloc(len, M_TEMP, M_WAITOK);
2606
2607 aiov.iov_base = argv;
2608 aiov.iov_len = len;
2609 auio.uio_iov = &aiov;
2610 auio.uio_iovcnt = 1;
2611 auio.uio_offset = (off_t)(unsigned long)tmp;
2612 auio.uio_resid = len;
2613 auio.uio_rw = UIO_READ;
2614 UIO_SETUP_SYSSPACE(&auio);
2615 error = uvm_io(&vmspace->vm_map, &auio);
2616 if (error)
2617 goto done;
2618
2619 /*
2620 * Now copy each string.
2621 */
2622 len = 0; /* bytes written to user buffer */
2623 for (i = 0; i < nargv; i++) {
2624 int finished = 0;
2625 vaddr_t base;
2626 size_t xlen;
2627 int j;
2628
2629 #ifdef COMPAT_NETBSD32
2630 if (p->p_flag & P_32) {
2631 netbsd32_charp *argv32;
2632
2633 argv32 = (netbsd32_charp *)argv;
2634
2635 base = (vaddr_t)NETBSD32PTR64(argv32[i]);
2636 } else
2637 #endif
2638 base = (vaddr_t)argv[i];
2639
2640 while (!finished) {
2641 xlen = PAGE_SIZE - (base & PAGE_MASK);
2642
2643 aiov.iov_base = arg;
2644 aiov.iov_len = PAGE_SIZE;
2645 auio.uio_iov = &aiov;
2646 auio.uio_iovcnt = 1;
2647 auio.uio_offset = base;
2648 auio.uio_resid = xlen;
2649 auio.uio_rw = UIO_READ;
2650 UIO_SETUP_SYSSPACE(&auio);
2651 error = uvm_io(&vmspace->vm_map, &auio);
2652 if (error)
2653 goto done;
2654
2655 /* Look for the end of the string */
2656 for (j = 0; j < xlen; j++) {
2657 if (arg[j] == '\0') {
2658 xlen = j + 1;
2659 finished = 1;
2660 break;
2661 }
2662 }
2663
2664 /* Check for user buffer overflow */
2665 if (len + xlen > *oldlenp) {
2666 finished = 1;
2667 if (len > *oldlenp)
2668 xlen = 0;
2669 else
2670 xlen = *oldlenp - len;
2671 }
2672
2673 /* Copyout the page */
2674 error = dcopyout(l, arg, (char *)oldp + len, xlen);
2675 if (error)
2676 goto done;
2677
2678 len += xlen;
2679 base += xlen;
2680 }
2681 }
2682 *oldlenp = len;
2683
2684 done:
2685 if (argv != NULL)
2686 free(argv, M_TEMP);
2687
2688 uvmspace_free(vmspace);
2689
2690 free(arg, M_TEMP);
2691 return error;
2692
2693 out_locked:
2694 rw_exit(&proclist_lock);
2695 return error;
2696 }
2697
2698 /*
2699 * Sysctl helper routine for Verified Exec.
2700 */
2701 #if NVERIEXEC > 0
2702 static int
2703 sysctl_kern_veriexec(SYSCTLFN_ARGS)
2704 {
2705 int newval, error;
2706 int *var = NULL, raise_only = 0;
2707 struct sysctlnode node;
2708
2709 node = *rnode;
2710
2711 switch (rnode->sysctl_num) {
2712 case VERIEXEC_STRICT:
2713 raise_only = 1;
2714 var = &veriexec_strict;
2715 break;
2716 case VERIEXEC_ALGORITHMS:
2717 node.sysctl_data = veriexec_fp_names;
2718 node.sysctl_size = strlen(veriexec_fp_names) + 1;
2719 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
2720 default:
2721 return (EINVAL);
2722 }
2723
2724 newval = *var;
2725
2726 node.sysctl_data = &newval;
2727 error = sysctl_lookup(SYSCTLFN_CALL(&node));
2728 if (error || newp == NULL) {
2729 return (error);
2730 }
2731
2732 if (raise_only && (newval < *var))
2733 return (EPERM);
2734
2735 *var = newval;
2736
2737 return (error);
2738 }
2739 #endif /* NVERIEXEC > 0 */
2740
2741 static int
2742 sysctl_security_setidcore(SYSCTLFN_ARGS)
2743 {
2744 int newsize, error;
2745 struct sysctlnode node;
2746
2747 node = *rnode;
2748 node.sysctl_data = &newsize;
2749 newsize = *(int *)rnode->sysctl_data;
2750 error = sysctl_lookup(SYSCTLFN_CALL(&node));
2751 if (error || newp == NULL)
2752 return error;
2753
2754 if (kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SETIDCORE,
2755 0, NULL, NULL, NULL))
2756 return (EPERM);
2757
2758 *(int *)rnode->sysctl_data = newsize;
2759
2760 return 0;
2761 }
2762
2763 static int
2764 sysctl_security_setidcorename(SYSCTLFN_ARGS)
2765 {
2766 int error;
2767 char *newsetidcorename;
2768 struct sysctlnode node;
2769
2770 newsetidcorename = PNBUF_GET();
2771 node = *rnode;
2772 node.sysctl_data = newsetidcorename;
2773 memcpy(node.sysctl_data, rnode->sysctl_data, MAXPATHLEN);
2774 error = sysctl_lookup(SYSCTLFN_CALL(&node));
2775 if (error || newp == NULL) {
2776 goto out;
2777 }
2778 if (kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_SETIDCORE,
2779 0, NULL, NULL, NULL)) {
2780 error = EPERM;
2781 goto out;
2782 }
2783 if (strlen(newsetidcorename) == 0) {
2784 error = EINVAL;
2785 goto out;
2786 }
2787 memcpy(rnode->sysctl_data, node.sysctl_data, MAXPATHLEN);
2788 out:
2789 PNBUF_PUT(newsetidcorename);
2790 return error;
2791 }
2792
2793 /*
2794 * sysctl helper routine for kern.cp_id node. maps cpus to their
2795 * cpuids.
2796 */
2797 static int
2798 sysctl_kern_cpid(SYSCTLFN_ARGS)
2799 {
2800 struct sysctlnode node = *rnode;
2801
2802 #ifndef MULTIPROCESSOR
2803 uint64_t id;
2804
2805 if (namelen == 1) {
2806 if (name[0] != 0)
2807 return (ENOENT);
2808 /*
2809 * you're allowed to ask for the zero'th processor
2810 */
2811 name++;
2812 namelen--;
2813 }
2814 node.sysctl_data = &id;
2815 node.sysctl_size = sizeof(id);
2816 id = cpu_number();
2817 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
2818
2819 #else /* MULTIPROCESSOR */
2820 uint64_t *cp_id = NULL;
2821 int error, n = sysctl_ncpus();
2822 struct cpu_info *ci;
2823 CPU_INFO_ITERATOR cii;
2824
2825 /*
2826 * here you may either retrieve a single cpu id or the whole
2827 * set. the size you get back when probing depends on what
2828 * you ask for.
2829 */
2830 switch (namelen) {
2831 case 0:
2832 node.sysctl_size = n * sizeof(uint64_t);
2833 n = -2; /* ALL */
2834 break;
2835 case 1:
2836 if (name[0] < 0 || name[0] >= n)
2837 return (ENOENT); /* ENOSUCHPROCESSOR */
2838 node.sysctl_size = sizeof(uint64_t);
2839 n = name[0];
2840 /*
2841 * adjust these so that sysctl_lookup() will be happy
2842 */
2843 name++;
2844 namelen--;
2845 break;
2846 default:
2847 return (EINVAL);
2848 }
2849
2850 cp_id = malloc(node.sysctl_size, M_TEMP, M_WAITOK|M_CANFAIL);
2851 if (cp_id == NULL)
2852 return (ENOMEM);
2853 node.sysctl_data = cp_id;
2854 memset(cp_id, 0, node.sysctl_size);
2855
2856 for (CPU_INFO_FOREACH(cii, ci)) {
2857 if (n <= 0)
2858 cp_id[0] = ci->ci_cpuid;
2859 /*
2860 * if a specific processor was requested and we just
2861 * did it, we're done here
2862 */
2863 if (n == 0)
2864 break;
2865 /*
2866 * if doing "all", skip to next cp_id slot for next processor
2867 */
2868 if (n == -2)
2869 cp_id++;
2870 /*
2871 * if we're doing a specific processor, we're one
2872 * processor closer
2873 */
2874 if (n > 0)
2875 n--;
2876 }
2877
2878 error = sysctl_lookup(SYSCTLFN_CALL(&node));
2879 free(node.sysctl_data, M_TEMP);
2880 return (error);
2881
2882 #endif /* MULTIPROCESSOR */
2883 }
2884
2885 /*
2886 * sysctl helper routine for hw.usermem and hw.usermem64. values are
2887 * calculate on the fly taking into account integer overflow and the
2888 * current wired count.
2889 */
2890 static int
2891 sysctl_hw_usermem(SYSCTLFN_ARGS)
2892 {
2893 u_int ui;
2894 u_quad_t uq;
2895 struct sysctlnode node;
2896
2897 node = *rnode;
2898 switch (rnode->sysctl_num) {
2899 case HW_USERMEM:
2900 if ((ui = physmem - uvmexp.wired) > (UINT_MAX / PAGE_SIZE))
2901 ui = UINT_MAX;
2902 else
2903 ui *= PAGE_SIZE;
2904 node.sysctl_data = &ui;
2905 break;
2906 case HW_USERMEM64:
2907 uq = (u_quad_t)(physmem - uvmexp.wired) * PAGE_SIZE;
2908 node.sysctl_data = &uq;
2909 break;
2910 default:
2911 return (EINVAL);
2912 }
2913
2914 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
2915 }
2916
2917 /*
2918 * sysctl helper routine for kern.cnmagic node. pulls the old value
2919 * out, encoded, and stuffs the new value in for decoding.
2920 */
2921 static int
2922 sysctl_hw_cnmagic(SYSCTLFN_ARGS)
2923 {
2924 char magic[CNS_LEN];
2925 int error;
2926 struct sysctlnode node;
2927
2928 if (oldp)
2929 cn_get_magic(magic, CNS_LEN);
2930 node = *rnode;
2931 node.sysctl_data = &magic[0];
2932 error = sysctl_lookup(SYSCTLFN_CALL(&node));
2933 if (error || newp == NULL)
2934 return (error);
2935
2936 return (cn_set_magic(magic));
2937 }
2938
2939 static int
2940 sysctl_hw_ncpu(SYSCTLFN_ARGS)
2941 {
2942 int ncpu;
2943 struct sysctlnode node;
2944
2945 ncpu = sysctl_ncpus();
2946 node = *rnode;
2947 node.sysctl_data = &ncpu;
2948
2949 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
2950 }
2951
2952
2953 /*
2954 * ********************************************************************
2955 * section 3: public helper routines that are used for more than one
2956 * node
2957 * ********************************************************************
2958 */
2959
2960 /*
2961 * sysctl helper routine for the kern.root_device node and some ports'
2962 * machdep.root_device nodes.
2963 */
2964 int
2965 sysctl_root_device(SYSCTLFN_ARGS)
2966 {
2967 struct sysctlnode node;
2968
2969 node = *rnode;
2970 node.sysctl_data = root_device->dv_xname;
2971 node.sysctl_size = strlen(root_device->dv_xname) + 1;
2972 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
2973 }
2974
2975 /*
2976 * sysctl helper routine for kern.consdev, dependent on the current
2977 * state of the console. also used for machdep.console_device on some
2978 * ports.
2979 */
2980 int
2981 sysctl_consdev(SYSCTLFN_ARGS)
2982 {
2983 dev_t consdev;
2984 struct sysctlnode node;
2985
2986 if (cn_tab != NULL)
2987 consdev = cn_tab->cn_dev;
2988 else
2989 consdev = NODEV;
2990 node = *rnode;
2991 node.sysctl_data = &consdev;
2992 node.sysctl_size = sizeof(consdev);
2993 return (sysctl_lookup(SYSCTLFN_CALL(&node)));
2994 }
2995
2996 /*
2997 * ********************************************************************
2998 * section 4: support for some helpers
2999 * ********************************************************************
3000 */
3001
3002 /*
3003 * Fill in a kinfo_proc2 structure for the specified process.
3004 */
3005 static void
3006 fill_kproc2(struct proc *p, struct kinfo_proc2 *ki)
3007 {
3008 struct tty *tp;
3009 struct lwp *l, *l2;
3010 struct timeval ut, st, rt;
3011 sigset_t ss1, ss2;
3012
3013 memset(ki, 0, sizeof(*ki));
3014
3015 ki->p_paddr = PTRTOUINT64(p);
3016 ki->p_fd = PTRTOUINT64(p->p_fd);
3017 ki->p_cwdi = PTRTOUINT64(p->p_cwdi);
3018 ki->p_stats = PTRTOUINT64(p->p_stats);
3019 ki->p_limit = PTRTOUINT64(p->p_limit);
3020 ki->p_vmspace = PTRTOUINT64(p->p_vmspace);
3021 ki->p_sigacts = PTRTOUINT64(p->p_sigacts);
3022 ki->p_sess = PTRTOUINT64(p->p_session);
3023 ki->p_tsess = 0; /* may be changed if controlling tty below */
3024 ki->p_ru = PTRTOUINT64(p->p_ru);
3025
3026 ki->p_eflag = 0;
3027 ki->p_exitsig = p->p_exitsig;
3028
3029 ki->p_flag = sysctl_map_flags(sysctl_flagmap, p->p_flag);
3030 ki->p_flag |= sysctl_map_flags(sysctl_sflagmap, p->p_sflag);
3031 ki->p_flag |= sysctl_map_flags(sysctl_slflagmap, p->p_slflag);
3032 ki->p_flag |= sysctl_map_flags(sysctl_lflagmap, p->p_lflag);
3033 ki->p_flag |= sysctl_map_flags(sysctl_stflagmap, p->p_stflag);
3034
3035 ki->p_pid = p->p_pid;
3036 if (p->p_pptr)
3037 ki->p_ppid = p->p_pptr->p_pid;
3038 else
3039 ki->p_ppid = 0;
3040 ki->p_sid = p->p_session->s_sid;
3041 ki->p__pgid = p->p_pgrp->pg_id;
3042
3043 ki->p_tpgid = NO_PGID; /* may be changed if controlling tty below */
3044
3045 ki->p_uid = kauth_cred_geteuid(p->p_cred);
3046 ki->p_ruid = kauth_cred_getuid(p->p_cred);
3047 ki->p_gid = kauth_cred_getegid(p->p_cred);
3048 ki->p_rgid = kauth_cred_getgid(p->p_cred);
3049 ki->p_svuid = kauth_cred_getsvuid(p->p_cred);
3050 ki->p_svgid = kauth_cred_getsvgid(p->p_cred);
3051
3052 ki->p_ngroups = kauth_cred_ngroups(p->p_cred);
3053 kauth_cred_getgroups(p->p_cred, ki->p_groups,
3054 min(ki->p_ngroups, sizeof(ki->p_groups) / sizeof(ki->p_groups[0])));
3055
3056 ki->p_jobc = p->p_pgrp->pg_jobc;
3057 if ((p->p_lflag & PL_CONTROLT) && (tp = p->p_session->s_ttyp)) {
3058 ki->p_tdev = tp->t_dev;
3059 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
3060 ki->p_tsess = PTRTOUINT64(tp->t_session);
3061 } else {
3062 ki->p_tdev = NODEV;
3063 }
3064
3065 ki->p_estcpu = p->p_estcpu;
3066 ki->p_cpticks = p->p_cpticks;
3067 ki->p_pctcpu = p->p_pctcpu;
3068
3069 ki->p_uticks = p->p_uticks;
3070 ki->p_sticks = p->p_sticks;
3071 ki->p_iticks = p->p_iticks;
3072
3073 ki->p_tracep = PTRTOUINT64(p->p_tracep);
3074 ki->p_traceflag = p->p_traceflag;
3075
3076 mutex_enter(&p->p_smutex);
3077
3078 memcpy(&ki->p_sigignore, &p->p_sigctx.ps_sigignore,sizeof(ki_sigset_t));
3079 memcpy(&ki->p_sigcatch, &p->p_sigctx.ps_sigcatch, sizeof(ki_sigset_t));
3080
3081 ss1 = p->p_sigpend.sp_set;
3082 LIST_FOREACH(l, &p->p_lwps, l_sibling) {
3083 /* This is hardly correct, but... */
3084 sigplusset(&l->l_sigpend.sp_set, &ss1);
3085 sigplusset(l->l_sigmask, &ss2);
3086 }
3087 memcpy(&ki->p_siglist, &ss1, sizeof(ki_sigset_t));
3088 memcpy(&ki->p_sigmask, &ss2, sizeof(ki_sigset_t));
3089
3090 ki->p_stat = p->p_stat; /* Will likely be overridden by LWP status */
3091 ki->p_realstat = p->p_stat;
3092 ki->p_nice = p->p_nice;
3093
3094 ki->p_xstat = p->p_xstat;
3095 ki->p_acflag = p->p_acflag;
3096
3097 strncpy(ki->p_comm, p->p_comm,
3098 min(sizeof(ki->p_comm), sizeof(p->p_comm)));
3099
3100 strncpy(ki->p_login, p->p_session->s_login,
3101 min(sizeof ki->p_login - 1, sizeof p->p_session->s_login));
3102
3103 ki->p_nlwps = p->p_nlwps;
3104 ki->p_realflag = ki->p_flag;
3105
3106 if (p->p_stat == SIDL || P_ZOMBIE(p)) {
3107 ki->p_vm_rssize = 0;
3108 ki->p_vm_tsize = 0;
3109 ki->p_vm_dsize = 0;
3110 ki->p_vm_ssize = 0;
3111 ki->p_nrlwps = 0;
3112 l = NULL;
3113 } else {
3114 struct vmspace *vm = p->p_vmspace;
3115 int tmp;
3116
3117 ki->p_vm_rssize = vm_resident_count(vm);
3118 ki->p_vm_tsize = vm->vm_tsize;
3119 ki->p_vm_dsize = vm->vm_dsize;
3120 ki->p_vm_ssize = vm->vm_ssize;
3121
3122 /* Pick a "representative" LWP */
3123 l = proc_representative_lwp(p, &tmp, 1);
3124 lwp_lock(l);
3125 ki->p_nrlwps = tmp;
3126 ki->p_forw = PTRTOUINT64(l->l_forw);
3127 ki->p_back = PTRTOUINT64(l->l_back);
3128 ki->p_addr = PTRTOUINT64(l->l_addr);
3129 ki->p_stat = l->l_stat;
3130 ki->p_flag |= sysctl_map_flags(sysctl_lwpflagmap, l->l_flag);
3131 ki->p_swtime = l->l_swtime;
3132 ki->p_slptime = l->l_slptime;
3133 if (l->l_stat == LSONPROC)
3134 ki->p_schedflags = l->l_cpu->ci_schedstate.spc_flags;
3135 else
3136 ki->p_schedflags = 0;
3137 ki->p_holdcnt = l->l_holdcnt;
3138 ki->p_priority = l->l_priority;
3139 ki->p_usrpri = l->l_usrpri;
3140 if (l->l_wmesg)
3141 strncpy(ki->p_wmesg, l->l_wmesg, sizeof(ki->p_wmesg));
3142 ki->p_wchan = PTRTOUINT64(l->l_wchan);
3143 lwp_unlock(l);
3144 }
3145 if (p->p_session->s_ttyvp)
3146 ki->p_eflag |= EPROC_CTTY;
3147 if (SESS_LEADER(p))
3148 ki->p_eflag |= EPROC_SLEADER;
3149
3150 /* XXX Is this double check necessary? */
3151 if (P_ZOMBIE(p)) {
3152 ki->p_uvalid = 0;
3153 ki->p_rtime_sec = 0;
3154 ki->p_rtime_usec = 0;
3155 } else {
3156 ki->p_uvalid = 1;
3157
3158 ki->p_ustart_sec = p->p_stats->p_start.tv_sec;
3159 ki->p_ustart_usec = p->p_stats->p_start.tv_usec;
3160
3161 calcru(p, &ut, &st, NULL, &rt);
3162 ki->p_rtime_sec = rt.tv_sec;
3163 ki->p_rtime_usec = rt.tv_usec;
3164 ki->p_uutime_sec = ut.tv_sec;
3165 ki->p_uutime_usec = ut.tv_usec;
3166 ki->p_ustime_sec = st.tv_sec;
3167 ki->p_ustime_usec = st.tv_usec;
3168
3169 ki->p_uru_maxrss = p->p_stats->p_ru.ru_maxrss;
3170 ki->p_uru_ixrss = p->p_stats->p_ru.ru_ixrss;
3171 ki->p_uru_idrss = p->p_stats->p_ru.ru_idrss;
3172 ki->p_uru_isrss = p->p_stats->p_ru.ru_isrss;
3173 ki->p_uru_minflt = p->p_stats->p_ru.ru_minflt;
3174 ki->p_uru_majflt = p->p_stats->p_ru.ru_majflt;
3175 ki->p_uru_nswap = p->p_stats->p_ru.ru_nswap;
3176 ki->p_uru_inblock = p->p_stats->p_ru.ru_inblock;
3177 ki->p_uru_oublock = p->p_stats->p_ru.ru_oublock;
3178 ki->p_uru_msgsnd = p->p_stats->p_ru.ru_msgsnd;
3179 ki->p_uru_msgrcv = p->p_stats->p_ru.ru_msgrcv;
3180 ki->p_uru_nsignals = p->p_stats->p_ru.ru_nsignals;
3181
3182 ki->p_uru_nvcsw = 0;
3183 ki->p_uru_nivcsw = 0;
3184 LIST_FOREACH(l2, &p->p_lwps, l_sibling) {
3185 ki->p_uru_nvcsw += l->l_nvcsw;
3186 ki->p_uru_nivcsw += l->l_nivcsw;
3187 }
3188
3189 timeradd(&p->p_stats->p_cru.ru_utime,
3190 &p->p_stats->p_cru.ru_stime, &ut);
3191 ki->p_uctime_sec = ut.tv_sec;
3192 ki->p_uctime_usec = ut.tv_usec;
3193 }
3194 #ifdef MULTIPROCESSOR
3195 if (l != NULL)
3196 ki->p_cpuid = l->l_cpu->ci_cpuid;
3197 else
3198 #endif
3199 ki->p_cpuid = KI_NOCPU;
3200
3201 mutex_exit(&p->p_smutex);
3202 }
3203
3204 /*
3205 * Fill in a kinfo_lwp structure for the specified lwp.
3206 */
3207 static void
3208 fill_lwp(struct lwp *l, struct kinfo_lwp *kl)
3209 {
3210
3211 kl->l_forw = PTRTOUINT64(l->l_forw);
3212 kl->l_back = PTRTOUINT64(l->l_back);
3213 kl->l_laddr = PTRTOUINT64(l);
3214 kl->l_addr = PTRTOUINT64(l->l_addr);
3215 kl->l_stat = l->l_stat;
3216 kl->l_lid = l->l_lid;
3217 kl->l_flag = l->l_flag;
3218
3219 kl->l_swtime = l->l_swtime;
3220 kl->l_slptime = l->l_slptime;
3221 if (l->l_stat == LSONPROC)
3222 kl->l_schedflags = l->l_cpu->ci_schedstate.spc_flags;
3223 else
3224 kl->l_schedflags = 0;
3225 kl->l_holdcnt = l->l_holdcnt;
3226 kl->l_priority = l->l_priority;
3227 kl->l_usrpri = l->l_usrpri;
3228 if (l->l_wmesg)
3229 strncpy(kl->l_wmesg, l->l_wmesg, sizeof(kl->l_wmesg));
3230 kl->l_wchan = PTRTOUINT64(l->l_wchan);
3231 #ifdef MULTIPROCESSOR
3232 kl->l_cpuid = l->l_cpu->ci_cpuid;
3233 #else
3234 kl->l_cpuid = KI_NOCPU;
3235 #endif
3236 }
3237
3238 /*
3239 * Fill in an eproc structure for the specified process.
3240 */
3241 void
3242 fill_eproc(struct proc *p, struct eproc *ep)
3243 {
3244 struct tty *tp;
3245 struct lwp *l;
3246
3247 ep->e_paddr = p;
3248 ep->e_sess = p->p_session;
3249 kauth_cred_topcred(p->p_cred, &ep->e_pcred);
3250 kauth_cred_toucred(p->p_cred, &ep->e_ucred);
3251 if (p->p_stat == SIDL || P_ZOMBIE(p)) {
3252 ep->e_vm.vm_rssize = 0;
3253 ep->e_vm.vm_tsize = 0;
3254 ep->e_vm.vm_dsize = 0;
3255 ep->e_vm.vm_ssize = 0;
3256 /* ep->e_vm.vm_pmap = XXX; */
3257 } else {
3258 struct vmspace *vm = p->p_vmspace;
3259
3260 ep->e_vm.vm_rssize = vm_resident_count(vm);
3261 ep->e_vm.vm_tsize = vm->vm_tsize;
3262 ep->e_vm.vm_dsize = vm->vm_dsize;
3263 ep->e_vm.vm_ssize = vm->vm_ssize;
3264
3265 /* Pick a "representative" LWP */
3266 mutex_enter(&p->p_smutex);
3267 l = proc_representative_lwp(p, NULL, 1);
3268 lwp_lock(l);
3269 if (l->l_wmesg)
3270 strncpy(ep->e_wmesg, l->l_wmesg, WMESGLEN);
3271 lwp_unlock(l);
3272 mutex_exit(&p->p_smutex);
3273 }
3274 if (p->p_pptr)
3275 ep->e_ppid = p->p_pptr->p_pid;
3276 else
3277 ep->e_ppid = 0;
3278 ep->e_pgid = p->p_pgrp->pg_id;
3279 ep->e_sid = ep->e_sess->s_sid;
3280 ep->e_jobc = p->p_pgrp->pg_jobc;
3281 if ((p->p_lflag & PL_CONTROLT) &&
3282 (tp = ep->e_sess->s_ttyp)) {
3283 ep->e_tdev = tp->t_dev;
3284 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
3285 ep->e_tsess = tp->t_session;
3286 } else
3287 ep->e_tdev = NODEV;
3288
3289 ep->e_xsize = ep->e_xrssize = 0;
3290 ep->e_xccount = ep->e_xswrss = 0;
3291 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
3292 if (SESS_LEADER(p))
3293 ep->e_flag |= EPROC_SLEADER;
3294 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME);
3295 }
3296
3297 u_int
3298 sysctl_map_flags(const u_int *map, u_int word)
3299 {
3300 u_int rv;
3301
3302 for (rv = 0; *map != 0; map += 2)
3303 if ((word & map[0]) != 0)
3304 rv |= map[1];
3305
3306 return rv;
3307 }
3308