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