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