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