]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_sysctl.c
xnu-1456.1.26.tar.gz
[apple/xnu.git] / bsd / kern / kern_sysctl.c
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
5d5c5d0d 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29/*-
30 * Copyright (c) 1982, 1986, 1989, 1993
31 * The Regents of the University of California. All rights reserved.
32 *
33 * This code is derived from software contributed to Berkeley by
34 * Mike Karels at Berkeley Software Design, Inc.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
65 */
2d21ac55
A
66/*
67 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
68 * support for mandatory and extensible security protections. This notice
69 * is included in support of clause 2.2 (b) of the Apple Public License,
70 * Version 2.0.
71 */
1c79356b
A
72
73/*
2d21ac55
A
74* DEPRECATED sysctl system call code
75 *
76 * Everything in this file is deprecated. Sysctls should be handled
77 * by the code in kern_newsysctl.c.
78 * The remaining "case" sections are supposed to be converted into
79 * SYSCTL_*-style definitions, and as soon as all of them are gone,
80 * this source file is supposed to die.
81 *
82 * DO NOT ADD ANY MORE "case" SECTIONS TO THIS FILE, instead define
83 * your sysctl with SYSCTL_INT, SYSCTL_PROC etc. in your source file.
1c79356b
A
84 */
85
86#include <sys/param.h>
87#include <sys/systm.h>
88#include <sys/kernel.h>
89#include <sys/malloc.h>
91447636
A
90#include <sys/proc_internal.h>
91#include <sys/kauth.h>
92#include <sys/file_internal.h>
93#include <sys/vnode_internal.h>
1c79356b
A
94#include <sys/unistd.h>
95#include <sys/buf.h>
96#include <sys/ioctl.h>
55e303ae 97#include <sys/namei.h>
1c79356b
A
98#include <sys/tty.h>
99#include <sys/disklabel.h>
100#include <sys/vm.h>
101#include <sys/sysctl.h>
9bccf70c 102#include <sys/user.h>
55e303ae 103#include <sys/aio_kern.h>
2d21ac55 104#include <sys/reboot.h>
e5568f75 105
b0d623f7
A
106#include <security/audit/audit.h>
107#include <kern/kalloc.h>
e5568f75 108
1c79356b
A
109#include <mach/machine.h>
110#include <mach/mach_types.h>
111#include <mach/vm_param.h>
b0d623f7 112#include <kern/mach_param.h>
1c79356b 113#include <kern/task.h>
91447636 114#include <kern/lock.h>
b0d623f7 115#include <kern/debug.h>
1c79356b 116#include <vm/vm_kern.h>
91447636 117#include <vm/vm_map.h>
1c79356b
A
118#include <mach/host_info.h>
119
91447636 120#include <sys/mount_internal.h>
1c79356b 121#include <sys/kdebug.h>
91447636 122#include <sys/sysproto.h>
1c79356b
A
123
124#include <IOKit/IOPlatformExpert.h>
125#include <pexpert/pexpert.h>
126
55e303ae 127#include <machine/machine_routines.h>
0c530ab8 128#include <machine/exec.h>
1c79356b 129
91447636
A
130#include <vm/vm_protos.h>
131
b0d623f7 132#if defined(__i386__) || defined(__x86_64__)
0c530ab8
A
133#include <i386/cpuid.h>
134#endif
135
1c79356b 136sysctlfn kern_sysctl;
b0d623f7 137#if DEBUG
1c79356b
A
138sysctlfn debug_sysctl;
139#endif
1c79356b
A
140extern sysctlfn net_sysctl;
141extern sysctlfn cpu_sysctl;
55e303ae
A
142extern int aio_max_requests;
143extern int aio_max_requests_per_process;
144extern int aio_worker_threads;
91447636
A
145extern int lowpri_IO_window_msecs;
146extern int lowpri_IO_delay_msecs;
0c530ab8 147extern int nx_enabled;
2d21ac55 148extern int speculative_reads_disabled;
b0d623f7
A
149extern unsigned int preheat_pages_max;
150extern unsigned int preheat_pages_min;
151extern unsigned int preheat_pages_mult;
152extern long numvnodes;
1c79356b 153
91447636 154static void
b0d623f7 155fill_user32_eproc(proc_t p, struct user32_eproc *ep);
91447636 156static void
b0d623f7 157fill_user32_externproc(proc_t p, struct user32_extern_proc *exp);
91447636 158static void
b0d623f7 159fill_user64_eproc(proc_t p, struct user64_eproc *ep);
91447636 160static void
b0d623f7 161fill_user64_proc(proc_t p, struct user64_kinfo_proc *kp);
91447636 162static void
b0d623f7 163fill_user64_externproc(proc_t p, struct user64_extern_proc *exp);
91447636
A
164extern int
165kdbg_control(int *name, u_int namelen, user_addr_t where, size_t * sizep);
1c79356b 166int
2d21ac55 167kdebug_ops(int *name, u_int namelen, user_addr_t where, size_t *sizep, proc_t p);
91447636
A
168#if NFSCLIENT
169extern int
170netboot_root(void);
171#endif
172int
173pcsamples_ops(int *name, u_int namelen, user_addr_t where, size_t *sizep,
2d21ac55 174 proc_t p);
91447636
A
175__private_extern__ kern_return_t
176reset_vmobjectcache(unsigned int val1, unsigned int val2);
91447636
A
177int
178sysctl_doproc(int *name, u_int namelen, user_addr_t where, size_t *sizep);
179int
180sysctl_doprof(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
181 user_addr_t newp, size_t newlen);
55e303ae 182static void
b0d623f7 183fill_user32_proc(proc_t p, struct user32_kinfo_proc *kp);
91447636
A
184int
185sysctl_procargs(int *name, u_int namelen, user_addr_t where,
2d21ac55 186 size_t *sizep, proc_t cur_proc);
55e303ae 187static int
91447636 188sysctl_procargs2(int *name, u_int namelen, user_addr_t where, size_t *sizep,
2d21ac55 189 proc_t cur_proc);
55e303ae 190static int
91447636 191sysctl_procargsx(int *name, u_int namelen, user_addr_t where, size_t *sizep,
2d21ac55 192 proc_t cur_proc, int argc_yes);
91447636
A
193int
194sysctl_struct(user_addr_t oldp, size_t *oldlenp, user_addr_t newp,
195 size_t newlen, void *sp, int len);
1c79356b 196
2d21ac55
A
197static int sysdoproc_filt_KERN_PROC_PID(proc_t p, void * arg);
198static int sysdoproc_filt_KERN_PROC_PGRP(proc_t p, void * arg);
199static int sysdoproc_filt_KERN_PROC_TTY(proc_t p, void * arg);
200static int sysdoproc_filt_KERN_PROC_UID(proc_t p, void * arg);
201static int sysdoproc_filt_KERN_PROC_RUID(proc_t p, void * arg);
b0d623f7 202#if CONFIG_LCTX
2d21ac55 203static int sysdoproc_filt_KERN_PROC_LCID(proc_t p, void * arg);
b0d623f7 204#endif
2d21ac55 205int sysdoproc_callback(proc_t p, void *arg);
1c79356b 206
b0d623f7 207static int __sysctl_funneled(proc_t p, struct __sysctl_args *uap, int32_t *retval);
2d21ac55
A
208
209extern void IORegistrySetOSBuildVersion(char * build_version);
91447636
A
210
211static void
b0d623f7 212fill_loadavg64(struct loadavg *la, struct user64_loadavg *la64)
91447636 213{
b0d623f7
A
214 la64->ldavg[0] = la->ldavg[0];
215 la64->ldavg[1] = la->ldavg[1];
216 la64->ldavg[2] = la->ldavg[2];
217 la64->fscale = (user64_long_t)la->fscale;
218}
219
220static void
221fill_loadavg32(struct loadavg *la, struct user32_loadavg *la32)
222{
223 la32->ldavg[0] = la->ldavg[0];
224 la32->ldavg[1] = la->ldavg[1];
225 la32->ldavg[2] = la->ldavg[2];
226 la32->fscale = (user32_long_t)la->fscale;
91447636
A
227}
228
1c79356b
A
229/*
230 * Locking and stats
231 */
2d21ac55 232static struct sysctl_lock memlock;
1c79356b 233
2d21ac55 234/* sysctl() syscall */
1c79356b 235int
b0d623f7 236__sysctl(proc_t p, struct __sysctl_args *uap, int32_t *retval)
2d21ac55
A
237{
238 boolean_t funnel_state;
239 int error;
240
241 funnel_state = thread_funnel_set(kernel_flock, TRUE);
242 error = __sysctl_funneled(p, uap, retval);
243 thread_funnel_set(kernel_flock, funnel_state);
244 return(error);
245}
246
247static int
b0d623f7 248__sysctl_funneled(proc_t p, struct __sysctl_args *uap, __unused int32_t *retval)
1c79356b
A
249{
250 int error, dolock = 1;
91447636
A
251 size_t savelen = 0, oldlen = 0, newlen;
252 sysctlfn *fnp = NULL;
1c79356b 253 int name[CTL_MAXNAME];
0b4e3aa0 254 int error1;
2d21ac55
A
255 boolean_t memlock_taken = FALSE;
256 boolean_t vslock_taken = FALSE;
257#if CONFIG_MACF
258 kauth_cred_t my_cred;
259#endif
1c79356b
A
260
261 /*
262 * all top-level sysctl names are non-terminal
263 */
264 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
265 return (EINVAL);
91447636
A
266 error = copyin(uap->name, &name[0], uap->namelen * sizeof(int));
267 if (error)
1c79356b 268 return (error);
91447636 269
e5568f75
A
270 AUDIT_ARG(ctlname, name, uap->namelen);
271
91447636
A
272 if (proc_is64bit(p)) {
273 /* uap->newlen is a size_t value which grows to 64 bits
274 * when coming from a 64-bit process. since it's doubtful we'll
275 * have a sysctl newp buffer greater than 4GB we shrink it to size_t
276 */
277 newlen = CAST_DOWN(size_t, uap->newlen);
278 }
279 else {
280 newlen = uap->newlen;
281 }
b0d623f7 282
1c79356b 283 /* CTL_UNSPEC is used to get oid to AUTO_OID */
91447636
A
284 if (uap->new != USER_ADDR_NULL
285 && ((name[0] == CTL_KERN
286 && !(name[1] == KERN_IPC || name[1] == KERN_PANICINFO || name[1] == KERN_PROCDELAYTERM ||
b0d623f7 287 name[1] == KERN_PROCNAME || name[1] == KERN_RAGEVNODE || name[1] == KERN_CHECKOPENEVT || name[1] == KERN_THREADNAME))
91447636 288 || (name[0] == CTL_HW)
2d21ac55 289 || (name[0] == CTL_VM))
91447636 290 && (error = suser(kauth_cred_get(), &p->p_acflag)))
1c79356b
A
291 return (error);
292
2d21ac55
A
293/* XXX: KERN, VFS and DEBUG are handled by their respective functions,
294 * but there is a fallback for all sysctls other than VFS to
295 * userland_sysctl() - KILL THIS! */
1c79356b
A
296 switch (name[0]) {
297 case CTL_KERN:
91447636 298 fnp = kern_sysctl;
0b4e3aa0
A
299 if ((name[1] != KERN_VNODE) && (name[1] != KERN_FILE)
300 && (name[1] != KERN_PROC))
1c79356b
A
301 dolock = 0;
302 break;
1c79356b 303 case CTL_VFS:
91447636 304 fnp = vfs_sysctl;
1c79356b 305 break;
b0d623f7 306#if DEBUG
1c79356b 307 case CTL_DEBUG:
91447636 308 fnp = debug_sysctl;
1c79356b
A
309 break;
310#endif
311 default:
91447636 312 fnp = NULL;
1c79356b
A
313 }
314
91447636
A
315 if (uap->oldlenp != USER_ADDR_NULL) {
316 uint64_t oldlen64 = fuulong(uap->oldlenp);
317
318 oldlen = CAST_DOWN(size_t, oldlen64);
319 /*
320 * If more than 4G, clamp to 4G - useracc() below will catch
321 * with an EFAULT, if it's actually necessary.
322 */
323 if (oldlen64 > 0x00000000ffffffffULL)
324 oldlen = 0xffffffffUL;
325 }
1c79356b 326
91447636
A
327 if (uap->old != USER_ADDR_NULL) {
328 if (!useracc(uap->old, (user_size_t)oldlen, B_WRITE))
1c79356b 329 return (EFAULT);
2d21ac55
A
330 /*
331 * The kernel debug mechanism does not need to take this lock, and
332 * we don't grab the memlock around calls to KERN_PROC because it is reentrant.
333 * Grabbing the lock for a KERN_PROC sysctl makes a deadlock possible 5024049.
334 */
335 if (!((name[1] == KERN_KDEBUG) && (name[2] == KERN_KDGETENTROPY)) &&
336 !(name[1] == KERN_PROC)) {
337 MEMLOCK_LOCK();
338 memlock_taken = TRUE;
339 }
340
341 if (dolock && oldlen) {
342 if ((error = vslock(uap->old, (user_size_t)oldlen))) {
343 if (memlock_taken == TRUE)
344 MEMLOCK_UNLOCK();
345 return(error);
0b4e3aa0 346 }
2d21ac55
A
347 savelen = oldlen;
348 vslock_taken = TRUE;
0b4e3aa0 349 }
1c79356b
A
350 }
351
2d21ac55
A
352#if CONFIG_MACF
353 my_cred = kauth_cred_proc_ref(p);
354 error = mac_system_check_sysctl(
355 my_cred,
356 (int *) name,
357 uap->namelen,
358 uap->old,
359 uap->oldlenp,
360 fnp == kern_sysctl ? 1 : 0,
361 uap->new,
362 newlen
363 );
364 kauth_cred_unref(&my_cred);
365 if (!error) {
366#endif
91447636 367 if (fnp) {
2d21ac55 368 error = (*fnp)(name + 1, uap->namelen - 1, uap->old,
91447636
A
369 &oldlen, uap->new, newlen, p);
370 }
1c79356b 371 else
2d21ac55
A
372 error = ENOTSUP;
373#if CONFIG_MACF
374 }
375#endif
376
377 if (vslock_taken == TRUE) {
378 error1 = vsunlock(uap->old, (user_size_t)savelen, B_WRITE);
379 if (!error)
380 error = error1;
381 }
382 if (memlock_taken == TRUE)
383 MEMLOCK_UNLOCK();
1c79356b 384
91447636 385 if ( (name[0] != CTL_VFS) && (error == ENOTSUP)) {
2d21ac55
A
386 size_t tmp = oldlen;
387 boolean_t funnel_state;
388
389 /*
390 * Drop the funnel when calling new sysctl code, which will conditionally
391 * grab the funnel if it really needs to.
392 */
393 funnel_state = thread_funnel_set(kernel_flock, FALSE);
394
91447636 395 error = userland_sysctl(p, name, uap->namelen, uap->old, &tmp,
b0d623f7 396 uap->new, newlen, &oldlen);
1c79356b 397
2d21ac55 398 thread_funnel_set(kernel_flock, funnel_state);
1c79356b 399 }
2d21ac55 400
1c79356b
A
401 if ((error) && (error != ENOMEM))
402 return (error);
403
2d21ac55
A
404 if (uap->oldlenp != USER_ADDR_NULL)
405 error = suulong(uap->oldlenp, oldlen);
1c79356b
A
406
407 return (error);
408}
409
410/*
411 * Attributes stored in the kernel.
412 */
e5568f75 413__private_extern__ char corefilename[MAXPATHLEN+1];
91447636
A
414__private_extern__ int do_coredump;
415__private_extern__ int sugid_coredump;
e5568f75 416
2d21ac55
A
417#if COUNT_SYSCALLS
418__private_extern__ int do_count_syscalls;
419#endif
55e303ae 420
1c79356b
A
421#ifdef INSECURE
422int securelevel = -1;
423#else
424int securelevel;
425#endif
426
55e303ae 427static int
91447636
A
428sysctl_affinity(
429 int *name,
430 u_int namelen,
431 user_addr_t oldBuf,
432 size_t *oldSize,
433 user_addr_t newBuf,
434 __unused size_t newSize,
2d21ac55 435 proc_t cur_proc)
55e303ae
A
436{
437 if (namelen < 1)
91447636 438 return (ENOTSUP);
55e303ae
A
439
440 if (name[0] == 0 && 1 == namelen) {
441 return sysctl_rdint(oldBuf, oldSize, newBuf,
91447636 442 (cur_proc->p_flag & P_AFFINITY) ? 1 : 0);
55e303ae
A
443 } else if (name[0] == 1 && 2 == namelen) {
444 if (name[1] == 0) {
b0d623f7 445 OSBitAndAtomic(~((uint32_t)P_AFFINITY), &cur_proc->p_flag);
55e303ae 446 } else {
b0d623f7 447 OSBitOrAtomic(P_AFFINITY, &cur_proc->p_flag);
55e303ae
A
448 }
449 return 0;
450 }
91447636 451 return (ENOTSUP);
55e303ae
A
452}
453
454static int
0c530ab8 455sysctl_translate(
91447636
A
456 int *name,
457 u_int namelen,
458 user_addr_t oldBuf,
459 size_t *oldSize,
460 user_addr_t newBuf,
461 __unused size_t newSize,
2d21ac55 462 proc_t cur_proc)
55e303ae 463{
2d21ac55
A
464 proc_t p;
465 int istranslated = 0;
466 kauth_cred_t my_cred;
467 uid_t uid;
55e303ae
A
468
469 if (namelen != 1)
91447636 470 return (ENOTSUP);
55e303ae 471
2d21ac55 472 p = proc_find(name[0]);
55e303ae
A
473 if (p == NULL)
474 return (EINVAL);
475
2d21ac55
A
476 my_cred = kauth_cred_proc_ref(p);
477 uid = kauth_cred_getuid(my_cred);
478 kauth_cred_unref(&my_cred);
479 if ((uid != kauth_cred_getuid(kauth_cred_get()))
480 && suser(kauth_cred_get(), &cur_proc->p_acflag)) {
481 proc_rele(p);
55e303ae 482 return (EPERM);
2d21ac55 483 }
55e303ae 484
2d21ac55
A
485 istranslated = (p->p_flag & P_TRANSLATED);
486 proc_rele(p);
55e303ae 487 return sysctl_rdint(oldBuf, oldSize, newBuf,
2d21ac55 488 (istranslated != 0) ? 1 : 0);
0c530ab8
A
489}
490
491int
2d21ac55 492set_archhandler(__unused proc_t p, int arch)
0c530ab8
A
493{
494 int error;
495 struct nameidata nd;
496 struct vnode_attr va;
2d21ac55
A
497 vfs_context_t ctx = vfs_context_current();
498 struct exec_archhandler *archhandler;
0c530ab8
A
499
500 switch(arch) {
501 case CPU_TYPE_POWERPC:
2d21ac55 502 archhandler = &exec_archhandler_ppc;
0c530ab8
A
503 break;
504 default:
505 return (EBADARCH);
506 }
507
b0d623f7 508 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
2d21ac55 509 CAST_USER_ADDR_T(archhandler->path), ctx);
0c530ab8
A
510 error = namei(&nd);
511 if (error)
512 return (error);
513 nameidone(&nd);
514
515 /* Check mount point */
516 if ((nd.ni_vp->v_mount->mnt_flag & MNT_NOEXEC) ||
517 (nd.ni_vp->v_type != VREG)) {
518 vnode_put(nd.ni_vp);
519 return (EACCES);
520 }
521
522 VATTR_INIT(&va);
523 VATTR_WANTED(&va, va_fsid);
524 VATTR_WANTED(&va, va_fileid);
2d21ac55 525 error = vnode_getattr(nd.ni_vp, &va, ctx);
0c530ab8
A
526 if (error) {
527 vnode_put(nd.ni_vp);
528 return (error);
529 }
530 vnode_put(nd.ni_vp);
531
2d21ac55 532 archhandler->fsid = va.va_fsid;
b0d623f7 533 archhandler->fileid = (u_int32_t)va.va_fileid;
0c530ab8 534 return 0;
55e303ae
A
535}
536
2d21ac55
A
537/* XXX remove once Rosetta is rev'ed */
538/*****************************************************************************/
55e303ae 539static int
0c530ab8 540sysctl_exec_archhandler_ppc(
91447636
A
541 __unused int *name,
542 __unused u_int namelen,
543 user_addr_t oldBuf,
544 size_t *oldSize,
545 user_addr_t newBuf,
546 size_t newSize,
2d21ac55 547 proc_t p)
55e303ae
A
548{
549 int error;
91447636 550 size_t len;
0c530ab8 551 char handler[sizeof(exec_archhandler_ppc.path)];
2d21ac55 552 vfs_context_t ctx = vfs_context_current();
91447636
A
553
554 if (oldSize) {
0c530ab8 555 len = strlen(exec_archhandler_ppc.path) + 1;
91447636
A
556 if (oldBuf) {
557 if (*oldSize < len)
558 return (ENOMEM);
0c530ab8 559 error = copyout(exec_archhandler_ppc.path, oldBuf, len);
91447636
A
560 if (error)
561 return (error);
562 }
563 *oldSize = len - 1;
564 }
55e303ae 565 if (newBuf) {
2d21ac55 566 error = suser(vfs_context_ucred(ctx), &p->p_acflag);
91447636
A
567 if (error)
568 return (error);
0c530ab8 569 if (newSize >= sizeof(exec_archhandler_ppc.path))
91447636 570 return (ENAMETOOLONG);
55e303ae
A
571 error = copyin(newBuf, handler, newSize);
572 if (error)
573 return (error);
574 handler[newSize] = 0;
2d21ac55 575 strlcpy(exec_archhandler_ppc.path, handler, MAXPATHLEN);
0c530ab8 576 error = set_archhandler(p, CPU_TYPE_POWERPC);
55e303ae
A
577 if (error)
578 return (error);
55e303ae 579 }
91447636 580 return 0;
55e303ae 581}
2d21ac55
A
582/*****************************************************************************/
583
584static int
585sysctl_handle_exec_archhandler_ppc(struct sysctl_oid *oidp, void *arg1,
586 int arg2, struct sysctl_req *req)
587{
588 int error = 0;
589
590 error = sysctl_handle_string(oidp, arg1, arg2, req);
591
592 if (error)
593 goto done;
594
595 if (req->newptr)
596 error = set_archhandler(req->p, CPU_TYPE_POWERPC);
597
598done:
599 return error;
600
601}
55e303ae 602
b0d623f7
A
603static int
604sysctl_handle_kern_threadname( __unused struct sysctl_oid *oidp, __unused void *arg1,
605 __unused int arg2, struct sysctl_req *req)
606{
607 int error;
608 struct uthread *ut = get_bsdthread_info(current_thread());
609 user_addr_t oldp=0, newp=0;
610 size_t *oldlenp=NULL;
611 size_t newlen=0;
612
613 oldp = req->oldptr;
614 oldlenp = &(req->oldlen);
615 newp = req->newptr;
616 newlen = req->newlen;
617
618 /* We want the current length, and maybe the string itself */
619 if(oldlenp) {
620 /* if we have no thread name yet tell'em we want MAXTHREADNAMESIZE - 1 */
621 size_t currlen = MAXTHREADNAMESIZE - 1;
622
623 if(ut->pth_name)
624 /* use length of current thread name */
625 currlen = strlen(ut->pth_name);
626 if(oldp) {
627 if(*oldlenp < currlen)
628 return ENOMEM;
629 /* NOTE - we do not copy the NULL terminator */
630 if(ut->pth_name) {
631 error = copyout(ut->pth_name,oldp,currlen);
632 if(error)
633 return error;
634 }
635 }
636 /* return length of thread name minus NULL terminator (just like strlen) */
637 req->oldidx = currlen;
638 }
639
640 /* We want to set the name to something */
641 if(newp)
642 {
643 if(newlen > (MAXTHREADNAMESIZE - 1))
644 return ENAMETOOLONG;
645 if(!ut->pth_name)
646 {
647 ut->pth_name = (char*)kalloc( MAXTHREADNAMESIZE );
648 if(!ut->pth_name)
649 return ENOMEM;
650 }
651 bzero(ut->pth_name, MAXTHREADNAMESIZE);
652 error = copyin(newp, ut->pth_name, newlen);
653 if(error)
654 return error;
655 }
656
657 return 0;
658}
659
660SYSCTL_PROC(_kern, KERN_THREADNAME, threadname, CTLFLAG_ANYBODY | CTLTYPE_STRING | CTLFLAG_RW, 0, 0, sysctl_handle_kern_threadname,"A","");
661
2d21ac55 662SYSCTL_NODE(_kern, KERN_EXEC, exec, CTLFLAG_RD|CTLFLAG_LOCKED, 0, "");
0c530ab8 663
2d21ac55 664SYSCTL_NODE(_kern_exec, OID_AUTO, archhandler, CTLFLAG_RD|CTLFLAG_LOCKED, 0, "");
0c530ab8 665
2d21ac55
A
666SYSCTL_PROC(_kern_exec_archhandler, OID_AUTO, powerpc,
667 CTLTYPE_STRING | CTLFLAG_RW, exec_archhandler_ppc.path, 0,
668 sysctl_handle_exec_archhandler_ppc, "A", "");
55e303ae 669
2d21ac55 670extern int get_kernel_symfile(proc_t, char **);
91447636
A
671__private_extern__ int
672sysctl_dopanicinfo(int *, u_int, user_addr_t, size_t *, user_addr_t,
2d21ac55 673 size_t, proc_t);
1c79356b
A
674
675/*
676 * kernel related system variables.
677 */
9bccf70c 678int
91447636 679kern_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
2d21ac55 680 user_addr_t newp, size_t newlen, proc_t p)
1c79356b 681{
9bccf70c
A
682 /* all sysctl names not listed below are terminal at this level */
683 if (namelen != 1
684 && !(name[0] == KERN_PROC
685 || name[0] == KERN_PROF
686 || name[0] == KERN_KDEBUG
593a1d5f 687#if !CONFIG_EMBEDDED
9bccf70c 688 || name[0] == KERN_PROCARGS
593a1d5f 689#endif
55e303ae 690 || name[0] == KERN_PROCARGS2
9bccf70c
A
691 || name[0] == KERN_IPC
692 || name[0] == KERN_SYSV
55e303ae 693 || name[0] == KERN_AFFINITY
0c530ab8
A
694 || name[0] == KERN_TRANSLATE
695 || name[0] == KERN_EXEC
91447636 696 || name[0] == KERN_PANICINFO
0c530ab8 697 || name[0] == KERN_POSIX
2d21ac55
A
698 || name[0] == KERN_TFP
699 || name[0] == KERN_TTY
700#if CONFIG_LCTX
701 || name[0] == KERN_LCTX
702#endif
703 )
9bccf70c 704 )
1c79356b
A
705 return (ENOTDIR); /* overloaded */
706
707 switch (name[0]) {
1c79356b
A
708 case KERN_PROC:
709 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
1c79356b
A
710#ifdef GPROF
711 case KERN_PROF:
712 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
713 newp, newlen));
1c79356b 714#endif
1c79356b
A
715 case KERN_KDEBUG:
716 return (kdebug_ops(name + 1, namelen - 1, oldp, oldlenp, p));
593a1d5f 717#if !CONFIG_EMBEDDED
1c79356b
A
718 case KERN_PROCARGS:
719 /* new one as it does not use kinfo_proc */
9bccf70c 720 return (sysctl_procargs(name + 1, namelen - 1, oldp, oldlenp, p));
593a1d5f 721#endif
55e303ae
A
722 case KERN_PROCARGS2:
723 /* new one as it does not use kinfo_proc */
724 return (sysctl_procargs2(name + 1, namelen - 1, oldp, oldlenp, p));
2d21ac55 725#if PANIC_INFO
9bccf70c
A
726 case KERN_PANICINFO:
727 return(sysctl_dopanicinfo(name + 1, namelen - 1, oldp, oldlenp,
728 newp, newlen, p));
2d21ac55 729#endif
55e303ae
A
730 case KERN_AFFINITY:
731 return sysctl_affinity(name+1, namelen-1, oldp, oldlenp,
732 newp, newlen, p);
0c530ab8
A
733 case KERN_TRANSLATE:
734 return sysctl_translate(name+1, namelen-1, oldp, oldlenp, newp,
735 newlen, p);
2d21ac55
A
736
737 /* XXX remove once Rosetta has rev'ed */
738 case KERN_EXEC:
0c530ab8
A
739 return sysctl_exec_archhandler_ppc(name+1, namelen-1, oldp,
740 oldlenp, newp, newlen, p);
2d21ac55
A
741#if COUNT_SYSCALLS
742 case KERN_COUNT_SYSCALLS:
91447636 743 {
2d21ac55
A
744 /* valid values passed in:
745 * = 0 means don't keep called counts for each bsd syscall
746 * > 0 means keep called counts for each bsd syscall
747 * = 2 means dump current counts to the system log
748 * = 3 means reset all counts
749 * for example, to dump current counts:
750 * sysctl -w kern.count_calls=2
0c530ab8 751 */
2d21ac55
A
752 error = sysctl_int(oldp, oldlenp, newp, newlen, &tmp);
753 if ( error != 0 ) {
754 return (error);
0c530ab8 755 }
2d21ac55
A
756
757 if ( tmp == 1 ) {
758 do_count_syscalls = 1;
759 }
760 else if ( tmp == 0 || tmp == 2 || tmp == 3 ) {
761 extern int nsysent;
762 extern int syscalls_log[];
763 extern const char * syscallnames[];
764 int i;
765 for ( i = 0; i < nsysent; i++ ) {
766 if ( syscalls_log[i] != 0 ) {
767 if ( tmp == 2 ) {
768 printf("%d calls - name %s \n", syscalls_log[i], syscallnames[i]);
0c530ab8 769 }
2d21ac55
A
770 else {
771 syscalls_log[i] = 0;
772 }
773 }
774 }
775 if ( tmp != 0 ) {
776 do_count_syscalls = 1;
777 }
778 }
779 return (0);
0c530ab8 780 }
2d21ac55 781#endif
1c79356b 782 default:
91447636 783 return (ENOTSUP);
1c79356b
A
784 }
785 /* NOTREACHED */
786}
787
b0d623f7 788#if DEBUG
1c79356b
A
789/*
790 * Debugging related system variables.
791 */
792#if DIAGNOSTIC
793extern
794#endif /* DIAGNOSTIC */
795struct ctldebug debug0, debug1;
796struct ctldebug debug2, debug3, debug4;
797struct ctldebug debug5, debug6, debug7, debug8, debug9;
798struct ctldebug debug10, debug11, debug12, debug13, debug14;
799struct ctldebug debug15, debug16, debug17, debug18, debug19;
800static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
801 &debug0, &debug1, &debug2, &debug3, &debug4,
802 &debug5, &debug6, &debug7, &debug8, &debug9,
803 &debug10, &debug11, &debug12, &debug13, &debug14,
804 &debug15, &debug16, &debug17, &debug18, &debug19,
805};
806int
91447636 807debug_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
2d21ac55 808 user_addr_t newp, size_t newlen, __unused proc_t p)
1c79356b
A
809{
810 struct ctldebug *cdp;
811
812 /* all sysctl names at this level are name and field */
813 if (namelen != 2)
b0d623f7 814 return (ENOTSUP); /* overloaded */
935ed37a 815 if (name[0] < 0 || name[0] >= CTL_DEBUG_MAXID)
b0d623f7 816 return (ENOTSUP);
1c79356b
A
817 cdp = debugvars[name[0]];
818 if (cdp->debugname == 0)
91447636 819 return (ENOTSUP);
1c79356b
A
820 switch (name[1]) {
821 case CTL_DEBUG_NAME:
822 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
823 case CTL_DEBUG_VALUE:
824 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
825 default:
91447636 826 return (ENOTSUP);
1c79356b
A
827 }
828 /* NOTREACHED */
829}
830#endif /* DEBUG */
831
2d21ac55
A
832/*
833 * The following sysctl_* functions should not be used
834 * any more, as they can only cope with callers in
835 * user mode: Use new-style
836 * sysctl_io_number()
837 * sysctl_io_string()
838 * sysctl_io_opaque()
839 * instead.
840 */
841
1c79356b
A
842/*
843 * Validate parameters and get old / set new parameters
844 * for an integer-valued sysctl function.
845 */
9bccf70c 846int
91447636
A
847sysctl_int(user_addr_t oldp, size_t *oldlenp,
848 user_addr_t newp, size_t newlen, int *valp)
1c79356b
A
849{
850 int error = 0;
851
91447636
A
852 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
853 return (EFAULT);
1c79356b
A
854 if (oldp && *oldlenp < sizeof(int))
855 return (ENOMEM);
856 if (newp && newlen != sizeof(int))
857 return (EINVAL);
858 *oldlenp = sizeof(int);
859 if (oldp)
860 error = copyout(valp, oldp, sizeof(int));
e5568f75 861 if (error == 0 && newp) {
1c79356b 862 error = copyin(newp, valp, sizeof(int));
b0d623f7 863 AUDIT_ARG(value32, *valp);
e5568f75 864 }
1c79356b
A
865 return (error);
866}
867
868/*
869 * As above, but read-only.
870 */
9bccf70c 871int
91447636 872sysctl_rdint(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, int val)
1c79356b
A
873{
874 int error = 0;
875
91447636
A
876 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
877 return (EFAULT);
1c79356b
A
878 if (oldp && *oldlenp < sizeof(int))
879 return (ENOMEM);
880 if (newp)
881 return (EPERM);
882 *oldlenp = sizeof(int);
883 if (oldp)
884 error = copyout((caddr_t)&val, oldp, sizeof(int));
885 return (error);
886}
887
9bccf70c
A
888/*
889 * Validate parameters and get old / set new parameters
890 * for an quad(64bit)-valued sysctl function.
891 */
892int
91447636
A
893sysctl_quad(user_addr_t oldp, size_t *oldlenp,
894 user_addr_t newp, size_t newlen, quad_t *valp)
9bccf70c
A
895{
896 int error = 0;
897
91447636
A
898 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
899 return (EFAULT);
9bccf70c
A
900 if (oldp && *oldlenp < sizeof(quad_t))
901 return (ENOMEM);
902 if (newp && newlen != sizeof(quad_t))
903 return (EINVAL);
904 *oldlenp = sizeof(quad_t);
905 if (oldp)
906 error = copyout(valp, oldp, sizeof(quad_t));
907 if (error == 0 && newp)
908 error = copyin(newp, valp, sizeof(quad_t));
909 return (error);
910}
911
912/*
913 * As above, but read-only.
914 */
915int
2d21ac55 916sysctl_rdquad(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, quad_t val)
9bccf70c
A
917{
918 int error = 0;
919
91447636
A
920 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
921 return (EFAULT);
9bccf70c
A
922 if (oldp && *oldlenp < sizeof(quad_t))
923 return (ENOMEM);
924 if (newp)
925 return (EPERM);
926 *oldlenp = sizeof(quad_t);
927 if (oldp)
2d21ac55 928 error = copyout((caddr_t)&val, oldp, sizeof(quad_t));
91447636
A
929 return (error);
930}
931
932/*
933 * Validate parameters and get old / set new parameters
934 * for a string-valued sysctl function. Unlike sysctl_string, if you
935 * give it a too small (but larger than 0 bytes) buffer, instead of
936 * returning ENOMEM, it truncates the returned string to the buffer
937 * size. This preserves the semantics of some library routines
938 * implemented via sysctl, which truncate their returned data, rather
939 * than simply returning an error. The returned string is always NUL
940 * terminated.
941 */
942int
943sysctl_trstring(user_addr_t oldp, size_t *oldlenp,
944 user_addr_t newp, size_t newlen, char *str, int maxlen)
945{
946 int len, copylen, error = 0;
947
948 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
949 return (EFAULT);
950 copylen = len = strlen(str) + 1;
951 if (oldp && (len < 0 || *oldlenp < 1))
952 return (ENOMEM);
953 if (oldp && (*oldlenp < (size_t)len))
954 copylen = *oldlenp + 1;
955 if (newp && (maxlen < 0 || newlen >= (size_t)maxlen))
956 return (EINVAL);
957 *oldlenp = copylen - 1; /* deal with NULL strings correctly */
958 if (oldp) {
959 error = copyout(str, oldp, copylen);
960 if (!error) {
961 unsigned char c = 0;
962 /* NUL terminate */
963 oldp += *oldlenp;
964 error = copyout((void *)&c, oldp, sizeof(char));
965 }
966 }
967 if (error == 0 && newp) {
968 error = copyin(newp, str, newlen);
969 str[newlen] = 0;
970 AUDIT_ARG(text, (char *)str);
971 }
9bccf70c
A
972 return (error);
973}
974
1c79356b
A
975/*
976 * Validate parameters and get old / set new parameters
977 * for a string-valued sysctl function.
978 */
9bccf70c 979int
91447636
A
980sysctl_string(user_addr_t oldp, size_t *oldlenp,
981 user_addr_t newp, size_t newlen, char *str, int maxlen)
1c79356b
A
982{
983 int len, error = 0;
984
91447636
A
985 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
986 return (EFAULT);
1c79356b 987 len = strlen(str) + 1;
91447636 988 if (oldp && (len < 0 || *oldlenp < (size_t)len))
1c79356b 989 return (ENOMEM);
91447636 990 if (newp && (maxlen < 0 || newlen >= (size_t)maxlen))
1c79356b 991 return (EINVAL);
9bccf70c 992 *oldlenp = len -1; /* deal with NULL strings correctly */
1c79356b 993 if (oldp) {
1c79356b
A
994 error = copyout(str, oldp, len);
995 }
996 if (error == 0 && newp) {
997 error = copyin(newp, str, newlen);
998 str[newlen] = 0;
e5568f75 999 AUDIT_ARG(text, (char *)str);
1c79356b
A
1000 }
1001 return (error);
1002}
1003
1004/*
1005 * As above, but read-only.
1006 */
9bccf70c 1007int
91447636
A
1008sysctl_rdstring(user_addr_t oldp, size_t *oldlenp,
1009 user_addr_t newp, char *str)
1c79356b
A
1010{
1011 int len, error = 0;
1012
91447636
A
1013 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1014 return (EFAULT);
1c79356b 1015 len = strlen(str) + 1;
91447636 1016 if (oldp && *oldlenp < (size_t)len)
1c79356b
A
1017 return (ENOMEM);
1018 if (newp)
1019 return (EPERM);
1020 *oldlenp = len;
1021 if (oldp)
1022 error = copyout(str, oldp, len);
1023 return (error);
1024}
1025
1026/*
1027 * Validate parameters and get old / set new parameters
1028 * for a structure oriented sysctl function.
1029 */
9bccf70c 1030int
91447636
A
1031sysctl_struct(user_addr_t oldp, size_t *oldlenp,
1032 user_addr_t newp, size_t newlen, void *sp, int len)
1c79356b
A
1033{
1034 int error = 0;
1035
91447636
A
1036 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1037 return (EFAULT);
1038 if (oldp && (len < 0 || *oldlenp < (size_t)len))
1c79356b 1039 return (ENOMEM);
91447636 1040 if (newp && (len < 0 || newlen > (size_t)len))
1c79356b
A
1041 return (EINVAL);
1042 if (oldp) {
1043 *oldlenp = len;
1044 error = copyout(sp, oldp, len);
1045 }
1046 if (error == 0 && newp)
1047 error = copyin(newp, sp, len);
1048 return (error);
1049}
1050
1051/*
1052 * Validate parameters and get old parameters
1053 * for a structure oriented sysctl function.
1054 */
9bccf70c 1055int
91447636
A
1056sysctl_rdstruct(user_addr_t oldp, size_t *oldlenp,
1057 user_addr_t newp, void *sp, int len)
1c79356b
A
1058{
1059 int error = 0;
1060
91447636
A
1061 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1062 return (EFAULT);
1063 if (oldp && (len < 0 || *oldlenp < (size_t)len))
1c79356b
A
1064 return (ENOMEM);
1065 if (newp)
1066 return (EPERM);
1067 *oldlenp = len;
1068 if (oldp)
1069 error = copyout(sp, oldp, len);
1070 return (error);
1071}
1072
1073/*
1074 * Get file structures.
1075 */
2d21ac55
A
1076static int
1077sysctl_file
1078(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
1c79356b 1079{
2d21ac55 1080 int error;
91447636 1081 struct fileglob *fg;
91447636 1082 struct extern_file nef;
1c79356b 1083
2d21ac55 1084 if (req->oldptr == USER_ADDR_NULL) {
1c79356b
A
1085 /*
1086 * overestimate by 10 files
1087 */
2d21ac55 1088 req->oldidx = sizeof(filehead) + (nfiles + 10) * sizeof(struct extern_file);
1c79356b
A
1089 return (0);
1090 }
1091
1092 /*
1093 * first copyout filehead
1094 */
2d21ac55 1095 error = SYSCTL_OUT(req, &filehead, sizeof(filehead));
91447636 1096 if (error)
1c79356b 1097 return (error);
1c79356b
A
1098
1099 /*
1100 * followed by an array of file structures
1101 */
91447636 1102 for (fg = filehead.lh_first; fg != 0; fg = fg->f_list.le_next) {
91447636
A
1103 nef.f_list.le_next = (struct extern_file *)fg->f_list.le_next;
1104 nef.f_list.le_prev = (struct extern_file **)fg->f_list.le_prev;
1105 nef.f_flag = (fg->fg_flag & FMASK);
1106 nef.f_type = fg->fg_type;
1107 nef.f_count = fg->fg_count;
1108 nef.f_msgcount = fg->fg_msgcount;
1109 nef.f_cred = fg->fg_cred;
1110 nef.f_ops = fg->fg_ops;
1111 nef.f_offset = fg->fg_offset;
1112 nef.f_data = fg->fg_data;
2d21ac55 1113 error = SYSCTL_OUT(req, &nef, sizeof(nef));
91447636 1114 if (error)
1c79356b 1115 return (error);
1c79356b 1116 }
1c79356b
A
1117 return (0);
1118}
1119
2d21ac55
A
1120SYSCTL_PROC(_kern, KERN_FILE, file,
1121 CTLTYPE_STRUCT | CTLFLAG_RW,
1122 0, 0, sysctl_file, "S,filehead", "");
1123
1124static int
1125sysdoproc_filt_KERN_PROC_PID(proc_t p, void * arg)
1126{
b0d623f7 1127 if (p->p_pid != (pid_t)*(int*)arg)
2d21ac55
A
1128 return(0);
1129 else
1130 return(1);
1131}
1132
1133static int
1134sysdoproc_filt_KERN_PROC_PGRP(proc_t p, void * arg)
1135{
b0d623f7 1136 if (p->p_pgrpid != (pid_t)*(int*)arg)
2d21ac55
A
1137 return(0);
1138 else
1139 return(1);
1140}
1141
1142static int
1143sysdoproc_filt_KERN_PROC_TTY(proc_t p, void * arg)
1144{
1145 boolean_t funnel_state;
1146 int retval;
b0d623f7 1147 struct tty *tp;
2d21ac55
A
1148
1149
1150 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1151 /* This is very racy but list lock is held.. Hmmm. */
1152 if ((p->p_flag & P_CONTROLT) == 0 ||
1153 (p->p_pgrp == NULL) || (p->p_pgrp->pg_session == NULL) ||
b0d623f7
A
1154 (tp = SESSION_TP(p->p_pgrp->pg_session)) == TTY_NULL ||
1155 tp->t_dev != (dev_t)*(int*)arg)
2d21ac55
A
1156 retval = 0;
1157 else
1158 retval = 1;
1159
1160 thread_funnel_set(kernel_flock, funnel_state);
1161
1162 return(retval);
1163}
1164
1165static int
1166sysdoproc_filt_KERN_PROC_UID(proc_t p, void * arg)
1167{
1168 kauth_cred_t my_cred;
1169 uid_t uid;
1170
1171 if (p->p_ucred == NULL)
1172 return(0);
1173 my_cred = kauth_cred_proc_ref(p);
1174 uid = kauth_cred_getuid(my_cred);
1175 kauth_cred_unref(&my_cred);
1176
b0d623f7 1177 if (uid != (uid_t)*(int*)arg)
2d21ac55
A
1178 return(0);
1179 else
1180 return(1);
1181}
1182
1183
1184static int
1185sysdoproc_filt_KERN_PROC_RUID(proc_t p, void * arg)
1186{
1187 kauth_cred_t my_cred;
1188 uid_t ruid;
1189
1190 if (p->p_ucred == NULL)
1191 return(0);
1192 my_cred = kauth_cred_proc_ref(p);
1193 ruid = my_cred->cr_ruid;
1194 kauth_cred_unref(&my_cred);
1195
b0d623f7 1196 if (ruid != (uid_t)*(int*)arg)
2d21ac55
A
1197 return(0);
1198 else
1199 return(1);
1200}
1201
b0d623f7 1202#if CONFIG_LCTX
2d21ac55
A
1203static int
1204sysdoproc_filt_KERN_PROC_LCID(proc_t p, void * arg)
1205{
1206 if ((p->p_lctx == NULL) ||
b0d623f7 1207 (p->p_lctx->lc_id != (pid_t)*(int*)arg))
2d21ac55
A
1208 return(0);
1209 else
1210 return(1);
1211}
b0d623f7 1212#endif
2d21ac55 1213
1c79356b
A
1214/*
1215 * try over estimating by 5 procs
1216 */
1217#define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
2d21ac55
A
1218struct sysdoproc_args {
1219 int buflen;
1220 caddr_t kprocp;
1221 boolean_t is_64_bit;
1222 user_addr_t dp;
1223 size_t needed;
1224 int sizeof_kproc;
1225 int * errorp;
1226 int uidcheck;
1227 int ruidcheck;
1228 int ttycheck;
1229 int uidval;
1230};
1231
1232int
1233sysdoproc_callback(proc_t p, void * arg)
1234{
1235 struct sysdoproc_args * args = (struct sysdoproc_args *)arg;
1236 int error=0;
1237
1238 if (args->buflen >= args->sizeof_kproc) {
b0d623f7 1239 if ((args->ruidcheck != 0) && (sysdoproc_filt_KERN_PROC_RUID(p, &args->uidval) == 0))
2d21ac55 1240 return(PROC_RETURNED);
b0d623f7 1241 if ((args->uidcheck != 0) && (sysdoproc_filt_KERN_PROC_UID(p, &args->uidval) == 0))
2d21ac55 1242 return(PROC_RETURNED);
b0d623f7 1243 if ((args->ttycheck != 0) && (sysdoproc_filt_KERN_PROC_TTY(p, &args->uidval) == 0))
2d21ac55
A
1244 return(PROC_RETURNED);
1245
1246 bzero(args->kprocp, args->sizeof_kproc);
1247 if (args->is_64_bit) {
b0d623f7 1248 fill_user64_proc(p, (struct user64_kinfo_proc *) args->kprocp);
2d21ac55
A
1249 }
1250 else {
b0d623f7 1251 fill_user32_proc(p, (struct user32_kinfo_proc *) args->kprocp);
2d21ac55
A
1252 }
1253 error = copyout(args->kprocp, args->dp, args->sizeof_kproc);
1254 if (error) {
1255 *args->errorp = error;
1256 return(PROC_RETURNED_DONE);
1257 return (error);
1258 }
1259 args->dp += args->sizeof_kproc;
1260 args->buflen -= args->sizeof_kproc;
1261 }
1262 args->needed += args->sizeof_kproc;
1263 return(PROC_RETURNED);
1264}
1c79356b 1265
9bccf70c 1266int
91447636 1267sysctl_doproc(int *name, u_int namelen, user_addr_t where, size_t *sizep)
1c79356b 1268{
91447636
A
1269 user_addr_t dp = where;
1270 size_t needed = 0;
1271 int buflen = where != USER_ADDR_NULL ? *sizep : 0;
1c79356b 1272 int error = 0;
91447636 1273 boolean_t is_64_bit = FALSE;
b0d623f7
A
1274 struct user32_kinfo_proc user32_kproc;
1275 struct user64_kinfo_proc user_kproc;
91447636
A
1276 int sizeof_kproc;
1277 caddr_t kprocp;
2d21ac55
A
1278 int (*filterfn)(proc_t, void *) = 0;
1279 struct sysdoproc_args args;
1280 int uidcheck = 0;
1281 int ruidcheck = 0;
1282 int ttycheck = 0;
1c79356b
A
1283
1284 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
1285 return (EINVAL);
91447636
A
1286 is_64_bit = proc_is64bit(current_proc());
1287 if (is_64_bit) {
1288 sizeof_kproc = sizeof(user_kproc);
1289 kprocp = (caddr_t) &user_kproc;
1290 }
1291 else {
b0d623f7
A
1292 sizeof_kproc = sizeof(user32_kproc);
1293 kprocp = (caddr_t) &user32_kproc;
91447636 1294 }
2d21ac55
A
1295
1296
1297 switch (name[0]) {
1c79356b
A
1298
1299 case KERN_PROC_PID:
2d21ac55 1300 filterfn = sysdoproc_filt_KERN_PROC_PID;
1c79356b
A
1301 break;
1302
1303 case KERN_PROC_PGRP:
2d21ac55 1304 filterfn = sysdoproc_filt_KERN_PROC_PGRP;
1c79356b 1305 break;
2d21ac55 1306
1c79356b 1307 case KERN_PROC_TTY:
2d21ac55 1308 ttycheck = 1;
1c79356b
A
1309 break;
1310
1311 case KERN_PROC_UID:
2d21ac55 1312 uidcheck = 1;
1c79356b
A
1313 break;
1314
1315 case KERN_PROC_RUID:
2d21ac55 1316 ruidcheck = 1;
1c79356b 1317 break;
2d21ac55
A
1318
1319#if CONFIG_LCTX
1320 case KERN_PROC_LCID:
1321 filterfn = sysdoproc_filt_KERN_PROC_LCID;
1322 break;
1323#endif
1c79356b 1324 }
2d21ac55
A
1325
1326 error = 0;
1327 args.buflen = buflen;
1328 args.kprocp = kprocp;
1329 args.is_64_bit = is_64_bit;
1330 args.dp = dp;
1331 args.needed = needed;
1332 args.errorp = &error;
1333 args.uidcheck = uidcheck;
1334 args.ruidcheck = ruidcheck;
1335 args.ttycheck = ttycheck;
1336 args.sizeof_kproc = sizeof_kproc;
1337 args.uidval = name[1];
1338
b0d623f7 1339 proc_iterate((PROC_ALLPROCLIST | PROC_ZOMBPROCLIST), sysdoproc_callback, &args, filterfn, &name[1]);
2d21ac55
A
1340
1341 if (error)
1342 return(error);
1343
1344 dp = args.dp;
1345 needed = args.needed;
1346
91447636
A
1347 if (where != USER_ADDR_NULL) {
1348 *sizep = dp - where;
1c79356b
A
1349 if (needed > *sizep)
1350 return (ENOMEM);
1351 } else {
1352 needed += KERN_PROCSLOP;
1353 *sizep = needed;
1354 }
1355 return (0);
1356}
1357
1c79356b
A
1358/*
1359 * Fill in an eproc structure for the specified process.
1360 */
55e303ae 1361static void
b0d623f7 1362fill_user32_eproc(proc_t p, struct user32_eproc *ep)
1c79356b 1363{
2d21ac55
A
1364 struct tty *tp;
1365 kauth_cred_t my_cred;
1366 struct pgrp * pg;
1367 struct session * sessp;
1368
1369 pg = proc_pgrp(p);
1370 sessp = proc_session(p);
1c79356b 1371
b0d623f7 1372 ep->e_paddr = CAST_DOWN_EXPLICIT(uint32_t,p);
2d21ac55
A
1373
1374 if (pg != PGRP_NULL) {
b0d623f7 1375 ep->e_sess = CAST_DOWN_EXPLICIT(uint32_t,sessp);
2d21ac55
A
1376 ep->e_pgid = p->p_pgrpid;
1377 ep->e_jobc = pg->pg_jobc;
1378 if ((sessp != SESSION_NULL) && sessp->s_ttyvp)
55e303ae
A
1379 ep->e_flag = EPROC_CTTY;
1380 } else {
b0d623f7 1381 ep->e_sess = 0;
55e303ae
A
1382 ep->e_pgid = 0;
1383 ep->e_jobc = 0;
1384 }
2d21ac55
A
1385#if CONFIG_LCTX
1386 if (p->p_lctx) {
1387 ep->e_lcid = p->p_lctx->lc_id;
1388 } else {
1389 ep->e_lcid = 0;
1390 }
1391#endif
1392 ep->e_ppid = p->p_ppid;
91447636 1393 /* Pre-zero the fake historical pcred */
b0d623f7 1394 bzero(&ep->e_pcred, sizeof(ep->e_pcred));
91447636 1395 if (p->p_ucred) {
2d21ac55 1396 my_cred = kauth_cred_proc_ref(p);
91447636
A
1397
1398 /* A fake historical pcred */
2d21ac55
A
1399 ep->e_pcred.p_ruid = my_cred->cr_ruid;
1400 ep->e_pcred.p_svuid = my_cred->cr_svuid;
1401 ep->e_pcred.p_rgid = my_cred->cr_rgid;
1402 ep->e_pcred.p_svgid = my_cred->cr_svgid;
91447636 1403 /* A fake historical *kauth_cred_t */
2d21ac55
A
1404 ep->e_ucred.cr_ref = my_cred->cr_ref;
1405 ep->e_ucred.cr_uid = kauth_cred_getuid(my_cred);
1406 ep->e_ucred.cr_ngroups = my_cred->cr_ngroups;
1407 bcopy(my_cred->cr_groups, ep->e_ucred.cr_groups, NGROUPS*sizeof(gid_t));
91447636 1408
2d21ac55 1409 kauth_cred_unref(&my_cred);
55e303ae 1410 }
1c79356b 1411 if (p->p_stat == SIDL || p->p_stat == SZOMB) {
1c79356b
A
1412 ep->e_vm.vm_tsize = 0;
1413 ep->e_vm.vm_dsize = 0;
1414 ep->e_vm.vm_ssize = 0;
1c79356b 1415 }
9bccf70c 1416 ep->e_vm.vm_rssize = 0;
55e303ae 1417
2d21ac55 1418 if ((p->p_flag & P_CONTROLT) && (sessp != SESSION_NULL) &&
b0d623f7 1419 (tp = SESSION_TP(sessp))) {
1c79356b 1420 ep->e_tdev = tp->t_dev;
2d21ac55 1421 ep->e_tpgid = sessp->s_ttypgrpid;
b0d623f7 1422 ep->e_tsess = CAST_DOWN_EXPLICIT(uint32_t,tp->t_session);
1c79356b
A
1423 } else
1424 ep->e_tdev = NODEV;
55e303ae 1425
2d21ac55 1426 if (SESS_LEADER(p, sessp))
1c79356b 1427 ep->e_flag |= EPROC_SLEADER;
2d21ac55 1428 bzero(&ep->e_wmesg[0], WMESGLEN+1);
1c79356b
A
1429 ep->e_xsize = ep->e_xrssize = 0;
1430 ep->e_xccount = ep->e_xswrss = 0;
2d21ac55
A
1431 if (sessp != SESSION_NULL)
1432 session_rele(sessp);
1433 if(pg != PGRP_NULL)
1434 pg_rele(pg);
1c79356b 1435}
55e303ae 1436
91447636
A
1437/*
1438 * Fill in an LP64 version of eproc structure for the specified process.
1439 */
1440static void
b0d623f7 1441fill_user64_eproc(proc_t p, struct user64_eproc *ep)
91447636 1442{
2d21ac55
A
1443 struct tty *tp;
1444 struct session *sessp = NULL;
1445 struct pgrp * pg;
1446 kauth_cred_t my_cred;
1447
1448 pg = proc_pgrp(p);
1449 sessp = proc_session(p);
91447636
A
1450
1451 ep->e_paddr = CAST_USER_ADDR_T(p);
2d21ac55
A
1452 if (pg != PGRP_NULL) {
1453 ep->e_sess = CAST_USER_ADDR_T(sessp);
1454 ep->e_pgid = p->p_pgrpid;
1455 ep->e_jobc = pg->pg_jobc;
1456 if (sessp != SESSION_NULL) {
1457 if (sessp->s_ttyvp)
91447636
A
1458 ep->e_flag = EPROC_CTTY;
1459 }
1460 } else {
1461 ep->e_sess = USER_ADDR_NULL;
1462 ep->e_pgid = 0;
1463 ep->e_jobc = 0;
1464 }
2d21ac55
A
1465#if CONFIG_LCTX
1466 if (p->p_lctx) {
1467 ep->e_lcid = p->p_lctx->lc_id;
1468 } else {
1469 ep->e_lcid = 0;
1470 }
1471#endif
1472 ep->e_ppid = p->p_ppid;
91447636
A
1473 /* Pre-zero the fake historical pcred */
1474 bzero(&ep->e_pcred, sizeof(ep->e_pcred));
1475 if (p->p_ucred) {
2d21ac55 1476 my_cred = kauth_cred_proc_ref(p);
91447636
A
1477
1478 /* A fake historical pcred */
2d21ac55
A
1479 ep->e_pcred.p_ruid = my_cred->cr_ruid;
1480 ep->e_pcred.p_svuid = my_cred->cr_svuid;
1481 ep->e_pcred.p_rgid = my_cred->cr_rgid;
1482 ep->e_pcred.p_svgid = my_cred->cr_svgid;
91447636
A
1483
1484 /* A fake historical *kauth_cred_t */
2d21ac55
A
1485 ep->e_ucred.cr_ref = my_cred->cr_ref;
1486 ep->e_ucred.cr_uid = kauth_cred_getuid(my_cred);
1487 ep->e_ucred.cr_ngroups = my_cred->cr_ngroups;
1488 bcopy(my_cred->cr_groups, ep->e_ucred.cr_groups, NGROUPS*sizeof(gid_t));
91447636 1489
2d21ac55 1490 kauth_cred_unref(&my_cred);
91447636
A
1491 }
1492 if (p->p_stat == SIDL || p->p_stat == SZOMB) {
1493 ep->e_vm.vm_tsize = 0;
1494 ep->e_vm.vm_dsize = 0;
1495 ep->e_vm.vm_ssize = 0;
1496 }
1497 ep->e_vm.vm_rssize = 0;
1498
2d21ac55 1499 if ((p->p_flag & P_CONTROLT) && (sessp != SESSION_NULL) &&
b0d623f7 1500 (tp = SESSION_TP(sessp))) {
91447636 1501 ep->e_tdev = tp->t_dev;
2d21ac55 1502 ep->e_tpgid = sessp->s_ttypgrpid;
91447636
A
1503 ep->e_tsess = CAST_USER_ADDR_T(tp->t_session);
1504 } else
1505 ep->e_tdev = NODEV;
1506
2d21ac55 1507 if (SESS_LEADER(p, sessp))
91447636 1508 ep->e_flag |= EPROC_SLEADER;
2d21ac55 1509 bzero(&ep->e_wmesg[0], WMESGLEN+1);
91447636
A
1510 ep->e_xsize = ep->e_xrssize = 0;
1511 ep->e_xccount = ep->e_xswrss = 0;
2d21ac55
A
1512 if (sessp != SESSION_NULL)
1513 session_rele(sessp);
1514 if (pg != PGRP_NULL)
1515 pg_rele(pg);
91447636
A
1516}
1517
1c79356b
A
1518/*
1519 * Fill in an eproc structure for the specified process.
1520 */
55e303ae 1521static void
b0d623f7 1522fill_user32_externproc(proc_t p, struct user32_extern_proc *exp)
1c79356b 1523{
b0d623f7
A
1524 exp->p_forw = exp->p_back = 0;
1525 exp->p_starttime.tv_sec = p->p_start.tv_sec;
1526 exp->p_starttime.tv_usec = p->p_start.tv_usec;
1527 exp->p_vmspace = 0;
1528 exp->p_sigacts = CAST_DOWN_EXPLICIT(uint32_t,p->p_sigacts);
1c79356b 1529 exp->p_flag = p->p_flag;
2d21ac55
A
1530 if (p->p_lflag & P_LTRACED)
1531 exp->p_flag |= P_TRACED;
1532 if (p->p_lflag & P_LPPWAIT)
1533 exp->p_flag |= P_PPWAIT;
1534 if (p->p_lflag & P_LEXIT)
1535 exp->p_flag |= P_WEXIT;
1c79356b
A
1536 exp->p_stat = p->p_stat ;
1537 exp->p_pid = p->p_pid ;
1538 exp->p_oppid = p->p_oppid ;
1c79356b 1539 /* Mach related */
b0d623f7
A
1540 exp->user_stack = p->user_stack;
1541 exp->exit_thread = CAST_DOWN_EXPLICIT(uint32_t,p->exit_thread);
1c79356b
A
1542 exp->p_debugger = p->p_debugger ;
1543 exp->sigwait = p->sigwait ;
1544 /* scheduling */
2d21ac55 1545#ifdef _PROC_HAS_SCHEDINFO_
1c79356b 1546 exp->p_estcpu = p->p_estcpu ;
1c79356b 1547 exp->p_pctcpu = p->p_pctcpu ;
1c79356b 1548 exp->p_slptime = p->p_slptime ;
2d21ac55
A
1549#else
1550 exp->p_estcpu = 0 ;
1551 exp->p_pctcpu = 0 ;
1552 exp->p_slptime = 0 ;
1553#endif
1554 exp->p_cpticks = 0 ;
1555 exp->p_wchan = 0 ;
1556 exp->p_wmesg = 0 ;
1557 exp->p_swtime = 0 ;
1c79356b
A
1558 bcopy(&p->p_realtimer, &exp->p_realtimer,sizeof(struct itimerval));
1559 bcopy(&p->p_rtime, &exp->p_rtime,sizeof(struct timeval));
2d21ac55
A
1560 exp->p_uticks = 0 ;
1561 exp->p_sticks = 0 ;
1562 exp->p_iticks = 0 ;
1563 exp->p_traceflag = 0;
1564 exp->p_tracep = 0 ;
9bccf70c 1565 exp->p_siglist = 0 ; /* No longer relevant */
b0d623f7 1566 exp->p_textvp = CAST_DOWN_EXPLICIT(uint32_t,p->p_textvp) ;
1c79356b 1567 exp->p_holdcnt = 0 ;
9bccf70c 1568 exp->p_sigmask = 0 ; /* no longer avaialable */
1c79356b
A
1569 exp->p_sigignore = p->p_sigignore ;
1570 exp->p_sigcatch = p->p_sigcatch ;
1571 exp->p_priority = p->p_priority ;
2d21ac55 1572 exp->p_usrpri = 0 ;
1c79356b
A
1573 exp->p_nice = p->p_nice ;
1574 bcopy(&p->p_comm, &exp->p_comm,MAXCOMLEN);
1575 exp->p_comm[MAXCOMLEN] = '\0';
b0d623f7
A
1576 exp->p_pgrp = CAST_DOWN_EXPLICIT(uint32_t,p->p_pgrp) ;
1577 exp->p_addr = 0;
1c79356b
A
1578 exp->p_xstat = p->p_xstat ;
1579 exp->p_acflag = p->p_acflag ;
b0d623f7 1580 exp->p_ru = CAST_DOWN_EXPLICIT(uint32_t,p->p_ru) ; /* XXX may be NULL */
91447636
A
1581}
1582
1583/*
1584 * Fill in an LP64 version of extern_proc structure for the specified process.
1585 */
1586static void
b0d623f7 1587fill_user64_externproc(proc_t p, struct user64_extern_proc *exp)
91447636
A
1588{
1589 exp->p_forw = exp->p_back = USER_ADDR_NULL;
2d21ac55
A
1590 exp->p_starttime.tv_sec = p->p_start.tv_sec;
1591 exp->p_starttime.tv_usec = p->p_start.tv_usec;
91447636
A
1592 exp->p_vmspace = USER_ADDR_NULL;
1593 exp->p_sigacts = CAST_USER_ADDR_T(p->p_sigacts);
1594 exp->p_flag = p->p_flag;
2d21ac55
A
1595 if (p->p_lflag & P_LTRACED)
1596 exp->p_flag |= P_TRACED;
1597 if (p->p_lflag & P_LPPWAIT)
1598 exp->p_flag |= P_PPWAIT;
1599 if (p->p_lflag & P_LEXIT)
1600 exp->p_flag |= P_WEXIT;
91447636
A
1601 exp->p_stat = p->p_stat ;
1602 exp->p_pid = p->p_pid ;
1603 exp->p_oppid = p->p_oppid ;
91447636
A
1604 /* Mach related */
1605 exp->user_stack = p->user_stack;
1606 exp->exit_thread = CAST_USER_ADDR_T(p->exit_thread);
1607 exp->p_debugger = p->p_debugger ;
1608 exp->sigwait = p->sigwait ;
1609 /* scheduling */
2d21ac55 1610#ifdef _PROC_HAS_SCHEDINFO_
91447636 1611 exp->p_estcpu = p->p_estcpu ;
91447636 1612 exp->p_pctcpu = p->p_pctcpu ;
91447636 1613 exp->p_slptime = p->p_slptime ;
2d21ac55
A
1614#else
1615 exp->p_estcpu = 0 ;
1616 exp->p_pctcpu = 0 ;
1617 exp->p_slptime = 0 ;
1618#endif
1619 exp->p_cpticks = 0 ;
1620 exp->p_wchan = 0;
1621 exp->p_wmesg = 0;
1622 exp->p_swtime = 0 ;
91447636
A
1623 exp->p_realtimer.it_interval.tv_sec = p->p_realtimer.it_interval.tv_sec;
1624 exp->p_realtimer.it_interval.tv_usec = p->p_realtimer.it_interval.tv_usec;
1625 exp->p_realtimer.it_value.tv_sec = p->p_realtimer.it_value.tv_sec;
1626 exp->p_realtimer.it_value.tv_usec = p->p_realtimer.it_value.tv_usec;
1627 exp->p_rtime.tv_sec = p->p_rtime.tv_sec;
1628 exp->p_rtime.tv_usec = p->p_rtime.tv_usec;
2d21ac55
A
1629 exp->p_uticks = 0 ;
1630 exp->p_sticks = 0 ;
1631 exp->p_iticks = 0 ;
1632 exp->p_traceflag = 0 ;
1633 exp->p_tracep = 0;
91447636
A
1634 exp->p_siglist = 0 ; /* No longer relevant */
1635 exp->p_textvp = CAST_USER_ADDR_T(p->p_textvp);
1636 exp->p_holdcnt = 0 ;
1637 exp->p_sigmask = 0 ; /* no longer avaialable */
1638 exp->p_sigignore = p->p_sigignore ;
1639 exp->p_sigcatch = p->p_sigcatch ;
1640 exp->p_priority = p->p_priority ;
2d21ac55 1641 exp->p_usrpri = 0 ;
91447636
A
1642 exp->p_nice = p->p_nice ;
1643 bcopy(&p->p_comm, &exp->p_comm,MAXCOMLEN);
1644 exp->p_comm[MAXCOMLEN] = '\0';
1645 exp->p_pgrp = CAST_USER_ADDR_T(p->p_pgrp);
1646 exp->p_addr = USER_ADDR_NULL;
1647 exp->p_xstat = p->p_xstat ;
1648 exp->p_acflag = p->p_acflag ;
1649 exp->p_ru = CAST_USER_ADDR_T(p->p_ru); /* XXX may be NULL */
1c79356b
A
1650}
1651
55e303ae 1652static void
b0d623f7 1653fill_user32_proc(proc_t p, struct user32_kinfo_proc *kp)
55e303ae 1654{
b0d623f7
A
1655 /* on a 64 bit kernel, 32 bit users will get some truncated information */
1656 fill_user32_externproc(p, &kp->kp_proc);
1657 fill_user32_eproc(p, &kp->kp_eproc);
55e303ae
A
1658}
1659
91447636 1660static void
b0d623f7 1661fill_user64_proc(proc_t p, struct user64_kinfo_proc *kp)
91447636 1662{
b0d623f7
A
1663 fill_user64_externproc(p, &kp->kp_proc);
1664 fill_user64_eproc(p, &kp->kp_eproc);
91447636
A
1665}
1666
9bccf70c 1667int
91447636 1668kdebug_ops(int *name, u_int namelen, user_addr_t where,
2d21ac55 1669 size_t *sizep, proc_t p)
1c79356b 1670{
9bccf70c 1671 int ret=0;
1c79356b 1672
c910b4d9
A
1673 if (namelen == 0)
1674 return(ENOTSUP);
b0d623f7 1675
91447636
A
1676 ret = suser(kauth_cred_get(), &p->p_acflag);
1677 if (ret)
9bccf70c 1678 return(ret);
b0d623f7 1679
1c79356b
A
1680 switch(name[0]) {
1681 case KERN_KDEFLAGS:
1682 case KERN_KDDFLAGS:
1683 case KERN_KDENABLE:
1684 case KERN_KDGETBUF:
1685 case KERN_KDSETUP:
1686 case KERN_KDREMOVE:
1687 case KERN_KDSETREG:
1688 case KERN_KDGETREG:
1689 case KERN_KDREADTR:
1690 case KERN_KDPIDTR:
1691 case KERN_KDTHRMAP:
1692 case KERN_KDPIDEX:
1693 case KERN_KDSETRTCDEC:
1694 case KERN_KDSETBUF:
9bccf70c 1695 case KERN_KDGETENTROPY:
1c79356b
A
1696 ret = kdbg_control(name, namelen, where, sizep);
1697 break;
1698 default:
91447636 1699 ret= ENOTSUP;
1c79356b
A
1700 break;
1701 }
1702 return(ret);
1703}
1704
1c79356b
A
1705
1706/*
55e303ae
A
1707 * Return the top *sizep bytes of the user stack, or the entire area of the
1708 * user stack down through the saved exec_path, whichever is smaller.
1c79356b 1709 */
9bccf70c 1710int
91447636 1711sysctl_procargs(int *name, u_int namelen, user_addr_t where,
2d21ac55 1712 size_t *sizep, proc_t cur_proc)
55e303ae
A
1713{
1714 return sysctl_procargsx( name, namelen, where, sizep, cur_proc, 0);
1715}
1716
1717static int
91447636 1718sysctl_procargs2(int *name, u_int namelen, user_addr_t where,
2d21ac55 1719 size_t *sizep, proc_t cur_proc)
55e303ae
A
1720{
1721 return sysctl_procargsx( name, namelen, where, sizep, cur_proc, 1);
1722}
1723
1724static int
c910b4d9 1725sysctl_procargsx(int *name, u_int namelen, user_addr_t where,
2d21ac55 1726 size_t *sizep, proc_t cur_proc, int argc_yes)
1c79356b 1727{
2d21ac55 1728 proc_t p;
91447636 1729 int buflen = where != USER_ADDR_NULL ? *sizep : 0;
1c79356b 1730 int error = 0;
2d21ac55 1731 struct _vm_map *proc_map;
1c79356b
A
1732 struct task * task;
1733 vm_map_copy_t tmp;
91447636
A
1734 user_addr_t arg_addr;
1735 size_t arg_size;
1c79356b 1736 caddr_t data;
2d21ac55 1737 size_t argslen=0;
91447636 1738 int size;
1c79356b 1739 vm_offset_t copy_start, copy_end;
1c79356b
A
1740 kern_return_t ret;
1741 int pid;
2d21ac55
A
1742 kauth_cred_t my_cred;
1743 uid_t uid;
1c79356b 1744
c910b4d9
A
1745 if ( namelen < 1 )
1746 return(EINVAL);
b0d623f7 1747
55e303ae 1748 if (argc_yes)
91447636 1749 buflen -= sizeof(int); /* reserve first word to return argc */
1c79356b 1750
91447636
A
1751 /* we only care about buflen when where (oldp from sysctl) is not NULL. */
1752 /* when where (oldp from sysctl) is NULL and sizep (oldlenp from sysctl */
1753 /* is not NULL then the caller wants us to return the length needed to */
1754 /* hold the data we would return */
1755 if (where != USER_ADDR_NULL && (buflen <= 0 || buflen > ARG_MAX)) {
1c79356b
A
1756 return(EINVAL);
1757 }
1758 arg_size = buflen;
1759
1760 /*
1761 * Lookup process by pid
1762 */
1763 pid = name[0];
2d21ac55 1764 p = proc_find(pid);
1c79356b
A
1765 if (p == NULL) {
1766 return(EINVAL);
1767 }
1768
1769 /*
1770 * Copy the top N bytes of the stack.
1771 * On all machines we have so far, the stack grows
1772 * downwards.
1773 *
1774 * If the user expects no more than N bytes of
1775 * argument list, use that as a guess for the
1776 * size.
1777 */
1778
2d21ac55
A
1779 if (!p->user_stack) {
1780 proc_rele(p);
1c79356b 1781 return(EINVAL);
2d21ac55 1782 }
1c79356b 1783
91447636
A
1784 if (where == USER_ADDR_NULL) {
1785 /* caller only wants to know length of proc args data */
2d21ac55
A
1786 if (sizep == NULL) {
1787 proc_rele(p);
91447636 1788 return(EFAULT);
2d21ac55 1789 }
91447636
A
1790
1791 size = p->p_argslen;
2d21ac55 1792 proc_rele(p);
91447636
A
1793 if (argc_yes) {
1794 size += sizeof(int);
1795 }
1796 else {
1797 /*
1798 * old PROCARGS will return the executable's path and plus some
1799 * extra space for work alignment and data tags
1800 */
1801 size += PATH_MAX + (6 * sizeof(int));
1802 }
1803 size += (size & (sizeof(int) - 1)) ? (sizeof(int) - (size & (sizeof(int) - 1))) : 0;
1804 *sizep = size;
1805 return (0);
1806 }
1807
2d21ac55
A
1808 my_cred = kauth_cred_proc_ref(p);
1809 uid = kauth_cred_getuid(my_cred);
1810 kauth_cred_unref(&my_cred);
1811
1812 if ((uid != kauth_cred_getuid(kauth_cred_get()))
1813 && suser(kauth_cred_get(), &cur_proc->p_acflag)) {
1814 proc_rele(p);
9bccf70c 1815 return (EINVAL);
2d21ac55 1816 }
91447636
A
1817
1818 if ((u_int)arg_size > p->p_argslen)
1819 arg_size = round_page(p->p_argslen);
1820
1821 arg_addr = p->user_stack - arg_size;
1c79356b
A
1822
1823
1824 /*
1825 * Before we can block (any VM code), make another
1826 * reference to the map to keep it alive. We do
1827 * that by getting a reference on the task itself.
1828 */
1829 task = p->task;
2d21ac55
A
1830 if (task == NULL) {
1831 proc_rele(p);
1c79356b 1832 return(EINVAL);
2d21ac55 1833 }
1c79356b 1834
2d21ac55 1835 argslen = p->p_argslen;
0b4e3aa0 1836 /*
91447636
A
1837 * Once we have a task reference we can convert that into a
1838 * map reference, which we will use in the calls below. The
1839 * task/process may change its map after we take this reference
1840 * (see execve), but the worst that will happen then is a return
1841 * of stale info (which is always a possibility).
0b4e3aa0 1842 */
91447636 1843 task_reference(task);
2d21ac55 1844 proc_rele(p);
91447636
A
1845 proc_map = get_task_map_reference(task);
1846 task_deallocate(task);
2d21ac55 1847
91447636
A
1848 if (proc_map == NULL)
1849 return(EINVAL);
1c79356b 1850
91447636
A
1851
1852 ret = kmem_alloc(kernel_map, &copy_start, round_page(arg_size));
1c79356b 1853 if (ret != KERN_SUCCESS) {
91447636 1854 vm_map_deallocate(proc_map);
1c79356b
A
1855 return(ENOMEM);
1856 }
1857
91447636 1858 copy_end = round_page(copy_start + arg_size);
1c79356b 1859
91447636
A
1860 if( vm_map_copyin(proc_map, (vm_map_address_t)arg_addr,
1861 (vm_map_size_t)arg_size, FALSE, &tmp) != KERN_SUCCESS) {
1862 vm_map_deallocate(proc_map);
1c79356b 1863 kmem_free(kernel_map, copy_start,
91447636 1864 round_page(arg_size));
1c79356b
A
1865 return (EIO);
1866 }
1867
1868 /*
1869 * Now that we've done the copyin from the process'
1870 * map, we can release the reference to it.
1871 */
91447636 1872 vm_map_deallocate(proc_map);
1c79356b 1873
91447636
A
1874 if( vm_map_copy_overwrite(kernel_map,
1875 (vm_map_address_t)copy_start,
1876 tmp, FALSE) != KERN_SUCCESS) {
1c79356b 1877 kmem_free(kernel_map, copy_start,
91447636 1878 round_page(arg_size));
1c79356b
A
1879 return (EIO);
1880 }
1881
2d21ac55
A
1882 if (arg_size > argslen) {
1883 data = (caddr_t) (copy_end - argslen);
1884 size = argslen;
55e303ae 1885 } else {
91447636
A
1886 data = (caddr_t) (copy_end - arg_size);
1887 size = arg_size;
55e303ae 1888 }
1c79356b 1889
55e303ae
A
1890 if (argc_yes) {
1891 /* Put processes argc as the first word in the copyout buffer */
1892 suword(where, p->p_argc);
91447636
A
1893 error = copyout(data, (where + sizeof(int)), size);
1894 size += sizeof(int);
55e303ae
A
1895 } else {
1896 error = copyout(data, where, size);
1897
1898 /*
1899 * Make the old PROCARGS work to return the executable's path
1900 * But, only if there is enough space in the provided buffer
1901 *
1902 * on entry: data [possibily] points to the beginning of the path
1903 *
1904 * Note: we keep all pointers&sizes aligned to word boundries
1905 */
2d21ac55 1906 if ( (! error) && (buflen > 0 && (u_int)buflen > argslen) )
55e303ae 1907 {
91447636 1908 int binPath_sz, alignedBinPath_sz = 0;
55e303ae 1909 int extraSpaceNeeded, addThis;
91447636 1910 user_addr_t placeHere;
55e303ae 1911 char * str = (char *) data;
91447636 1912 int max_len = size;
55e303ae
A
1913
1914 /* Some apps are really bad about messing up their stacks
1915 So, we have to be extra careful about getting the length
1916 of the executing binary. If we encounter an error, we bail.
1917 */
1918
1919 /* Limit ourselves to PATH_MAX paths */
1920 if ( max_len > PATH_MAX ) max_len = PATH_MAX;
1921
1922 binPath_sz = 0;
1923
1924 while ( (binPath_sz < max_len-1) && (*str++ != 0) )
1925 binPath_sz++;
1926
91447636 1927 /* If we have a NUL terminator, copy it, too */
55e303ae
A
1928 if (binPath_sz < max_len-1) binPath_sz += 1;
1929
1930 /* Pre-Flight the space requiremnts */
1931
1932 /* Account for the padding that fills out binPath to the next word */
91447636 1933 alignedBinPath_sz += (binPath_sz & (sizeof(int)-1)) ? (sizeof(int)-(binPath_sz & (sizeof(int)-1))) : 0;
55e303ae
A
1934
1935 placeHere = where + size;
1936
1937 /* Account for the bytes needed to keep placeHere word aligned */
91447636 1938 addThis = (placeHere & (sizeof(int)-1)) ? (sizeof(int)-(placeHere & (sizeof(int)-1))) : 0;
55e303ae
A
1939
1940 /* Add up all the space that is needed */
91447636 1941 extraSpaceNeeded = alignedBinPath_sz + addThis + binPath_sz + (4 * sizeof(int));
55e303ae
A
1942
1943 /* is there is room to tack on argv[0]? */
2d21ac55 1944 if ( (buflen & ~(sizeof(int)-1)) >= ( argslen + extraSpaceNeeded ))
55e303ae
A
1945 {
1946 placeHere += addThis;
1947 suword(placeHere, 0);
91447636 1948 placeHere += sizeof(int);
55e303ae 1949 suword(placeHere, 0xBFFF0000);
91447636 1950 placeHere += sizeof(int);
55e303ae 1951 suword(placeHere, 0);
91447636 1952 placeHere += sizeof(int);
55e303ae
A
1953 error = copyout(data, placeHere, binPath_sz);
1954 if ( ! error )
1955 {
1956 placeHere += binPath_sz;
1957 suword(placeHere, 0);
1958 size += extraSpaceNeeded;
1959 }
1960 }
1961 }
1962 }
1963
1964 if (copy_start != (vm_offset_t) 0) {
1965 kmem_free(kernel_map, copy_start, copy_end - copy_start);
1c79356b
A
1966 }
1967 if (error) {
1968 return(error);
1969 }
1970
91447636 1971 if (where != USER_ADDR_NULL)
1c79356b
A
1972 *sizep = size;
1973 return (0);
1974}
55e303ae
A
1975
1976
1977/*
2d21ac55 1978 * Max number of concurrent aio requests
55e303ae
A
1979 */
1980static int
2d21ac55
A
1981sysctl_aiomax
1982(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
55e303ae 1983{
2d21ac55
A
1984 int new_value, changed;
1985 int error = sysctl_io_number(req, aio_max_requests, sizeof(int), &new_value, &changed);
1986 if (changed) {
1987 /* make sure the system-wide limit is greater than the per process limit */
1988 if (new_value >= aio_max_requests_per_process)
55e303ae
A
1989 aio_max_requests = new_value;
1990 else
1991 error = EINVAL;
1992 }
2d21ac55
A
1993 return(error);
1994}
55e303ae
A
1995
1996
1997/*
2d21ac55 1998 * Max number of concurrent aio requests per process
55e303ae
A
1999 */
2000static int
2d21ac55
A
2001sysctl_aioprocmax
2002(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
55e303ae 2003{
2d21ac55
A
2004 int new_value, changed;
2005 int error = sysctl_io_number(req, aio_max_requests_per_process, sizeof(int), &new_value, &changed);
2006 if (changed) {
2007 /* make sure per process limit is less than the system-wide limit */
2008 if (new_value <= aio_max_requests && new_value >= AIO_LISTIO_MAX)
55e303ae
A
2009 aio_max_requests_per_process = new_value;
2010 else
2011 error = EINVAL;
2012 }
2d21ac55
A
2013 return(error);
2014}
55e303ae
A
2015
2016
2017/*
2d21ac55 2018 * Max number of async IO worker threads
55e303ae
A
2019 */
2020static int
2d21ac55
A
2021sysctl_aiothreads
2022(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
55e303ae 2023{
2d21ac55
A
2024 int new_value, changed;
2025 int error = sysctl_io_number(req, aio_worker_threads, sizeof(int), &new_value, &changed);
2026 if (changed) {
2027 /* we only allow an increase in the number of worker threads */
55e303ae 2028 if (new_value > aio_worker_threads ) {
2d21ac55 2029 _aio_create_worker_threads((new_value - aio_worker_threads));
55e303ae
A
2030 aio_worker_threads = new_value;
2031 }
2032 else
2033 error = EINVAL;
2034 }
2d21ac55
A
2035 return(error);
2036}
55e303ae
A
2037
2038
2039/*
2d21ac55 2040 * System-wide limit on the max number of processes
55e303ae
A
2041 */
2042static int
2d21ac55
A
2043sysctl_maxproc
2044(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
55e303ae 2045{
2d21ac55
A
2046 int new_value, changed;
2047 int error = sysctl_io_number(req, maxproc, sizeof(int), &new_value, &changed);
2048 if (changed) {
b0d623f7 2049 AUDIT_ARG(value32, new_value);
2d21ac55
A
2050 /* make sure the system-wide limit is less than the configured hard
2051 limit set at kernel compilation */
2052 if (new_value <= hard_maxproc && new_value > 0)
2053 maxproc = new_value;
2054 else
55e303ae
A
2055 error = EINVAL;
2056 }
2d21ac55
A
2057 return(error);
2058}
55e303ae 2059
2d21ac55
A
2060SYSCTL_STRING(_kern, KERN_OSTYPE, ostype,
2061 CTLFLAG_RD | CTLFLAG_KERN,
2062 ostype, 0, "");
2063SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease,
2064 CTLFLAG_RD | CTLFLAG_KERN,
2065 osrelease, 0, "");
2066SYSCTL_INT(_kern, KERN_OSREV, osrevision,
2067 CTLFLAG_RD | CTLFLAG_KERN,
b0d623f7 2068 (int *)NULL, BSD, "");
2d21ac55
A
2069SYSCTL_STRING(_kern, KERN_VERSION, version,
2070 CTLFLAG_RD | CTLFLAG_KERN,
2071 version, 0, "");
2072
b0d623f7
A
2073#if DEBUG
2074int debug_kprint_syscall = 0;
2075char debug_kprint_syscall_process[MAXCOMLEN+1];
2076
2077SYSCTL_INT (_debug, OID_AUTO, kprint_syscall,
2078 CTLFLAG_RW, &debug_kprint_syscall, 0, "kprintf syscall tracing");
2079SYSCTL_STRING(_debug, OID_AUTO, kprint_syscall_process,
2080 CTLFLAG_RW, debug_kprint_syscall_process, sizeof(debug_kprint_syscall_process),
2081 "name of process for kprintf syscall tracing");
2082
2083int debug_kprint_current_process(const char **namep)
2084{
2085 struct proc *p = current_proc();
2086
2087 if (p == NULL) {
2088 return 0;
2089 }
2090
2091 if (debug_kprint_syscall_process[0]) {
2092 /* user asked to scope tracing to a particular process name */
2093 if(0 == strncmp(debug_kprint_syscall_process,
2094 p->p_comm, sizeof(debug_kprint_syscall_process))) {
2095 /* no value in telling the user that we traced what they asked */
2096 if(namep) *namep = NULL;
2097
2098 return 1;
2099 } else {
2100 return 0;
2101 }
2102 }
2103
2104 /* trace all processes. Tell user what we traced */
2105 if (namep) {
2106 *namep = p->p_comm;
2107 }
2108
2109 return 1;
2110}
2111#endif
2112
2d21ac55
A
2113/* PR-5293665: need to use a callback function for kern.osversion to set
2114 * osversion in IORegistry */
55e303ae 2115
55e303ae 2116static int
2d21ac55 2117sysctl_osversion(__unused struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req)
55e303ae 2118{
2d21ac55 2119 int rval = 0;
55e303ae 2120
2d21ac55
A
2121 rval = sysctl_handle_string(oidp, arg1, arg2, req);
2122
2123 if (req->newptr) {
2124 IORegistrySetOSBuildVersion((char *)arg1);
2125 }
2126
2127 return rval;
2128}
2129
2130SYSCTL_PROC(_kern, KERN_OSVERSION, osversion,
2131 CTLFLAG_RW | CTLFLAG_KERN | CTLTYPE_STRING,
2132 osversion, 256 /* OSVERSIZE*/,
2133 sysctl_osversion, "A", "");
2134
2135static int
2136sysctl_sysctl_bootargs
2137(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2138{
2139 int error;
2140 char buf[256];
2141
2142 strlcpy(buf, PE_boot_args(), 256);
2143 error = sysctl_io_string(req, buf, 256, 0, NULL);
2144 return(error);
2145}
2146
2147SYSCTL_PROC(_kern, OID_AUTO, bootargs,
2148 CTLFLAG_LOCKED | CTLFLAG_RD | CTLFLAG_KERN | CTLTYPE_STRING,
2149 NULL, 0,
2150 sysctl_sysctl_bootargs, "A", "bootargs");
2151
2152SYSCTL_INT(_kern, KERN_MAXFILES, maxfiles,
2153 CTLFLAG_RW | CTLFLAG_KERN,
2154 &maxfiles, 0, "");
2155SYSCTL_INT(_kern, KERN_ARGMAX, argmax,
2156 CTLFLAG_RD | CTLFLAG_KERN,
b0d623f7 2157 (int *)NULL, ARG_MAX, "");
2d21ac55
A
2158SYSCTL_INT(_kern, KERN_POSIX1, posix1version,
2159 CTLFLAG_RD | CTLFLAG_KERN,
b0d623f7 2160 (int *)NULL, _POSIX_VERSION, "");
2d21ac55
A
2161SYSCTL_INT(_kern, KERN_NGROUPS, ngroups,
2162 CTLFLAG_RD | CTLFLAG_KERN,
b0d623f7 2163 (int *)NULL, NGROUPS_MAX, "");
2d21ac55
A
2164SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control,
2165 CTLFLAG_RD | CTLFLAG_KERN,
b0d623f7 2166 (int *)NULL, 1, "");
2d21ac55
A
2167#if 1 /* _POSIX_SAVED_IDS from <unistd.h> */
2168SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids,
2169 CTLFLAG_RD | CTLFLAG_KERN,
b0d623f7 2170 (int *)NULL, 1, "");
2d21ac55
A
2171#else
2172SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids,
2173 CTLFLAG_RD | CTLFLAG_KERN,
2174 NULL, 0, "");
2175#endif
b0d623f7
A
2176SYSCTL_INT(_kern, OID_AUTO, num_files,
2177 CTLFLAG_RD,
2178 &nfiles, 0, "");
2179SYSCTL_COMPAT_INT(_kern, OID_AUTO, num_vnodes,
2180 CTLFLAG_RD,
2181 &numvnodes, 0, "");
2182SYSCTL_INT(_kern, OID_AUTO, num_tasks,
2183 CTLFLAG_RD,
2184 &task_max, 0, "");
2185SYSCTL_INT(_kern, OID_AUTO, num_threads,
2186 CTLFLAG_RD,
2187 &thread_max, 0, "");
2188SYSCTL_INT(_kern, OID_AUTO, num_taskthreads,
2189 CTLFLAG_RD,
2190 &task_threadmax, 0, "");
2d21ac55
A
2191
2192static int
2193sysctl_maxvnodes (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2194{
b0d623f7 2195 int oldval = desiredvnodes;
2d21ac55 2196 int error = sysctl_io_number(req, desiredvnodes, sizeof(int), &desiredvnodes, NULL);
b0d623f7
A
2197
2198 if (oldval != desiredvnodes) {
2199 reset_vmobjectcache(oldval, desiredvnodes);
2200 resize_namecache(desiredvnodes);
2201 }
2202
2d21ac55
A
2203 return(error);
2204}
2205
2206SYSCTL_PROC(_kern, KERN_MAXVNODES, maxvnodes,
2207 CTLTYPE_INT | CTLFLAG_RW,
2208 0, 0, sysctl_maxvnodes, "I", "");
2209
2210SYSCTL_PROC(_kern, KERN_MAXPROC, maxproc,
2211 CTLTYPE_INT | CTLFLAG_RW,
2212 0, 0, sysctl_maxproc, "I", "");
2213
2214SYSCTL_PROC(_kern, KERN_AIOMAX, aiomax,
2215 CTLTYPE_INT | CTLFLAG_RW,
2216 0, 0, sysctl_aiomax, "I", "");
2217
2218SYSCTL_PROC(_kern, KERN_AIOPROCMAX, aioprocmax,
2219 CTLTYPE_INT | CTLFLAG_RW,
2220 0, 0, sysctl_aioprocmax, "I", "");
2221
2222SYSCTL_PROC(_kern, KERN_AIOTHREADS, aiothreads,
2223 CTLTYPE_INT | CTLFLAG_RW,
2224 0, 0, sysctl_aiothreads, "I", "");
2225
2226static int
2227sysctl_securelvl
2228(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2229{
2230 int new_value, changed;
2231 int error = sysctl_io_number(req, securelevel, sizeof(int), &new_value, &changed);
2232 if (changed) {
2233 if (!(new_value < securelevel && req->p->p_pid != 1)) {
2234 proc_list_lock();
2235 securelevel = new_value;
2236 proc_list_unlock();
2237 } else {
2238 error = EPERM;
e5568f75 2239 }
2d21ac55
A
2240 }
2241 return(error);
2242}
2243
2244SYSCTL_PROC(_kern, KERN_SECURELVL, securelevel,
2245 CTLTYPE_INT | CTLFLAG_RW,
2246 0, 0, sysctl_securelvl, "I", "");
2247
2248
2249static int
2250sysctl_domainname
2251(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2252{
2253 int error, changed;
2254 error = sysctl_io_string(req, domainname, sizeof(domainname), 0, &changed);
2255 if (changed) {
2256 domainnamelen = strlen(domainname);
2257 }
2258 return(error);
2259}
2260
2261SYSCTL_PROC(_kern, KERN_DOMAINNAME, nisdomainname,
2262 CTLTYPE_STRING | CTLFLAG_RW,
2263 0, 0, sysctl_domainname, "A", "");
2264
b0d623f7 2265SYSCTL_COMPAT_INT(_kern, KERN_HOSTID, hostid,
2d21ac55
A
2266 CTLFLAG_RW | CTLFLAG_KERN,
2267 &hostid, 0, "");
2268
2269static int
2270sysctl_hostname
2271(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2272{
2273 int error, changed;
2274 error = sysctl_io_string(req, hostname, sizeof(hostname), 1, &changed);
2275 if (changed) {
2276 hostnamelen = req->newlen;
2277 }
2278 return(error);
2279}
2280
2281
2282SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname,
2283 CTLTYPE_STRING | CTLFLAG_RW,
2284 0, 0, sysctl_hostname, "A", "");
2285
2286static int
2287sysctl_procname
2288(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2289{
2290 /* Original code allowed writing, I'm copying this, although this all makes
2291 no sense to me. Besides, this sysctl is never used. */
2292 return sysctl_io_string(req, &req->p->p_name[0], (2*MAXCOMLEN+1), 1, NULL);
2293}
2294
2295SYSCTL_PROC(_kern, KERN_PROCNAME, procname,
2296 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_ANYBODY,
2297 0, 0, sysctl_procname, "A", "");
2298
2299SYSCTL_INT(_kern, KERN_SPECULATIVE_READS, speculative_reads_disabled,
2300 CTLFLAG_RW | CTLFLAG_KERN,
2301 &speculative_reads_disabled, 0, "");
2302
b0d623f7
A
2303SYSCTL_UINT(_kern, OID_AUTO, preheat_pages_max,
2304 CTLFLAG_RW | CTLFLAG_KERN,
2305 &preheat_pages_max, 0, "");
2306
2307SYSCTL_UINT(_kern, OID_AUTO, preheat_pages_min,
2308 CTLFLAG_RW | CTLFLAG_KERN,
2309 &preheat_pages_min, 0, "");
2310
2311SYSCTL_UINT(_kern, OID_AUTO, preheat_pages_mult,
2312 CTLFLAG_RW | CTLFLAG_KERN,
2313 &preheat_pages_mult, 0, "");
2314
2d21ac55
A
2315static int
2316sysctl_boottime
2317(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2318{
b0d623f7
A
2319 time_t tv_sec = boottime_sec();
2320 struct proc *p = req->p;
2d21ac55 2321
b0d623f7
A
2322 if (proc_is64bit(p)) {
2323 struct user64_timeval t;
2324 t.tv_sec = tv_sec;
2325 t.tv_usec = 0;
2326 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
2327 } else {
2328 struct user32_timeval t;
2329 t.tv_sec = tv_sec;
2330 t.tv_usec = 0;
2331 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
2332 }
2d21ac55
A
2333}
2334
2335SYSCTL_PROC(_kern, KERN_BOOTTIME, boottime,
2336 CTLTYPE_STRUCT | CTLFLAG_RD,
2337 0, 0, sysctl_boottime, "S,timeval", "");
2338
2339static int
2340sysctl_symfile
2341(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2342{
2343 char *str;
2344 int error = get_kernel_symfile(req->p, &str);
2345 if (error)
2346 return (error);
2347 return sysctl_io_string(req, str, 0, 0, NULL);
2348}
2349
2350
2351SYSCTL_PROC(_kern, KERN_SYMFILE, symfile,
2352 CTLTYPE_STRING | CTLFLAG_RD,
2353 0, 0, sysctl_symfile, "A", "");
2354
2355#if NFSCLIENT
2356static int
2357sysctl_netboot
2358(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2359{
2360 return sysctl_io_number(req, netboot_root(), sizeof(int), NULL, NULL);
2361}
2362
2363SYSCTL_PROC(_kern, KERN_NETBOOT, netboot,
2364 CTLTYPE_INT | CTLFLAG_RD,
2365 0, 0, sysctl_netboot, "I", "");
2366#endif
2367
2368static int
2369sysctl_usrstack
2370(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2371{
2372 return sysctl_io_number(req, (int)req->p->user_stack, sizeof(int), NULL, NULL);
2373}
2374
b0d623f7 2375SYSCTL_PROC(_kern, KERN_USRSTACK32, usrstack,
2d21ac55
A
2376 CTLTYPE_INT | CTLFLAG_RD,
2377 0, 0, sysctl_usrstack, "I", "");
2378
2379static int
2380sysctl_usrstack64
2381(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2382{
2383 return sysctl_io_number(req, req->p->user_stack, sizeof(req->p->user_stack), NULL, NULL);
2384}
2385
2386SYSCTL_PROC(_kern, KERN_USRSTACK64, usrstack64,
2387 CTLTYPE_QUAD | CTLFLAG_RD,
2388 0, 0, sysctl_usrstack64, "Q", "");
2389
2390SYSCTL_STRING(_kern, KERN_COREFILE, corefile,
2391 CTLFLAG_RW | CTLFLAG_KERN,
2392 corefilename, sizeof(corefilename), "");
2393
2394static int
2395sysctl_coredump
2396(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2397{
593a1d5f
A
2398#ifdef SECURE_KERNEL
2399 return (ENOTSUP);
2400#endif
2d21ac55
A
2401 int new_value, changed;
2402 int error = sysctl_io_number(req, do_coredump, sizeof(int), &new_value, &changed);
2403 if (changed) {
2404 if ((new_value == 0) || (new_value == 1))
2405 do_coredump = new_value;
2406 else
2407 error = EINVAL;
2408 }
2409 return(error);
2410}
2411
2412SYSCTL_PROC(_kern, KERN_COREDUMP, coredump,
2413 CTLTYPE_INT | CTLFLAG_RW,
2414 0, 0, sysctl_coredump, "I", "");
2415
2416static int
2417sysctl_suid_coredump
2418(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2419{
593a1d5f
A
2420#ifdef SECURE_KERNEL
2421 return (ENOTSUP);
2422#endif
2d21ac55
A
2423 int new_value, changed;
2424 int error = sysctl_io_number(req, sugid_coredump, sizeof(int), &new_value, &changed);
2425 if (changed) {
2426 if ((new_value == 0) || (new_value == 1))
2427 sugid_coredump = new_value;
55e303ae
A
2428 else
2429 error = EINVAL;
2430 }
2d21ac55
A
2431 return(error);
2432}
2433
2434SYSCTL_PROC(_kern, KERN_SUGID_COREDUMP, sugid_coredump,
2435 CTLTYPE_INT | CTLFLAG_RW,
2436 0, 0, sysctl_suid_coredump, "I", "");
2437
2438static int
2439sysctl_delayterm
2440(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2441{
2442 struct proc *p = req->p;
2443 int new_value, changed;
2444 int error = sysctl_io_number(req, (req->p->p_lflag & P_LDELAYTERM)? 1: 0, sizeof(int), &new_value, &changed);
2445 if (changed) {
2446 proc_lock(p);
2447 if (new_value)
2448 req->p->p_lflag |= P_LDELAYTERM;
2449 else
2450 req->p->p_lflag &= ~P_LDELAYTERM;
2451 proc_unlock(p);
2452 }
2453 return(error);
2454}
2455
2456SYSCTL_PROC(_kern, KERN_PROCDELAYTERM, delayterm,
2457 CTLTYPE_INT | CTLFLAG_RW,
2458 0, 0, sysctl_delayterm, "I", "");
2459
55e303ae 2460
55e303ae 2461static int
2d21ac55
A
2462sysctl_rage_vnode
2463(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
55e303ae 2464{
2d21ac55
A
2465 struct proc *p = req->p;
2466 struct uthread *ut;
2467 int new_value, old_value, changed;
2468 int error;
55e303ae 2469
2d21ac55
A
2470 ut = get_bsdthread_info(current_thread());
2471
2472 if (ut->uu_flag & UT_RAGE_VNODES)
2473 old_value = KERN_RAGE_THREAD;
2474 else if (p->p_lflag & P_LRAGE_VNODES)
2475 old_value = KERN_RAGE_PROC;
2476 else
2477 old_value = 0;
2478
2479 error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
2480
2481 if (error == 0) {
2482 switch (new_value) {
2483 case KERN_RAGE_PROC:
2484 proc_lock(p);
2485 p->p_lflag |= P_LRAGE_VNODES;
2486 proc_unlock(p);
2487 break;
2488 case KERN_UNRAGE_PROC:
2489 proc_lock(p);
2490 p->p_lflag &= ~P_LRAGE_VNODES;
2491 proc_unlock(p);
2492 break;
2493
2494 case KERN_RAGE_THREAD:
2495 ut->uu_flag |= UT_RAGE_VNODES;
2496 break;
2497 case KERN_UNRAGE_THREAD:
2498 ut = get_bsdthread_info(current_thread());
2499 ut->uu_flag &= ~UT_RAGE_VNODES;
2500 break;
e5568f75 2501 }
2d21ac55
A
2502 }
2503 return(error);
2504}
2505
2506SYSCTL_PROC(_kern, KERN_RAGEVNODE, rage_vnode,
b0d623f7 2507 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
2d21ac55
A
2508 0, 0, sysctl_rage_vnode, "I", "");
2509
2510
2511static int
2512sysctl_kern_check_openevt
2513(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2514{
2515 struct proc *p = req->p;
2516 int new_value, old_value, changed;
2517 int error;
2518
2519 if (p->p_flag & P_CHECKOPENEVT) {
2520 old_value = KERN_OPENEVT_PROC;
2521 } else {
2522 old_value = 0;
2523 }
2524
2525 error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
2526
2527 if (error == 0) {
2528 switch (new_value) {
2529 case KERN_OPENEVT_PROC:
b0d623f7 2530 OSBitOrAtomic(P_CHECKOPENEVT, &p->p_flag);
2d21ac55
A
2531 break;
2532
2533 case KERN_UNOPENEVT_PROC:
b0d623f7 2534 OSBitAndAtomic(~((uint32_t)P_CHECKOPENEVT), &p->p_flag);
2d21ac55
A
2535 break;
2536
2537 default:
55e303ae 2538 error = EINVAL;
2d21ac55 2539 }
55e303ae 2540 }
2d21ac55
A
2541 return(error);
2542}
2543
2544SYSCTL_PROC(_kern, KERN_CHECKOPENEVT, check_openevt, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
2545 0, 0, sysctl_kern_check_openevt, "I", "set the per-process check-open-evt flag");
2546
2547
2548
2549static int
2550sysctl_nx
2551(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2552{
4a3eedf9
A
2553#ifdef SECURE_KERNEL
2554 return ENOTSUP;
2555#endif
2d21ac55
A
2556 int new_value, changed;
2557 int error;
2558
2559 error = sysctl_io_number(req, nx_enabled, sizeof(nx_enabled), &new_value, &changed);
4a3eedf9
A
2560 if (error)
2561 return error;
2d21ac55 2562
4a3eedf9 2563 if (changed) {
b0d623f7 2564#if defined(__i386__) || defined(__x86_64__)
2d21ac55
A
2565 /*
2566 * Only allow setting if NX is supported on the chip
2567 */
2568 if (!(cpuid_extfeatures() & CPUID_EXTFEATURE_XD))
4a3eedf9 2569 return ENOTSUP;
2d21ac55 2570#endif
4a3eedf9
A
2571 nx_enabled = new_value;
2572 }
2d21ac55
A
2573 return(error);
2574}
2575
2576
2577
2578SYSCTL_PROC(_kern, KERN_NX_PROTECTION, nx,
2579 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN,
2580 0, 0, sysctl_nx, "I", "");
2581
2582static int
2583sysctl_loadavg
2584(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2585{
2586 if (proc_is64bit(req->p)) {
b0d623f7
A
2587 struct user64_loadavg loadinfo64;
2588 fill_loadavg64(&averunnable, &loadinfo64);
2d21ac55
A
2589 return sysctl_io_opaque(req, &loadinfo64, sizeof(loadinfo64), NULL);
2590 } else {
b0d623f7
A
2591 struct user32_loadavg loadinfo32;
2592 fill_loadavg32(&averunnable, &loadinfo32);
2593 return sysctl_io_opaque(req, &loadinfo32, sizeof(loadinfo32), NULL);
2d21ac55
A
2594 }
2595}
2596
2597SYSCTL_PROC(_vm, VM_LOADAVG, loadavg,
2598 CTLTYPE_STRUCT | CTLFLAG_RD,
2599 0, 0, sysctl_loadavg, "S,loadavg", "");
2600
2601static int
2602sysctl_swapusage
2603(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2604{
2605 int error;
2606 uint64_t swap_total;
2607 uint64_t swap_avail;
b0d623f7 2608 vm_size_t swap_pagesize;
2d21ac55
A
2609 boolean_t swap_encrypted;
2610 struct xsw_usage xsu;
2611
2612 error = macx_swapinfo(&swap_total,
2613 &swap_avail,
2614 &swap_pagesize,
2615 &swap_encrypted);
2616 if (error)
2617 return error;
2618
2619 xsu.xsu_total = swap_total;
2620 xsu.xsu_avail = swap_avail;
2621 xsu.xsu_used = swap_total - swap_avail;
2622 xsu.xsu_pagesize = swap_pagesize;
2623 xsu.xsu_encrypted = swap_encrypted;
2624 return sysctl_io_opaque(req, &xsu, sizeof(xsu), NULL);
2625}
2626
2627
2628
2629SYSCTL_PROC(_vm, VM_SWAPUSAGE, swapusage,
2630 CTLTYPE_STRUCT | CTLFLAG_RD,
2631 0, 0, sysctl_swapusage, "S,xsw_usage", "");
2632
2633
2634/* this kernel does NOT implement shared_region_make_private_np() */
2635SYSCTL_INT(_kern, KERN_SHREG_PRIVATIZABLE, shreg_private,
2636 CTLFLAG_RD,
b0d623f7 2637 (int *)NULL, 0, "");
0c530ab8 2638
b0d623f7 2639#if defined(__i386__) || defined(__x86_64__)
0c530ab8 2640static int
2d21ac55
A
2641sysctl_sysctl_exec_affinity(__unused struct sysctl_oid *oidp,
2642 __unused void *arg1, __unused int arg2,
2643 struct sysctl_req *req)
0c530ab8 2644{
2d21ac55 2645 proc_t cur_proc = req->p;
0c530ab8
A
2646 int error;
2647
2648 if (req->oldptr != USER_ADDR_NULL) {
2649 cpu_type_t oldcputype = (cur_proc->p_flag & P_AFFINITY) ? CPU_TYPE_POWERPC : CPU_TYPE_I386;
2650 if ((error = SYSCTL_OUT(req, &oldcputype, sizeof(oldcputype))))
2651 return error;
2652 }
2653
2654 if (req->newptr != USER_ADDR_NULL) {
2655 cpu_type_t newcputype;
2656 if ((error = SYSCTL_IN(req, &newcputype, sizeof(newcputype))))
2657 return error;
2658 if (newcputype == CPU_TYPE_I386)
b0d623f7 2659 OSBitAndAtomic(~((uint32_t)P_AFFINITY), &cur_proc->p_flag);
0c530ab8 2660 else if (newcputype == CPU_TYPE_POWERPC)
b0d623f7 2661 OSBitOrAtomic(P_AFFINITY, &cur_proc->p_flag);
0c530ab8
A
2662 else
2663 return (EINVAL);
2664 }
2665
2666 return 0;
2667}
2668SYSCTL_PROC(_sysctl, OID_AUTO, proc_exec_affinity, CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, 0, 0, sysctl_sysctl_exec_affinity ,"I","proc_exec_affinity");
2669#endif
2670
2671static int
2672fetch_process_cputype(
2d21ac55 2673 proc_t cur_proc,
0c530ab8
A
2674 int *name,
2675 u_int namelen,
2676 cpu_type_t *cputype)
2677{
2d21ac55
A
2678 proc_t p = PROC_NULL;
2679 int refheld = 0;
0c530ab8 2680 cpu_type_t ret = 0;
2d21ac55 2681 int error = 0;
0c530ab8
A
2682
2683 if (namelen == 0)
2684 p = cur_proc;
2685 else if (namelen == 1) {
2d21ac55 2686 p = proc_find(name[0]);
0c530ab8
A
2687 if (p == NULL)
2688 return (EINVAL);
2d21ac55 2689 refheld = 1;
0c530ab8 2690 } else {
2d21ac55
A
2691 error = EINVAL;
2692 goto out;
0c530ab8
A
2693 }
2694
b0d623f7 2695#if defined(__i386__) || defined(__x86_64__)
0c530ab8
A
2696 if (p->p_flag & P_TRANSLATED) {
2697 ret = CPU_TYPE_POWERPC;
2698 }
2699 else
2700#endif
2701 {
2702 ret = cpu_type();
2703 if (IS_64BIT_PROCESS(p))
2704 ret |= CPU_ARCH_ABI64;
2705 }
2706 *cputype = ret;
2707
2d21ac55
A
2708 if (refheld != 0)
2709 proc_rele(p);
2710out:
2711 return (error);
0c530ab8
A
2712}
2713
2714static int
2d21ac55
A
2715sysctl_sysctl_native(__unused struct sysctl_oid *oidp, void *arg1, int arg2,
2716 struct sysctl_req *req)
0c530ab8
A
2717{
2718 int error;
2719 cpu_type_t proc_cputype = 0;
2720 if ((error = fetch_process_cputype(req->p, (int *)arg1, arg2, &proc_cputype)) != 0)
2721 return error;
2722 int res = 1;
2723 if ((proc_cputype & ~CPU_ARCH_MASK) != (cpu_type() & ~CPU_ARCH_MASK))
2724 res = 0;
2725 return SYSCTL_OUT(req, &res, sizeof(res));
2726}
2727SYSCTL_PROC(_sysctl, OID_AUTO, proc_native, CTLTYPE_NODE|CTLFLAG_RD, 0, 0, sysctl_sysctl_native ,"I","proc_native");
2728
2729static int
2d21ac55
A
2730sysctl_sysctl_cputype(__unused struct sysctl_oid *oidp, void *arg1, int arg2,
2731 struct sysctl_req *req)
0c530ab8
A
2732{
2733 int error;
2734 cpu_type_t proc_cputype = 0;
2735 if ((error = fetch_process_cputype(req->p, (int *)arg1, arg2, &proc_cputype)) != 0)
2736 return error;
2737 return SYSCTL_OUT(req, &proc_cputype, sizeof(proc_cputype));
2738}
2739SYSCTL_PROC(_sysctl, OID_AUTO, proc_cputype, CTLTYPE_NODE|CTLFLAG_RD, 0, 0, sysctl_sysctl_cputype ,"I","proc_cputype");
2740
2d21ac55
A
2741static int
2742sysctl_safeboot
2743(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2744{
2745 return sysctl_io_number(req, boothowto & RB_SAFEBOOT ? 1 : 0, sizeof(int), NULL, NULL);
2746}
2747
2748SYSCTL_PROC(_kern, KERN_SAFEBOOT, safeboot,
2749 CTLTYPE_INT | CTLFLAG_RD,
2750 0, 0, sysctl_safeboot, "I", "");
2751
2752static int
2753sysctl_singleuser
2754(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2755{
2756 return sysctl_io_number(req, boothowto & RB_SINGLE ? 1 : 0, sizeof(int), NULL, NULL);
2757}
2758
2759SYSCTL_PROC(_kern, OID_AUTO, singleuser,
2760 CTLTYPE_INT | CTLFLAG_RD,
2761 0, 0, sysctl_singleuser, "I", "");
2762
2763/*
2764 * Controls for debugging affinity sets - see osfmk/kern/affinity.c
2765 */
2766extern boolean_t affinity_sets_enabled;
2767extern int affinity_sets_mapping;
2768
2769SYSCTL_INT (_kern, OID_AUTO, affinity_sets_enabled,
2770 CTLFLAG_RW, (int *) &affinity_sets_enabled, 0, "hinting enabled");
2771SYSCTL_INT (_kern, OID_AUTO, affinity_sets_mapping,
2772 CTLFLAG_RW, &affinity_sets_mapping, 0, "mapping policy");
2773
2774/*
2775 * Limit on total memory users can wire.
2776 *
2777 * vm_global_user_wire_limit - system wide limit on wired memory from all processes combined.
2778 *
2779 * vm_user_wire_limit - per address space limit on wired memory. This puts a cap on the process's rlimit value.
2780 *
2781 * These values are initialized to reasonable defaults at boot time based on the available physical memory in
2782 * kmem_init().
2783 *
2784 * All values are in bytes.
2785 */
2786
b0d623f7 2787vm_map_size_t vm_global_no_user_wire_amount;
2d21ac55
A
2788vm_map_size_t vm_global_user_wire_limit;
2789vm_map_size_t vm_user_wire_limit;
2790
b0d623f7
A
2791/*
2792 * There needs to be a more automatic/elegant way to do this
2793 */
2794
2795SYSCTL_QUAD(_vm, OID_AUTO, global_no_user_wire_amount, CTLFLAG_RW, &vm_global_no_user_wire_amount, "");
2d21ac55
A
2796SYSCTL_QUAD(_vm, OID_AUTO, global_user_wire_limit, CTLFLAG_RW, &vm_global_user_wire_limit, "");
2797SYSCTL_QUAD(_vm, OID_AUTO, user_wire_limit, CTLFLAG_RW, &vm_user_wire_limit, "");
b0d623f7
A
2798
2799
2800
2801/*
2802 * enable back trace events for thread blocks
2803 */
2804
2805extern uint32_t kdebug_thread_block;
2806
2807SYSCTL_INT (_kern, OID_AUTO, kdebug_thread_block,
2808 CTLFLAG_RW, &kdebug_thread_block, 0, "kdebug thread_block");
2809
2810/*
2811 * Kernel stack size and depth
2812 */
2813SYSCTL_INT (_kern, OID_AUTO, stack_size,
2814 CTLFLAG_RD, (int *) &kernel_stack_size, 0, "Kernel stack size");
2815SYSCTL_INT (_kern, OID_AUTO, stack_depth_max,
2816 CTLFLAG_RD, (int *) &kernel_stack_depth_max, 0, "Max kernel stack depth at interrupt or context switch");
2817