]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_sysctl.c
xnu-2422.110.17.tar.gz
[apple/xnu.git] / bsd / kern / kern_sysctl.c
CommitLineData
1c79356b 1/*
316670eb 2 * Copyright (c) 2000-2011 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 109#include <mach/machine.h>
6d2010ae 110#include <mach/mach_host.h>
1c79356b
A
111#include <mach/mach_types.h>
112#include <mach/vm_param.h>
b0d623f7 113#include <kern/mach_param.h>
1c79356b 114#include <kern/task.h>
316670eb 115#include <kern/thread.h>
91447636 116#include <kern/lock.h>
6d2010ae 117#include <kern/processor.h>
b0d623f7 118#include <kern/debug.h>
1c79356b 119#include <vm/vm_kern.h>
91447636 120#include <vm/vm_map.h>
1c79356b
A
121#include <mach/host_info.h>
122
91447636 123#include <sys/mount_internal.h>
1c79356b 124#include <sys/kdebug.h>
91447636 125#include <sys/sysproto.h>
1c79356b
A
126
127#include <IOKit/IOPlatformExpert.h>
128#include <pexpert/pexpert.h>
129
55e303ae 130#include <machine/machine_routines.h>
0c530ab8 131#include <machine/exec.h>
1c79356b 132
91447636 133#include <vm/vm_protos.h>
39236c6e 134#include <vm/vm_pageout.h>
6d2010ae 135#include <sys/imgsrc.h>
91447636 136
b0d623f7 137#if defined(__i386__) || defined(__x86_64__)
0c530ab8
A
138#include <i386/cpuid.h>
139#endif
140
316670eb
A
141#if CONFIG_FREEZE
142#include <sys/kern_memorystatus.h>
143#endif
144
39236c6e
A
145#if KPERF
146#include <kperf/kperf.h>
147#endif
148
316670eb
A
149/*
150 * deliberately setting max requests to really high number
151 * so that runaway settings do not cause MALLOC overflows
152 */
153#define AIO_MAX_REQUESTS (128 * CONFIG_AIO_MAX)
154
1c79356b
A
155extern sysctlfn net_sysctl;
156extern sysctlfn cpu_sysctl;
55e303ae
A
157extern int aio_max_requests;
158extern int aio_max_requests_per_process;
159extern int aio_worker_threads;
91447636
A
160extern int lowpri_IO_window_msecs;
161extern int lowpri_IO_delay_msecs;
0c530ab8 162extern int nx_enabled;
2d21ac55 163extern int speculative_reads_disabled;
6d2010ae
A
164extern int ignore_is_ssd;
165extern unsigned int speculative_prefetch_max;
316670eb 166extern unsigned int speculative_prefetch_max_iosize;
b0d623f7
A
167extern unsigned int preheat_pages_max;
168extern unsigned int preheat_pages_min;
b0d623f7 169extern long numvnodes;
1c79356b 170
39236c6e
A
171extern uuid_string_t bootsessionuuid_string;
172
6d2010ae
A
173extern unsigned int vm_max_delayed_work_limit;
174extern unsigned int vm_max_batch;
175
176extern unsigned int vm_page_free_min;
177extern unsigned int vm_page_free_target;
178extern unsigned int vm_page_free_reserved;
179extern unsigned int vm_page_speculative_percentage;
180extern unsigned int vm_page_speculative_q_age_ms;
181
182/*
183 * Conditionally allow dtrace to see these functions for debugging purposes.
184 */
185#ifdef STATIC
186#undef STATIC
187#endif
188#if 0
189#define STATIC
190#else
191#define STATIC static
192#endif
193
194extern boolean_t mach_timer_coalescing_enabled;
195
39236c6e
A
196extern uint64_t timer_deadline_tracking_bin_1, timer_deadline_tracking_bin_2;
197
6d2010ae 198STATIC void
316670eb
A
199fill_user32_eproc(proc_t, struct user32_eproc *__restrict);
200STATIC void
201fill_user32_externproc(proc_t, struct user32_extern_proc *__restrict);
6d2010ae 202STATIC void
316670eb 203fill_user64_eproc(proc_t, struct user64_eproc *__restrict);
6d2010ae 204STATIC void
316670eb 205fill_user64_proc(proc_t, struct user64_kinfo_proc *__restrict);
6d2010ae 206STATIC void
316670eb 207fill_user64_externproc(proc_t, struct user64_extern_proc *__restrict);
6d2010ae 208STATIC void
316670eb
A
209fill_user32_proc(proc_t, struct user32_kinfo_proc *__restrict);
210
91447636
A
211extern int
212kdbg_control(int *name, u_int namelen, user_addr_t where, size_t * sizep);
91447636
A
213#if NFSCLIENT
214extern int
215netboot_root(void);
216#endif
217int
218pcsamples_ops(int *name, u_int namelen, user_addr_t where, size_t *sizep,
2d21ac55 219 proc_t p);
91447636
A
220__private_extern__ kern_return_t
221reset_vmobjectcache(unsigned int val1, unsigned int val2);
91447636
A
222int
223sysctl_procargs(int *name, u_int namelen, user_addr_t where,
2d21ac55 224 size_t *sizep, proc_t cur_proc);
6d2010ae 225STATIC int
91447636 226sysctl_procargsx(int *name, u_int namelen, user_addr_t where, size_t *sizep,
2d21ac55 227 proc_t cur_proc, int argc_yes);
91447636
A
228int
229sysctl_struct(user_addr_t oldp, size_t *oldlenp, user_addr_t newp,
230 size_t newlen, void *sp, int len);
1c79356b 231
6d2010ae
A
232STATIC int sysdoproc_filt_KERN_PROC_PID(proc_t p, void * arg);
233STATIC int sysdoproc_filt_KERN_PROC_PGRP(proc_t p, void * arg);
234STATIC int sysdoproc_filt_KERN_PROC_TTY(proc_t p, void * arg);
235STATIC int sysdoproc_filt_KERN_PROC_UID(proc_t p, void * arg);
236STATIC int sysdoproc_filt_KERN_PROC_RUID(proc_t p, void * arg);
b0d623f7 237#if CONFIG_LCTX
6d2010ae 238STATIC int sysdoproc_filt_KERN_PROC_LCID(proc_t p, void * arg);
b0d623f7 239#endif
2d21ac55 240int sysdoproc_callback(proc_t p, void *arg);
1c79356b 241
6d2010ae
A
242
243/* forward declarations for non-static STATIC */
244STATIC void fill_loadavg64(struct loadavg *la, struct user64_loadavg *la64);
245STATIC void fill_loadavg32(struct loadavg *la, struct user32_loadavg *la32);
6d2010ae
A
246STATIC int sysctl_handle_kern_threadname(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
247STATIC int sysctl_sched_stats(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
248STATIC int sysctl_sched_stats_enable(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
6d2010ae
A
249STATIC int sysctl_kdebug_ops SYSCTL_HANDLER_ARGS;
250STATIC int sysctl_dotranslate SYSCTL_HANDLER_ARGS;
251STATIC int sysctl_doaffinity SYSCTL_HANDLER_ARGS;
252#if COUNT_SYSCALLS
253STATIC int sysctl_docountsyscalls SYSCTL_HANDLER_ARGS;
254#endif /* COUNT_SYSCALLS */
6d2010ae 255STATIC int sysctl_doprocargs SYSCTL_HANDLER_ARGS;
6d2010ae
A
256STATIC int sysctl_doprocargs2 SYSCTL_HANDLER_ARGS;
257STATIC int sysctl_prochandle SYSCTL_HANDLER_ARGS;
258#if DEBUG
259STATIC int sysctl_dodebug SYSCTL_HANDLER_ARGS;
260#endif
261STATIC int sysctl_aiomax(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
262STATIC int sysctl_aioprocmax(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
263STATIC int sysctl_aiothreads(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
264STATIC int sysctl_maxproc(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
265STATIC int sysctl_osversion(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
266STATIC int sysctl_sysctl_bootargs(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
267STATIC int sysctl_maxvnodes(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
268STATIC int sysctl_securelvl(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
269STATIC int sysctl_domainname(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
270STATIC int sysctl_hostname(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
271STATIC int sysctl_procname(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
272STATIC int sysctl_boottime(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
273STATIC int sysctl_symfile(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
274#if NFSCLIENT
275STATIC int sysctl_netboot(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
276#endif
277#ifdef CONFIG_IMGSRC_ACCESS
278STATIC int sysctl_imgsrcdev(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
279#endif
280STATIC int sysctl_usrstack(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
281STATIC int sysctl_usrstack64(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
282STATIC int sysctl_coredump(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
283STATIC int sysctl_suid_coredump(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
284STATIC int sysctl_delayterm(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
285STATIC int sysctl_rage_vnode(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
286STATIC int sysctl_kern_check_openevt(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
287STATIC int sysctl_nx(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
288STATIC int sysctl_loadavg(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
289STATIC int sysctl_vm_toggle_address_reuse(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
290STATIC int sysctl_swapusage(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
291#if defined(__i386__) || defined(__x86_64__)
292STATIC int sysctl_sysctl_exec_affinity(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
293#endif
294STATIC int fetch_process_cputype( proc_t cur_proc, int *name, u_int namelen, cpu_type_t *cputype);
295STATIC int sysctl_sysctl_native(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
296STATIC int sysctl_sysctl_cputype(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
297STATIC int sysctl_safeboot(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
298STATIC int sysctl_singleuser(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
316670eb 299STATIC int sysctl_slide(struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req);
6d2010ae 300
2d21ac55
A
301
302extern void IORegistrySetOSBuildVersion(char * build_version);
91447636 303
6d2010ae 304STATIC void
b0d623f7 305fill_loadavg64(struct loadavg *la, struct user64_loadavg *la64)
91447636 306{
b0d623f7
A
307 la64->ldavg[0] = la->ldavg[0];
308 la64->ldavg[1] = la->ldavg[1];
309 la64->ldavg[2] = la->ldavg[2];
310 la64->fscale = (user64_long_t)la->fscale;
311}
312
6d2010ae 313STATIC void
b0d623f7
A
314fill_loadavg32(struct loadavg *la, struct user32_loadavg *la32)
315{
316 la32->ldavg[0] = la->ldavg[0];
317 la32->ldavg[1] = la->ldavg[1];
318 la32->ldavg[2] = la->ldavg[2];
319 la32->fscale = (user32_long_t)la->fscale;
91447636
A
320}
321
6d2010ae
A
322/*
323 * sysctl_mem_hold
324 *
325 * Description: Wire down the callers address map on behalf of sysctl's
326 * that perform their own copy operations while holding
327 * locks e.g. in the paging path, which could lead to a
328 * deadlock, or while holding a spinlock.
329 *
330 * Parameters: addr User buffer address
331 * len User buffer length
332 *
333 * Returns: 0 Success
334 * vslock:ENOMEM Insufficient physical pages to wire
335 * vslock:EACCES Bad protection mode
336 * vslock:EINVAL Invalid parameters
337 *
338 * Notes: This code is invoked for the first OID element where the
339 * CTLFLAG_LOCKED is not specified for a given OID node
340 * element durng OID traversal, and is held for all
341 * subsequent node traversals, and only released after the
342 * leaf node handler invocation is complete.
343 *
344 * Legacy: For legacy scyctl's provided by third party code which
345 * expect funnel protection for calls into their code, this
346 * routine will also take the funnel, which will also only
347 * be released after the leaf node handler is complete.
348 *
349 * This is to support legacy 32 bit BSD KEXTs and legacy 32
350 * bit single threaded filesystem KEXTs and similar code
351 * which relies on funnel protection, e.g. for things like
352 * FSID based sysctl's.
353 *
354 * NEW CODE SHOULD NOT RELY ON THIS BEHAVIOUR! IT WILL BE
355 * REMOVED IN A FUTURE RELASE OF Mac OS X!
356 *
357 * Bugs: This routine does nothing with the new_addr and new_len
358 * at present, but it should, since read from the user space
359 * process adddress space which could potentially trigger
360 * paging may also be occurring deep down. This is due to
361 * a current limitation of the vslock() routine, which will
362 * always request a wired mapping be read/write, due to not
363 * taking an access mode parameter. Note that this could
364 * also cause problems for output on architectures where
365 * write access does not require read acccess if the current
366 * mapping lacks read access.
367 *
368 * XXX: To be moved to kern_newsysctl.c to avoid __private_extern__
369 */
370int sysctl_mem_lock(user_addr_t old_addr, user_size_t old_len, user_addr_t new_addr, user_size_t new_len);
371int
372sysctl_mem_lock(__unused user_addr_t old_addr, __unused user_size_t old_len, __unused user_addr_t new_addr, __unused user_size_t new_len)
373{
374 return 0;
375}
376
1c79356b
A
377/*
378 * Locking and stats
379 */
1c79356b 380
2d21ac55 381/* sysctl() syscall */
1c79356b 382int
6d2010ae 383__sysctl(proc_t p, struct __sysctl_args *uap, __unused int32_t *retval)
2d21ac55 384{
6d2010ae 385 boolean_t funnel_state = FALSE; /* not held if unknown */
2d21ac55 386 int error;
91447636 387 size_t savelen = 0, oldlen = 0, newlen;
1c79356b 388 int name[CTL_MAXNAME];
0b4e3aa0 389 int error1;
2d21ac55 390 boolean_t vslock_taken = FALSE;
6d2010ae 391 boolean_t funnel_taken = FALSE;
2d21ac55
A
392#if CONFIG_MACF
393 kauth_cred_t my_cred;
394#endif
1c79356b
A
395
396 /*
397 * all top-level sysctl names are non-terminal
398 */
399 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
400 return (EINVAL);
91447636
A
401 error = copyin(uap->name, &name[0], uap->namelen * sizeof(int));
402 if (error)
1c79356b 403 return (error);
91447636 404
e5568f75
A
405 AUDIT_ARG(ctlname, name, uap->namelen);
406
91447636
A
407 if (proc_is64bit(p)) {
408 /* uap->newlen is a size_t value which grows to 64 bits
409 * when coming from a 64-bit process. since it's doubtful we'll
410 * have a sysctl newp buffer greater than 4GB we shrink it to size_t
411 */
412 newlen = CAST_DOWN(size_t, uap->newlen);
413 }
414 else {
415 newlen = uap->newlen;
416 }
6d2010ae
A
417
418/*
419 * XXX TODO: push down rights check for CTL_HW OIDs; most duplicate
420 * XXX it anyway, which is a performance sink, and requires use
421 * XXX of SUID root programs (see <rdar://3915692>).
422 *
423 * Note: Opt out of non-leaf node enforcement by removing this
424 * check for the top level OID value, and then adding
425 * CTLFLAG_ANYBODY to the leaf nodes in question. Enforce as
426 * suser for writed in leaf nodes by omitting this flag.
427 * Enforce with a higher granularity by making the leaf node
428 * of type SYSCTL_PROC() in order to provide a procedural
429 * enforcement call site.
430 *
431 * NOTE: This function is called prior to any subfunctions being
432 * called with a fallback to userland_sysctl(); as such, this
433 * permissions check here will veto the fallback operation.
434 */
1c79356b 435 /* CTL_UNSPEC is used to get oid to AUTO_OID */
91447636 436 if (uap->new != USER_ADDR_NULL
6d2010ae 437 && ((name[0] == CTL_HW)
2d21ac55 438 || (name[0] == CTL_VM))
91447636 439 && (error = suser(kauth_cred_get(), &p->p_acflag)))
1c79356b
A
440 return (error);
441
6d2010ae
A
442// XXX need to relocate into each terminal instead of leaving this here...
443// XXX macf preemptory check.
444#if CONFIG_MACF
445 my_cred = kauth_cred_proc_ref(p);
446 error = mac_system_check_sysctl(
447 my_cred,
448 (int *) name,
449 uap->namelen,
450 uap->old,
451 uap->oldlenp,
452 0, /* XXX 1 for CTL_KERN checks */
453 uap->new,
454 newlen
455 );
456 kauth_cred_unref(&my_cred);
457 if (error)
458 return (error);
1c79356b 459#endif
1c79356b 460
91447636
A
461 if (uap->oldlenp != USER_ADDR_NULL) {
462 uint64_t oldlen64 = fuulong(uap->oldlenp);
463
464 oldlen = CAST_DOWN(size_t, oldlen64);
465 /*
466 * If more than 4G, clamp to 4G - useracc() below will catch
467 * with an EFAULT, if it's actually necessary.
468 */
469 if (oldlen64 > 0x00000000ffffffffULL)
470 oldlen = 0xffffffffUL;
471 }
1c79356b 472
6d2010ae 473 if ((name[0] == CTL_VFS || name[0] == CTL_VM)) {
2d21ac55 474 /*
6d2010ae
A
475 * Always take the funnel for CTL_VFS and CTL_VM
476 *
477 * XXX We should also take it for any OID without the
478 * XXX CTLFLAG_LOCKED set on it; fix this later!
479 */
480 funnel_state = thread_funnel_set(kernel_flock, TRUE);
481 funnel_taken = TRUE;
482
483 /*
484 * XXX Take the vslock() only when we are copying out; this
485 * XXX erroneously assumes that the copy in will not cause
486 * XXX a fault if caled from the paging path due to the
487 * XXX having been recently touched in order to establish
488 * XXX the input data. This is a bad assumption.
489 *
490 * Note: This is overkill, but third parties might
491 * already call sysctl internally in KEXTs that
492 * implement mass storage drivers. If you are
493 * writing a new KEXT, don't do that.
2d21ac55 494 */
6d2010ae
A
495 if(uap->old != USER_ADDR_NULL) {
496 if (!useracc(uap->old, (user_size_t)oldlen, B_WRITE)) {
497 thread_funnel_set(kernel_flock, funnel_state);
498 return (EFAULT);
499 }
500
501 if (oldlen) {
502 if ((error = vslock(uap->old, (user_size_t)oldlen))) {
503 thread_funnel_set(kernel_flock, funnel_state);
504 return(error);
505 }
506 savelen = oldlen;
507 vslock_taken = TRUE;
0b4e3aa0 508 }
0b4e3aa0 509 }
1c79356b
A
510 }
511
6d2010ae
A
512 /*
513 * XXX convert vfs_sysctl subelements to newsysctl; this is hard
514 * XXX because of VFS_NUMMNTOPS being top level.
515 */
516 error = ENOTSUP;
517 if (name[0] == CTL_VFS) {
518 error = vfs_sysctl(name + 1, uap->namelen - 1, uap->old,
91447636
A
519 &oldlen, uap->new, newlen, p);
520 }
2d21ac55
A
521
522 if (vslock_taken == TRUE) {
523 error1 = vsunlock(uap->old, (user_size_t)savelen, B_WRITE);
524 if (!error)
525 error = error1;
526 }
1c79356b 527
6d2010ae
A
528 if ( (name[0] != CTL_VFS) && (error == ENOTSUP) ) {
529 size_t tmp = oldlen;
91447636 530 error = userland_sysctl(p, name, uap->namelen, uap->old, &tmp,
b0d623f7 531 uap->new, newlen, &oldlen);
6d2010ae 532 }
1c79356b 533
6d2010ae
A
534 /*
535 * If we took the funnel, which we only do for CTL_VFS and CTL_VM on
536 * 32 bit architectures, then drop it.
537 *
538 * XXX the grabbing and dropping need to move into the leaf nodes,
539 * XXX for sysctl's that are not marked CTLFLAG_LOCKED, but this is
540 * XXX true for the vslock, as well. We have a start at a routine
541 * to wrapper this (above), but it's not turned on. The current code
542 * removed the funnel and the vslock() from all but these two top
543 * level OIDs. Note that VFS only needs to take the funnel if the FS
544 * against which it's operating is not thread safe (but since an FS
545 * can be in the paging path, it still needs to take the vslock()).
546 */
547 if (funnel_taken)
2d21ac55 548 thread_funnel_set(kernel_flock, funnel_state);
2d21ac55 549
1c79356b
A
550 if ((error) && (error != ENOMEM))
551 return (error);
552
2d21ac55
A
553 if (uap->oldlenp != USER_ADDR_NULL)
554 error = suulong(uap->oldlenp, oldlen);
1c79356b
A
555
556 return (error);
557}
558
559/*
560 * Attributes stored in the kernel.
561 */
39236c6e
A
562extern char corefilename[MAXPATHLEN+1];
563extern int do_coredump;
564extern int sugid_coredump;
e5568f75 565
2d21ac55 566#if COUNT_SYSCALLS
39236c6e 567extern int do_count_syscalls;
2d21ac55 568#endif
55e303ae 569
1c79356b
A
570#ifdef INSECURE
571int securelevel = -1;
572#else
573int securelevel;
574#endif
575
6d2010ae
A
576STATIC int
577sysctl_doaffinity SYSCTL_HANDLER_ARGS
55e303ae 578{
6d2010ae
A
579 __unused int cmd = oidp->oid_arg2; /* subcommand*/
580 int *name = arg1; /* oid element argument vector */
581 int namelen = arg2; /* number of oid element arguments */
582 user_addr_t oldp = req->oldptr; /* user buffer copy out address */
583 size_t *oldlenp = &req->oldlen; /* user buffer copy out size */
584 user_addr_t newp = req->newptr; /* user buffer copy in address */
585// size_t newlen = req->newlen; /* user buffer copy in size */
586
587 int error = ENOTSUP; /* Default to failure */
588
589 proc_t cur_proc = current_proc();
590
55e303ae 591 if (namelen < 1)
91447636 592 return (ENOTSUP);
55e303ae
A
593
594 if (name[0] == 0 && 1 == namelen) {
6d2010ae 595 error = sysctl_rdint(oldp, oldlenp, newp,
91447636 596 (cur_proc->p_flag & P_AFFINITY) ? 1 : 0);
55e303ae
A
597 } else if (name[0] == 1 && 2 == namelen) {
598 if (name[1] == 0) {
b0d623f7 599 OSBitAndAtomic(~((uint32_t)P_AFFINITY), &cur_proc->p_flag);
55e303ae 600 } else {
b0d623f7 601 OSBitOrAtomic(P_AFFINITY, &cur_proc->p_flag);
55e303ae 602 }
6d2010ae 603 error = 0;
55e303ae 604 }
6d2010ae
A
605
606 /* adjust index so we return the right required/consumed amount */
607 if (!error)
608 req->oldidx += req->oldlen;
609
610 return (error);
55e303ae 611}
6d2010ae
A
612SYSCTL_PROC(_kern, KERN_AFFINITY, affinity, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED,
613 0, /* Pointer argument (arg1) */
614 0, /* Integer argument (arg2) */
615 sysctl_doaffinity, /* Handler function */
616 NULL, /* Data pointer */
617 "");
618
619STATIC int
620sysctl_dotranslate SYSCTL_HANDLER_ARGS
621{
622 __unused int cmd = oidp->oid_arg2; /* subcommand*/
623 int *name = arg1; /* oid element argument vector */
624 int namelen = arg2; /* number of oid element arguments */
625 user_addr_t oldp = req->oldptr; /* user buffer copy out address */
626 size_t *oldlenp = &req->oldlen; /* user buffer copy out size */
627 user_addr_t newp = req->newptr; /* user buffer copy in address */
628// size_t newlen = req->newlen; /* user buffer copy in size */
629 int error;
55e303ae 630
6d2010ae 631 proc_t cur_proc = current_proc();
2d21ac55
A
632 proc_t p;
633 int istranslated = 0;
634 kauth_cred_t my_cred;
635 uid_t uid;
55e303ae
A
636
637 if (namelen != 1)
91447636 638 return (ENOTSUP);
55e303ae 639
2d21ac55 640 p = proc_find(name[0]);
55e303ae
A
641 if (p == NULL)
642 return (EINVAL);
643
2d21ac55
A
644 my_cred = kauth_cred_proc_ref(p);
645 uid = kauth_cred_getuid(my_cred);
646 kauth_cred_unref(&my_cred);
647 if ((uid != kauth_cred_getuid(kauth_cred_get()))
648 && suser(kauth_cred_get(), &cur_proc->p_acflag)) {
649 proc_rele(p);
55e303ae 650 return (EPERM);
2d21ac55 651 }
55e303ae 652
2d21ac55
A
653 istranslated = (p->p_flag & P_TRANSLATED);
654 proc_rele(p);
6d2010ae 655 error = sysctl_rdint(oldp, oldlenp, newp,
2d21ac55 656 (istranslated != 0) ? 1 : 0);
6d2010ae
A
657
658 /* adjust index so we return the right required/consumed amount */
659 if (!error)
660 req->oldidx += req->oldlen;
661
662 return (error);
0c530ab8 663}
6d2010ae
A
664/*
665 * XXX make CTLFLAG_RW so sysctl_rdint() will EPERM on attempts to write;
666 * XXX this may not be necessary.
667 */
668SYSCTL_PROC(_kern, KERN_TRANSLATE, translate, CTLTYPE_NODE|CTLFLAG_RW | CTLFLAG_LOCKED,
669 0, /* Pointer argument (arg1) */
670 0, /* Integer argument (arg2) */
671 sysctl_dotranslate, /* Handler function */
672 NULL, /* Data pointer */
673 "");
0c530ab8 674
6d2010ae 675STATIC int
b0d623f7
A
676sysctl_handle_kern_threadname( __unused struct sysctl_oid *oidp, __unused void *arg1,
677 __unused int arg2, struct sysctl_req *req)
678{
679 int error;
680 struct uthread *ut = get_bsdthread_info(current_thread());
681 user_addr_t oldp=0, newp=0;
682 size_t *oldlenp=NULL;
683 size_t newlen=0;
684
685 oldp = req->oldptr;
686 oldlenp = &(req->oldlen);
687 newp = req->newptr;
688 newlen = req->newlen;
689
690 /* We want the current length, and maybe the string itself */
691 if(oldlenp) {
692 /* if we have no thread name yet tell'em we want MAXTHREADNAMESIZE - 1 */
693 size_t currlen = MAXTHREADNAMESIZE - 1;
694
695 if(ut->pth_name)
696 /* use length of current thread name */
697 currlen = strlen(ut->pth_name);
698 if(oldp) {
699 if(*oldlenp < currlen)
700 return ENOMEM;
701 /* NOTE - we do not copy the NULL terminator */
702 if(ut->pth_name) {
703 error = copyout(ut->pth_name,oldp,currlen);
704 if(error)
705 return error;
706 }
707 }
708 /* return length of thread name minus NULL terminator (just like strlen) */
709 req->oldidx = currlen;
710 }
711
712 /* We want to set the name to something */
713 if(newp)
714 {
715 if(newlen > (MAXTHREADNAMESIZE - 1))
716 return ENAMETOOLONG;
717 if(!ut->pth_name)
718 {
719 ut->pth_name = (char*)kalloc( MAXTHREADNAMESIZE );
720 if(!ut->pth_name)
721 return ENOMEM;
722 }
723 bzero(ut->pth_name, MAXTHREADNAMESIZE);
724 error = copyin(newp, ut->pth_name, newlen);
725 if(error)
726 return error;
727 }
728
729 return 0;
730}
731
6d2010ae 732SYSCTL_PROC(_kern, KERN_THREADNAME, threadname, CTLFLAG_ANYBODY | CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0, sysctl_handle_kern_threadname,"A","");
b0d623f7 733
6d2010ae
A
734#define BSD_HOST 1
735STATIC int
736sysctl_sched_stats(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
737{
738 host_basic_info_data_t hinfo;
739 kern_return_t kret;
740 uint32_t size;
741 int changed;
742 mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
743 struct _processor_statistics_np *buf;
744 int error;
55e303ae 745
6d2010ae
A
746 kret = host_info((host_t)BSD_HOST, HOST_BASIC_INFO, (host_info_t)&hinfo, &count);
747 if (kret != KERN_SUCCESS) {
748 return EINVAL;
749 }
1c79356b 750
6d2010ae
A
751 size = sizeof(struct _processor_statistics_np) * (hinfo.logical_cpu_max + 2); /* One for RT Queue, One for Fair Share Queue */
752
753 if (req->oldlen < size) {
754 return EINVAL;
755 }
756
757 MALLOC(buf, struct _processor_statistics_np*, size, M_TEMP, M_ZERO | M_WAITOK);
758
759 kret = get_sched_statistics(buf, &size);
760 if (kret != KERN_SUCCESS) {
761 error = EINVAL;
762 goto out;
763 }
764
765 error = sysctl_io_opaque(req, buf, size, &changed);
766 if (error) {
767 goto out;
768 }
769
770 if (changed) {
771 panic("Sched info changed?!");
772 }
773out:
774 FREE(buf, M_TEMP);
775 return error;
776}
777
778SYSCTL_PROC(_kern, OID_AUTO, sched_stats, CTLFLAG_LOCKED, 0, 0, sysctl_sched_stats, "-", "");
779
780STATIC int
781sysctl_sched_stats_enable(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, __unused struct sysctl_req *req)
782{
783 boolean_t active;
784 int res;
785
786 if (req->newlen != sizeof(active)) {
787 return EINVAL;
788 }
789
790 res = copyin(req->newptr, &active, sizeof(active));
791 if (res != 0) {
792 return res;
793 }
794
795 return set_sched_stats_active(active);
796}
797
798SYSCTL_PROC(_kern, OID_AUTO, sched_stats_enable, CTLFLAG_LOCKED | CTLFLAG_WR, 0, 0, sysctl_sched_stats_enable, "-", "");
799
800extern int get_kernel_symfile(proc_t, char **);
1c79356b 801
2d21ac55 802#if COUNT_SYSCALLS
6d2010ae
A
803#define KERN_COUNT_SYSCALLS (KERN_OSTYPE + 1000)
804
805extern int nsysent;
806extern int syscalls_log[];
807extern const char *syscallnames[];
808
809STATIC int
810sysctl_docountsyscalls SYSCTL_HANDLER_ARGS
811{
812 __unused int cmd = oidp->oid_arg2; /* subcommand*/
813 __unused int *name = arg1; /* oid element argument vector */
814 __unused int namelen = arg2; /* number of oid element arguments */
815 user_addr_t oldp = req->oldptr; /* user buffer copy out address */
816 size_t *oldlenp = &req->oldlen; /* user buffer copy out size */
817 user_addr_t newp = req->newptr; /* user buffer copy in address */
818 size_t newlen = req->newlen; /* user buffer copy in size */
819 int error;
820
821 int tmp;
822
823 /* valid values passed in:
824 * = 0 means don't keep called counts for each bsd syscall
825 * > 0 means keep called counts for each bsd syscall
826 * = 2 means dump current counts to the system log
827 * = 3 means reset all counts
828 * for example, to dump current counts:
829 * sysctl -w kern.count_calls=2
830 */
831 error = sysctl_int(oldp, oldlenp, newp, newlen, &tmp);
832 if ( error != 0 ) {
833 return (error);
834 }
835
836 if ( tmp == 1 ) {
837 do_count_syscalls = 1;
838 }
839 else if ( tmp == 0 || tmp == 2 || tmp == 3 ) {
840 int i;
841 for ( i = 0; i < nsysent; i++ ) {
842 if ( syscalls_log[i] != 0 ) {
843 if ( tmp == 2 ) {
844 printf("%d calls - name %s \n", syscalls_log[i], syscallnames[i]);
845 }
846 else {
847 syscalls_log[i] = 0;
2d21ac55 848 }
2d21ac55
A
849 }
850 }
6d2010ae
A
851 if ( tmp != 0 ) {
852 do_count_syscalls = 1;
853 }
1c79356b 854 }
6d2010ae
A
855
856 /* adjust index so we return the right required/consumed amount */
857 if (!error)
858 req->oldidx += req->oldlen;
859
860 return (error);
1c79356b 861}
6d2010ae
A
862SYSCTL_PROC(_kern, KERN_COUNT_SYSCALLS, count_syscalls, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED,
863 0, /* Pointer argument (arg1) */
864 0, /* Integer argument (arg2) */
865 sysctl_docountsyscalls, /* Handler function */
866 NULL, /* Data pointer */
867 "");
868#endif /* COUNT_SYSCALLS */
1c79356b 869
b0d623f7 870#if DEBUG
1c79356b
A
871/*
872 * Debugging related system variables.
873 */
874#if DIAGNOSTIC
875extern
876#endif /* DIAGNOSTIC */
877struct ctldebug debug0, debug1;
878struct ctldebug debug2, debug3, debug4;
879struct ctldebug debug5, debug6, debug7, debug8, debug9;
880struct ctldebug debug10, debug11, debug12, debug13, debug14;
881struct ctldebug debug15, debug16, debug17, debug18, debug19;
6d2010ae 882STATIC struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
1c79356b
A
883 &debug0, &debug1, &debug2, &debug3, &debug4,
884 &debug5, &debug6, &debug7, &debug8, &debug9,
885 &debug10, &debug11, &debug12, &debug13, &debug14,
886 &debug15, &debug16, &debug17, &debug18, &debug19,
887};
6d2010ae
A
888STATIC int
889sysctl_dodebug SYSCTL_HANDLER_ARGS
890{
891 int cmd = oidp->oid_arg2; /* subcommand*/
892 int *name = arg1; /* oid element argument vector */
893 int namelen = arg2; /* number of oid element arguments */
894 user_addr_t oldp = req->oldptr; /* user buffer copy out address */
895 size_t *oldlenp = &req->oldlen; /* user buffer copy out size */
896 user_addr_t newp = req->newptr; /* user buffer copy in address */
897 size_t newlen = req->newlen; /* user buffer copy in size */
898 int error;
899
1c79356b
A
900 struct ctldebug *cdp;
901
902 /* all sysctl names at this level are name and field */
6d2010ae 903 if (namelen != 1)
b0d623f7 904 return (ENOTSUP); /* overloaded */
6d2010ae 905 if (cmd < 0 || cmd >= CTL_DEBUG_MAXID)
b0d623f7 906 return (ENOTSUP);
6d2010ae 907 cdp = debugvars[cmd];
1c79356b 908 if (cdp->debugname == 0)
91447636 909 return (ENOTSUP);
6d2010ae 910 switch (name[0]) {
1c79356b 911 case CTL_DEBUG_NAME:
6d2010ae
A
912 error = sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname);
913 break;
1c79356b 914 case CTL_DEBUG_VALUE:
6d2010ae
A
915 error = sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar);
916 break;
1c79356b 917 default:
6d2010ae
A
918 error = ENOTSUP;
919 break;
1c79356b 920 }
6d2010ae
A
921
922 /* adjust index so we return the right required/consumed amount */
923 if (!error)
924 req->oldidx += req->oldlen;
925
926 return (error);
1c79356b 927}
6d2010ae
A
928/*
929 * XXX We mark this RW instead of RD to let sysctl_rdstring() return the
930 * XXX historical error.
931 */
932SYSCTL_PROC(_debug, CTL_DEBUG_NAME, name, CTLTYPE_NODE|CTLFLAG_RW | CTLFLAG_LOCKED,
933 0, /* Pointer argument (arg1) */
934 CTL_DEBUG_NAME, /* Integer argument (arg2) */
935 sysctl_dodebug, /* Handler function */
936 NULL, /* Data pointer */
937 "Debugging");
938SYSCTL_PROC(_debug, CTL_DEBUG_VALUE, value, CTLTYPE_NODE|CTLFLAG_RW | CTLFLAG_LOCKED,
939 0, /* Pointer argument (arg1) */
940 CTL_DEBUG_VALUE, /* Integer argument (arg2) */
941 sysctl_dodebug, /* Handler function */
942 NULL, /* Data pointer */
943 "Debugging");
1c79356b
A
944#endif /* DEBUG */
945
2d21ac55
A
946/*
947 * The following sysctl_* functions should not be used
948 * any more, as they can only cope with callers in
949 * user mode: Use new-style
950 * sysctl_io_number()
951 * sysctl_io_string()
952 * sysctl_io_opaque()
953 * instead.
954 */
955
1c79356b
A
956/*
957 * Validate parameters and get old / set new parameters
958 * for an integer-valued sysctl function.
959 */
9bccf70c 960int
91447636
A
961sysctl_int(user_addr_t oldp, size_t *oldlenp,
962 user_addr_t newp, size_t newlen, int *valp)
1c79356b
A
963{
964 int error = 0;
965
91447636
A
966 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
967 return (EFAULT);
1c79356b
A
968 if (oldp && *oldlenp < sizeof(int))
969 return (ENOMEM);
970 if (newp && newlen != sizeof(int))
971 return (EINVAL);
972 *oldlenp = sizeof(int);
973 if (oldp)
974 error = copyout(valp, oldp, sizeof(int));
e5568f75 975 if (error == 0 && newp) {
1c79356b 976 error = copyin(newp, valp, sizeof(int));
b0d623f7 977 AUDIT_ARG(value32, *valp);
e5568f75 978 }
1c79356b
A
979 return (error);
980}
981
982/*
983 * As above, but read-only.
984 */
9bccf70c 985int
91447636 986sysctl_rdint(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, int val)
1c79356b
A
987{
988 int error = 0;
989
91447636
A
990 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
991 return (EFAULT);
1c79356b
A
992 if (oldp && *oldlenp < sizeof(int))
993 return (ENOMEM);
994 if (newp)
995 return (EPERM);
996 *oldlenp = sizeof(int);
997 if (oldp)
998 error = copyout((caddr_t)&val, oldp, sizeof(int));
999 return (error);
1000}
1001
9bccf70c
A
1002/*
1003 * Validate parameters and get old / set new parameters
1004 * for an quad(64bit)-valued sysctl function.
1005 */
1006int
91447636
A
1007sysctl_quad(user_addr_t oldp, size_t *oldlenp,
1008 user_addr_t newp, size_t newlen, quad_t *valp)
9bccf70c
A
1009{
1010 int error = 0;
1011
91447636
A
1012 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1013 return (EFAULT);
9bccf70c
A
1014 if (oldp && *oldlenp < sizeof(quad_t))
1015 return (ENOMEM);
1016 if (newp && newlen != sizeof(quad_t))
1017 return (EINVAL);
1018 *oldlenp = sizeof(quad_t);
1019 if (oldp)
1020 error = copyout(valp, oldp, sizeof(quad_t));
1021 if (error == 0 && newp)
1022 error = copyin(newp, valp, sizeof(quad_t));
1023 return (error);
1024}
1025
1026/*
1027 * As above, but read-only.
1028 */
1029int
2d21ac55 1030sysctl_rdquad(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, quad_t val)
9bccf70c
A
1031{
1032 int error = 0;
1033
91447636
A
1034 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1035 return (EFAULT);
9bccf70c
A
1036 if (oldp && *oldlenp < sizeof(quad_t))
1037 return (ENOMEM);
1038 if (newp)
1039 return (EPERM);
1040 *oldlenp = sizeof(quad_t);
1041 if (oldp)
2d21ac55 1042 error = copyout((caddr_t)&val, oldp, sizeof(quad_t));
91447636
A
1043 return (error);
1044}
1045
1046/*
1047 * Validate parameters and get old / set new parameters
1048 * for a string-valued sysctl function. Unlike sysctl_string, if you
1049 * give it a too small (but larger than 0 bytes) buffer, instead of
1050 * returning ENOMEM, it truncates the returned string to the buffer
1051 * size. This preserves the semantics of some library routines
1052 * implemented via sysctl, which truncate their returned data, rather
1053 * than simply returning an error. The returned string is always NUL
1054 * terminated.
1055 */
1056int
1057sysctl_trstring(user_addr_t oldp, size_t *oldlenp,
1058 user_addr_t newp, size_t newlen, char *str, int maxlen)
1059{
1060 int len, copylen, error = 0;
1061
1062 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1063 return (EFAULT);
1064 copylen = len = strlen(str) + 1;
1065 if (oldp && (len < 0 || *oldlenp < 1))
1066 return (ENOMEM);
1067 if (oldp && (*oldlenp < (size_t)len))
1068 copylen = *oldlenp + 1;
1069 if (newp && (maxlen < 0 || newlen >= (size_t)maxlen))
1070 return (EINVAL);
1071 *oldlenp = copylen - 1; /* deal with NULL strings correctly */
1072 if (oldp) {
1073 error = copyout(str, oldp, copylen);
1074 if (!error) {
1075 unsigned char c = 0;
1076 /* NUL terminate */
1077 oldp += *oldlenp;
1078 error = copyout((void *)&c, oldp, sizeof(char));
1079 }
1080 }
1081 if (error == 0 && newp) {
1082 error = copyin(newp, str, newlen);
1083 str[newlen] = 0;
1084 AUDIT_ARG(text, (char *)str);
1085 }
9bccf70c
A
1086 return (error);
1087}
1088
1c79356b
A
1089/*
1090 * Validate parameters and get old / set new parameters
1091 * for a string-valued sysctl function.
1092 */
9bccf70c 1093int
91447636
A
1094sysctl_string(user_addr_t oldp, size_t *oldlenp,
1095 user_addr_t newp, size_t newlen, char *str, int maxlen)
1c79356b
A
1096{
1097 int len, error = 0;
1098
91447636
A
1099 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1100 return (EFAULT);
1c79356b 1101 len = strlen(str) + 1;
91447636 1102 if (oldp && (len < 0 || *oldlenp < (size_t)len))
1c79356b 1103 return (ENOMEM);
91447636 1104 if (newp && (maxlen < 0 || newlen >= (size_t)maxlen))
1c79356b 1105 return (EINVAL);
9bccf70c 1106 *oldlenp = len -1; /* deal with NULL strings correctly */
1c79356b 1107 if (oldp) {
1c79356b
A
1108 error = copyout(str, oldp, len);
1109 }
1110 if (error == 0 && newp) {
1111 error = copyin(newp, str, newlen);
1112 str[newlen] = 0;
e5568f75 1113 AUDIT_ARG(text, (char *)str);
1c79356b
A
1114 }
1115 return (error);
1116}
1117
1118/*
1119 * As above, but read-only.
1120 */
9bccf70c 1121int
91447636
A
1122sysctl_rdstring(user_addr_t oldp, size_t *oldlenp,
1123 user_addr_t newp, char *str)
1c79356b
A
1124{
1125 int len, error = 0;
1126
91447636
A
1127 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1128 return (EFAULT);
1c79356b 1129 len = strlen(str) + 1;
91447636 1130 if (oldp && *oldlenp < (size_t)len)
1c79356b
A
1131 return (ENOMEM);
1132 if (newp)
1133 return (EPERM);
1134 *oldlenp = len;
1135 if (oldp)
1136 error = copyout(str, oldp, len);
1137 return (error);
1138}
1139
1140/*
1141 * Validate parameters and get old / set new parameters
1142 * for a structure oriented sysctl function.
1143 */
9bccf70c 1144int
91447636
A
1145sysctl_struct(user_addr_t oldp, size_t *oldlenp,
1146 user_addr_t newp, size_t newlen, void *sp, int len)
1c79356b
A
1147{
1148 int error = 0;
1149
91447636
A
1150 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1151 return (EFAULT);
1152 if (oldp && (len < 0 || *oldlenp < (size_t)len))
1c79356b 1153 return (ENOMEM);
91447636 1154 if (newp && (len < 0 || newlen > (size_t)len))
1c79356b
A
1155 return (EINVAL);
1156 if (oldp) {
1157 *oldlenp = len;
1158 error = copyout(sp, oldp, len);
1159 }
1160 if (error == 0 && newp)
1161 error = copyin(newp, sp, len);
1162 return (error);
1163}
1164
1165/*
1166 * Validate parameters and get old parameters
1167 * for a structure oriented sysctl function.
1168 */
9bccf70c 1169int
91447636
A
1170sysctl_rdstruct(user_addr_t oldp, size_t *oldlenp,
1171 user_addr_t newp, void *sp, int len)
1c79356b
A
1172{
1173 int error = 0;
1174
91447636
A
1175 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1176 return (EFAULT);
1177 if (oldp && (len < 0 || *oldlenp < (size_t)len))
1c79356b
A
1178 return (ENOMEM);
1179 if (newp)
1180 return (EPERM);
1181 *oldlenp = len;
1182 if (oldp)
1183 error = copyout(sp, oldp, len);
1184 return (error);
1185}
1186
6d2010ae 1187STATIC int
2d21ac55
A
1188sysdoproc_filt_KERN_PROC_PID(proc_t p, void * arg)
1189{
b0d623f7 1190 if (p->p_pid != (pid_t)*(int*)arg)
2d21ac55
A
1191 return(0);
1192 else
1193 return(1);
1194}
1195
6d2010ae 1196STATIC int
2d21ac55
A
1197sysdoproc_filt_KERN_PROC_PGRP(proc_t p, void * arg)
1198{
b0d623f7 1199 if (p->p_pgrpid != (pid_t)*(int*)arg)
2d21ac55
A
1200 return(0);
1201 else
1202 return(1);
1203}
1204
6d2010ae 1205STATIC int
2d21ac55
A
1206sysdoproc_filt_KERN_PROC_TTY(proc_t p, void * arg)
1207{
1208 boolean_t funnel_state;
1209 int retval;
b0d623f7 1210 struct tty *tp;
2d21ac55
A
1211
1212
1213 funnel_state = thread_funnel_set(kernel_flock, TRUE);
1214 /* This is very racy but list lock is held.. Hmmm. */
1215 if ((p->p_flag & P_CONTROLT) == 0 ||
1216 (p->p_pgrp == NULL) || (p->p_pgrp->pg_session == NULL) ||
b0d623f7
A
1217 (tp = SESSION_TP(p->p_pgrp->pg_session)) == TTY_NULL ||
1218 tp->t_dev != (dev_t)*(int*)arg)
2d21ac55
A
1219 retval = 0;
1220 else
1221 retval = 1;
1222
1223 thread_funnel_set(kernel_flock, funnel_state);
1224
1225 return(retval);
1226}
1227
6d2010ae 1228STATIC int
2d21ac55
A
1229sysdoproc_filt_KERN_PROC_UID(proc_t p, void * arg)
1230{
1231 kauth_cred_t my_cred;
1232 uid_t uid;
1233
1234 if (p->p_ucred == NULL)
1235 return(0);
1236 my_cred = kauth_cred_proc_ref(p);
1237 uid = kauth_cred_getuid(my_cred);
1238 kauth_cred_unref(&my_cred);
1239
b0d623f7 1240 if (uid != (uid_t)*(int*)arg)
2d21ac55
A
1241 return(0);
1242 else
1243 return(1);
1244}
1245
1246
6d2010ae 1247STATIC int
2d21ac55
A
1248sysdoproc_filt_KERN_PROC_RUID(proc_t p, void * arg)
1249{
1250 kauth_cred_t my_cred;
1251 uid_t ruid;
1252
1253 if (p->p_ucred == NULL)
1254 return(0);
1255 my_cred = kauth_cred_proc_ref(p);
6d2010ae 1256 ruid = kauth_cred_getruid(my_cred);
2d21ac55
A
1257 kauth_cred_unref(&my_cred);
1258
b0d623f7 1259 if (ruid != (uid_t)*(int*)arg)
2d21ac55
A
1260 return(0);
1261 else
1262 return(1);
1263}
1264
b0d623f7 1265#if CONFIG_LCTX
6d2010ae 1266STATIC int
2d21ac55
A
1267sysdoproc_filt_KERN_PROC_LCID(proc_t p, void * arg)
1268{
1269 if ((p->p_lctx == NULL) ||
b0d623f7 1270 (p->p_lctx->lc_id != (pid_t)*(int*)arg))
2d21ac55
A
1271 return(0);
1272 else
1273 return(1);
1274}
b0d623f7 1275#endif
2d21ac55 1276
1c79356b
A
1277/*
1278 * try over estimating by 5 procs
1279 */
1280#define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
2d21ac55
A
1281struct sysdoproc_args {
1282 int buflen;
316670eb 1283 void *kprocp;
2d21ac55
A
1284 boolean_t is_64_bit;
1285 user_addr_t dp;
1286 size_t needed;
1287 int sizeof_kproc;
316670eb 1288 int *errorp;
2d21ac55
A
1289 int uidcheck;
1290 int ruidcheck;
1291 int ttycheck;
1292 int uidval;
1293};
1294
1295int
316670eb 1296sysdoproc_callback(proc_t p, void *arg)
2d21ac55 1297{
316670eb 1298 struct sysdoproc_args *args = arg;
2d21ac55
A
1299
1300 if (args->buflen >= args->sizeof_kproc) {
316670eb
A
1301 if ((args->ruidcheck != 0) && (sysdoproc_filt_KERN_PROC_RUID(p, &args->uidval) == 0))
1302 return (PROC_RETURNED);
1303 if ((args->uidcheck != 0) && (sysdoproc_filt_KERN_PROC_UID(p, &args->uidval) == 0))
1304 return (PROC_RETURNED);
1305 if ((args->ttycheck != 0) && (sysdoproc_filt_KERN_PROC_TTY(p, &args->uidval) == 0))
1306 return (PROC_RETURNED);
2d21ac55
A
1307
1308 bzero(args->kprocp, args->sizeof_kproc);
316670eb
A
1309 if (args->is_64_bit)
1310 fill_user64_proc(p, args->kprocp);
1311 else
1312 fill_user32_proc(p, args->kprocp);
1313 int error = copyout(args->kprocp, args->dp, args->sizeof_kproc);
2d21ac55
A
1314 if (error) {
1315 *args->errorp = error;
316670eb 1316 return (PROC_RETURNED_DONE);
2d21ac55
A
1317 }
1318 args->dp += args->sizeof_kproc;
1319 args->buflen -= args->sizeof_kproc;
1320 }
1321 args->needed += args->sizeof_kproc;
316670eb 1322 return (PROC_RETURNED);
2d21ac55 1323}
1c79356b 1324
6d2010ae
A
1325SYSCTL_NODE(_kern, KERN_PROC, proc, CTLFLAG_RD | CTLFLAG_LOCKED, 0, "");
1326STATIC int
1327sysctl_prochandle SYSCTL_HANDLER_ARGS
1c79356b 1328{
6d2010ae
A
1329 int cmd = oidp->oid_arg2; /* subcommand for multiple nodes */
1330 int *name = arg1; /* oid element argument vector */
1331 int namelen = arg2; /* number of oid element arguments */
1332 user_addr_t where = req->oldptr;/* user buffer copy out address */
1333
91447636
A
1334 user_addr_t dp = where;
1335 size_t needed = 0;
6d2010ae 1336 int buflen = where != USER_ADDR_NULL ? req->oldlen : 0;
1c79356b 1337 int error = 0;
316670eb 1338 boolean_t is_64_bit = proc_is64bit(current_proc());
b0d623f7
A
1339 struct user32_kinfo_proc user32_kproc;
1340 struct user64_kinfo_proc user_kproc;
91447636 1341 int sizeof_kproc;
316670eb 1342 void *kprocp;
2d21ac55
A
1343 int (*filterfn)(proc_t, void *) = 0;
1344 struct sysdoproc_args args;
1345 int uidcheck = 0;
1346 int ruidcheck = 0;
1347 int ttycheck = 0;
1c79356b 1348
6d2010ae 1349 if (namelen != 1 && !(namelen == 0 && cmd == KERN_PROC_ALL))
1c79356b 1350 return (EINVAL);
6d2010ae 1351
91447636
A
1352 if (is_64_bit) {
1353 sizeof_kproc = sizeof(user_kproc);
316670eb
A
1354 kprocp = &user_kproc;
1355 } else {
b0d623f7 1356 sizeof_kproc = sizeof(user32_kproc);
316670eb 1357 kprocp = &user32_kproc;
91447636 1358 }
2d21ac55 1359
6d2010ae 1360 switch (cmd) {
1c79356b
A
1361
1362 case KERN_PROC_PID:
2d21ac55 1363 filterfn = sysdoproc_filt_KERN_PROC_PID;
1c79356b
A
1364 break;
1365
1366 case KERN_PROC_PGRP:
2d21ac55 1367 filterfn = sysdoproc_filt_KERN_PROC_PGRP;
1c79356b 1368 break;
2d21ac55 1369
1c79356b 1370 case KERN_PROC_TTY:
2d21ac55 1371 ttycheck = 1;
1c79356b
A
1372 break;
1373
1374 case KERN_PROC_UID:
2d21ac55 1375 uidcheck = 1;
1c79356b
A
1376 break;
1377
1378 case KERN_PROC_RUID:
2d21ac55 1379 ruidcheck = 1;
1c79356b 1380 break;
2d21ac55
A
1381
1382#if CONFIG_LCTX
1383 case KERN_PROC_LCID:
1384 filterfn = sysdoproc_filt_KERN_PROC_LCID;
1385 break;
1386#endif
6d2010ae
A
1387 case KERN_PROC_ALL:
1388 break;
1389
1390 default:
1391 /* must be kern.proc.<unknown> */
1392 return (ENOTSUP);
1c79356b 1393 }
2d21ac55
A
1394
1395 error = 0;
1396 args.buflen = buflen;
1397 args.kprocp = kprocp;
1398 args.is_64_bit = is_64_bit;
1399 args.dp = dp;
1400 args.needed = needed;
1401 args.errorp = &error;
1402 args.uidcheck = uidcheck;
1403 args.ruidcheck = ruidcheck;
1404 args.ttycheck = ttycheck;
1405 args.sizeof_kproc = sizeof_kproc;
6d2010ae 1406 if (namelen)
316670eb 1407 args.uidval = name[0];
2d21ac55 1408
316670eb
A
1409 proc_iterate((PROC_ALLPROCLIST | PROC_ZOMBPROCLIST),
1410 sysdoproc_callback, &args, filterfn, name);
2d21ac55
A
1411
1412 if (error)
316670eb 1413 return (error);
2d21ac55
A
1414
1415 dp = args.dp;
1416 needed = args.needed;
1417
91447636 1418 if (where != USER_ADDR_NULL) {
6d2010ae
A
1419 req->oldlen = dp - where;
1420 if (needed > req->oldlen)
1c79356b
A
1421 return (ENOMEM);
1422 } else {
1423 needed += KERN_PROCSLOP;
6d2010ae 1424 req->oldlen = needed;
1c79356b 1425 }
6d2010ae
A
1426 /* adjust index so we return the right required/consumed amount */
1427 req->oldidx += req->oldlen;
1c79356b
A
1428 return (0);
1429}
316670eb 1430
6d2010ae
A
1431/*
1432 * We specify the subcommand code for multiple nodes as the 'req->arg2' value
1433 * in the sysctl declaration itself, which comes into the handler function
1434 * as 'oidp->oid_arg2'.
1435 *
1436 * For these particular sysctls, since they have well known OIDs, we could
1437 * have just obtained it from the '((int *)arg1)[0]' parameter, but that would
1438 * not demonstrate how to handle multiple sysctls that used OID_AUTO instead
1439 * of a well known value with a common handler function. This is desirable,
1440 * because we want well known values to "go away" at some future date.
1441 *
1442 * It should be noted that the value of '((int *)arg1)[1]' is used for many
1443 * an integer parameter to the subcommand for many of these sysctls; we'd
1444 * rather have used '((int *)arg1)[0]' for that, or even better, an element
1445 * in a structure passed in as the the 'newp' argument to sysctlbyname(3),
1446 * and then use leaf-node permissions enforcement, but that would have
1447 * necessitated modifying user space code to correspond to the interface
1448 * change, and we are striving for binary backward compatibility here; even
1449 * though these are SPI, and not intended for use by user space applications
1450 * which are not themselves system tools or libraries, some applications
1451 * have erroneously used them.
1452 */
1453SYSCTL_PROC(_kern_proc, KERN_PROC_ALL, all, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED,
1454 0, /* Pointer argument (arg1) */
1455 KERN_PROC_ALL, /* Integer argument (arg2) */
1456 sysctl_prochandle, /* Handler function */
1457 NULL, /* Data is size variant on ILP32/LP64 */
1458 "");
1459SYSCTL_PROC(_kern_proc, KERN_PROC_PID, pid, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED,
1460 0, /* Pointer argument (arg1) */
1461 KERN_PROC_PID, /* Integer argument (arg2) */
1462 sysctl_prochandle, /* Handler function */
1463 NULL, /* Data is size variant on ILP32/LP64 */
1464 "");
1465SYSCTL_PROC(_kern_proc, KERN_PROC_TTY, tty, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED,
1466 0, /* Pointer argument (arg1) */
1467 KERN_PROC_TTY, /* Integer argument (arg2) */
1468 sysctl_prochandle, /* Handler function */
1469 NULL, /* Data is size variant on ILP32/LP64 */
1470 "");
1471SYSCTL_PROC(_kern_proc, KERN_PROC_PGRP, pgrp, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED,
1472 0, /* Pointer argument (arg1) */
1473 KERN_PROC_PGRP, /* Integer argument (arg2) */
1474 sysctl_prochandle, /* Handler function */
1475 NULL, /* Data is size variant on ILP32/LP64 */
1476 "");
1477SYSCTL_PROC(_kern_proc, KERN_PROC_UID, uid, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED,
1478 0, /* Pointer argument (arg1) */
1479 KERN_PROC_UID, /* Integer argument (arg2) */
1480 sysctl_prochandle, /* Handler function */
1481 NULL, /* Data is size variant on ILP32/LP64 */
1482 "");
1483SYSCTL_PROC(_kern_proc, KERN_PROC_RUID, ruid, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED,
1484 0, /* Pointer argument (arg1) */
1485 KERN_PROC_RUID, /* Integer argument (arg2) */
1486 sysctl_prochandle, /* Handler function */
1487 NULL, /* Data is size variant on ILP32/LP64 */
1488 "");
1489SYSCTL_PROC(_kern_proc, KERN_PROC_LCID, lcid, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED,
1490 0, /* Pointer argument (arg1) */
1491 KERN_PROC_LCID, /* Integer argument (arg2) */
1492 sysctl_prochandle, /* Handler function */
1493 NULL, /* Data is size variant on ILP32/LP64 */
1494 "");
1495
1c79356b 1496
1c79356b 1497/*
316670eb 1498 * Fill in non-zero fields of an eproc structure for the specified process.
1c79356b 1499 */
6d2010ae 1500STATIC void
316670eb 1501fill_user32_eproc(proc_t p, struct user32_eproc *__restrict ep)
1c79356b 1502{
2d21ac55 1503 struct tty *tp;
316670eb
A
1504 struct pgrp *pg;
1505 struct session *sessp;
2d21ac55 1506 kauth_cred_t my_cred;
2d21ac55
A
1507
1508 pg = proc_pgrp(p);
1509 sessp = proc_session(p);
1c79356b 1510
2d21ac55 1511 if (pg != PGRP_NULL) {
2d21ac55
A
1512 ep->e_pgid = p->p_pgrpid;
1513 ep->e_jobc = pg->pg_jobc;
316670eb 1514 if (sessp != SESSION_NULL && sessp->s_ttyvp)
55e303ae 1515 ep->e_flag = EPROC_CTTY;
55e303ae 1516 }
2d21ac55 1517#if CONFIG_LCTX
316670eb 1518 if (p->p_lctx)
2d21ac55 1519 ep->e_lcid = p->p_lctx->lc_id;
2d21ac55
A
1520#endif
1521 ep->e_ppid = p->p_ppid;
91447636 1522 if (p->p_ucred) {
2d21ac55 1523 my_cred = kauth_cred_proc_ref(p);
91447636
A
1524
1525 /* A fake historical pcred */
6d2010ae
A
1526 ep->e_pcred.p_ruid = kauth_cred_getruid(my_cred);
1527 ep->e_pcred.p_svuid = kauth_cred_getsvuid(my_cred);
1528 ep->e_pcred.p_rgid = kauth_cred_getrgid(my_cred);
1529 ep->e_pcred.p_svgid = kauth_cred_getsvgid(my_cred);
316670eb 1530
91447636 1531 /* A fake historical *kauth_cred_t */
2d21ac55
A
1532 ep->e_ucred.cr_ref = my_cred->cr_ref;
1533 ep->e_ucred.cr_uid = kauth_cred_getuid(my_cred);
6d2010ae 1534 ep->e_ucred.cr_ngroups = posix_cred_get(my_cred)->cr_ngroups;
316670eb
A
1535 bcopy(posix_cred_get(my_cred)->cr_groups,
1536 ep->e_ucred.cr_groups, NGROUPS * sizeof (gid_t));
91447636 1537
2d21ac55 1538 kauth_cred_unref(&my_cred);
55e303ae 1539 }
55e303ae 1540
2d21ac55 1541 if ((p->p_flag & P_CONTROLT) && (sessp != SESSION_NULL) &&
b0d623f7 1542 (tp = SESSION_TP(sessp))) {
1c79356b 1543 ep->e_tdev = tp->t_dev;
2d21ac55 1544 ep->e_tpgid = sessp->s_ttypgrpid;
1c79356b
A
1545 } else
1546 ep->e_tdev = NODEV;
55e303ae 1547
316670eb
A
1548 if (sessp != SESSION_NULL) {
1549 if (SESS_LEADER(p, sessp))
1550 ep->e_flag |= EPROC_SLEADER;
2d21ac55 1551 session_rele(sessp);
316670eb
A
1552 }
1553 if (pg != PGRP_NULL)
2d21ac55 1554 pg_rele(pg);
1c79356b 1555}
55e303ae 1556
91447636 1557/*
316670eb 1558 * Fill in non-zero fields of an LP64 eproc structure for the specified process.
91447636 1559 */
6d2010ae 1560STATIC void
316670eb 1561fill_user64_eproc(proc_t p, struct user64_eproc *__restrict ep)
91447636 1562{
2d21ac55 1563 struct tty *tp;
316670eb
A
1564 struct pgrp *pg;
1565 struct session *sessp;
2d21ac55
A
1566 kauth_cred_t my_cred;
1567
1568 pg = proc_pgrp(p);
1569 sessp = proc_session(p);
91447636 1570
2d21ac55 1571 if (pg != PGRP_NULL) {
2d21ac55
A
1572 ep->e_pgid = p->p_pgrpid;
1573 ep->e_jobc = pg->pg_jobc;
316670eb
A
1574 if (sessp != SESSION_NULL && sessp->s_ttyvp)
1575 ep->e_flag = EPROC_CTTY;
91447636 1576 }
2d21ac55 1577#if CONFIG_LCTX
316670eb 1578 if (p->p_lctx)
2d21ac55 1579 ep->e_lcid = p->p_lctx->lc_id;
2d21ac55
A
1580#endif
1581 ep->e_ppid = p->p_ppid;
91447636 1582 if (p->p_ucred) {
2d21ac55 1583 my_cred = kauth_cred_proc_ref(p);
91447636
A
1584
1585 /* A fake historical pcred */
6d2010ae
A
1586 ep->e_pcred.p_ruid = kauth_cred_getruid(my_cred);
1587 ep->e_pcred.p_svuid = kauth_cred_getsvuid(my_cred);
1588 ep->e_pcred.p_rgid = kauth_cred_getrgid(my_cred);
1589 ep->e_pcred.p_svgid = kauth_cred_getsvgid(my_cred);
91447636
A
1590
1591 /* A fake historical *kauth_cred_t */
2d21ac55
A
1592 ep->e_ucred.cr_ref = my_cred->cr_ref;
1593 ep->e_ucred.cr_uid = kauth_cred_getuid(my_cred);
6d2010ae 1594 ep->e_ucred.cr_ngroups = posix_cred_get(my_cred)->cr_ngroups;
316670eb
A
1595 bcopy(posix_cred_get(my_cred)->cr_groups,
1596 ep->e_ucred.cr_groups, NGROUPS * sizeof (gid_t));
91447636 1597
2d21ac55 1598 kauth_cred_unref(&my_cred);
91447636 1599 }
91447636 1600
2d21ac55 1601 if ((p->p_flag & P_CONTROLT) && (sessp != SESSION_NULL) &&
b0d623f7 1602 (tp = SESSION_TP(sessp))) {
91447636 1603 ep->e_tdev = tp->t_dev;
2d21ac55 1604 ep->e_tpgid = sessp->s_ttypgrpid;
91447636
A
1605 } else
1606 ep->e_tdev = NODEV;
1607
316670eb
A
1608 if (sessp != SESSION_NULL) {
1609 if (SESS_LEADER(p, sessp))
1610 ep->e_flag |= EPROC_SLEADER;
2d21ac55 1611 session_rele(sessp);
316670eb 1612 }
2d21ac55
A
1613 if (pg != PGRP_NULL)
1614 pg_rele(pg);
91447636
A
1615}
1616
1c79356b
A
1617/*
1618 * Fill in an eproc structure for the specified process.
316670eb 1619 * bzeroed by our caller, so only set non-zero fields.
1c79356b 1620 */
6d2010ae 1621STATIC void
316670eb 1622fill_user32_externproc(proc_t p, struct user32_extern_proc *__restrict exp)
1c79356b 1623{
b0d623f7
A
1624 exp->p_starttime.tv_sec = p->p_start.tv_sec;
1625 exp->p_starttime.tv_usec = p->p_start.tv_usec;
316670eb 1626 exp->p_flag = p->p_flag;
2d21ac55
A
1627 if (p->p_lflag & P_LTRACED)
1628 exp->p_flag |= P_TRACED;
1629 if (p->p_lflag & P_LPPWAIT)
1630 exp->p_flag |= P_PPWAIT;
1631 if (p->p_lflag & P_LEXIT)
1632 exp->p_flag |= P_WEXIT;
316670eb
A
1633 exp->p_stat = p->p_stat;
1634 exp->p_pid = p->p_pid;
1635 exp->p_oppid = p->p_oppid;
1c79356b 1636 /* Mach related */
316670eb
A
1637 exp->user_stack = p->user_stack;
1638 exp->p_debugger = p->p_debugger;
1639 exp->sigwait = p->sigwait;
1c79356b 1640 /* scheduling */
2d21ac55 1641#ifdef _PROC_HAS_SCHEDINFO_
316670eb
A
1642 exp->p_estcpu = p->p_estcpu;
1643 exp->p_pctcpu = p->p_pctcpu;
1644 exp->p_slptime = p->p_slptime;
2d21ac55 1645#endif
316670eb
A
1646 exp->p_realtimer.it_interval.tv_sec =
1647 (user32_time_t)p->p_realtimer.it_interval.tv_sec;
1648 exp->p_realtimer.it_interval.tv_usec =
1649 (__int32_t)p->p_realtimer.it_interval.tv_usec;
1650
1651 exp->p_realtimer.it_value.tv_sec =
1652 (user32_time_t)p->p_realtimer.it_value.tv_sec;
1653 exp->p_realtimer.it_value.tv_usec =
1654 (__int32_t)p->p_realtimer.it_value.tv_usec;
1655
1656 exp->p_rtime.tv_sec = (user32_time_t)p->p_rtime.tv_sec;
1657 exp->p_rtime.tv_usec = (__int32_t)p->p_rtime.tv_usec;
1658
1659 exp->p_sigignore = p->p_sigignore;
1660 exp->p_sigcatch = p->p_sigcatch;
1661 exp->p_priority = p->p_priority;
1662 exp->p_nice = p->p_nice;
1663 bcopy(&p->p_comm, &exp->p_comm, MAXCOMLEN);
1664 exp->p_xstat = p->p_xstat;
1665 exp->p_acflag = p->p_acflag;
91447636
A
1666}
1667
1668/*
1669 * Fill in an LP64 version of extern_proc structure for the specified process.
1670 */
6d2010ae 1671STATIC void
316670eb 1672fill_user64_externproc(proc_t p, struct user64_extern_proc *__restrict exp)
91447636 1673{
2d21ac55
A
1674 exp->p_starttime.tv_sec = p->p_start.tv_sec;
1675 exp->p_starttime.tv_usec = p->p_start.tv_usec;
316670eb 1676 exp->p_flag = p->p_flag;
2d21ac55
A
1677 if (p->p_lflag & P_LTRACED)
1678 exp->p_flag |= P_TRACED;
1679 if (p->p_lflag & P_LPPWAIT)
1680 exp->p_flag |= P_PPWAIT;
1681 if (p->p_lflag & P_LEXIT)
1682 exp->p_flag |= P_WEXIT;
316670eb
A
1683 exp->p_stat = p->p_stat;
1684 exp->p_pid = p->p_pid;
1685 exp->p_oppid = p->p_oppid;
91447636 1686 /* Mach related */
316670eb
A
1687 exp->user_stack = p->user_stack;
1688 exp->p_debugger = p->p_debugger;
1689 exp->sigwait = p->sigwait;
91447636 1690 /* scheduling */
2d21ac55 1691#ifdef _PROC_HAS_SCHEDINFO_
316670eb
A
1692 exp->p_estcpu = p->p_estcpu;
1693 exp->p_pctcpu = p->p_pctcpu;
1694 exp->p_slptime = p->p_slptime;
2d21ac55 1695#endif
91447636
A
1696 exp->p_realtimer.it_interval.tv_sec = p->p_realtimer.it_interval.tv_sec;
1697 exp->p_realtimer.it_interval.tv_usec = p->p_realtimer.it_interval.tv_usec;
316670eb 1698
91447636
A
1699 exp->p_realtimer.it_value.tv_sec = p->p_realtimer.it_value.tv_sec;
1700 exp->p_realtimer.it_value.tv_usec = p->p_realtimer.it_value.tv_usec;
316670eb 1701
91447636
A
1702 exp->p_rtime.tv_sec = p->p_rtime.tv_sec;
1703 exp->p_rtime.tv_usec = p->p_rtime.tv_usec;
316670eb
A
1704
1705 exp->p_sigignore = p->p_sigignore;
1706 exp->p_sigcatch = p->p_sigcatch;
1707 exp->p_priority = p->p_priority;
1708 exp->p_nice = p->p_nice;
1709 bcopy(&p->p_comm, &exp->p_comm, MAXCOMLEN);
1710 exp->p_xstat = p->p_xstat;
1711 exp->p_acflag = p->p_acflag;
1c79356b
A
1712}
1713
6d2010ae 1714STATIC void
316670eb 1715fill_user32_proc(proc_t p, struct user32_kinfo_proc *__restrict kp)
55e303ae 1716{
316670eb 1717 /* on a 64 bit kernel, 32 bit users get some truncated information */
b0d623f7
A
1718 fill_user32_externproc(p, &kp->kp_proc);
1719 fill_user32_eproc(p, &kp->kp_eproc);
55e303ae
A
1720}
1721
6d2010ae 1722STATIC void
316670eb 1723fill_user64_proc(proc_t p, struct user64_kinfo_proc *__restrict kp)
91447636 1724{
b0d623f7
A
1725 fill_user64_externproc(p, &kp->kp_proc);
1726 fill_user64_eproc(p, &kp->kp_eproc);
91447636
A
1727}
1728
6d2010ae
A
1729STATIC int
1730sysctl_kdebug_ops SYSCTL_HANDLER_ARGS
1c79356b 1731{
6d2010ae
A
1732 __unused int cmd = oidp->oid_arg2; /* subcommand*/
1733 int *name = arg1; /* oid element argument vector */
1734 int namelen = arg2; /* number of oid element arguments */
1735 user_addr_t oldp = req->oldptr; /* user buffer copy out address */
1736 size_t *oldlenp = &req->oldlen; /* user buffer copy out size */
1737// user_addr_t newp = req->newptr; /* user buffer copy in address */
1738// size_t newlen = req->newlen; /* user buffer copy in size */
1739
1740 proc_t p = current_proc();
9bccf70c 1741 int ret=0;
1c79356b 1742
c910b4d9
A
1743 if (namelen == 0)
1744 return(ENOTSUP);
b0d623f7 1745
6d2010ae 1746 ret = suser(kauth_cred_get(), &p->p_acflag);
39236c6e
A
1747#if KPERF
1748 /* Non-root processes may be blessed by kperf to access data
1749 * logged into trace.
1750 */
1751 if (ret)
1752 ret = kperf_access_check();
1753#endif /* KPERF */
91447636 1754 if (ret)
9bccf70c 1755 return(ret);
b0d623f7 1756
1c79356b
A
1757 switch(name[0]) {
1758 case KERN_KDEFLAGS:
1759 case KERN_KDDFLAGS:
1760 case KERN_KDENABLE:
1761 case KERN_KDGETBUF:
1762 case KERN_KDSETUP:
1763 case KERN_KDREMOVE:
1764 case KERN_KDSETREG:
1765 case KERN_KDGETREG:
1766 case KERN_KDREADTR:
6d2010ae
A
1767 case KERN_KDWRITETR:
1768 case KERN_KDWRITEMAP:
1c79356b
A
1769 case KERN_KDPIDTR:
1770 case KERN_KDTHRMAP:
1771 case KERN_KDPIDEX:
1772 case KERN_KDSETRTCDEC:
1773 case KERN_KDSETBUF:
9bccf70c 1774 case KERN_KDGETENTROPY:
316670eb
A
1775 case KERN_KDENABLE_BG_TRACE:
1776 case KERN_KDDISABLE_BG_TRACE:
39236c6e 1777 case KERN_KDREADCURTHRMAP:
316670eb 1778 case KERN_KDSET_TYPEFILTER:
39236c6e
A
1779 case KERN_KDBUFWAIT:
1780 case KERN_KDCPUMAP:
316670eb 1781
6d2010ae 1782 ret = kdbg_control(name, namelen, oldp, oldlenp);
1c79356b
A
1783 break;
1784 default:
91447636 1785 ret= ENOTSUP;
1c79356b
A
1786 break;
1787 }
6d2010ae
A
1788
1789 /* adjust index so we return the right required/consumed amount */
1790 if (!ret)
1791 req->oldidx += req->oldlen;
1792
1793 return (ret);
1c79356b 1794}
6d2010ae
A
1795SYSCTL_PROC(_kern, KERN_KDEBUG, kdebug, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED,
1796 0, /* Pointer argument (arg1) */
1797 0, /* Integer argument (arg2) */
1798 sysctl_kdebug_ops, /* Handler function */
1799 NULL, /* Data pointer */
1800 "");
1c79356b 1801
1c79356b
A
1802
1803/*
55e303ae
A
1804 * Return the top *sizep bytes of the user stack, or the entire area of the
1805 * user stack down through the saved exec_path, whichever is smaller.
1c79356b 1806 */
6d2010ae
A
1807STATIC int
1808sysctl_doprocargs SYSCTL_HANDLER_ARGS
1809{
1810 __unused int cmd = oidp->oid_arg2; /* subcommand*/
1811 int *name = arg1; /* oid element argument vector */
1812 int namelen = arg2; /* number of oid element arguments */
1813 user_addr_t oldp = req->oldptr; /* user buffer copy out address */
1814 size_t *oldlenp = &req->oldlen; /* user buffer copy out size */
1815// user_addr_t newp = req->newptr; /* user buffer copy in address */
1816// size_t newlen = req->newlen; /* user buffer copy in size */
1817 int error;
1818
1819 error = sysctl_procargsx( name, namelen, oldp, oldlenp, current_proc(), 0);
1820
1821 /* adjust index so we return the right required/consumed amount */
1822 if (!error)
1823 req->oldidx += req->oldlen;
1824
1825 return (error);
55e303ae 1826}
6d2010ae
A
1827SYSCTL_PROC(_kern, KERN_PROCARGS, procargs, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED,
1828 0, /* Pointer argument (arg1) */
1829 0, /* Integer argument (arg2) */
1830 sysctl_doprocargs, /* Handler function */
1831 NULL, /* Data pointer */
1832 "");
6d2010ae
A
1833
1834STATIC int
1835sysctl_doprocargs2 SYSCTL_HANDLER_ARGS
1836{
1837 __unused int cmd = oidp->oid_arg2; /* subcommand*/
1838 int *name = arg1; /* oid element argument vector */
1839 int namelen = arg2; /* number of oid element arguments */
1840 user_addr_t oldp = req->oldptr; /* user buffer copy out address */
1841 size_t *oldlenp = &req->oldlen; /* user buffer copy out size */
1842// user_addr_t newp = req->newptr; /* user buffer copy in address */
1843// size_t newlen = req->newlen; /* user buffer copy in size */
1844 int error;
55e303ae 1845
6d2010ae
A
1846 error = sysctl_procargsx( name, namelen, oldp, oldlenp, current_proc(), 1);
1847
1848 /* adjust index so we return the right required/consumed amount */
1849 if (!error)
1850 req->oldidx += req->oldlen;
1851
1852 return (error);
55e303ae 1853}
6d2010ae
A
1854SYSCTL_PROC(_kern, KERN_PROCARGS2, procargs2, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED,
1855 0, /* Pointer argument (arg1) */
1856 0, /* Integer argument (arg2) */
1857 sysctl_doprocargs2, /* Handler function */
1858 NULL, /* Data pointer */
1859 "");
55e303ae 1860
6d2010ae 1861STATIC int
c910b4d9 1862sysctl_procargsx(int *name, u_int namelen, user_addr_t where,
2d21ac55 1863 size_t *sizep, proc_t cur_proc, int argc_yes)
1c79356b 1864{
2d21ac55 1865 proc_t p;
91447636 1866 int buflen = where != USER_ADDR_NULL ? *sizep : 0;
1c79356b 1867 int error = 0;
2d21ac55 1868 struct _vm_map *proc_map;
1c79356b
A
1869 struct task * task;
1870 vm_map_copy_t tmp;
91447636
A
1871 user_addr_t arg_addr;
1872 size_t arg_size;
1c79356b 1873 caddr_t data;
2d21ac55 1874 size_t argslen=0;
91447636 1875 int size;
1c79356b 1876 vm_offset_t copy_start, copy_end;
1c79356b
A
1877 kern_return_t ret;
1878 int pid;
2d21ac55
A
1879 kauth_cred_t my_cred;
1880 uid_t uid;
1c79356b 1881
c910b4d9
A
1882 if ( namelen < 1 )
1883 return(EINVAL);
b0d623f7 1884
55e303ae 1885 if (argc_yes)
91447636 1886 buflen -= sizeof(int); /* reserve first word to return argc */
1c79356b 1887
91447636
A
1888 /* we only care about buflen when where (oldp from sysctl) is not NULL. */
1889 /* when where (oldp from sysctl) is NULL and sizep (oldlenp from sysctl */
1890 /* is not NULL then the caller wants us to return the length needed to */
1891 /* hold the data we would return */
1892 if (where != USER_ADDR_NULL && (buflen <= 0 || buflen > ARG_MAX)) {
1c79356b
A
1893 return(EINVAL);
1894 }
1895 arg_size = buflen;
1896
1897 /*
1898 * Lookup process by pid
1899 */
1900 pid = name[0];
2d21ac55 1901 p = proc_find(pid);
1c79356b
A
1902 if (p == NULL) {
1903 return(EINVAL);
1904 }
1905
1906 /*
1907 * Copy the top N bytes of the stack.
1908 * On all machines we have so far, the stack grows
1909 * downwards.
1910 *
1911 * If the user expects no more than N bytes of
1912 * argument list, use that as a guess for the
1913 * size.
1914 */
1915
2d21ac55
A
1916 if (!p->user_stack) {
1917 proc_rele(p);
1c79356b 1918 return(EINVAL);
2d21ac55 1919 }
1c79356b 1920
91447636
A
1921 if (where == USER_ADDR_NULL) {
1922 /* caller only wants to know length of proc args data */
2d21ac55
A
1923 if (sizep == NULL) {
1924 proc_rele(p);
91447636 1925 return(EFAULT);
2d21ac55 1926 }
91447636
A
1927
1928 size = p->p_argslen;
2d21ac55 1929 proc_rele(p);
91447636
A
1930 if (argc_yes) {
1931 size += sizeof(int);
1932 }
1933 else {
1934 /*
1935 * old PROCARGS will return the executable's path and plus some
1936 * extra space for work alignment and data tags
1937 */
1938 size += PATH_MAX + (6 * sizeof(int));
1939 }
1940 size += (size & (sizeof(int) - 1)) ? (sizeof(int) - (size & (sizeof(int) - 1))) : 0;
1941 *sizep = size;
1942 return (0);
1943 }
1944
2d21ac55
A
1945 my_cred = kauth_cred_proc_ref(p);
1946 uid = kauth_cred_getuid(my_cred);
1947 kauth_cred_unref(&my_cred);
1948
1949 if ((uid != kauth_cred_getuid(kauth_cred_get()))
1950 && suser(kauth_cred_get(), &cur_proc->p_acflag)) {
1951 proc_rele(p);
9bccf70c 1952 return (EINVAL);
2d21ac55 1953 }
91447636
A
1954
1955 if ((u_int)arg_size > p->p_argslen)
1956 arg_size = round_page(p->p_argslen);
1957
1958 arg_addr = p->user_stack - arg_size;
1c79356b
A
1959
1960
1961 /*
1962 * Before we can block (any VM code), make another
1963 * reference to the map to keep it alive. We do
1964 * that by getting a reference on the task itself.
1965 */
1966 task = p->task;
2d21ac55
A
1967 if (task == NULL) {
1968 proc_rele(p);
1c79356b 1969 return(EINVAL);
2d21ac55 1970 }
1c79356b 1971
2d21ac55 1972 argslen = p->p_argslen;
0b4e3aa0 1973 /*
91447636
A
1974 * Once we have a task reference we can convert that into a
1975 * map reference, which we will use in the calls below. The
1976 * task/process may change its map after we take this reference
1977 * (see execve), but the worst that will happen then is a return
1978 * of stale info (which is always a possibility).
0b4e3aa0 1979 */
91447636 1980 task_reference(task);
2d21ac55 1981 proc_rele(p);
91447636
A
1982 proc_map = get_task_map_reference(task);
1983 task_deallocate(task);
2d21ac55 1984
91447636
A
1985 if (proc_map == NULL)
1986 return(EINVAL);
1c79356b 1987
91447636
A
1988
1989 ret = kmem_alloc(kernel_map, &copy_start, round_page(arg_size));
1c79356b 1990 if (ret != KERN_SUCCESS) {
91447636 1991 vm_map_deallocate(proc_map);
1c79356b
A
1992 return(ENOMEM);
1993 }
1994
91447636 1995 copy_end = round_page(copy_start + arg_size);
1c79356b 1996
91447636
A
1997 if( vm_map_copyin(proc_map, (vm_map_address_t)arg_addr,
1998 (vm_map_size_t)arg_size, FALSE, &tmp) != KERN_SUCCESS) {
1999 vm_map_deallocate(proc_map);
1c79356b 2000 kmem_free(kernel_map, copy_start,
91447636 2001 round_page(arg_size));
1c79356b
A
2002 return (EIO);
2003 }
2004
2005 /*
2006 * Now that we've done the copyin from the process'
2007 * map, we can release the reference to it.
2008 */
91447636 2009 vm_map_deallocate(proc_map);
1c79356b 2010
91447636
A
2011 if( vm_map_copy_overwrite(kernel_map,
2012 (vm_map_address_t)copy_start,
2013 tmp, FALSE) != KERN_SUCCESS) {
1c79356b 2014 kmem_free(kernel_map, copy_start,
91447636 2015 round_page(arg_size));
1c79356b
A
2016 return (EIO);
2017 }
2018
2d21ac55
A
2019 if (arg_size > argslen) {
2020 data = (caddr_t) (copy_end - argslen);
2021 size = argslen;
55e303ae 2022 } else {
91447636
A
2023 data = (caddr_t) (copy_end - arg_size);
2024 size = arg_size;
55e303ae 2025 }
1c79356b 2026
55e303ae
A
2027 if (argc_yes) {
2028 /* Put processes argc as the first word in the copyout buffer */
2029 suword(where, p->p_argc);
91447636
A
2030 error = copyout(data, (where + sizeof(int)), size);
2031 size += sizeof(int);
55e303ae
A
2032 } else {
2033 error = copyout(data, where, size);
2034
2035 /*
2036 * Make the old PROCARGS work to return the executable's path
2037 * But, only if there is enough space in the provided buffer
2038 *
2039 * on entry: data [possibily] points to the beginning of the path
2040 *
2041 * Note: we keep all pointers&sizes aligned to word boundries
2042 */
2d21ac55 2043 if ( (! error) && (buflen > 0 && (u_int)buflen > argslen) )
55e303ae 2044 {
91447636 2045 int binPath_sz, alignedBinPath_sz = 0;
55e303ae 2046 int extraSpaceNeeded, addThis;
91447636 2047 user_addr_t placeHere;
55e303ae 2048 char * str = (char *) data;
91447636 2049 int max_len = size;
55e303ae
A
2050
2051 /* Some apps are really bad about messing up their stacks
2052 So, we have to be extra careful about getting the length
2053 of the executing binary. If we encounter an error, we bail.
2054 */
2055
2056 /* Limit ourselves to PATH_MAX paths */
2057 if ( max_len > PATH_MAX ) max_len = PATH_MAX;
2058
2059 binPath_sz = 0;
2060
2061 while ( (binPath_sz < max_len-1) && (*str++ != 0) )
2062 binPath_sz++;
2063
91447636 2064 /* If we have a NUL terminator, copy it, too */
55e303ae
A
2065 if (binPath_sz < max_len-1) binPath_sz += 1;
2066
2067 /* Pre-Flight the space requiremnts */
2068
2069 /* Account for the padding that fills out binPath to the next word */
91447636 2070 alignedBinPath_sz += (binPath_sz & (sizeof(int)-1)) ? (sizeof(int)-(binPath_sz & (sizeof(int)-1))) : 0;
55e303ae
A
2071
2072 placeHere = where + size;
2073
2074 /* Account for the bytes needed to keep placeHere word aligned */
91447636 2075 addThis = (placeHere & (sizeof(int)-1)) ? (sizeof(int)-(placeHere & (sizeof(int)-1))) : 0;
55e303ae
A
2076
2077 /* Add up all the space that is needed */
91447636 2078 extraSpaceNeeded = alignedBinPath_sz + addThis + binPath_sz + (4 * sizeof(int));
55e303ae
A
2079
2080 /* is there is room to tack on argv[0]? */
2d21ac55 2081 if ( (buflen & ~(sizeof(int)-1)) >= ( argslen + extraSpaceNeeded ))
55e303ae
A
2082 {
2083 placeHere += addThis;
2084 suword(placeHere, 0);
91447636 2085 placeHere += sizeof(int);
55e303ae 2086 suword(placeHere, 0xBFFF0000);
91447636 2087 placeHere += sizeof(int);
55e303ae 2088 suword(placeHere, 0);
91447636 2089 placeHere += sizeof(int);
55e303ae
A
2090 error = copyout(data, placeHere, binPath_sz);
2091 if ( ! error )
2092 {
2093 placeHere += binPath_sz;
2094 suword(placeHere, 0);
2095 size += extraSpaceNeeded;
2096 }
2097 }
2098 }
2099 }
2100
2101 if (copy_start != (vm_offset_t) 0) {
2102 kmem_free(kernel_map, copy_start, copy_end - copy_start);
1c79356b
A
2103 }
2104 if (error) {
2105 return(error);
2106 }
2107
91447636 2108 if (where != USER_ADDR_NULL)
1c79356b
A
2109 *sizep = size;
2110 return (0);
2111}
55e303ae
A
2112
2113
2114/*
2d21ac55 2115 * Max number of concurrent aio requests
55e303ae 2116 */
6d2010ae 2117STATIC int
2d21ac55
A
2118sysctl_aiomax
2119(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
55e303ae 2120{
2d21ac55
A
2121 int new_value, changed;
2122 int error = sysctl_io_number(req, aio_max_requests, sizeof(int), &new_value, &changed);
2123 if (changed) {
2124 /* make sure the system-wide limit is greater than the per process limit */
316670eb 2125 if (new_value >= aio_max_requests_per_process && new_value <= AIO_MAX_REQUESTS)
55e303ae
A
2126 aio_max_requests = new_value;
2127 else
2128 error = EINVAL;
2129 }
2d21ac55
A
2130 return(error);
2131}
55e303ae
A
2132
2133
2134/*
2d21ac55 2135 * Max number of concurrent aio requests per process
55e303ae 2136 */
6d2010ae 2137STATIC int
2d21ac55
A
2138sysctl_aioprocmax
2139(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
55e303ae 2140{
2d21ac55
A
2141 int new_value, changed;
2142 int error = sysctl_io_number(req, aio_max_requests_per_process, sizeof(int), &new_value, &changed);
2143 if (changed) {
2144 /* make sure per process limit is less than the system-wide limit */
2145 if (new_value <= aio_max_requests && new_value >= AIO_LISTIO_MAX)
55e303ae
A
2146 aio_max_requests_per_process = new_value;
2147 else
2148 error = EINVAL;
2149 }
2d21ac55
A
2150 return(error);
2151}
55e303ae
A
2152
2153
2154/*
2d21ac55 2155 * Max number of async IO worker threads
55e303ae 2156 */
6d2010ae 2157STATIC int
2d21ac55
A
2158sysctl_aiothreads
2159(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
55e303ae 2160{
2d21ac55
A
2161 int new_value, changed;
2162 int error = sysctl_io_number(req, aio_worker_threads, sizeof(int), &new_value, &changed);
2163 if (changed) {
2164 /* we only allow an increase in the number of worker threads */
55e303ae 2165 if (new_value > aio_worker_threads ) {
2d21ac55 2166 _aio_create_worker_threads((new_value - aio_worker_threads));
55e303ae
A
2167 aio_worker_threads = new_value;
2168 }
2169 else
2170 error = EINVAL;
2171 }
2d21ac55
A
2172 return(error);
2173}
55e303ae
A
2174
2175
2176/*
2d21ac55 2177 * System-wide limit on the max number of processes
55e303ae 2178 */
6d2010ae 2179STATIC int
2d21ac55
A
2180sysctl_maxproc
2181(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
55e303ae 2182{
2d21ac55
A
2183 int new_value, changed;
2184 int error = sysctl_io_number(req, maxproc, sizeof(int), &new_value, &changed);
2185 if (changed) {
b0d623f7 2186 AUDIT_ARG(value32, new_value);
2d21ac55
A
2187 /* make sure the system-wide limit is less than the configured hard
2188 limit set at kernel compilation */
2189 if (new_value <= hard_maxproc && new_value > 0)
2190 maxproc = new_value;
2191 else
55e303ae
A
2192 error = EINVAL;
2193 }
2d21ac55
A
2194 return(error);
2195}
55e303ae 2196
2d21ac55 2197SYSCTL_STRING(_kern, KERN_OSTYPE, ostype,
6d2010ae 2198 CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
2d21ac55
A
2199 ostype, 0, "");
2200SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease,
6d2010ae 2201 CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
2d21ac55
A
2202 osrelease, 0, "");
2203SYSCTL_INT(_kern, KERN_OSREV, osrevision,
6d2010ae 2204 CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
b0d623f7 2205 (int *)NULL, BSD, "");
2d21ac55 2206SYSCTL_STRING(_kern, KERN_VERSION, version,
6d2010ae 2207 CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
2d21ac55 2208 version, 0, "");
6d2010ae
A
2209SYSCTL_STRING(_kern, OID_AUTO, uuid,
2210 CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
39236c6e 2211 &kernel_uuid_string[0], 0, "");
2d21ac55 2212
b0d623f7
A
2213#if DEBUG
2214int debug_kprint_syscall = 0;
2215char debug_kprint_syscall_process[MAXCOMLEN+1];
2216
6d2010ae 2217/* Thread safe: bits and string value are not used to reclaim state */
b0d623f7 2218SYSCTL_INT (_debug, OID_AUTO, kprint_syscall,
6d2010ae 2219 CTLFLAG_RW | CTLFLAG_LOCKED, &debug_kprint_syscall, 0, "kprintf syscall tracing");
b0d623f7 2220SYSCTL_STRING(_debug, OID_AUTO, kprint_syscall_process,
6d2010ae 2221 CTLFLAG_RW | CTLFLAG_LOCKED, debug_kprint_syscall_process, sizeof(debug_kprint_syscall_process),
b0d623f7
A
2222 "name of process for kprintf syscall tracing");
2223
2224int debug_kprint_current_process(const char **namep)
2225{
2226 struct proc *p = current_proc();
2227
2228 if (p == NULL) {
2229 return 0;
2230 }
2231
2232 if (debug_kprint_syscall_process[0]) {
2233 /* user asked to scope tracing to a particular process name */
2234 if(0 == strncmp(debug_kprint_syscall_process,
2235 p->p_comm, sizeof(debug_kprint_syscall_process))) {
2236 /* no value in telling the user that we traced what they asked */
2237 if(namep) *namep = NULL;
2238
2239 return 1;
2240 } else {
2241 return 0;
2242 }
2243 }
2244
2245 /* trace all processes. Tell user what we traced */
2246 if (namep) {
2247 *namep = p->p_comm;
2248 }
2249
2250 return 1;
2251}
2252#endif
2253
2d21ac55
A
2254/* PR-5293665: need to use a callback function for kern.osversion to set
2255 * osversion in IORegistry */
55e303ae 2256
6d2010ae 2257STATIC int
2d21ac55 2258sysctl_osversion(__unused struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req)
55e303ae 2259{
2d21ac55 2260 int rval = 0;
55e303ae 2261
2d21ac55
A
2262 rval = sysctl_handle_string(oidp, arg1, arg2, req);
2263
2264 if (req->newptr) {
2265 IORegistrySetOSBuildVersion((char *)arg1);
2266 }
2267
2268 return rval;
2269}
2270
2271SYSCTL_PROC(_kern, KERN_OSVERSION, osversion,
6d2010ae 2272 CTLFLAG_RW | CTLFLAG_KERN | CTLTYPE_STRING | CTLFLAG_LOCKED,
2d21ac55
A
2273 osversion, 256 /* OSVERSIZE*/,
2274 sysctl_osversion, "A", "");
2275
6d2010ae 2276STATIC int
2d21ac55
A
2277sysctl_sysctl_bootargs
2278(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2279{
2280 int error;
2281 char buf[256];
2282
2283 strlcpy(buf, PE_boot_args(), 256);
2284 error = sysctl_io_string(req, buf, 256, 0, NULL);
2285 return(error);
2286}
2287
2288SYSCTL_PROC(_kern, OID_AUTO, bootargs,
2289 CTLFLAG_LOCKED | CTLFLAG_RD | CTLFLAG_KERN | CTLTYPE_STRING,
2290 NULL, 0,
2291 sysctl_sysctl_bootargs, "A", "bootargs");
2292
2293SYSCTL_INT(_kern, KERN_MAXFILES, maxfiles,
6d2010ae 2294 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2d21ac55
A
2295 &maxfiles, 0, "");
2296SYSCTL_INT(_kern, KERN_ARGMAX, argmax,
6d2010ae 2297 CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
b0d623f7 2298 (int *)NULL, ARG_MAX, "");
2d21ac55 2299SYSCTL_INT(_kern, KERN_POSIX1, posix1version,
6d2010ae 2300 CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
b0d623f7 2301 (int *)NULL, _POSIX_VERSION, "");
2d21ac55 2302SYSCTL_INT(_kern, KERN_NGROUPS, ngroups,
6d2010ae 2303 CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
b0d623f7 2304 (int *)NULL, NGROUPS_MAX, "");
2d21ac55 2305SYSCTL_INT(_kern, KERN_JOB_CONTROL, job_control,
6d2010ae 2306 CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
b0d623f7 2307 (int *)NULL, 1, "");
2d21ac55
A
2308#if 1 /* _POSIX_SAVED_IDS from <unistd.h> */
2309SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids,
6d2010ae 2310 CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
b0d623f7 2311 (int *)NULL, 1, "");
2d21ac55
A
2312#else
2313SYSCTL_INT(_kern, KERN_SAVED_IDS, saved_ids,
6d2010ae 2314 CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
2d21ac55
A
2315 NULL, 0, "");
2316#endif
b0d623f7 2317SYSCTL_INT(_kern, OID_AUTO, num_files,
6d2010ae 2318 CTLFLAG_RD | CTLFLAG_LOCKED,
b0d623f7
A
2319 &nfiles, 0, "");
2320SYSCTL_COMPAT_INT(_kern, OID_AUTO, num_vnodes,
6d2010ae 2321 CTLFLAG_RD | CTLFLAG_LOCKED,
b0d623f7
A
2322 &numvnodes, 0, "");
2323SYSCTL_INT(_kern, OID_AUTO, num_tasks,
6d2010ae 2324 CTLFLAG_RD | CTLFLAG_LOCKED,
b0d623f7
A
2325 &task_max, 0, "");
2326SYSCTL_INT(_kern, OID_AUTO, num_threads,
6d2010ae 2327 CTLFLAG_RD | CTLFLAG_LOCKED,
b0d623f7
A
2328 &thread_max, 0, "");
2329SYSCTL_INT(_kern, OID_AUTO, num_taskthreads,
6d2010ae 2330 CTLFLAG_RD | CTLFLAG_LOCKED,
b0d623f7 2331 &task_threadmax, 0, "");
2d21ac55 2332
6d2010ae 2333STATIC int
2d21ac55
A
2334sysctl_maxvnodes (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2335{
b0d623f7 2336 int oldval = desiredvnodes;
2d21ac55 2337 int error = sysctl_io_number(req, desiredvnodes, sizeof(int), &desiredvnodes, NULL);
b0d623f7
A
2338
2339 if (oldval != desiredvnodes) {
2340 reset_vmobjectcache(oldval, desiredvnodes);
2341 resize_namecache(desiredvnodes);
2342 }
2343
2d21ac55
A
2344 return(error);
2345}
2346
6d2010ae
A
2347SYSCTL_INT(_kern, OID_AUTO, namecache_disabled,
2348 CTLFLAG_RW | CTLFLAG_LOCKED,
2349 &nc_disabled, 0, "");
2350
2d21ac55 2351SYSCTL_PROC(_kern, KERN_MAXVNODES, maxvnodes,
6d2010ae 2352 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
2d21ac55
A
2353 0, 0, sysctl_maxvnodes, "I", "");
2354
2355SYSCTL_PROC(_kern, KERN_MAXPROC, maxproc,
6d2010ae 2356 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
2d21ac55
A
2357 0, 0, sysctl_maxproc, "I", "");
2358
2359SYSCTL_PROC(_kern, KERN_AIOMAX, aiomax,
6d2010ae 2360 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
2d21ac55
A
2361 0, 0, sysctl_aiomax, "I", "");
2362
2363SYSCTL_PROC(_kern, KERN_AIOPROCMAX, aioprocmax,
6d2010ae 2364 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
2d21ac55
A
2365 0, 0, sysctl_aioprocmax, "I", "");
2366
2367SYSCTL_PROC(_kern, KERN_AIOTHREADS, aiothreads,
6d2010ae 2368 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
2d21ac55
A
2369 0, 0, sysctl_aiothreads, "I", "");
2370
6d2010ae 2371STATIC int
2d21ac55
A
2372sysctl_securelvl
2373(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2374{
2375 int new_value, changed;
2376 int error = sysctl_io_number(req, securelevel, sizeof(int), &new_value, &changed);
2377 if (changed) {
2378 if (!(new_value < securelevel && req->p->p_pid != 1)) {
2379 proc_list_lock();
2380 securelevel = new_value;
2381 proc_list_unlock();
2382 } else {
2383 error = EPERM;
e5568f75 2384 }
2d21ac55
A
2385 }
2386 return(error);
2387}
2388
2389SYSCTL_PROC(_kern, KERN_SECURELVL, securelevel,
6d2010ae 2390 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
2d21ac55
A
2391 0, 0, sysctl_securelvl, "I", "");
2392
2393
6d2010ae 2394STATIC int
2d21ac55
A
2395sysctl_domainname
2396(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2397{
2398 int error, changed;
2399 error = sysctl_io_string(req, domainname, sizeof(domainname), 0, &changed);
2400 if (changed) {
2401 domainnamelen = strlen(domainname);
2402 }
2403 return(error);
2404}
2405
2406SYSCTL_PROC(_kern, KERN_DOMAINNAME, nisdomainname,
6d2010ae 2407 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_LOCKED,
2d21ac55
A
2408 0, 0, sysctl_domainname, "A", "");
2409
b0d623f7 2410SYSCTL_COMPAT_INT(_kern, KERN_HOSTID, hostid,
6d2010ae 2411 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2d21ac55
A
2412 &hostid, 0, "");
2413
6d2010ae 2414STATIC int
2d21ac55
A
2415sysctl_hostname
2416(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2417{
2418 int error, changed;
2419 error = sysctl_io_string(req, hostname, sizeof(hostname), 1, &changed);
2420 if (changed) {
2421 hostnamelen = req->newlen;
2422 }
2423 return(error);
2424}
2425
2426
2427SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname,
6d2010ae 2428 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_LOCKED,
2d21ac55
A
2429 0, 0, sysctl_hostname, "A", "");
2430
6d2010ae 2431STATIC int
2d21ac55
A
2432sysctl_procname
2433(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2434{
2435 /* Original code allowed writing, I'm copying this, although this all makes
2436 no sense to me. Besides, this sysctl is never used. */
2437 return sysctl_io_string(req, &req->p->p_name[0], (2*MAXCOMLEN+1), 1, NULL);
2438}
2439
2440SYSCTL_PROC(_kern, KERN_PROCNAME, procname,
6d2010ae 2441 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED,
2d21ac55
A
2442 0, 0, sysctl_procname, "A", "");
2443
2444SYSCTL_INT(_kern, KERN_SPECULATIVE_READS, speculative_reads_disabled,
6d2010ae 2445 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2d21ac55
A
2446 &speculative_reads_disabled, 0, "");
2447
6d2010ae
A
2448SYSCTL_INT(_kern, OID_AUTO, ignore_is_ssd,
2449 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2450 &ignore_is_ssd, 0, "");
2451
b0d623f7 2452SYSCTL_UINT(_kern, OID_AUTO, preheat_pages_max,
6d2010ae 2453 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
b0d623f7
A
2454 &preheat_pages_max, 0, "");
2455
2456SYSCTL_UINT(_kern, OID_AUTO, preheat_pages_min,
6d2010ae 2457 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
b0d623f7
A
2458 &preheat_pages_min, 0, "");
2459
6d2010ae
A
2460SYSCTL_UINT(_kern, OID_AUTO, speculative_prefetch_max,
2461 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2462 &speculative_prefetch_max, 0, "");
b0d623f7 2463
316670eb
A
2464SYSCTL_UINT(_kern, OID_AUTO, speculative_prefetch_max_iosize,
2465 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2466 &speculative_prefetch_max_iosize, 0, "");
2467
6d2010ae
A
2468SYSCTL_UINT(_kern, OID_AUTO, vm_page_free_target,
2469 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2470 &vm_page_free_target, 0, "");
2471
2472SYSCTL_UINT(_kern, OID_AUTO, vm_page_free_min,
2473 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2474 &vm_page_free_min, 0, "");
2475
2476SYSCTL_UINT(_kern, OID_AUTO, vm_page_free_reserved,
2477 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2478 &vm_page_free_reserved, 0, "");
2479
2480SYSCTL_UINT(_kern, OID_AUTO, vm_page_speculative_percentage,
2481 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2482 &vm_page_speculative_percentage, 0, "");
2483
2484SYSCTL_UINT(_kern, OID_AUTO, vm_page_speculative_q_age_ms,
2485 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2486 &vm_page_speculative_q_age_ms, 0, "");
2487
2488SYSCTL_UINT(_kern, OID_AUTO, vm_max_delayed_work_limit,
2489 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2490 &vm_max_delayed_work_limit, 0, "");
2491
2492SYSCTL_UINT(_kern, OID_AUTO, vm_max_batch,
2493 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2494 &vm_max_batch, 0, "");
2495
39236c6e
A
2496SYSCTL_STRING(_kern, OID_AUTO, bootsessionuuid,
2497 CTLFLAG_RD | CTLFLAG_LOCKED,
2498 &bootsessionuuid_string, sizeof(bootsessionuuid_string) , "");
6d2010ae
A
2499
2500STATIC int
2d21ac55
A
2501sysctl_boottime
2502(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2503{
b0d623f7
A
2504 time_t tv_sec = boottime_sec();
2505 struct proc *p = req->p;
2d21ac55 2506
b0d623f7
A
2507 if (proc_is64bit(p)) {
2508 struct user64_timeval t;
2509 t.tv_sec = tv_sec;
2510 t.tv_usec = 0;
2511 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
2512 } else {
2513 struct user32_timeval t;
2514 t.tv_sec = tv_sec;
2515 t.tv_usec = 0;
2516 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
2517 }
2d21ac55
A
2518}
2519
2520SYSCTL_PROC(_kern, KERN_BOOTTIME, boottime,
6d2010ae 2521 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
2d21ac55
A
2522 0, 0, sysctl_boottime, "S,timeval", "");
2523
6d2010ae 2524STATIC int
2d21ac55
A
2525sysctl_symfile
2526(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2527{
2528 char *str;
2529 int error = get_kernel_symfile(req->p, &str);
2530 if (error)
2531 return (error);
2532 return sysctl_io_string(req, str, 0, 0, NULL);
2533}
2534
2535
2536SYSCTL_PROC(_kern, KERN_SYMFILE, symfile,
6d2010ae 2537 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_LOCKED,
2d21ac55
A
2538 0, 0, sysctl_symfile, "A", "");
2539
2540#if NFSCLIENT
6d2010ae 2541STATIC int
2d21ac55
A
2542sysctl_netboot
2543(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2544{
2545 return sysctl_io_number(req, netboot_root(), sizeof(int), NULL, NULL);
2546}
2547
2548SYSCTL_PROC(_kern, KERN_NETBOOT, netboot,
6d2010ae 2549 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED,
2d21ac55
A
2550 0, 0, sysctl_netboot, "I", "");
2551#endif
2552
b7266188 2553#ifdef CONFIG_IMGSRC_ACCESS
6d2010ae
A
2554/*
2555 * Legacy--act as if only one layer of nesting is possible.
2556 */
2557STATIC int
b7266188
A
2558sysctl_imgsrcdev
2559(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2560{
2561 vfs_context_t ctx = vfs_context_current();
2562 vnode_t devvp;
2563 int result;
2564
2565 if (!vfs_context_issuser(ctx)) {
2566 return EPERM;
2567 }
2568
6d2010ae 2569 if (imgsrc_rootvnodes[0] == NULL) {
b7266188
A
2570 return ENOENT;
2571 }
2572
6d2010ae 2573 result = vnode_getwithref(imgsrc_rootvnodes[0]);
b7266188
A
2574 if (result != 0) {
2575 return result;
2576 }
2577
6d2010ae 2578 devvp = vnode_mount(imgsrc_rootvnodes[0])->mnt_devvp;
b7266188
A
2579 result = vnode_getwithref(devvp);
2580 if (result != 0) {
2581 goto out;
2582 }
2583
2584 result = sysctl_io_number(req, vnode_specrdev(devvp), sizeof(dev_t), NULL, NULL);
2585
2586 vnode_put(devvp);
2587out:
6d2010ae 2588 vnode_put(imgsrc_rootvnodes[0]);
b7266188
A
2589 return result;
2590}
2591
2592SYSCTL_PROC(_kern, OID_AUTO, imgsrcdev,
6d2010ae 2593 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED,
b7266188 2594 0, 0, sysctl_imgsrcdev, "I", "");
6d2010ae
A
2595
2596STATIC int
2597sysctl_imgsrcinfo
2598(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2599{
2600 int error;
2601 struct imgsrc_info info[MAX_IMAGEBOOT_NESTING]; /* 2 for now, no problem */
2602 uint32_t i;
2603 vnode_t rvp, devvp;
2604
2605 if (imgsrc_rootvnodes[0] == NULLVP) {
2606 return ENXIO;
2607 }
2608
2609 for (i = 0; i < MAX_IMAGEBOOT_NESTING; i++) {
2610 /*
2611 * Go get the root vnode.
2612 */
2613 rvp = imgsrc_rootvnodes[i];
2614 if (rvp == NULLVP) {
2615 break;
2616 }
2617
2618 error = vnode_get(rvp);
2619 if (error != 0) {
2620 return error;
2621 }
2622
2623 /*
2624 * For now, no getting at a non-local volume.
2625 */
2626 devvp = vnode_mount(rvp)->mnt_devvp;
2627 if (devvp == NULL) {
2628 vnode_put(rvp);
2629 return EINVAL;
2630 }
2631
2632 error = vnode_getwithref(devvp);
2633 if (error != 0) {
2634 vnode_put(rvp);
2635 return error;
2636 }
2637
2638 /*
2639 * Fill in info.
2640 */
2641 info[i].ii_dev = vnode_specrdev(devvp);
2642 info[i].ii_flags = 0;
2643 info[i].ii_height = i;
2644 bzero(info[i].ii_reserved, sizeof(info[i].ii_reserved));
2645
2646 vnode_put(devvp);
2647 vnode_put(rvp);
2648 }
2649
2650 return sysctl_io_opaque(req, info, i * sizeof(info[0]), NULL);
2651}
2652
2653SYSCTL_PROC(_kern, OID_AUTO, imgsrcinfo,
2654 CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_LOCKED,
2655 0, 0, sysctl_imgsrcinfo, "I", "");
2656
b7266188
A
2657#endif /* CONFIG_IMGSRC_ACCESS */
2658
39236c6e
A
2659
2660SYSCTL_DECL(_kern_timer);
2661SYSCTL_NODE(_kern, OID_AUTO, timer, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "timer");
2662
2663SYSCTL_INT(_kern_timer, OID_AUTO, coalescing_enabled,
2664 CTLFLAG_KERN | CTLFLAG_RW | CTLFLAG_LOCKED,
6d2010ae
A
2665 &mach_timer_coalescing_enabled, 0, "");
2666
39236c6e
A
2667SYSCTL_QUAD(_kern_timer, OID_AUTO, deadline_tracking_bin_1,
2668 CTLFLAG_RW | CTLFLAG_LOCKED,
2669 &timer_deadline_tracking_bin_1, "");
2670SYSCTL_QUAD(_kern_timer, OID_AUTO, deadline_tracking_bin_2,
2671 CTLFLAG_RW | CTLFLAG_LOCKED,
2672 &timer_deadline_tracking_bin_2, "");
2673
2674SYSCTL_DECL(_kern_timer_longterm);
2675SYSCTL_NODE(_kern_timer, OID_AUTO, longterm, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "longterm");
2676
2677/* Must match definition in osfmk/kern/timer_call.c */
2678enum {
2679 THRESHOLD, QCOUNT,
2680 ENQUEUES, DEQUEUES, ESCALATES, SCANS, PREEMPTS,
2681 LATENCY, LATENCY_MIN, LATENCY_MAX
2682};
2683extern uint64_t timer_sysctl_get(int);
2684extern int timer_sysctl_set(int, uint64_t);
2685
2686STATIC int
2687sysctl_timer
2688(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2689{
2690 int oid = (int)arg1;
2691 uint64_t value = timer_sysctl_get(oid);
2692 uint64_t new_value;
2693 int error;
2694 int changed;
2695
2696 error = sysctl_io_number(req, value, sizeof(value), &new_value, &changed);
2697 if (changed)
2698 error = timer_sysctl_set(oid, new_value);
2699
2700 return error;
2701}
2702
2703SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, threshold,
2704 CTLTYPE_QUAD | CTLFLAG_RW | CTLFLAG_LOCKED,
2705 (void *) THRESHOLD, 0, sysctl_timer, "Q", "");
2706SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, qlen,
2707 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED,
2708 (void *) QCOUNT, 0, sysctl_timer, "Q", "");
2709#if DEBUG
2710SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, enqueues,
2711 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED,
2712 (void *) ENQUEUES, 0, sysctl_timer, "Q", "");
2713SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, dequeues,
2714 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED,
2715 (void *) DEQUEUES, 0, sysctl_timer, "Q", "");
2716SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, escalates,
2717 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED,
2718 (void *) ESCALATES, 0, sysctl_timer, "Q", "");
2719SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, scans,
2720 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED,
2721 (void *) SCANS, 0, sysctl_timer, "Q", "");
2722SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, preempts,
2723 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED,
2724 (void *) PREEMPTS, 0, sysctl_timer, "Q", "");
2725SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, latency,
2726 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED,
2727 (void *) LATENCY, 0, sysctl_timer, "Q", "");
2728SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, latency_min,
2729 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED,
2730 (void *) LATENCY_MIN, 0, sysctl_timer, "Q", "");
2731SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, latency_max,
2732 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED,
2733 (void *) LATENCY_MAX, 0, sysctl_timer, "Q", "");
2734#endif /* DEBUG */
2735
6d2010ae 2736STATIC int
2d21ac55
A
2737sysctl_usrstack
2738(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2739{
2740 return sysctl_io_number(req, (int)req->p->user_stack, sizeof(int), NULL, NULL);
2741}
2742
b0d623f7 2743SYSCTL_PROC(_kern, KERN_USRSTACK32, usrstack,
6d2010ae 2744 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED,
2d21ac55
A
2745 0, 0, sysctl_usrstack, "I", "");
2746
6d2010ae 2747STATIC int
2d21ac55
A
2748sysctl_usrstack64
2749(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2750{
2751 return sysctl_io_number(req, req->p->user_stack, sizeof(req->p->user_stack), NULL, NULL);
2752}
2753
2754SYSCTL_PROC(_kern, KERN_USRSTACK64, usrstack64,
6d2010ae 2755 CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED,
2d21ac55
A
2756 0, 0, sysctl_usrstack64, "Q", "");
2757
2758SYSCTL_STRING(_kern, KERN_COREFILE, corefile,
6d2010ae 2759 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2d21ac55
A
2760 corefilename, sizeof(corefilename), "");
2761
6d2010ae 2762STATIC int
2d21ac55
A
2763sysctl_coredump
2764(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2765{
593a1d5f
A
2766#ifdef SECURE_KERNEL
2767 return (ENOTSUP);
2768#endif
2d21ac55
A
2769 int new_value, changed;
2770 int error = sysctl_io_number(req, do_coredump, sizeof(int), &new_value, &changed);
2771 if (changed) {
2772 if ((new_value == 0) || (new_value == 1))
2773 do_coredump = new_value;
2774 else
2775 error = EINVAL;
2776 }
2777 return(error);
2778}
2779
2780SYSCTL_PROC(_kern, KERN_COREDUMP, coredump,
6d2010ae 2781 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
2d21ac55
A
2782 0, 0, sysctl_coredump, "I", "");
2783
6d2010ae 2784STATIC int
2d21ac55
A
2785sysctl_suid_coredump
2786(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2787{
593a1d5f
A
2788#ifdef SECURE_KERNEL
2789 return (ENOTSUP);
2790#endif
2d21ac55
A
2791 int new_value, changed;
2792 int error = sysctl_io_number(req, sugid_coredump, sizeof(int), &new_value, &changed);
2793 if (changed) {
2794 if ((new_value == 0) || (new_value == 1))
2795 sugid_coredump = new_value;
55e303ae
A
2796 else
2797 error = EINVAL;
2798 }
2d21ac55
A
2799 return(error);
2800}
2801
2802SYSCTL_PROC(_kern, KERN_SUGID_COREDUMP, sugid_coredump,
6d2010ae 2803 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
2d21ac55
A
2804 0, 0, sysctl_suid_coredump, "I", "");
2805
6d2010ae 2806STATIC int
2d21ac55
A
2807sysctl_delayterm
2808(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2809{
2810 struct proc *p = req->p;
2811 int new_value, changed;
2812 int error = sysctl_io_number(req, (req->p->p_lflag & P_LDELAYTERM)? 1: 0, sizeof(int), &new_value, &changed);
2813 if (changed) {
2814 proc_lock(p);
2815 if (new_value)
2816 req->p->p_lflag |= P_LDELAYTERM;
2817 else
2818 req->p->p_lflag &= ~P_LDELAYTERM;
2819 proc_unlock(p);
2820 }
2821 return(error);
2822}
2823
2824SYSCTL_PROC(_kern, KERN_PROCDELAYTERM, delayterm,
6d2010ae 2825 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
2d21ac55
A
2826 0, 0, sysctl_delayterm, "I", "");
2827
55e303ae 2828
6d2010ae 2829STATIC int
2d21ac55
A
2830sysctl_rage_vnode
2831(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
55e303ae 2832{
2d21ac55
A
2833 struct proc *p = req->p;
2834 struct uthread *ut;
2835 int new_value, old_value, changed;
2836 int error;
55e303ae 2837
2d21ac55
A
2838 ut = get_bsdthread_info(current_thread());
2839
2840 if (ut->uu_flag & UT_RAGE_VNODES)
2841 old_value = KERN_RAGE_THREAD;
2842 else if (p->p_lflag & P_LRAGE_VNODES)
2843 old_value = KERN_RAGE_PROC;
2844 else
2845 old_value = 0;
2846
2847 error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
2848
2849 if (error == 0) {
2850 switch (new_value) {
2851 case KERN_RAGE_PROC:
2852 proc_lock(p);
2853 p->p_lflag |= P_LRAGE_VNODES;
2854 proc_unlock(p);
2855 break;
2856 case KERN_UNRAGE_PROC:
2857 proc_lock(p);
2858 p->p_lflag &= ~P_LRAGE_VNODES;
2859 proc_unlock(p);
2860 break;
2861
2862 case KERN_RAGE_THREAD:
2863 ut->uu_flag |= UT_RAGE_VNODES;
2864 break;
2865 case KERN_UNRAGE_THREAD:
2866 ut = get_bsdthread_info(current_thread());
2867 ut->uu_flag &= ~UT_RAGE_VNODES;
2868 break;
e5568f75 2869 }
2d21ac55
A
2870 }
2871 return(error);
2872}
2873
2874SYSCTL_PROC(_kern, KERN_RAGEVNODE, rage_vnode,
6d2010ae 2875 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED,
2d21ac55
A
2876 0, 0, sysctl_rage_vnode, "I", "");
2877
316670eb
A
2878/* XXX move this interface into libproc and remove this sysctl */
2879STATIC int
2880sysctl_setthread_cpupercent
2881(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2882{
2883 int new_value, old_value;
2884 int error = 0;
2885 kern_return_t kret = KERN_SUCCESS;
2886 uint8_t percent = 0;
2887 int ms_refill = 0;
2888
39236c6e
A
2889 if (!req->newptr)
2890 return (0);
2891
316670eb
A
2892 old_value = 0;
2893
2894 if ((error = sysctl_io_number(req, old_value, sizeof(old_value), &new_value, NULL)) != 0)
2895 return (error);
2896
2897 percent = new_value & 0xff; /* low 8 bytes for perent */
2898 ms_refill = (new_value >> 8) & 0xffffff; /* upper 24bytes represent ms refill value */
2899 if (percent > 100)
2900 return (EINVAL);
2901
2902 /*
2903 * If the caller is specifying a percentage of 0, this will unset the CPU limit, if present.
2904 */
39236c6e 2905 if ((kret = thread_set_cpulimit(THREAD_CPULIMIT_BLOCK, percent, ms_refill * (int)NSEC_PER_MSEC)) != 0)
316670eb
A
2906 return (EIO);
2907
2908 return (0);
2909}
2910
2911SYSCTL_PROC(_kern, OID_AUTO, setthread_cpupercent,
39236c6e 2912 CTLTYPE_INT | CTLFLAG_WR | CTLFLAG_ANYBODY,
316670eb
A
2913 0, 0, sysctl_setthread_cpupercent, "I", "set thread cpu percentage limit");
2914
2d21ac55 2915
6d2010ae 2916STATIC int
2d21ac55
A
2917sysctl_kern_check_openevt
2918(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2919{
2920 struct proc *p = req->p;
2921 int new_value, old_value, changed;
2922 int error;
2923
2924 if (p->p_flag & P_CHECKOPENEVT) {
2925 old_value = KERN_OPENEVT_PROC;
2926 } else {
2927 old_value = 0;
2928 }
2929
2930 error = sysctl_io_number(req, old_value, sizeof(int), &new_value, &changed);
2931
2932 if (error == 0) {
2933 switch (new_value) {
2934 case KERN_OPENEVT_PROC:
b0d623f7 2935 OSBitOrAtomic(P_CHECKOPENEVT, &p->p_flag);
2d21ac55
A
2936 break;
2937
2938 case KERN_UNOPENEVT_PROC:
b0d623f7 2939 OSBitAndAtomic(~((uint32_t)P_CHECKOPENEVT), &p->p_flag);
2d21ac55
A
2940 break;
2941
2942 default:
55e303ae 2943 error = EINVAL;
2d21ac55 2944 }
55e303ae 2945 }
2d21ac55
A
2946 return(error);
2947}
2948
6d2010ae 2949SYSCTL_PROC(_kern, KERN_CHECKOPENEVT, check_openevt, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED,
2d21ac55
A
2950 0, 0, sysctl_kern_check_openevt, "I", "set the per-process check-open-evt flag");
2951
2952
2953
6d2010ae 2954STATIC int
2d21ac55
A
2955sysctl_nx
2956(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2957{
4a3eedf9
A
2958#ifdef SECURE_KERNEL
2959 return ENOTSUP;
2960#endif
2d21ac55
A
2961 int new_value, changed;
2962 int error;
2963
2964 error = sysctl_io_number(req, nx_enabled, sizeof(nx_enabled), &new_value, &changed);
4a3eedf9
A
2965 if (error)
2966 return error;
2d21ac55 2967
4a3eedf9 2968 if (changed) {
b0d623f7 2969#if defined(__i386__) || defined(__x86_64__)
2d21ac55
A
2970 /*
2971 * Only allow setting if NX is supported on the chip
2972 */
2973 if (!(cpuid_extfeatures() & CPUID_EXTFEATURE_XD))
4a3eedf9 2974 return ENOTSUP;
2d21ac55 2975#endif
4a3eedf9
A
2976 nx_enabled = new_value;
2977 }
2d21ac55
A
2978 return(error);
2979}
2980
2981
2982
2983SYSCTL_PROC(_kern, KERN_NX_PROTECTION, nx,
6d2010ae 2984 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
2d21ac55
A
2985 0, 0, sysctl_nx, "I", "");
2986
6d2010ae 2987STATIC int
2d21ac55
A
2988sysctl_loadavg
2989(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
2990{
2991 if (proc_is64bit(req->p)) {
b0d623f7
A
2992 struct user64_loadavg loadinfo64;
2993 fill_loadavg64(&averunnable, &loadinfo64);
2d21ac55
A
2994 return sysctl_io_opaque(req, &loadinfo64, sizeof(loadinfo64), NULL);
2995 } else {
b0d623f7
A
2996 struct user32_loadavg loadinfo32;
2997 fill_loadavg32(&averunnable, &loadinfo32);
2998 return sysctl_io_opaque(req, &loadinfo32, sizeof(loadinfo32), NULL);
2d21ac55
A
2999 }
3000}
3001
3002SYSCTL_PROC(_vm, VM_LOADAVG, loadavg,
6d2010ae 3003 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
2d21ac55
A
3004 0, 0, sysctl_loadavg, "S,loadavg", "");
3005
6d2010ae
A
3006/*
3007 * Note: Thread safe; vm_map_lock protects in vm_toggle_entry_reuse()
3008 */
3009STATIC int
3010sysctl_vm_toggle_address_reuse(__unused struct sysctl_oid *oidp, __unused void *arg1,
3011 __unused int arg2, struct sysctl_req *req)
3012{
3013 int old_value=0, new_value=0, error=0;
3014
3015 if(vm_toggle_entry_reuse( VM_TOGGLE_GETVALUE, &old_value ))
3016 return(error);
3017 error = sysctl_io_number(req, old_value, sizeof(int), &new_value, NULL);
3018 if (!error) {
3019 return (vm_toggle_entry_reuse(new_value, NULL));
3020 }
3021 return(error);
3022}
3023
3024SYSCTL_PROC(_debug, OID_AUTO, toggle_address_reuse, CTLFLAG_ANYBODY | CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0, sysctl_vm_toggle_address_reuse,"I","");
3025
3026STATIC int
2d21ac55
A
3027sysctl_swapusage
3028(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
3029{
3030 int error;
3031 uint64_t swap_total;
3032 uint64_t swap_avail;
b0d623f7 3033 vm_size_t swap_pagesize;
2d21ac55
A
3034 boolean_t swap_encrypted;
3035 struct xsw_usage xsu;
3036
3037 error = macx_swapinfo(&swap_total,
3038 &swap_avail,
3039 &swap_pagesize,
3040 &swap_encrypted);
3041 if (error)
3042 return error;
3043
3044 xsu.xsu_total = swap_total;
3045 xsu.xsu_avail = swap_avail;
3046 xsu.xsu_used = swap_total - swap_avail;
3047 xsu.xsu_pagesize = swap_pagesize;
3048 xsu.xsu_encrypted = swap_encrypted;
3049 return sysctl_io_opaque(req, &xsu, sizeof(xsu), NULL);
3050}
3051
3052
3053
3054SYSCTL_PROC(_vm, VM_SWAPUSAGE, swapusage,
6d2010ae 3055 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
2d21ac55
A
3056 0, 0, sysctl_swapusage, "S,xsw_usage", "");
3057
6d2010ae
A
3058#if CONFIG_FREEZE
3059extern void vm_page_reactivate_all_throttled(void);
3060
3061static int
3062sysctl_freeze_enabled SYSCTL_HANDLER_ARGS
3063{
3064#pragma unused(arg1, arg2)
316670eb 3065 int error, val = memorystatus_freeze_enabled ? 1 : 0;
6d2010ae
A
3066 boolean_t disabled;
3067
3068 error = sysctl_handle_int(oidp, &val, 0, req);
3069 if (error || !req->newptr)
3070 return (error);
3071
39236c6e
A
3072 if (COMPRESSED_PAGER_IS_ACTIVE || DEFAULT_FREEZER_COMPRESSED_PAGER_IS_ACTIVE) {
3073 //assert(req->newptr);
3074 printf("Failed this request to set the sysctl\n");
3075 return EINVAL;
3076 }
3077
6d2010ae
A
3078 /*
3079 * If freeze is being disabled, we need to move dirty pages out from the throttle to the active queue.
3080 */
316670eb 3081 disabled = (!val && memorystatus_freeze_enabled);
6d2010ae 3082
316670eb 3083 memorystatus_freeze_enabled = val ? TRUE : FALSE;
6d2010ae
A
3084
3085 if (disabled) {
3086 vm_page_reactivate_all_throttled();
3087 }
3088
3089 return (0);
3090}
3091
316670eb 3092SYSCTL_PROC(_vm, OID_AUTO, freeze_enabled, CTLTYPE_INT|CTLFLAG_RW, &memorystatus_freeze_enabled, 0, sysctl_freeze_enabled, "I", "");
6d2010ae 3093#endif /* CONFIG_FREEZE */
2d21ac55
A
3094
3095/* this kernel does NOT implement shared_region_make_private_np() */
3096SYSCTL_INT(_kern, KERN_SHREG_PRIVATIZABLE, shreg_private,
6d2010ae 3097 CTLFLAG_RD | CTLFLAG_LOCKED,
b0d623f7 3098 (int *)NULL, 0, "");
0c530ab8 3099
b0d623f7 3100#if defined(__i386__) || defined(__x86_64__)
6d2010ae 3101STATIC int
2d21ac55
A
3102sysctl_sysctl_exec_affinity(__unused struct sysctl_oid *oidp,
3103 __unused void *arg1, __unused int arg2,
3104 struct sysctl_req *req)
0c530ab8 3105{
2d21ac55 3106 proc_t cur_proc = req->p;
0c530ab8
A
3107 int error;
3108
3109 if (req->oldptr != USER_ADDR_NULL) {
3110 cpu_type_t oldcputype = (cur_proc->p_flag & P_AFFINITY) ? CPU_TYPE_POWERPC : CPU_TYPE_I386;
3111 if ((error = SYSCTL_OUT(req, &oldcputype, sizeof(oldcputype))))
3112 return error;
3113 }
3114
3115 if (req->newptr != USER_ADDR_NULL) {
3116 cpu_type_t newcputype;
3117 if ((error = SYSCTL_IN(req, &newcputype, sizeof(newcputype))))
3118 return error;
3119 if (newcputype == CPU_TYPE_I386)
b0d623f7 3120 OSBitAndAtomic(~((uint32_t)P_AFFINITY), &cur_proc->p_flag);
0c530ab8 3121 else if (newcputype == CPU_TYPE_POWERPC)
b0d623f7 3122 OSBitOrAtomic(P_AFFINITY, &cur_proc->p_flag);
0c530ab8
A
3123 else
3124 return (EINVAL);
3125 }
3126
3127 return 0;
3128}
6d2010ae 3129SYSCTL_PROC(_sysctl, OID_AUTO, proc_exec_affinity, CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY | CTLFLAG_LOCKED, 0, 0, sysctl_sysctl_exec_affinity ,"I","proc_exec_affinity");
0c530ab8
A
3130#endif
3131
6d2010ae 3132STATIC int
0c530ab8 3133fetch_process_cputype(
2d21ac55 3134 proc_t cur_proc,
0c530ab8
A
3135 int *name,
3136 u_int namelen,
3137 cpu_type_t *cputype)
3138{
2d21ac55
A
3139 proc_t p = PROC_NULL;
3140 int refheld = 0;
0c530ab8 3141 cpu_type_t ret = 0;
2d21ac55 3142 int error = 0;
0c530ab8
A
3143
3144 if (namelen == 0)
3145 p = cur_proc;
3146 else if (namelen == 1) {
2d21ac55 3147 p = proc_find(name[0]);
0c530ab8
A
3148 if (p == NULL)
3149 return (EINVAL);
2d21ac55 3150 refheld = 1;
0c530ab8 3151 } else {
2d21ac55
A
3152 error = EINVAL;
3153 goto out;
0c530ab8
A
3154 }
3155
b0d623f7 3156#if defined(__i386__) || defined(__x86_64__)
0c530ab8
A
3157 if (p->p_flag & P_TRANSLATED) {
3158 ret = CPU_TYPE_POWERPC;
3159 }
3160 else
3161#endif
3162 {
39236c6e 3163 ret = cpu_type() & ~CPU_ARCH_MASK;
0c530ab8
A
3164 if (IS_64BIT_PROCESS(p))
3165 ret |= CPU_ARCH_ABI64;
3166 }
3167 *cputype = ret;
3168
2d21ac55
A
3169 if (refheld != 0)
3170 proc_rele(p);
3171out:
3172 return (error);
0c530ab8
A
3173}
3174
6d2010ae 3175STATIC int
2d21ac55
A
3176sysctl_sysctl_native(__unused struct sysctl_oid *oidp, void *arg1, int arg2,
3177 struct sysctl_req *req)
0c530ab8
A
3178{
3179 int error;
3180 cpu_type_t proc_cputype = 0;
3181 if ((error = fetch_process_cputype(req->p, (int *)arg1, arg2, &proc_cputype)) != 0)
3182 return error;
3183 int res = 1;
3184 if ((proc_cputype & ~CPU_ARCH_MASK) != (cpu_type() & ~CPU_ARCH_MASK))
3185 res = 0;
3186 return SYSCTL_OUT(req, &res, sizeof(res));
3187}
6d2010ae 3188SYSCTL_PROC(_sysctl, OID_AUTO, proc_native, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0, sysctl_sysctl_native ,"I","proc_native");
0c530ab8 3189
6d2010ae 3190STATIC int
2d21ac55
A
3191sysctl_sysctl_cputype(__unused struct sysctl_oid *oidp, void *arg1, int arg2,
3192 struct sysctl_req *req)
0c530ab8
A
3193{
3194 int error;
3195 cpu_type_t proc_cputype = 0;
3196 if ((error = fetch_process_cputype(req->p, (int *)arg1, arg2, &proc_cputype)) != 0)
3197 return error;
3198 return SYSCTL_OUT(req, &proc_cputype, sizeof(proc_cputype));
3199}
6d2010ae 3200SYSCTL_PROC(_sysctl, OID_AUTO, proc_cputype, CTLTYPE_NODE|CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0, sysctl_sysctl_cputype ,"I","proc_cputype");
0c530ab8 3201
6d2010ae 3202STATIC int
2d21ac55
A
3203sysctl_safeboot
3204(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
3205{
3206 return sysctl_io_number(req, boothowto & RB_SAFEBOOT ? 1 : 0, sizeof(int), NULL, NULL);
3207}
3208
3209SYSCTL_PROC(_kern, KERN_SAFEBOOT, safeboot,
6d2010ae 3210 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED,
2d21ac55
A
3211 0, 0, sysctl_safeboot, "I", "");
3212
6d2010ae 3213STATIC int
2d21ac55
A
3214sysctl_singleuser
3215(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
3216{
3217 return sysctl_io_number(req, boothowto & RB_SINGLE ? 1 : 0, sizeof(int), NULL, NULL);
3218}
3219
3220SYSCTL_PROC(_kern, OID_AUTO, singleuser,
6d2010ae 3221 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED,
2d21ac55
A
3222 0, 0, sysctl_singleuser, "I", "");
3223
3224/*
3225 * Controls for debugging affinity sets - see osfmk/kern/affinity.c
3226 */
3227extern boolean_t affinity_sets_enabled;
3228extern int affinity_sets_mapping;
3229
3230SYSCTL_INT (_kern, OID_AUTO, affinity_sets_enabled,
6d2010ae 3231 CTLFLAG_RW | CTLFLAG_LOCKED, (int *) &affinity_sets_enabled, 0, "hinting enabled");
2d21ac55 3232SYSCTL_INT (_kern, OID_AUTO, affinity_sets_mapping,
6d2010ae 3233 CTLFLAG_RW | CTLFLAG_LOCKED, &affinity_sets_mapping, 0, "mapping policy");
2d21ac55 3234
316670eb
A
3235/*
3236 * Boolean indicating if KASLR is active.
3237 */
3238STATIC int
3239sysctl_slide
3240(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
3241{
3242 uint32_t slide;
3243
3244 slide = vm_kernel_slide ? 1 : 0;
3245
3246 return sysctl_io_number( req, slide, sizeof(int), NULL, NULL);
3247}
3248
3249SYSCTL_PROC(_kern, OID_AUTO, slide,
3250 CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED,
3251 0, 0, sysctl_slide, "I", "");
3252
2d21ac55
A
3253/*
3254 * Limit on total memory users can wire.
3255 *
3256 * vm_global_user_wire_limit - system wide limit on wired memory from all processes combined.
3257 *
3258 * vm_user_wire_limit - per address space limit on wired memory. This puts a cap on the process's rlimit value.
3259 *
3260 * These values are initialized to reasonable defaults at boot time based on the available physical memory in
3261 * kmem_init().
3262 *
3263 * All values are in bytes.
3264 */
3265
b0d623f7 3266vm_map_size_t vm_global_no_user_wire_amount;
2d21ac55
A
3267vm_map_size_t vm_global_user_wire_limit;
3268vm_map_size_t vm_user_wire_limit;
3269
b0d623f7
A
3270/*
3271 * There needs to be a more automatic/elegant way to do this
3272 */
6d2010ae
A
3273SYSCTL_QUAD(_vm, OID_AUTO, global_no_user_wire_amount, CTLFLAG_RW | CTLFLAG_LOCKED, &vm_global_no_user_wire_amount, "");
3274SYSCTL_QUAD(_vm, OID_AUTO, global_user_wire_limit, CTLFLAG_RW | CTLFLAG_LOCKED, &vm_global_user_wire_limit, "");
3275SYSCTL_QUAD(_vm, OID_AUTO, user_wire_limit, CTLFLAG_RW | CTLFLAG_LOCKED, &vm_user_wire_limit, "");
b0d623f7 3276
e2d2fc5c
A
3277extern int vm_map_copy_overwrite_aligned_src_not_internal;
3278extern int vm_map_copy_overwrite_aligned_src_not_symmetric;
3279extern int vm_map_copy_overwrite_aligned_src_large;
3280SYSCTL_INT(_vm, OID_AUTO, vm_copy_src_not_internal, CTLFLAG_RD | CTLFLAG_LOCKED, &vm_map_copy_overwrite_aligned_src_not_internal, 0, "");
3281SYSCTL_INT(_vm, OID_AUTO, vm_copy_src_not_symmetric, CTLFLAG_RD | CTLFLAG_LOCKED, &vm_map_copy_overwrite_aligned_src_not_symmetric, 0, "");
3282SYSCTL_INT(_vm, OID_AUTO, vm_copy_src_large, CTLFLAG_RD | CTLFLAG_LOCKED, &vm_map_copy_overwrite_aligned_src_large, 0, "");
b0d623f7
A
3283
3284
39236c6e
A
3285extern uint32_t vm_page_external_count;
3286extern uint32_t vm_page_filecache_min;
3287
3288SYSCTL_INT(_vm, OID_AUTO, vm_page_external_count, CTLFLAG_RD | CTLFLAG_LOCKED, &vm_page_external_count, 0, "");
3289SYSCTL_INT(_vm, OID_AUTO, vm_page_filecache_min, CTLFLAG_RW | CTLFLAG_LOCKED, &vm_page_filecache_min, 0, "");
3290
3291extern int vm_compressor_mode;
3292extern uint32_t swapout_target_age;
3293extern int64_t compressor_bytes_used;
3294extern uint32_t compressor_eval_period_in_msecs;
3295extern uint32_t compressor_sample_min_in_msecs;
3296extern uint32_t compressor_sample_max_in_msecs;
3297extern uint32_t compressor_thrashing_threshold_per_10msecs;
3298extern uint32_t compressor_thrashing_min_per_10msecs;
3299extern uint32_t vm_compressor_minorcompact_threshold_divisor;
3300extern uint32_t vm_compressor_majorcompact_threshold_divisor;
3301extern uint32_t vm_compressor_unthrottle_threshold_divisor;
3302extern uint32_t vm_compressor_catchup_threshold_divisor;
3303
3304SYSCTL_INT(_vm, OID_AUTO, compressor_mode, CTLFLAG_RD | CTLFLAG_LOCKED, &vm_compressor_mode, 0, "");
3305SYSCTL_QUAD(_vm, OID_AUTO, compressor_bytes_used, CTLFLAG_RD | CTLFLAG_LOCKED, &compressor_bytes_used, "");
3306SYSCTL_INT(_vm, OID_AUTO, compressor_swapout_target_age, CTLFLAG_RD | CTLFLAG_LOCKED, &swapout_target_age, 0, "");
3307
3308SYSCTL_INT(_vm, OID_AUTO, compressor_eval_period_in_msecs, CTLFLAG_RW | CTLFLAG_LOCKED, &compressor_eval_period_in_msecs, 0, "");
3309SYSCTL_INT(_vm, OID_AUTO, compressor_sample_min_in_msecs, CTLFLAG_RW | CTLFLAG_LOCKED, &compressor_sample_min_in_msecs, 0, "");
3310SYSCTL_INT(_vm, OID_AUTO, compressor_sample_max_in_msecs, CTLFLAG_RW | CTLFLAG_LOCKED, &compressor_sample_max_in_msecs, 0, "");
3311SYSCTL_INT(_vm, OID_AUTO, compressor_thrashing_threshold_per_10msecs, CTLFLAG_RW | CTLFLAG_LOCKED, &compressor_thrashing_threshold_per_10msecs, 0, "");
3312SYSCTL_INT(_vm, OID_AUTO, compressor_thrashing_min_per_10msecs, CTLFLAG_RW | CTLFLAG_LOCKED, &compressor_thrashing_min_per_10msecs, 0, "");
3313SYSCTL_INT(_vm, OID_AUTO, compressor_minorcompact_threshold_divisor, CTLFLAG_RW | CTLFLAG_LOCKED, &vm_compressor_minorcompact_threshold_divisor, 0, "");
3314SYSCTL_INT(_vm, OID_AUTO, compressor_majorcompact_threshold_divisor, CTLFLAG_RW | CTLFLAG_LOCKED, &vm_compressor_majorcompact_threshold_divisor, 0, "");
3315SYSCTL_INT(_vm, OID_AUTO, compressor_unthrottle_threshold_divisor, CTLFLAG_RW | CTLFLAG_LOCKED, &vm_compressor_unthrottle_threshold_divisor, 0, "");
3316SYSCTL_INT(_vm, OID_AUTO, compressor_catchup_threshold_divisor, CTLFLAG_RW | CTLFLAG_LOCKED, &vm_compressor_catchup_threshold_divisor, 0, "");
3317
b0d623f7
A
3318/*
3319 * enable back trace events for thread blocks
3320 */
3321
3322extern uint32_t kdebug_thread_block;
3323
3324SYSCTL_INT (_kern, OID_AUTO, kdebug_thread_block,
6d2010ae 3325 CTLFLAG_RW | CTLFLAG_LOCKED, &kdebug_thread_block, 0, "kdebug thread_block");
b0d623f7
A
3326
3327/*
3328 * Kernel stack size and depth
3329 */
3330SYSCTL_INT (_kern, OID_AUTO, stack_size,
6d2010ae 3331 CTLFLAG_RD | CTLFLAG_LOCKED, (int *) &kernel_stack_size, 0, "Kernel stack size");
b0d623f7 3332SYSCTL_INT (_kern, OID_AUTO, stack_depth_max,
6d2010ae 3333 CTLFLAG_RD | CTLFLAG_LOCKED, (int *) &kernel_stack_depth_max, 0, "Max kernel stack depth at interrupt or context switch");
b0d623f7 3334
b7266188
A
3335/*
3336 * enable back trace for port allocations
3337 */
3338extern int ipc_portbt;
3339
3340SYSCTL_INT(_kern, OID_AUTO, ipc_portbt,
6d2010ae 3341 CTLFLAG_RW | CTLFLAG_KERN | CTLFLAG_LOCKED,
b7266188
A
3342 &ipc_portbt, 0, "");
3343
6d2010ae
A
3344/*
3345 * Scheduler sysctls
3346 */
3347
3348/*
3349 * See osfmk/kern/sched_prim.c for the corresponding definition
3350 * in osfmk/. If either version changes, update the other.
3351 */
3352#define SCHED_STRING_MAX_LENGTH (48)
3353
3354extern char sched_string[SCHED_STRING_MAX_LENGTH];
3355SYSCTL_STRING(_kern, OID_AUTO, sched,
3356 CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOCKED,
3357 sched_string, sizeof(sched_string),
3358 "Timeshare scheduler implementation");
316670eb
A
3359
3360/*
3361 * Only support runtime modification on embedded platforms
3362 * with development config enabled
3363 */