init_sysctl.c revision 1.5
1/* $NetBSD: init_sysctl.c,v 1.5 2003/12/06 21:33:51 martin 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 "opt_sysv.h" 40#include "opt_multiprocessor.h" 41#include "opt_posix.h" 42#include "pty.h" 43#include "rnd.h" 44 45#include <sys/types.h> 46#include <sys/param.h> 47#include <sys/sysctl.h> 48#include <sys/errno.h> 49#include <sys/systm.h> 50#include <sys/kernel.h> 51#include <sys/unistd.h> 52#include <sys/disklabel.h> 53#include <sys/rnd.h> 54#include <sys/vnode.h> 55#include <sys/mount.h> 56#include <sys/namei.h> 57#include <sys/msgbuf.h> 58#include <dev/cons.h> 59#include <sys/socketvar.h> 60#include <sys/file.h> 61#include <sys/tty.h> 62#include <sys/malloc.h> 63#include <sys/resource.h> 64#include <sys/resourcevar.h> 65#include <sys/exec.h> 66#include <sys/conf.h> 67#include <sys/device.h> 68 69#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 70#include <sys/ipc.h> 71#endif 72#ifdef SYSVMSG 73#include <sys/msg.h> 74#endif 75#ifdef SYSVSEM 76#include <sys/sem.h> 77#endif 78#ifdef SYSVSHM 79#include <sys/shm.h> 80#endif 81 82#include <machine/cpu.h> 83 84/* 85 * try over estimating by 5 procs/lwps 86 */ 87#define KERN_PROCSLOP (5 * sizeof(struct kinfo_proc)) 88#define KERN_LWPSLOP (5 * sizeof(struct kinfo_lwp)) 89 90/* 91 * convert pointer to 64 int for struct kinfo_proc2 92 */ 93#define PTRTOINT64(foo) ((u_int64_t)(uintptr_t)(foo)) 94 95#ifndef MULTIPROCESSOR 96#define sysctl_ncpus() (1) 97#else /* MULTIPROCESSOR */ 98#ifndef CPU_INFO_FOREACH 99#define CPU_INFO_ITERATOR int 100#define CPU_INFO_FOREACH(cii, ci) cii = 0, ci = curcpu(); ci != NULL; ci = NULL 101#endif 102static int 103sysctl_ncpus(void) 104{ 105 struct cpu_info *ci; 106 CPU_INFO_ITERATOR cii; 107 108 int ncpus = 0; 109 for (CPU_INFO_FOREACH(cii, ci)) 110 ncpus++; 111 return (ncpus); 112} 113#endif /* MULTIPROCESSOR */ 114 115static int sysctl_kern_maxvnodes(SYSCTLFN_PROTO); 116static int sysctl_kern_maxproc(SYSCTLFN_PROTO); 117static int sysctl_kern_securelevel(SYSCTLFN_PROTO); 118static int sysctl_kern_hostid(SYSCTLFN_PROTO); 119static int sysctl_kern_clockrate(SYSCTLFN_PROTO); 120static int sysctl_kern_file(SYSCTLFN_PROTO); 121static int sysctl_kern_autonice(SYSCTLFN_PROTO); 122static int sysctl_msgbuf(SYSCTLFN_PROTO); 123static int sysctl_kern_defcorename(SYSCTLFN_PROTO); 124static int sysctl_kern_cptime(SYSCTLFN_PROTO); 125#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 126static int sysctl_kern_sysvipc(SYSCTLFN_PROTO); 127#endif /* defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) */ 128static int sysctl_kern_maxptys(SYSCTLFN_PROTO); 129static int sysctl_kern_sbmax(SYSCTLFN_PROTO); 130static int sysctl_kern_urnd(SYSCTLFN_PROTO); 131static int sysctl_kern_lwp(SYSCTLFN_PROTO); 132static int sysctl_kern_forkfsleep(SYSCTLFN_PROTO); 133static int sysctl_kern_somaxkva(SYSCTLFN_PROTO); 134static int sysctl_kern_root_partition(SYSCTLFN_PROTO); 135static int sysctl_kern_drivers(SYSCTLFN_PROTO); 136static int sysctl_doeproc(SYSCTLFN_PROTO); 137static int sysctl_kern_proc_args(SYSCTLFN_PROTO); 138static int sysctl_hw_usermem(SYSCTLFN_PROTO); 139static int sysctl_hw_cnmagic(SYSCTLFN_PROTO); 140static int sysctl_hw_ncpu(SYSCTLFN_PROTO); 141 142static void fill_kproc2(struct proc *, struct kinfo_proc2 *); 143static void fill_lwp(struct lwp *l, struct kinfo_lwp *kl); 144 145/* 146 * ******************************************************************** 147 * section 1: setup routines 148 * ******************************************************************** 149 * these functions are stuffed into a link set for sysctl setup 150 * functions. they're never called or referenced from anywhere else. 151 * ******************************************************************** 152 */ 153 154/* 155 * sets up the base nodes... 156 */ 157SYSCTL_SETUP(sysctl_root_setup, "sysctl base setup") 158{ 159 160 sysctl_createv(SYSCTL_PERMANENT, 161 CTLTYPE_NODE, "kern", NULL, 162 NULL, 0, NULL, 0, 163 CTL_KERN, CTL_EOL); 164 sysctl_createv(SYSCTL_PERMANENT, 165 CTLTYPE_NODE, "vm", NULL, 166 NULL, 0, NULL, 0, 167 CTL_VM, CTL_EOL); 168 sysctl_createv(SYSCTL_PERMANENT, 169 CTLTYPE_NODE, "vfs", NULL, 170 NULL, 0, NULL, 0, 171 CTL_VFS, CTL_EOL); 172 sysctl_createv(SYSCTL_PERMANENT, 173 CTLTYPE_NODE, "net", NULL, 174 NULL, 0, NULL, 0, 175 CTL_NET, CTL_EOL); 176 sysctl_createv(SYSCTL_PERMANENT, 177 CTLTYPE_NODE, "debug", NULL, 178 NULL, 0, NULL, 0, 179 CTL_DEBUG, CTL_EOL); 180 sysctl_createv(SYSCTL_PERMANENT, 181 CTLTYPE_NODE, "hw", NULL, 182 NULL, 0, NULL, 0, 183 CTL_HW, CTL_EOL); 184 sysctl_createv(SYSCTL_PERMANENT, 185 CTLTYPE_NODE, "machdep", NULL, 186 NULL, 0, NULL, 0, 187 CTL_MACHDEP, CTL_EOL); 188 /* 189 * this node is inserted so that the sysctl nodes in libc can 190 * operate. 191 */ 192 sysctl_createv(SYSCTL_PERMANENT, 193 CTLTYPE_NODE, "user", NULL, 194 NULL, 0, NULL, 0, 195 CTL_USER, CTL_EOL); 196 sysctl_createv(SYSCTL_PERMANENT, 197 CTLTYPE_NODE, "ddb", NULL, 198 NULL, 0, NULL, 0, 199 CTL_DDB, CTL_EOL); 200 sysctl_createv(SYSCTL_PERMANENT, 201 CTLTYPE_NODE, "proc", NULL, 202 NULL, 0, NULL, 0, 203 CTL_PROC, CTL_EOL); 204 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 205 CTLTYPE_NODE, "vendor", NULL, 206 NULL, 0, NULL, 0, 207 CTL_VENDOR, CTL_EOL); 208 sysctl_createv(SYSCTL_PERMANENT, 209 CTLTYPE_NODE, "emul", NULL, 210 NULL, 0, NULL, 0, 211 CTL_EMUL, CTL_EOL); 212} 213 214/* 215 * this setup routine is a replacement for kern_sysctl() 216 */ 217SYSCTL_SETUP(sysctl_kern_setup, "sysctl kern subtree setup") 218{ 219 extern int kern_logsigexit; /* defined in kern/kern_sig.c */ 220 extern fixpt_t ccpu; /* defined in kern/kern_synch.c */ 221 extern int dumponpanic; /* defined in kern/subr_prf.c */ 222 223 sysctl_createv(SYSCTL_PERMANENT, 224 CTLTYPE_NODE, "kern", NULL, 225 NULL, 0, NULL, 0, 226 CTL_KERN, CTL_EOL); 227 228 sysctl_createv(SYSCTL_PERMANENT, 229 CTLTYPE_STRING, "ostype", NULL, 230 NULL, 0, &ostype, 0, 231 CTL_KERN, KERN_OSTYPE, CTL_EOL); 232 sysctl_createv(SYSCTL_PERMANENT, 233 CTLTYPE_STRING, "osrelease", NULL, 234 NULL, 0, &osrelease, 0, 235 CTL_KERN, KERN_OSRELEASE, CTL_EOL); 236 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 237 CTLTYPE_INT, "osrevision", NULL, 238 NULL, __NetBSD_Version__, NULL, 0, 239 CTL_KERN, KERN_OSREV, CTL_EOL); 240 sysctl_createv(SYSCTL_PERMANENT, 241 CTLTYPE_STRING, "version", NULL, 242 NULL, 0, &version, 0, 243 CTL_KERN, KERN_VERSION, CTL_EOL); 244 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 245 CTLTYPE_INT, "maxvnodes", NULL, 246 sysctl_kern_maxvnodes, 0, NULL, 0, 247 CTL_KERN, KERN_MAXVNODES, CTL_EOL); 248 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 249 CTLTYPE_INT, "maxproc", NULL, 250 sysctl_kern_maxproc, 0, NULL, 0, 251 CTL_KERN, KERN_MAXPROC, CTL_EOL); 252 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 253 CTLTYPE_INT, "maxfiles", NULL, 254 NULL, 0, &maxfiles, 0, 255 CTL_KERN, KERN_MAXFILES, CTL_EOL); 256 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 257 CTLTYPE_INT, "argmax", NULL, 258 NULL, ARG_MAX, NULL, 0, 259 CTL_KERN, KERN_ARGMAX, CTL_EOL); 260 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 261 CTLTYPE_INT, "securelevel", NULL, 262 sysctl_kern_securelevel, 0, &securelevel, 0, 263 CTL_KERN, KERN_SECURELVL, CTL_EOL); 264 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 265 CTLTYPE_STRING, "hostname", NULL, 266 NULL, 0, &hostname, MAXHOSTNAMELEN, 267 CTL_KERN, KERN_HOSTNAME, CTL_EOL); 268 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 269 CTLTYPE_INT, "hostid", NULL, 270 sysctl_kern_hostid, 0, NULL, 0, 271 CTL_KERN, KERN_HOSTID, CTL_EOL); 272 sysctl_createv(SYSCTL_PERMANENT, 273 CTLTYPE_STRUCT, "clockrate", NULL, 274 sysctl_kern_clockrate, 0, NULL, 275 sizeof(struct clockinfo), 276 CTL_KERN, KERN_CLOCKRATE, CTL_EOL); 277 sysctl_createv(SYSCTL_PERMANENT, 278 CTLTYPE_STRUCT, "vnode", NULL, 279 sysctl_kern_vnode, 0, NULL, 0, 280 CTL_KERN, KERN_VNODE, CTL_EOL); 281 sysctl_createv(SYSCTL_PERMANENT, 282 CTLTYPE_STRUCT, "file", NULL, 283 sysctl_kern_file, 0, NULL, 0, 284 CTL_KERN, KERN_FILE, CTL_EOL); 285#ifndef GPROF 286 sysctl_createv(SYSCTL_PERMANENT, 287 CTLTYPE_NODE, "profiling", NULL, 288 sysctl_notavail, 0, NULL, 0, 289 CTL_KERN, KERN_PROF, CTL_EOL); 290#endif 291 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 292 CTLTYPE_INT, "posix1version", NULL, 293 NULL, _POSIX_VERSION, NULL, 0, 294 CTL_KERN, KERN_POSIX1, CTL_EOL); 295 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 296 CTLTYPE_INT, "ngroups", NULL, 297 NULL, NGROUPS_MAX, NULL, 0, 298 CTL_KERN, KERN_NGROUPS, CTL_EOL); 299 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 300 CTLTYPE_INT, "job_control", NULL, 301 NULL, 1, NULL, 0, 302 CTL_KERN, KERN_JOB_CONTROL, CTL_EOL); 303 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 304 CTLTYPE_INT, "saved_ids", NULL, NULL, 305#ifdef _POSIX_SAVED_IDS 306 1, 307#else /* _POSIX_SAVED_IDS */ 308 0, 309#endif /* _POSIX_SAVED_IDS */ 310 NULL, 0, CTL_KERN, KERN_SAVED_IDS, CTL_EOL); 311 sysctl_createv(SYSCTL_PERMANENT, 312 CTLTYPE_STRUCT, "boottime", NULL, 313 NULL, 0, &boottime, sizeof(boottime), 314 CTL_KERN, KERN_BOOTTIME, CTL_EOL); 315 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 316 CTLTYPE_STRING, "domainname", NULL, 317 NULL, 0, &domainname, MAXHOSTNAMELEN, 318 CTL_KERN, KERN_DOMAINNAME, CTL_EOL); 319 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 320 CTLTYPE_INT, "maxpartitions", NULL, 321 NULL, MAXPARTITIONS, NULL, 0, 322 CTL_KERN, KERN_MAXPARTITIONS, CTL_EOL); 323 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 324 CTLTYPE_INT, "rawpartition", NULL, 325 NULL, RAW_PART, NULL, 0, 326 CTL_KERN, KERN_RAWPARTITION, CTL_EOL); 327 sysctl_createv(SYSCTL_PERMANENT, 328 CTLTYPE_STRUCT, "timex", NULL, 329 sysctl_notavail, 0, NULL, 0, 330 CTL_KERN, KERN_TIMEX, CTL_EOL); 331 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 332 CTLTYPE_INT, "autonicetime", NULL, 333 sysctl_kern_autonice, 0, &autonicetime, 0, 334 CTL_KERN, KERN_AUTONICETIME, CTL_EOL); 335 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 336 CTLTYPE_INT, "autoniceval", NULL, 337 sysctl_kern_autonice, 0, &autoniceval, 0, 338 CTL_KERN, KERN_AUTONICEVAL, CTL_EOL); 339 sysctl_createv(SYSCTL_PERMANENT, 340 CTLTYPE_INT, "rtc_offset", NULL, 341 NULL, 0, &rtc_offset, 0, 342 CTL_KERN, KERN_RTC_OFFSET, CTL_EOL); 343 sysctl_createv(SYSCTL_PERMANENT, 344 CTLTYPE_STRING, "root_device", NULL, 345 sysctl_root_device, 0, NULL, 0, 346 CTL_KERN, KERN_ROOT_DEVICE, CTL_EOL); 347 sysctl_createv(SYSCTL_PERMANENT, 348 CTLTYPE_INT, "msgbufsize", NULL, 349 sysctl_msgbuf, 0, &msgbufp->msg_bufs, 0, 350 CTL_KERN, KERN_MSGBUFSIZE, CTL_EOL); 351 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 352 CTLTYPE_INT, "fsync", NULL, 353 NULL, 1, NULL, 0, 354 CTL_KERN, KERN_FSYNC, CTL_EOL); 355 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 356 CTLTYPE_INT, "sysvmsg", NULL, NULL, 357#ifdef SYSVMSG 358 1, 359#else /* SYSVMSG */ 360 0, 361#endif /* SYSVMSG */ 362 NULL, 0, CTL_KERN, KERN_SYSVMSG, CTL_EOL); 363 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 364 CTLTYPE_INT, "sysvsem", NULL, NULL, 365#ifdef SYSVSEM 366 1, 367#else /* SYSVSEM */ 368 0, 369#endif /* SYSVSEM */ 370 NULL, 0, CTL_KERN, KERN_SYSVSEM, CTL_EOL); 371 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 372 CTLTYPE_INT, "sysvshm", NULL, NULL, 373#ifdef SYSVSHM 374 1, 375#else /* SYSVSHM */ 376 0, 377#endif /* SYSVSHM */ 378 NULL, 0, CTL_KERN, KERN_SYSVSHM, CTL_EOL); 379 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 380 CTLTYPE_INT, "synchronized_io", NULL, 381 NULL, 1, NULL, 0, 382 CTL_KERN, KERN_SYNCHRONIZED_IO, CTL_EOL); 383 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 384 CTLTYPE_INT, "iov_max", NULL, 385 NULL, IOV_MAX, NULL, 0, 386 CTL_KERN, KERN_IOV_MAX, CTL_EOL); 387 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 388 CTLTYPE_INT, "mapped_files", NULL, 389 NULL, 1, NULL, 0, 390 CTL_KERN, KERN_MAPPED_FILES, CTL_EOL); 391 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 392 CTLTYPE_INT, "memlock", NULL, 393 NULL, 1, NULL, 0, 394 CTL_KERN, KERN_MEMLOCK, CTL_EOL); 395 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 396 CTLTYPE_INT, "memlock_range", NULL, 397 NULL, 1, NULL, 0, 398 CTL_KERN, KERN_MEMLOCK_RANGE, CTL_EOL); 399 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 400 CTLTYPE_INT, "memory_protection", NULL, 401 NULL, 1, NULL, 0, 402 CTL_KERN, KERN_MEMORY_PROTECTION, CTL_EOL); 403 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 404 CTLTYPE_INT, "login_name_max", NULL, 405 NULL, LOGIN_NAME_MAX, NULL, 0, 406 CTL_KERN, KERN_LOGIN_NAME_MAX, CTL_EOL); 407 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 408 CTLTYPE_STRING, "defcorename", NULL, 409 sysctl_kern_defcorename, 0, defcorename, MAXPATHLEN, 410 CTL_KERN, KERN_DEFCORENAME, CTL_EOL); 411 sysctl_createv(SYSCTL_PERMANENT, 412 CTLTYPE_INT, "logsigexit", NULL, 413 NULL, 0, &kern_logsigexit, 0, 414 CTL_KERN, KERN_LOGSIGEXIT, CTL_EOL); 415 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 416 CTLTYPE_INT, "fscale", NULL, 417 NULL, FSCALE, NULL, 0, 418 CTL_KERN, KERN_FSCALE, CTL_EOL); 419 sysctl_createv(SYSCTL_PERMANENT, 420 CTLTYPE_INT, "ccpu", NULL, 421 NULL, 0, &ccpu, 0, 422 CTL_KERN, KERN_CCPU, CTL_EOL); 423 sysctl_createv(SYSCTL_PERMANENT, 424 CTLTYPE_STRUCT, "cp_time", NULL, 425 sysctl_kern_cptime, 0, NULL, 0, 426 CTL_KERN, KERN_CP_TIME, CTL_EOL); 427#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 428 sysctl_createv(SYSCTL_PERMANENT, 429 CTLTYPE_STRUCT, "sysvipc_info", NULL, 430 sysctl_kern_sysvipc, 0, NULL, 0, 431 CTL_KERN, KERN_SYSVIPC_INFO, CTL_EOL); 432#endif /* SYSVMSG || SYSVSEM || SYSVSHM */ 433 sysctl_createv(SYSCTL_PERMANENT, 434 CTLTYPE_INT, "msgbuf", NULL, 435 sysctl_msgbuf, 0, NULL, 0, 436 CTL_KERN, KERN_MSGBUF, CTL_EOL); 437 sysctl_createv(SYSCTL_PERMANENT, 438 CTLTYPE_STRUCT, "consdev", NULL, 439 sysctl_consdev, 0, NULL, sizeof(dev_t), 440 CTL_KERN, KERN_CONSDEV, CTL_EOL); 441#if NPTY > 0 442 sysctl_createv(SYSCTL_PERMANENT, 443 CTLTYPE_INT, "maxptys", NULL, 444 sysctl_kern_maxptys, 0, NULL, 0, 445 CTL_KERN, KERN_MAXPTYS, CTL_EOL); 446#endif /* NPTY > 0 */ 447 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 448 CTLTYPE_INT, "maxphys", NULL, 449 NULL, MAXPHYS, NULL, 0, 450 CTL_KERN, KERN_MAXPHYS, CTL_EOL); 451 sysctl_createv(SYSCTL_PERMANENT, 452 CTLTYPE_INT, "sbmax", NULL, 453 sysctl_kern_sbmax, 0, NULL, 0, 454 CTL_KERN, KERN_SBMAX, CTL_EOL); 455 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 456 CTLTYPE_INT, "monotonic_clock", NULL, 457 /* XXX _POSIX_VERSION */ 458 NULL, _POSIX_MONOTONIC_CLOCK, NULL, 0, 459 CTL_KERN, KERN_MONOTONIC_CLOCK, CTL_EOL); 460 sysctl_createv(SYSCTL_PERMANENT, 461 CTLTYPE_INT, "urandom", NULL, 462 sysctl_kern_urnd, 0, NULL, 0, 463 CTL_KERN, KERN_URND, CTL_EOL); 464 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 465 CTLTYPE_INT, "labelsector", NULL, 466 NULL, LABELSECTOR, NULL, 0, 467 CTL_KERN, KERN_LABELSECTOR, CTL_EOL); 468 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 469 CTLTYPE_INT, "labeloffset", NULL, 470 NULL, LABELOFFSET, NULL, 0, 471 CTL_KERN, KERN_LABELOFFSET, CTL_EOL); 472 sysctl_createv(SYSCTL_PERMANENT, 473 CTLTYPE_NODE, "lwp", NULL, 474 sysctl_kern_lwp, 0, NULL, 0, 475 CTL_KERN, KERN_LWP, CTL_EOL); 476 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 477 CTLTYPE_INT, "forkfsleep", NULL, 478 sysctl_kern_forkfsleep, 0, NULL, 0, 479 CTL_KERN, KERN_FORKFSLEEP, CTL_EOL); 480 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 481 CTLTYPE_INT, "posix_threads", NULL, 482 /* XXX _POSIX_VERSION */ 483 NULL, _POSIX_THREADS, NULL, 0, 484 CTL_KERN, KERN_POSIX_THREADS, CTL_EOL); 485 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 486 CTLTYPE_INT, "posix_semaphores", NULL, NULL, 487#ifdef P1003_1B_SEMAPHORE 488 200112, 489#else /* P1003_1B_SEMAPHORE */ 490 0, 491#endif /* P1003_1B_SEMAPHORE */ 492 NULL, 0, CTL_KERN, KERN_POSIX_SEMAPHORES, CTL_EOL); 493 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 494 CTLTYPE_INT, "posix_barriers", NULL, 495 /* XXX _POSIX_VERSION */ 496 NULL, _POSIX_BARRIERS, NULL, 0, 497 CTL_KERN, KERN_POSIX_BARRIERS, CTL_EOL); 498 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 499 CTLTYPE_INT, "posix_timers", NULL, 500 /* XXX _POSIX_VERSION */ 501 NULL, _POSIX_TIMERS, NULL, 0, 502 CTL_KERN, KERN_POSIX_TIMERS, CTL_EOL); 503 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 504 CTLTYPE_INT, "posix_spin_locks", NULL, 505 /* XXX _POSIX_VERSION */ 506 NULL, _POSIX_SPIN_LOCKS, NULL, 0, 507 CTL_KERN, KERN_POSIX_SPIN_LOCKS, CTL_EOL); 508 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 509 CTLTYPE_INT, "posix_reader_writer_locks", NULL, 510 /* XXX _POSIX_VERSION */ 511 NULL, _POSIX_READER_WRITER_LOCKS, NULL, 0, 512 CTL_KERN, KERN_POSIX_READER_WRITER_LOCKS, CTL_EOL); 513 sysctl_createv(SYSCTL_PERMANENT, 514 CTLTYPE_INT, "dump_on_panic", NULL, 515 NULL, 0, &dumponpanic, 0, 516 CTL_KERN, KERN_DUMP_ON_PANIC, CTL_EOL); 517 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 518 CTLTYPE_INT, "somaxkva", NULL, 519 sysctl_kern_somaxkva, 0, NULL, 0, 520 CTL_KERN, KERN_SOMAXKVA, CTL_EOL); 521 sysctl_createv(SYSCTL_PERMANENT, 522 CTLTYPE_INT, "root_partition", NULL, 523 sysctl_kern_root_partition, 0, NULL, 0, 524 CTL_KERN, KERN_ROOT_PARTITION, CTL_EOL); 525 sysctl_createv(SYSCTL_PERMANENT, 526 CTLTYPE_STRUCT, "drivers", NULL, 527 sysctl_kern_drivers, 0, NULL, 0, 528 CTL_KERN, KERN_DRIVERS, CTL_EOL); 529} 530 531SYSCTL_SETUP(sysctl_kern_proc_setup, 532 "sysctl kern.proc/proc2/proc_args subtree setup") 533{ 534 535 sysctl_createv(SYSCTL_PERMANENT, 536 CTLTYPE_NODE, "kern", NULL, 537 NULL, 0, NULL, 0, 538 CTL_KERN, CTL_EOL); 539 540 sysctl_createv(SYSCTL_PERMANENT, 541 CTLTYPE_NODE, "proc", NULL, 542 sysctl_doeproc, 0, NULL, 0, 543 CTL_KERN, KERN_PROC, CTL_EOL); 544 sysctl_createv(SYSCTL_PERMANENT, 545 CTLTYPE_NODE, "proc2", NULL, 546 sysctl_doeproc, 0, NULL, 0, 547 CTL_KERN, KERN_PROC2, CTL_EOL); 548 sysctl_createv(SYSCTL_PERMANENT, 549 CTLTYPE_NODE, "proc_args", NULL, 550 sysctl_kern_proc_args, 0, NULL, 0, 551 CTL_KERN, KERN_PROC_ARGS, CTL_EOL); 552 553 /* 554 "nodes" under these: 555 556 KERN_PROC_ALL 557 KERN_PROC_PID pid 558 KERN_PROC_PGRP pgrp 559 KERN_PROC_SESSION sess 560 KERN_PROC_TTY tty 561 KERN_PROC_UID uid 562 KERN_PROC_RUID uid 563 KERN_PROC_GID gid 564 KERN_PROC_RGID gid 565 566 all in all, probably not worth the effort... 567 */ 568} 569 570SYSCTL_SETUP(sysctl_hw_setup, "sysctl hw subtree setup") 571{ 572 u_int u; 573 u_quad_t q; 574 575 sysctl_createv(SYSCTL_PERMANENT, 576 CTLTYPE_NODE, "hw", NULL, 577 NULL, 0, NULL, 0, 578 CTL_HW, CTL_EOL); 579 580 sysctl_createv(SYSCTL_PERMANENT, 581 CTLTYPE_STRING, "machine", NULL, 582 NULL, 0, machine, 0, 583 CTL_HW, HW_MACHINE, CTL_EOL); 584 sysctl_createv(SYSCTL_PERMANENT, 585 CTLTYPE_STRING, "model", NULL, 586 NULL, 0, cpu_model, 0, 587 CTL_HW, HW_MODEL, CTL_EOL); 588 sysctl_createv(SYSCTL_PERMANENT, 589 CTLTYPE_INT, "ncpu", NULL, 590 sysctl_hw_ncpu, 0, NULL, 0, 591 CTL_HW, HW_NCPU, CTL_EOL); 592 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 593 CTLTYPE_INT, "byteorder", NULL, 594 NULL, BYTE_ORDER, NULL, 0, 595 CTL_HW, HW_BYTEORDER, CTL_EOL); 596 u = ((u_int)physmem > (UINT_MAX / PAGE_SIZE)) ? 597 UINT_MAX : physmem * PAGE_SIZE; 598 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 599 CTLTYPE_INT, "physmem", NULL, 600 NULL, u, NULL, 0, 601 CTL_HW, HW_PHYSMEM, CTL_EOL); 602 sysctl_createv(SYSCTL_PERMANENT, 603 CTLTYPE_INT, "usermem", NULL, 604 sysctl_hw_usermem, 0, NULL, 0, 605 CTL_HW, HW_USERMEM, CTL_EOL); 606 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 607 CTLTYPE_INT, "pagesize", NULL, 608 NULL, PAGE_SIZE, NULL, 0, 609 CTL_HW, HW_PAGESIZE, CTL_EOL); 610 sysctl_createv(SYSCTL_PERMANENT, 611 CTLTYPE_STRING, "disknames", NULL, 612 sysctl_hw_disknames, 0, NULL, 0, 613 CTL_HW, HW_DISKNAMES, CTL_EOL); 614 sysctl_createv(SYSCTL_PERMANENT, 615 CTLTYPE_STRUCT, "diskstats", NULL, 616 sysctl_hw_diskstats, 0, NULL, 0, 617 CTL_HW, HW_DISKSTATS, CTL_EOL); 618 sysctl_createv(SYSCTL_PERMANENT, 619 CTLTYPE_STRING, "machine_arch", NULL, 620 NULL, 0, machine_arch, 0, 621 CTL_HW, HW_MACHINE_ARCH, CTL_EOL); 622 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 623 CTLTYPE_INT, "alignbytes", NULL, 624 NULL, ALIGNBYTES, NULL, 0, 625 CTL_HW, HW_ALIGNBYTES, CTL_EOL); 626 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE|SYSCTL_HEX, 627 CTLTYPE_STRING, "cnmagic", NULL, 628 sysctl_hw_cnmagic, 0, NULL, CNS_LEN, 629 CTL_HW, HW_CNMAGIC, CTL_EOL); 630 q = (u_quad_t)physmem * PAGE_SIZE; 631 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 632 CTLTYPE_QUAD, "physmem64", NULL, 633 NULL, q, NULL, 0, 634 CTL_HW, HW_PHYSMEM64, CTL_EOL); 635 sysctl_createv(SYSCTL_PERMANENT, 636 CTLTYPE_QUAD, "usermem64", NULL, 637 sysctl_hw_usermem, 0, NULL, 0, 638 CTL_HW, HW_USERMEM64, CTL_EOL); 639} 640 641#ifdef DEBUG 642/* 643 * Debugging related system variables. 644 */ 645struct ctldebug /* debug0, */ /* debug1, */ debug2, debug3, debug4; 646struct ctldebug debug5, debug6, debug7, debug8, debug9; 647struct ctldebug debug10, debug11, debug12, debug13, debug14; 648struct ctldebug debug15, debug16, debug17, debug18, debug19; 649static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 650 &debug0, &debug1, &debug2, &debug3, &debug4, 651 &debug5, &debug6, &debug7, &debug8, &debug9, 652 &debug10, &debug11, &debug12, &debug13, &debug14, 653 &debug15, &debug16, &debug17, &debug18, &debug19, 654}; 655 656/* 657 * this setup routine is a replacement for debug_sysctl() 658 * 659 * note that it creates several nodes per defined debug variable 660 */ 661SYSCTL_SETUP(sysctl_debug_setup, "sysctl debug subtree setup") 662{ 663 struct ctldebug *cdp; 664 char nodename[20]; 665 int i; 666 667 /* 668 * two ways here: 669 * 670 * the "old" way (debug.name -> value) which was emulated by 671 * the sysctl(8) binary 672 * 673 * the new way, which the sysctl(8) binary was actually using 674 675 node debug 676 node debug.0 677 string debug.0.name 678 int debug.0.value 679 int debug.name 680 681 */ 682 683 sysctl_createv(SYSCTL_PERMANENT, 684 CTLTYPE_NODE, "debug", NULL, 685 NULL, 0, NULL, 0, 686 CTL_DEBUG, CTL_EOL); 687 688 for (i = 0; i < CTL_DEBUG_MAXID; i++) { 689 cdp = debugvars[i]; 690 if (cdp->debugname == NULL || cdp->debugvar == NULL) 691 continue; 692 693 snprintf(nodename, sizeof(nodename), "debug%d", i); 694 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_HIDDEN, 695 CTLTYPE_NODE, nodename, NULL, 696 NULL, 0, NULL, 0, 697 CTL_DEBUG, i, CTL_EOL); 698 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_HIDDEN, 699 CTLTYPE_STRING, "name", NULL, 700 NULL, 0, cdp->debugname, 0, 701 CTL_DEBUG, i, CTL_DEBUG_NAME, CTL_EOL); 702 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_HIDDEN, 703 CTLTYPE_INT, "value", NULL, 704 NULL, 0, cdp->debugvar, 0, 705 CTL_DEBUG, i, CTL_DEBUG_VALUE, CTL_EOL); 706 sysctl_createv(SYSCTL_PERMANENT, 707 CTLTYPE_INT, cdp->debugname, NULL, 708 NULL, 0, cdp->debugvar, 0, 709 CTL_DEBUG, CTL_CREATE, CTL_EOL); 710 } 711} 712#endif /* DEBUG */ 713 714/* 715 * ******************************************************************** 716 * section 2: private node-specific helper routines. 717 * ******************************************************************** 718 */ 719 720/* 721 * sysctl helper routine for kern.maxvnodes. handles ensuring that 722 * new values never falls below desiredvnodes and then calls reinit 723 * routines that needs to adjust to the new value. 724 */ 725static int 726sysctl_kern_maxvnodes(SYSCTLFN_ARGS) 727{ 728 int error, new_vnodes; 729 struct sysctlnode node; 730 731 new_vnodes = desiredvnodes; 732 node = *rnode; 733 node.sysctl_data = &new_vnodes; 734 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 735 if (error || newp == NULL) 736 return (error); 737 738 if (new_vnodes < desiredvnodes) 739 return (EINVAL); 740 desiredvnodes = new_vnodes; 741 vfs_reinit(); 742 nchreinit(); 743 744 return (0); 745} 746 747/* 748 * sysctl helper routine for kern.maxvnodes. ensures that the new 749 * values are not too low or too high. 750 */ 751static int 752sysctl_kern_maxproc(SYSCTLFN_ARGS) 753{ 754 int error, nmaxproc; 755 struct sysctlnode node; 756 757 nmaxproc = maxproc; 758 node = *rnode; 759 node.sysctl_data = &nmaxproc; 760 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 761 if (error || newp == NULL) 762 return (error); 763 764 if (nmaxproc < 0 || nmaxproc >= PID_MAX) 765 return (EINVAL); 766#ifdef __HAVE_CPU_MAXPROC 767 if (nmaxproc > cpu_maxproc()) 768 return (EINVAL); 769#endif 770 maxproc = nmaxproc; 771 772 return (0); 773} 774 775/* 776 * sysctl helper routine for kern.securelevel. ensures that the value 777 * only rises unless the caller has pid 1 (assumed to be init). 778 */ 779static int 780sysctl_kern_securelevel(SYSCTLFN_ARGS) 781{ 782 int newsecurelevel, error; 783 struct sysctlnode node; 784 785 newsecurelevel = securelevel; 786 node = *rnode; 787 node.sysctl_data = &newsecurelevel; 788 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 789 if (error || newp == NULL) 790 return (error); 791 792 if (newsecurelevel < securelevel && l->l_proc->p_pid != 1) 793 return (EPERM); 794 securelevel = newsecurelevel; 795 796 return (error); 797} 798 799/* 800 * sysctl helper function for kern.hostid. the hostid is a long, but 801 * we export it as an int, so we need to give it a little help. 802 */ 803static int 804sysctl_kern_hostid(SYSCTLFN_ARGS) 805{ 806 int error, inthostid; 807 struct sysctlnode node; 808 809 inthostid = hostid; /* XXX assumes sizeof int >= sizeof long */ 810 node = *rnode; 811 node.sysctl_data = &inthostid; 812 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 813 if (error || newp == NULL) 814 return (error); 815 816 hostid = inthostid; 817 818 return (0); 819} 820 821/* 822 * sysctl helper routine for kern.clockrate. assembles a struct on 823 * the fly to be returned to the caller. 824 */ 825static int 826sysctl_kern_clockrate(SYSCTLFN_ARGS) 827{ 828 struct clockinfo clkinfo; 829 struct sysctlnode node; 830 831 clkinfo.tick = tick; 832 clkinfo.tickadj = tickadj; 833 clkinfo.hz = hz; 834 clkinfo.profhz = profhz; 835 clkinfo.stathz = stathz ? stathz : hz; 836 837 node = *rnode; 838 node.sysctl_data = &clkinfo; 839 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 840} 841 842 843/* 844 * sysctl helper routine for kern.file pseudo-subtree. 845 */ 846static int 847sysctl_kern_file(SYSCTLFN_ARGS) 848{ 849 int error; 850 size_t buflen; 851 struct file *fp; 852 char *start, *where; 853 854 start = where = oldp; 855 buflen = *oldlenp; 856 if (where == NULL) { 857 /* 858 * overestimate by 10 files 859 */ 860 *oldlenp = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 861 return (0); 862 } 863 864 /* 865 * first copyout filehead 866 */ 867 if (buflen < sizeof(filehead)) { 868 *oldlenp = 0; 869 return (0); 870 } 871 error = copyout(&filehead, where, sizeof(filehead)); 872 if (error) 873 return (error); 874 buflen -= sizeof(filehead); 875 where += sizeof(filehead); 876 877 /* 878 * followed by an array of file structures 879 */ 880 LIST_FOREACH(fp, &filehead, f_list) { 881 if (buflen < sizeof(struct file)) { 882 *oldlenp = where - start; 883 return (ENOMEM); 884 } 885 error = copyout(fp, where, sizeof(struct file)); 886 if (error) 887 return (error); 888 buflen -= sizeof(struct file); 889 where += sizeof(struct file); 890 } 891 *oldlenp = where - start; 892 return (0); 893} 894 895/* 896 * sysctl helper routine for kern.autonicetime and kern.autoniceval. 897 * asserts that the assigned value is in the correct range. 898 */ 899static int 900sysctl_kern_autonice(SYSCTLFN_ARGS) 901{ 902 int error, t = 0; 903 struct sysctlnode node; 904 905 node = *rnode; 906 t = *(int*)node.sysctl_data; 907 node.sysctl_data = &t; 908 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 909 if (error || newp == NULL) 910 return (error); 911 912 switch (node.sysctl_num) { 913 case KERN_AUTONICETIME: 914 if (t >= 0) 915 autonicetime = t; 916 break; 917 case KERN_AUTONICEVAL: 918 if (t < PRIO_MIN) 919 t = PRIO_MIN; 920 else if (t > PRIO_MAX) 921 t = PRIO_MAX; 922 autoniceval = t; 923 break; 924 } 925 926 return (0); 927} 928 929/* 930 * sysctl helper routine for kern.msgbufsize and kern.msgbuf. for the 931 * former it merely checks the the message buffer is set up. for the 932 * latter, it also copies out the data if necessary. 933 */ 934static int 935sysctl_msgbuf(SYSCTLFN_ARGS) 936{ 937 char *where = oldp; 938 size_t len, maxlen; 939 long beg, end; 940 int error; 941 942 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) { 943 msgbufenabled = 0; 944 return (ENXIO); 945 } 946 947 switch (rnode->sysctl_num) { 948 case KERN_MSGBUFSIZE: 949 return (sysctl_lookup(SYSCTLFN_CALL(rnode))); 950 case KERN_MSGBUF: 951 break; 952 default: 953 return (EOPNOTSUPP); 954 } 955 956 if (newp != NULL) 957 return (EPERM); 958 959 if (oldp == NULL) { 960 /* always return full buffer size */ 961 *oldlenp = msgbufp->msg_bufs; 962 return (0); 963 } 964 965 error = 0; 966 maxlen = MIN(msgbufp->msg_bufs, *oldlenp); 967 968 /* 969 * First, copy from the write pointer to the end of 970 * message buffer. 971 */ 972 beg = msgbufp->msg_bufx; 973 end = msgbufp->msg_bufs; 974 while (maxlen > 0) { 975 len = MIN(end - beg, maxlen); 976 if (len == 0) 977 break; 978 error = copyout(&msgbufp->msg_bufc[beg], where, len); 979 if (error) 980 break; 981 where += len; 982 maxlen -= len; 983 984 /* 985 * ... then, copy from the beginning of message buffer to 986 * the write pointer. 987 */ 988 beg = 0; 989 end = msgbufp->msg_bufx; 990 } 991 992 return (error); 993} 994 995/* 996 * sysctl helper routine for kern.defcorename. in the case of a new 997 * string being assigned, check that it's not a zero-length string. 998 * (XXX the check in -current doesn't work, but do we really care?) 999 */ 1000static int 1001sysctl_kern_defcorename(SYSCTLFN_ARGS) 1002{ 1003 int error; 1004 char newcorename[MAXPATHLEN]; 1005 struct sysctlnode node; 1006 1007 node = *rnode; 1008 node.sysctl_data = &newcorename[0]; 1009 memcpy(node.sysctl_data, rnode->sysctl_data, MAXPATHLEN); 1010 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1011 if (error || newp == NULL) 1012 return (error); 1013 1014 /* 1015 * when sysctl_lookup() deals with a string, it's guaranteed 1016 * to come back nul terminated. so there. :) 1017 */ 1018 if (strlen(newcorename) == 0) 1019 return (EINVAL); 1020 1021 memcpy(rnode->sysctl_data, node.sysctl_data, MAXPATHLEN); 1022 1023 return (0); 1024} 1025 1026/* 1027 * sysctl helper routine for kern.cp_time node. adds up cpu time 1028 * across all cpus. 1029 */ 1030static int 1031sysctl_kern_cptime(SYSCTLFN_ARGS) 1032{ 1033 struct sysctlnode node = *rnode; 1034 1035#ifndef MULTIPROCESSOR 1036 1037 if (namelen == 1 && name[0] == 0) { 1038 /* 1039 * you're allowed to ask for the zero'th processor 1040 */ 1041 name++; 1042 namelen--; 1043 } 1044 node.sysctl_data = curcpu()->ci_schedstate.spc_cp_time; 1045 node.sysctl_size = sizeof(curcpu()->ci_schedstate.spc_cp_time); 1046 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 1047 1048#else /* MULTIPROCESSOR */ 1049 1050 u_int64_t *cp_time = NULL; 1051 int error, n = sysctl_ncpus(), i; 1052 struct cpu_info *ci; 1053 CPU_INFO_ITERATOR cii; 1054 1055 /* 1056 * if you specifically pass a buffer that is the size of the 1057 * sum, or if you are probing for the size, you get the "sum" 1058 * of cp_time (and the size thereof) across all processors. 1059 * 1060 * alternately, you can pass an additional mib number and get 1061 * cp_time for that particular processor. 1062 */ 1063 switch (namelen) { 1064 case 0: 1065 if (*oldlenp == sizeof(u_int64_t) * CPUSTATES || oldp == NULL) { 1066 node.sysctl_size = sizeof(u_int64_t) * CPUSTATES; 1067 n = -1; /* SUM */ 1068 } 1069 else { 1070 node.sysctl_size = n * sizeof(u_int64_t) * CPUSTATES; 1071 n = -2; /* ALL */ 1072 } 1073 break; 1074 case 1: 1075 if (name[0] < 0 || name[0] >= n) 1076 return (EINVAL); /* ENOSUCHPROCESSOR */ 1077 node.sysctl_size = sizeof(u_int64_t) * CPUSTATES; 1078 n = name[0]; 1079 /* 1080 * adjust these so that sysctl_lookup() will be happy 1081 */ 1082 name++; 1083 namelen--; 1084 default: 1085 return (EINVAL); 1086 } 1087 1088 cp_time = malloc(node.sysctl_size, M_TEMP, M_WAITOK|M_CANFAIL); 1089 if (cp_time == NULL) 1090 return (ENOMEM); 1091 node.sysctl_data = cp_time; 1092 memset(cp_time, 0, node.sysctl_size); 1093 1094 for (CPU_INFO_FOREACH(cii, ci)) { 1095 if (n <= 0) 1096 for (i = 0; i < CPUSTATES; i++) 1097 cp_time[i] += ci->ci_schedstate.spc_cp_time[i]; 1098 /* 1099 * if a specific processor was requested and we just 1100 * did it, we're done here 1101 */ 1102 if (n == 0) 1103 break; 1104 /* 1105 * if doing "all", skip to next cp_time set for next processor 1106 */ 1107 if (n == -2) 1108 cp_time += CPUSTATES; 1109 /* 1110 * if we're doing a specific processor, we're one 1111 * processor closer 1112 */ 1113 if (n > 0) 1114 n--; 1115 } 1116 1117 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1118 free(node.sysctl_data, M_TEMP); 1119 return (error); 1120 1121#endif /* MULTIPROCESSOR */ 1122} 1123 1124#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 1125/* 1126 * sysctl helper routine for kern.sysvipc_info subtree. 1127 */ 1128 1129#define FILL_PERM(src, dst) do { \ 1130 (dst)._key = (src)._key; \ 1131 (dst).uid = (src).uid; \ 1132 (dst).gid = (src).gid; \ 1133 (dst).cuid = (src).cuid; \ 1134 (dst).cgid = (src).cgid; \ 1135 (dst).mode = (src).mode; \ 1136 (dst)._seq = (src)._seq; \ 1137} while (/*CONSTCOND*/ 0); 1138#define FILL_MSG(src, dst) do { \ 1139 FILL_PERM((src).msg_perm, (dst).msg_perm); \ 1140 (dst).msg_qnum = (src).msg_qnum; \ 1141 (dst).msg_qbytes = (src).msg_qbytes; \ 1142 (dst)._msg_cbytes = (src)._msg_cbytes; \ 1143 (dst).msg_lspid = (src).msg_lspid; \ 1144 (dst).msg_lrpid = (src).msg_lrpid; \ 1145 (dst).msg_stime = (src).msg_stime; \ 1146 (dst).msg_rtime = (src).msg_rtime; \ 1147 (dst).msg_ctime = (src).msg_ctime; \ 1148} while (/*CONSTCOND*/ 0) 1149#define FILL_SEM(src, dst) do { \ 1150 FILL_PERM((src).sem_perm, (dst).sem_perm); \ 1151 (dst).sem_nsems = (src).sem_nsems; \ 1152 (dst).sem_otime = (src).sem_otime; \ 1153 (dst).sem_ctime = (src).sem_ctime; \ 1154} while (/*CONSTCOND*/ 0) 1155#define FILL_SHM(src, dst) do { \ 1156 FILL_PERM((src).shm_perm, (dst).shm_perm); \ 1157 (dst).shm_segsz = (src).shm_segsz; \ 1158 (dst).shm_lpid = (src).shm_lpid; \ 1159 (dst).shm_cpid = (src).shm_cpid; \ 1160 (dst).shm_atime = (src).shm_atime; \ 1161 (dst).shm_dtime = (src).shm_dtime; \ 1162 (dst).shm_ctime = (src).shm_ctime; \ 1163 (dst).shm_nattch = (src).shm_nattch; \ 1164} while (/*CONSTCOND*/ 0) 1165 1166static int 1167sysctl_kern_sysvipc(SYSCTLFN_ARGS) 1168{ 1169 void *where = oldp; 1170 size_t *sizep = oldlenp; 1171#ifdef SYSVMSG 1172 struct msg_sysctl_info *msgsi = NULL; 1173#endif 1174#ifdef SYSVSEM 1175 struct sem_sysctl_info *semsi = NULL; 1176#endif 1177#ifdef SYSVSHM 1178 struct shm_sysctl_info *shmsi = NULL; 1179#endif 1180 size_t infosize, dssize, tsize, buflen; 1181 void *buf = NULL; 1182 char *start; 1183 int32_t nds; 1184 int i, error, ret; 1185 1186 if (namelen != 1) 1187 return (EINVAL); 1188 1189 start = where; 1190 buflen = *sizep; 1191 1192 switch (*name) { 1193 case KERN_SYSVIPC_MSG_INFO: 1194#ifdef SYSVMSG 1195 infosize = sizeof(msgsi->msginfo); 1196 nds = msginfo.msgmni; 1197 dssize = sizeof(msgsi->msgids[0]); 1198 break; 1199#else 1200 return (EINVAL); 1201#endif 1202 case KERN_SYSVIPC_SEM_INFO: 1203#ifdef SYSVSEM 1204 infosize = sizeof(semsi->seminfo); 1205 nds = seminfo.semmni; 1206 dssize = sizeof(semsi->semids[0]); 1207 break; 1208#else 1209 return (EINVAL); 1210#endif 1211 case KERN_SYSVIPC_SHM_INFO: 1212#ifdef SYSVSHM 1213 infosize = sizeof(shmsi->shminfo); 1214 nds = shminfo.shmmni; 1215 dssize = sizeof(shmsi->shmids[0]); 1216 break; 1217#else 1218 return (EINVAL); 1219#endif 1220 default: 1221 return (EINVAL); 1222 } 1223 /* 1224 * Round infosize to 64 bit boundary if requesting more than just 1225 * the info structure or getting the total data size. 1226 */ 1227 if (where == NULL || *sizep > infosize) 1228 infosize = ((infosize + 7) / 8) * 8; 1229 tsize = infosize + nds * dssize; 1230 1231 /* Return just the total size required. */ 1232 if (where == NULL) { 1233 *sizep = tsize; 1234 return (0); 1235 } 1236 1237 /* Not enough room for even the info struct. */ 1238 if (buflen < infosize) { 1239 *sizep = 0; 1240 return (ENOMEM); 1241 } 1242 buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK); 1243 memset(buf, 0, min(tsize, buflen)); 1244 1245 switch (*name) { 1246#ifdef SYSVMSG 1247 case KERN_SYSVIPC_MSG_INFO: 1248 msgsi = (struct msg_sysctl_info *)buf; 1249 msgsi->msginfo = msginfo; 1250 break; 1251#endif 1252#ifdef SYSVSEM 1253 case KERN_SYSVIPC_SEM_INFO: 1254 semsi = (struct sem_sysctl_info *)buf; 1255 semsi->seminfo = seminfo; 1256 break; 1257#endif 1258#ifdef SYSVSHM 1259 case KERN_SYSVIPC_SHM_INFO: 1260 shmsi = (struct shm_sysctl_info *)buf; 1261 shmsi->shminfo = shminfo; 1262 break; 1263#endif 1264 } 1265 buflen -= infosize; 1266 1267 ret = 0; 1268 if (buflen > 0) { 1269 /* Fill in the IPC data structures. */ 1270 for (i = 0; i < nds; i++) { 1271 if (buflen < dssize) { 1272 ret = ENOMEM; 1273 break; 1274 } 1275 switch (*name) { 1276#ifdef SYSVMSG 1277 case KERN_SYSVIPC_MSG_INFO: 1278 FILL_MSG(msqids[i], msgsi->msgids[i]); 1279 break; 1280#endif 1281#ifdef SYSVSEM 1282 case KERN_SYSVIPC_SEM_INFO: 1283 FILL_SEM(sema[i], semsi->semids[i]); 1284 break; 1285#endif 1286#ifdef SYSVSHM 1287 case KERN_SYSVIPC_SHM_INFO: 1288 FILL_SHM(shmsegs[i], shmsi->shmids[i]); 1289 break; 1290#endif 1291 } 1292 buflen -= dssize; 1293 } 1294 } 1295 *sizep -= buflen; 1296 error = copyout(buf, start, *sizep); 1297 /* If copyout succeeded, use return code set earlier. */ 1298 if (error == 0) 1299 error = ret; 1300 if (buf) 1301 free(buf, M_TEMP); 1302 return (error); 1303} 1304 1305#undef FILL_PERM 1306#undef FILL_MSG 1307#undef FILL_SEM 1308#undef FILL_SHM 1309 1310#endif /* defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) */ 1311 1312#if NPTY > 0 1313/* 1314 * sysctl helper routine for kern.maxptys. ensures that any new value 1315 * is acceptable to the pty subsystem. 1316 */ 1317static int 1318sysctl_kern_maxptys(SYSCTLFN_ARGS) 1319{ 1320 int pty_maxptys(int, int); /* defined in kern/tty_pty.c */ 1321 int error, max; 1322 struct sysctlnode node; 1323 1324 /* get current value of maxptys */ 1325 max = pty_maxptys(0, 0); 1326 1327 node = *rnode; 1328 node.sysctl_data = &max; 1329 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1330 if (error || newp == NULL) 1331 return (error); 1332 1333 if (max != pty_maxptys(max, 1)) 1334 return (EINVAL); 1335 1336 return (0); 1337} 1338#endif /* NPTY > 0 */ 1339 1340/* 1341 * sysctl helper routine for kern.sbmax. basically just ensures that 1342 * any new value is not too small. 1343 */ 1344static int 1345sysctl_kern_sbmax(SYSCTLFN_ARGS) 1346{ 1347 int error, new_sbmax; 1348 struct sysctlnode node; 1349 1350 new_sbmax = sb_max; 1351 node = *rnode; 1352 node.sysctl_data = &new_sbmax; 1353 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1354 if (error || newp == NULL) 1355 return (error); 1356 1357 error = sb_max_set(new_sbmax); 1358 1359 return (error); 1360} 1361 1362/* 1363 * sysctl helper routine for kern.urandom node. picks a random number 1364 * for you. 1365 */ 1366static int 1367sysctl_kern_urnd(SYSCTLFN_ARGS) 1368{ 1369#if NRND > 0 1370 int v; 1371 1372 if (rnd_extract_data(&v, sizeof(v), RND_EXTRACT_ANY) == sizeof(v)) { 1373 struct sysctlnode node = *rnode; 1374 node.sysctl_data = &v; 1375 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 1376 } 1377 else 1378 return (EIO); /*XXX*/ 1379#else 1380 return (EOPNOTSUPP); 1381#endif 1382} 1383 1384/* 1385 * sysctl helper routine to do kern.lwp.* work. 1386 */ 1387static int 1388sysctl_kern_lwp(SYSCTLFN_ARGS) 1389{ 1390 struct kinfo_lwp klwp; 1391 struct proc *p; 1392 struct lwp *l2; 1393 char *where, *dp; 1394 int pid, elem_size, elem_count; 1395 int buflen, needed, error; 1396 1397 dp = where = oldp; 1398 buflen = where != NULL ? *oldlenp : 0; 1399 error = needed = 0; 1400 1401 if (newp != NULL || namelen != 4) 1402 return (EINVAL); 1403 pid = name[1]; 1404 elem_size = name[2]; 1405 elem_count = name[3]; 1406 1407 p = pfind(pid); 1408 if (p == NULL) 1409 return (ESRCH); 1410 LIST_FOREACH(l2, &p->p_lwps, l_sibling) { 1411 if (buflen >= elem_size && elem_count > 0) { 1412 fill_lwp(l2, &klwp); 1413 /* 1414 * Copy out elem_size, but not larger than 1415 * the size of a struct kinfo_proc2. 1416 */ 1417 error = copyout(&klwp, dp, 1418 min(sizeof(klwp), elem_size)); 1419 if (error) 1420 goto cleanup; 1421 dp += elem_size; 1422 buflen -= elem_size; 1423 elem_count--; 1424 } 1425 needed += elem_size; 1426 } 1427 1428 if (where != NULL) { 1429 *oldlenp = dp - where; 1430 if (needed > *oldlenp) 1431 return (ENOMEM); 1432 } else { 1433 needed += KERN_PROCSLOP; 1434 *oldlenp = needed; 1435 } 1436 return (0); 1437 cleanup: 1438 return (error); 1439} 1440 1441/* 1442 * sysctl helper routine for kern.forkfsleep node. ensures that the 1443 * given value is not too large or two small, and is at least one 1444 * timer tick if not zero. 1445 */ 1446static int 1447sysctl_kern_forkfsleep(SYSCTLFN_ARGS) 1448{ 1449 /* userland sees value in ms, internally is in ticks */ 1450 extern int forkfsleep; /* defined in kern/kern_fork.c */ 1451 int error, timo, lsleep; 1452 struct sysctlnode node; 1453 1454 lsleep = forkfsleep * 1000 / hz; 1455 node = *rnode; 1456 node.sysctl_data = &lsleep; 1457 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1458 if (error || newp == NULL) 1459 return (error); 1460 1461 /* refuse negative values, and overly 'long time' */ 1462 if (lsleep < 0 || lsleep > MAXSLP * 1000) 1463 return (EINVAL); 1464 1465 timo = mstohz(lsleep); 1466 1467 /* if the interval is >0 ms && <1 tick, use 1 tick */ 1468 if (lsleep != 0 && timo == 0) 1469 forkfsleep = 1; 1470 else 1471 forkfsleep = timo; 1472 1473 return (0); 1474} 1475 1476/* 1477 * sysctl helper routine for kern.somaxkva. ensures that the given 1478 * value is not too small. 1479 * (XXX should we maybe make sure it's not too large as well?) 1480 */ 1481static int 1482sysctl_kern_somaxkva(SYSCTLFN_ARGS) 1483{ 1484 int error, new_somaxkva; 1485 struct sysctlnode node; 1486 1487 new_somaxkva = somaxkva; 1488 node = *rnode; 1489 node.sysctl_data = &new_somaxkva; 1490 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1491 if (error || newp == NULL) 1492 return (error); 1493 1494 if (new_somaxkva < (16 * 1024 * 1024)) /* sanity */ 1495 return (EINVAL); 1496 somaxkva = new_somaxkva; 1497 1498 return (error); 1499} 1500 1501/* 1502 * sysctl helper routine for kern.root_partition 1503 */ 1504static int 1505sysctl_kern_root_partition(SYSCTLFN_ARGS) 1506{ 1507 int rootpart = DISKPART(rootdev); 1508 struct sysctlnode node = *rnode; 1509 1510 node.sysctl_data = &rootpart; 1511 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 1512} 1513 1514/* 1515 * sysctl helper function for kern.drivers 1516 */ 1517static int 1518sysctl_kern_drivers(SYSCTLFN_ARGS) 1519{ 1520 int error; 1521 size_t buflen; 1522 struct kinfo_drivers kd; 1523 char *start, *where; 1524 const char *dname; 1525 int i; 1526 extern struct devsw_conv *devsw_conv; 1527 extern int max_devsw_convs; 1528 1529 if (newp != NULL || namelen != 0) 1530 return (EINVAL); 1531 1532 start = where = oldp; 1533 buflen = *oldlenp; 1534 if (where == NULL) { 1535 *oldlenp = max_devsw_convs * sizeof kd; 1536 return 0; 1537 } 1538 1539 /* 1540 * An array of kinfo_drivers structures 1541 */ 1542 error = 0; 1543 for (i = 0; i < max_devsw_convs; i++) { 1544 dname = devsw_conv[i].d_name; 1545 if (dname == NULL) 1546 continue; 1547 if (buflen < sizeof kd) { 1548 error = ENOMEM; 1549 break; 1550 } 1551 kd.d_bmajor = devsw_conv[i].d_bmajor; 1552 kd.d_cmajor = devsw_conv[i].d_cmajor; 1553 strlcpy(kd.d_name, dname, sizeof kd.d_name); 1554 error = copyout(&kd, where, sizeof kd); 1555 if (error != 0) 1556 break; 1557 buflen -= sizeof kd; 1558 where += sizeof kd; 1559 } 1560 *oldlenp = where - start; 1561 return error; 1562} 1563 1564static int 1565sysctl_doeproc(SYSCTLFN_ARGS) 1566{ 1567 struct eproc eproc; 1568 struct kinfo_proc2 kproc2; 1569 struct kinfo_proc *dp; 1570 struct proc *p; 1571 const struct proclist_desc *pd; 1572 char *where, *dp2; 1573 int type, op, arg; 1574 u_int elem_size, elem_count; 1575 size_t buflen, needed; 1576 int error; 1577 1578 dp = oldp; 1579 dp2 = where = oldp; 1580 buflen = where != NULL ? *oldlenp : 0; 1581 error = 0; 1582 needed = 0; 1583 type = rnode->sysctl_num; 1584 1585 if (type == KERN_PROC) { 1586 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 1587 return (EINVAL); 1588 op = name[0]; 1589 if (op != KERN_PROC_ALL) 1590 arg = name[1]; 1591 else 1592 arg = 0; /* Quell compiler warning */ 1593 elem_size = elem_count = 0; /* Ditto */ 1594 } else { 1595 if (namelen != 4) 1596 return (EINVAL); 1597 op = name[0]; 1598 arg = name[1]; 1599 elem_size = name[2]; 1600 elem_count = name[3]; 1601 } 1602 1603 proclist_lock_read(); 1604 1605 pd = proclists; 1606again: 1607 for (p = LIST_FIRST(pd->pd_list); p != NULL; p = LIST_NEXT(p, p_list)) { 1608 /* 1609 * Skip embryonic processes. 1610 */ 1611 if (p->p_stat == SIDL) 1612 continue; 1613 /* 1614 * TODO - make more efficient (see notes below). 1615 * do by session. 1616 */ 1617 switch (op) { 1618 1619 case KERN_PROC_PID: 1620 /* could do this with just a lookup */ 1621 if (p->p_pid != (pid_t)arg) 1622 continue; 1623 break; 1624 1625 case KERN_PROC_PGRP: 1626 /* could do this by traversing pgrp */ 1627 if (p->p_pgrp->pg_id != (pid_t)arg) 1628 continue; 1629 break; 1630 1631 case KERN_PROC_SESSION: 1632 if (p->p_session->s_sid != (pid_t)arg) 1633 continue; 1634 break; 1635 1636 case KERN_PROC_TTY: 1637 if (arg == (int) KERN_PROC_TTY_REVOKE) { 1638 if ((p->p_flag & P_CONTROLT) == 0 || 1639 p->p_session->s_ttyp == NULL || 1640 p->p_session->s_ttyvp != NULL) 1641 continue; 1642 } else if ((p->p_flag & P_CONTROLT) == 0 || 1643 p->p_session->s_ttyp == NULL) { 1644 if ((dev_t)arg != KERN_PROC_TTY_NODEV) 1645 continue; 1646 } else if (p->p_session->s_ttyp->t_dev != (dev_t)arg) 1647 continue; 1648 break; 1649 1650 case KERN_PROC_UID: 1651 if (p->p_ucred->cr_uid != (uid_t)arg) 1652 continue; 1653 break; 1654 1655 case KERN_PROC_RUID: 1656 if (p->p_cred->p_ruid != (uid_t)arg) 1657 continue; 1658 break; 1659 1660 case KERN_PROC_GID: 1661 if (p->p_ucred->cr_gid != (uid_t)arg) 1662 continue; 1663 break; 1664 1665 case KERN_PROC_RGID: 1666 if (p->p_cred->p_rgid != (uid_t)arg) 1667 continue; 1668 break; 1669 1670 case KERN_PROC_ALL: 1671 /* allow everything */ 1672 break; 1673 1674 default: 1675 error = EINVAL; 1676 goto cleanup; 1677 } 1678 if (type == KERN_PROC) { 1679 if (buflen >= sizeof(struct kinfo_proc)) { 1680 fill_eproc(p, &eproc); 1681 error = copyout(p, &dp->kp_proc, 1682 sizeof(struct proc)); 1683 if (error) 1684 goto cleanup; 1685 error = copyout(&eproc, &dp->kp_eproc, 1686 sizeof(eproc)); 1687 if (error) 1688 goto cleanup; 1689 dp++; 1690 buflen -= sizeof(struct kinfo_proc); 1691 } 1692 needed += sizeof(struct kinfo_proc); 1693 } else { /* KERN_PROC2 */ 1694 if (buflen >= elem_size && elem_count > 0) { 1695 fill_kproc2(p, &kproc2); 1696 /* 1697 * Copy out elem_size, but not larger than 1698 * the size of a struct kinfo_proc2. 1699 */ 1700 error = copyout(&kproc2, dp2, 1701 min(sizeof(kproc2), elem_size)); 1702 if (error) 1703 goto cleanup; 1704 dp2 += elem_size; 1705 buflen -= elem_size; 1706 elem_count--; 1707 } 1708 needed += elem_size; 1709 } 1710 } 1711 pd++; 1712 if (pd->pd_list != NULL) 1713 goto again; 1714 proclist_unlock_read(); 1715 1716 if (where != NULL) { 1717 if (type == KERN_PROC) 1718 *oldlenp = (char *)dp - where; 1719 else 1720 *oldlenp = dp2 - where; 1721 if (needed > *oldlenp) 1722 return (ENOMEM); 1723 } else { 1724 needed += KERN_PROCSLOP; 1725 *oldlenp = needed; 1726 } 1727 return (0); 1728 cleanup: 1729 proclist_unlock_read(); 1730 return (error); 1731} 1732 1733/* 1734 * sysctl helper routine for kern.proc_args pseudo-subtree. 1735 */ 1736static int 1737sysctl_kern_proc_args(SYSCTLFN_ARGS) 1738{ 1739 struct ps_strings pss; 1740 struct proc *p, *up = l->l_proc; 1741 size_t len, upper_bound, xlen, i; 1742 struct uio auio; 1743 struct iovec aiov; 1744 vaddr_t argv; 1745 pid_t pid; 1746 int nargv, type, error; 1747 char *arg; 1748 char *tmp; 1749 1750 if (newp != NULL || namelen != 2) 1751 return (EINVAL); 1752 pid = name[0]; 1753 type = name[1]; 1754 1755 switch (type) { 1756 case KERN_PROC_ARGV: 1757 case KERN_PROC_NARGV: 1758 case KERN_PROC_ENV: 1759 case KERN_PROC_NENV: 1760 /* ok */ 1761 break; 1762 default: 1763 return (EINVAL); 1764 } 1765 1766 /* check pid */ 1767 if ((p = pfind(pid)) == NULL) 1768 return (EINVAL); 1769 1770 /* only root or same user change look at the environment */ 1771 if (type == KERN_PROC_ENV || type == KERN_PROC_NENV) { 1772 if (up->p_ucred->cr_uid != 0) { 1773 if (up->p_cred->p_ruid != p->p_cred->p_ruid || 1774 up->p_cred->p_ruid != p->p_cred->p_svuid) 1775 return (EPERM); 1776 } 1777 } 1778 1779 if (oldp == NULL) { 1780 if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV) 1781 *oldlenp = sizeof (int); 1782 else 1783 *oldlenp = ARG_MAX; /* XXX XXX XXX */ 1784 return (0); 1785 } 1786 1787 /* 1788 * Zombies don't have a stack, so we can't read their psstrings. 1789 * System processes also don't have a user stack. 1790 */ 1791 if (P_ZOMBIE(p) || (p->p_flag & P_SYSTEM) != 0) 1792 return (EINVAL); 1793 1794 /* 1795 * Lock the process down in memory. 1796 */ 1797 /* XXXCDC: how should locking work here? */ 1798 if ((p->p_flag & P_WEXIT) || (p->p_vmspace->vm_refcnt < 1)) 1799 return (EFAULT); 1800 1801 p->p_vmspace->vm_refcnt++; /* XXX */ 1802 1803 /* 1804 * Allocate a temporary buffer to hold the arguments. 1805 */ 1806 arg = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 1807 1808 /* 1809 * Read in the ps_strings structure. 1810 */ 1811 aiov.iov_base = &pss; 1812 aiov.iov_len = sizeof(pss); 1813 auio.uio_iov = &aiov; 1814 auio.uio_iovcnt = 1; 1815 auio.uio_offset = (vaddr_t)p->p_psstr; 1816 auio.uio_resid = sizeof(pss); 1817 auio.uio_segflg = UIO_SYSSPACE; 1818 auio.uio_rw = UIO_READ; 1819 auio.uio_procp = NULL; 1820 error = uvm_io(&p->p_vmspace->vm_map, &auio); 1821 if (error) 1822 goto done; 1823 1824 if (type == KERN_PROC_ARGV || type == KERN_PROC_NARGV) 1825 memcpy(&nargv, (char *)&pss + p->p_psnargv, sizeof(nargv)); 1826 else 1827 memcpy(&nargv, (char *)&pss + p->p_psnenv, sizeof(nargv)); 1828 if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV) { 1829 error = copyout(&nargv, oldp, sizeof(nargv)); 1830 *oldlenp = sizeof(nargv); 1831 goto done; 1832 } 1833 /* 1834 * Now read the address of the argument vector. 1835 */ 1836 switch (type) { 1837 case KERN_PROC_ARGV: 1838 /* XXX compat32 stuff here */ 1839 memcpy(&tmp, (char *)&pss + p->p_psargv, sizeof(tmp)); 1840 break; 1841 case KERN_PROC_ENV: 1842 memcpy(&tmp, (char *)&pss + p->p_psenv, sizeof(tmp)); 1843 break; 1844 default: 1845 return (EINVAL); 1846 } 1847 auio.uio_offset = (off_t)(long)tmp; 1848 aiov.iov_base = &argv; 1849 aiov.iov_len = sizeof(argv); 1850 auio.uio_iov = &aiov; 1851 auio.uio_iovcnt = 1; 1852 auio.uio_resid = sizeof(argv); 1853 auio.uio_segflg = UIO_SYSSPACE; 1854 auio.uio_rw = UIO_READ; 1855 auio.uio_procp = NULL; 1856 error = uvm_io(&p->p_vmspace->vm_map, &auio); 1857 if (error) 1858 goto done; 1859 1860 /* 1861 * Now copy in the actual argument vector, one page at a time, 1862 * since we don't know how long the vector is (though, we do 1863 * know how many NUL-terminated strings are in the vector). 1864 */ 1865 len = 0; 1866 upper_bound = *oldlenp; 1867 for (; nargv != 0 && len < upper_bound; len += xlen) { 1868 aiov.iov_base = arg; 1869 aiov.iov_len = PAGE_SIZE; 1870 auio.uio_iov = &aiov; 1871 auio.uio_iovcnt = 1; 1872 auio.uio_offset = argv + len; 1873 xlen = PAGE_SIZE - ((argv + len) & PAGE_MASK); 1874 auio.uio_resid = xlen; 1875 auio.uio_segflg = UIO_SYSSPACE; 1876 auio.uio_rw = UIO_READ; 1877 auio.uio_procp = NULL; 1878 error = uvm_io(&p->p_vmspace->vm_map, &auio); 1879 if (error) 1880 goto done; 1881 1882 for (i = 0; i < xlen && nargv != 0; i++) { 1883 if (arg[i] == '\0') 1884 nargv--; /* one full string */ 1885 } 1886 1887 /* 1888 * Make sure we don't copyout past the end of the user's 1889 * buffer. 1890 */ 1891 if (len + i > upper_bound) 1892 i = upper_bound - len; 1893 1894 error = copyout(arg, (char *)oldp + len, i); 1895 if (error) 1896 break; 1897 1898 if (nargv == 0) { 1899 len += i; 1900 break; 1901 } 1902 } 1903 *oldlenp = len; 1904 1905done: 1906 uvmspace_free(p->p_vmspace); 1907 1908 free(arg, M_TEMP); 1909 return (error); 1910} 1911 1912/* 1913 * sysctl helper routine for hw.usermem and hw.usermem64. values are 1914 * calculate on the fly taking into account integer overflow and the 1915 * current wired count. 1916 */ 1917static int 1918sysctl_hw_usermem(SYSCTLFN_ARGS) 1919{ 1920 u_int ui; 1921 u_quad_t uq; 1922 struct sysctlnode node; 1923 1924 node = *rnode; 1925 switch (rnode->sysctl_num) { 1926 case HW_USERMEM: 1927 if ((ui = physmem - uvmexp.wired) > (UINT_MAX / PAGE_SIZE)) 1928 ui = UINT_MAX; 1929 else 1930 ui *= PAGE_SIZE; 1931 node.sysctl_data = &ui; 1932 break; 1933 case HW_USERMEM64: 1934 uq = (u_quad_t)(physmem - uvmexp.wired) * PAGE_SIZE; 1935 node.sysctl_data = &uq; 1936 break; 1937 default: 1938 return (EINVAL); 1939 } 1940 1941 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 1942} 1943 1944/* 1945 * sysctl helper routine for kern.cnmagic node. pulls the old value 1946 * out, encoded, and stuffs the new value in for decoding. 1947 */ 1948static int 1949sysctl_hw_cnmagic(SYSCTLFN_ARGS) 1950{ 1951 char magic[CNS_LEN]; 1952 int error; 1953 struct sysctlnode node; 1954 1955 if (oldp) 1956 cn_get_magic(magic, CNS_LEN); 1957 node = *rnode; 1958 node.sysctl_data = &magic[0]; 1959 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1960 if (error || newp == NULL) 1961 return (error); 1962 1963 return (cn_set_magic(magic)); 1964} 1965 1966static int 1967sysctl_hw_ncpu(SYSCTLFN_ARGS) 1968{ 1969 int ncpu; 1970 struct sysctlnode node; 1971 1972 ncpu = sysctl_ncpus(); 1973 node = *rnode; 1974 node.sysctl_data = &ncpu; 1975 1976 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 1977} 1978 1979 1980/* 1981 * ******************************************************************** 1982 * section 3: public helper routines that are used for more than one 1983 * node 1984 * ******************************************************************** 1985 */ 1986 1987/* 1988 * sysctl helper routine for the kern.root_device node and some ports' 1989 * machdep.root_device nodes. 1990 */ 1991int 1992sysctl_root_device(SYSCTLFN_ARGS) 1993{ 1994 struct sysctlnode node; 1995 1996 node = *rnode; 1997 node.sysctl_data = root_device->dv_xname; 1998 node.sysctl_size = strlen(root_device->dv_xname) + 1; 1999 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 2000} 2001 2002/* 2003 * sysctl helper routine for kern.consdev, dependent on the current 2004 * state of the console. also used for machdep.console_device on some 2005 * ports. 2006 */ 2007int 2008sysctl_consdev(SYSCTLFN_ARGS) 2009{ 2010 dev_t consdev; 2011 struct sysctlnode node; 2012 2013 if (cn_tab != NULL) 2014 consdev = cn_tab->cn_dev; 2015 else 2016 consdev = NODEV; 2017 node = *rnode; 2018 node.sysctl_data = &consdev; 2019 node.sysctl_size = sizeof(consdev); 2020 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 2021} 2022 2023/* 2024 * ******************************************************************** 2025 * section 4: support for some helpers 2026 * ******************************************************************** 2027 */ 2028 2029/* 2030 * Fill in a kinfo_proc2 structure for the specified process. 2031 */ 2032static void 2033fill_kproc2(struct proc *p, struct kinfo_proc2 *ki) 2034{ 2035 struct tty *tp; 2036 struct lwp *l; 2037 struct timeval ut, st; 2038 2039 memset(ki, 0, sizeof(*ki)); 2040 2041 ki->p_paddr = PTRTOINT64(p); 2042 ki->p_fd = PTRTOINT64(p->p_fd); 2043 ki->p_cwdi = PTRTOINT64(p->p_cwdi); 2044 ki->p_stats = PTRTOINT64(p->p_stats); 2045 ki->p_limit = PTRTOINT64(p->p_limit); 2046 ki->p_vmspace = PTRTOINT64(p->p_vmspace); 2047 ki->p_sigacts = PTRTOINT64(p->p_sigacts); 2048 ki->p_sess = PTRTOINT64(p->p_session); 2049 ki->p_tsess = 0; /* may be changed if controlling tty below */ 2050 ki->p_ru = PTRTOINT64(p->p_ru); 2051 2052 ki->p_eflag = 0; 2053 ki->p_exitsig = p->p_exitsig; 2054 ki->p_flag = p->p_flag; 2055 2056 ki->p_pid = p->p_pid; 2057 if (p->p_pptr) 2058 ki->p_ppid = p->p_pptr->p_pid; 2059 else 2060 ki->p_ppid = 0; 2061 ki->p_sid = p->p_session->s_sid; 2062 ki->p__pgid = p->p_pgrp->pg_id; 2063 2064 ki->p_tpgid = NO_PGID; /* may be changed if controlling tty below */ 2065 2066 ki->p_uid = p->p_ucred->cr_uid; 2067 ki->p_ruid = p->p_cred->p_ruid; 2068 ki->p_gid = p->p_ucred->cr_gid; 2069 ki->p_rgid = p->p_cred->p_rgid; 2070 ki->p_svuid = p->p_cred->p_svuid; 2071 ki->p_svgid = p->p_cred->p_svgid; 2072 2073 memcpy(ki->p_groups, p->p_cred->pc_ucred->cr_groups, 2074 min(sizeof(ki->p_groups), sizeof(p->p_cred->pc_ucred->cr_groups))); 2075 ki->p_ngroups = p->p_cred->pc_ucred->cr_ngroups; 2076 2077 ki->p_jobc = p->p_pgrp->pg_jobc; 2078 if ((p->p_flag & P_CONTROLT) && (tp = p->p_session->s_ttyp)) { 2079 ki->p_tdev = tp->t_dev; 2080 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID; 2081 ki->p_tsess = PTRTOINT64(tp->t_session); 2082 } else { 2083 ki->p_tdev = NODEV; 2084 } 2085 2086 ki->p_estcpu = p->p_estcpu; 2087 ki->p_rtime_sec = p->p_rtime.tv_sec; 2088 ki->p_rtime_usec = p->p_rtime.tv_usec; 2089 ki->p_cpticks = p->p_cpticks; 2090 ki->p_pctcpu = p->p_pctcpu; 2091 2092 ki->p_uticks = p->p_uticks; 2093 ki->p_sticks = p->p_sticks; 2094 ki->p_iticks = p->p_iticks; 2095 2096 ki->p_tracep = PTRTOINT64(p->p_tracep); 2097 ki->p_traceflag = p->p_traceflag; 2098 2099 2100 memcpy(&ki->p_siglist, &p->p_sigctx.ps_siglist, sizeof(ki_sigset_t)); 2101 memcpy(&ki->p_sigmask, &p->p_sigctx.ps_sigmask, sizeof(ki_sigset_t)); 2102 memcpy(&ki->p_sigignore, &p->p_sigctx.ps_sigignore,sizeof(ki_sigset_t)); 2103 memcpy(&ki->p_sigcatch, &p->p_sigctx.ps_sigcatch, sizeof(ki_sigset_t)); 2104 2105 ki->p_stat = p->p_stat; /* Will likely be overridden by LWP status */ 2106 ki->p_realstat = p->p_stat; 2107 ki->p_nice = p->p_nice; 2108 2109 ki->p_xstat = p->p_xstat; 2110 ki->p_acflag = p->p_acflag; 2111 2112 strncpy(ki->p_comm, p->p_comm, 2113 min(sizeof(ki->p_comm), sizeof(p->p_comm))); 2114 2115 strncpy(ki->p_login, p->p_session->s_login, 2116 min(sizeof ki->p_login - 1, sizeof p->p_session->s_login)); 2117 2118 ki->p_nlwps = p->p_nlwps; 2119 ki->p_nrlwps = p->p_nrlwps; 2120 ki->p_realflag = p->p_flag; 2121 2122 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 2123 ki->p_vm_rssize = 0; 2124 ki->p_vm_tsize = 0; 2125 ki->p_vm_dsize = 0; 2126 ki->p_vm_ssize = 0; 2127 l = NULL; 2128 } else { 2129 struct vmspace *vm = p->p_vmspace; 2130 2131 ki->p_vm_rssize = vm_resident_count(vm); 2132 ki->p_vm_tsize = vm->vm_tsize; 2133 ki->p_vm_dsize = vm->vm_dsize; 2134 ki->p_vm_ssize = vm->vm_ssize; 2135 2136 /* Pick a "representative" LWP */ 2137 l = proc_representative_lwp(p); 2138 ki->p_forw = PTRTOINT64(l->l_forw); 2139 ki->p_back = PTRTOINT64(l->l_back); 2140 ki->p_addr = PTRTOINT64(l->l_addr); 2141 ki->p_stat = l->l_stat; 2142 ki->p_flag |= l->l_flag; 2143 ki->p_swtime = l->l_swtime; 2144 ki->p_slptime = l->l_slptime; 2145 if (l->l_stat == LSONPROC) { 2146 KDASSERT(l->l_cpu != NULL); 2147 ki->p_schedflags = l->l_cpu->ci_schedstate.spc_flags; 2148 } else 2149 ki->p_schedflags = 0; 2150 ki->p_holdcnt = l->l_holdcnt; 2151 ki->p_priority = l->l_priority; 2152 ki->p_usrpri = l->l_usrpri; 2153 if (l->l_wmesg) 2154 strncpy(ki->p_wmesg, l->l_wmesg, sizeof(ki->p_wmesg)); 2155 ki->p_wchan = PTRTOINT64(l->l_wchan); 2156 2157 } 2158 2159 if (p->p_session->s_ttyvp) 2160 ki->p_eflag |= EPROC_CTTY; 2161 if (SESS_LEADER(p)) 2162 ki->p_eflag |= EPROC_SLEADER; 2163 2164 /* XXX Is this double check necessary? */ 2165 if (P_ZOMBIE(p)) { 2166 ki->p_uvalid = 0; 2167 } else { 2168 ki->p_uvalid = 1; 2169 2170 ki->p_ustart_sec = p->p_stats->p_start.tv_sec; 2171 ki->p_ustart_usec = p->p_stats->p_start.tv_usec; 2172 2173 calcru(p, &ut, &st, 0); 2174 ki->p_uutime_sec = ut.tv_sec; 2175 ki->p_uutime_usec = ut.tv_usec; 2176 ki->p_ustime_sec = st.tv_sec; 2177 ki->p_ustime_usec = st.tv_usec; 2178 2179 ki->p_uru_maxrss = p->p_stats->p_ru.ru_maxrss; 2180 ki->p_uru_ixrss = p->p_stats->p_ru.ru_ixrss; 2181 ki->p_uru_idrss = p->p_stats->p_ru.ru_idrss; 2182 ki->p_uru_isrss = p->p_stats->p_ru.ru_isrss; 2183 ki->p_uru_minflt = p->p_stats->p_ru.ru_minflt; 2184 ki->p_uru_majflt = p->p_stats->p_ru.ru_majflt; 2185 ki->p_uru_nswap = p->p_stats->p_ru.ru_nswap; 2186 ki->p_uru_inblock = p->p_stats->p_ru.ru_inblock; 2187 ki->p_uru_oublock = p->p_stats->p_ru.ru_oublock; 2188 ki->p_uru_msgsnd = p->p_stats->p_ru.ru_msgsnd; 2189 ki->p_uru_msgrcv = p->p_stats->p_ru.ru_msgrcv; 2190 ki->p_uru_nsignals = p->p_stats->p_ru.ru_nsignals; 2191 ki->p_uru_nvcsw = p->p_stats->p_ru.ru_nvcsw; 2192 ki->p_uru_nivcsw = p->p_stats->p_ru.ru_nivcsw; 2193 2194 timeradd(&p->p_stats->p_cru.ru_utime, 2195 &p->p_stats->p_cru.ru_stime, &ut); 2196 ki->p_uctime_sec = ut.tv_sec; 2197 ki->p_uctime_usec = ut.tv_usec; 2198 } 2199#ifdef MULTIPROCESSOR 2200 if (l && l->l_cpu != NULL) 2201 ki->p_cpuid = l->l_cpu->ci_cpuid; 2202 else 2203#endif 2204 ki->p_cpuid = KI_NOCPU; 2205} 2206 2207/* 2208 * Fill in a kinfo_lwp structure for the specified lwp. 2209 */ 2210static void 2211fill_lwp(struct lwp *l, struct kinfo_lwp *kl) 2212{ 2213 2214 kl->l_forw = PTRTOINT64(l->l_forw); 2215 kl->l_back = PTRTOINT64(l->l_back); 2216 kl->l_laddr = PTRTOINT64(l); 2217 kl->l_addr = PTRTOINT64(l->l_addr); 2218 kl->l_stat = l->l_stat; 2219 kl->l_lid = l->l_lid; 2220 kl->l_flag = l->l_flag; 2221 2222 kl->l_swtime = l->l_swtime; 2223 kl->l_slptime = l->l_slptime; 2224 if (l->l_stat == LSONPROC) { 2225 KDASSERT(l->l_cpu != NULL); 2226 kl->l_schedflags = l->l_cpu->ci_schedstate.spc_flags; 2227 } else 2228 kl->l_schedflags = 0; 2229 kl->l_holdcnt = l->l_holdcnt; 2230 kl->l_priority = l->l_priority; 2231 kl->l_usrpri = l->l_usrpri; 2232 if (l->l_wmesg) 2233 strncpy(kl->l_wmesg, l->l_wmesg, sizeof(kl->l_wmesg)); 2234 kl->l_wchan = PTRTOINT64(l->l_wchan); 2235#ifdef MULTIPROCESSOR 2236 if (l->l_cpu != NULL) 2237 kl->l_cpuid = l->l_cpu->ci_cpuid; 2238 else 2239#endif 2240 kl->l_cpuid = KI_NOCPU; 2241} 2242 2243/* 2244 * Fill in an eproc structure for the specified process. 2245 */ 2246void 2247fill_eproc(struct proc *p, struct eproc *ep) 2248{ 2249 struct tty *tp; 2250 struct lwp *l; 2251 2252 ep->e_paddr = p; 2253 ep->e_sess = p->p_session; 2254 ep->e_pcred = *p->p_cred; 2255 ep->e_ucred = *p->p_ucred; 2256 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 2257 ep->e_vm.vm_rssize = 0; 2258 ep->e_vm.vm_tsize = 0; 2259 ep->e_vm.vm_dsize = 0; 2260 ep->e_vm.vm_ssize = 0; 2261 /* ep->e_vm.vm_pmap = XXX; */ 2262 } else { 2263 struct vmspace *vm = p->p_vmspace; 2264 2265 ep->e_vm.vm_rssize = vm_resident_count(vm); 2266 ep->e_vm.vm_tsize = vm->vm_tsize; 2267 ep->e_vm.vm_dsize = vm->vm_dsize; 2268 ep->e_vm.vm_ssize = vm->vm_ssize; 2269 2270 /* Pick a "representative" LWP */ 2271 l = proc_representative_lwp(p); 2272 2273 if (l->l_wmesg) 2274 strncpy(ep->e_wmesg, l->l_wmesg, WMESGLEN); 2275 } 2276 if (p->p_pptr) 2277 ep->e_ppid = p->p_pptr->p_pid; 2278 else 2279 ep->e_ppid = 0; 2280 ep->e_pgid = p->p_pgrp->pg_id; 2281 ep->e_sid = ep->e_sess->s_sid; 2282 ep->e_jobc = p->p_pgrp->pg_jobc; 2283 if ((p->p_flag & P_CONTROLT) && 2284 (tp = ep->e_sess->s_ttyp)) { 2285 ep->e_tdev = tp->t_dev; 2286 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID; 2287 ep->e_tsess = tp->t_session; 2288 } else 2289 ep->e_tdev = NODEV; 2290 2291 ep->e_xsize = ep->e_xrssize = 0; 2292 ep->e_xccount = ep->e_xswrss = 0; 2293 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 2294 if (SESS_LEADER(p)) 2295 ep->e_flag |= EPROC_SLEADER; 2296 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME); 2297} 2298