]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_sysctl.c
xnu-792.17.14.tar.gz
[apple/xnu.git] / bsd / kern / kern_sysctl.c
CommitLineData
1c79356b 1/*
5d5c5d0d
A
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
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.
14 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
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 */
66
67/*
68 * sysctl system call.
69 */
70
71#include <sys/param.h>
72#include <sys/systm.h>
73#include <sys/kernel.h>
74#include <sys/malloc.h>
91447636
A
75#include <sys/proc_internal.h>
76#include <sys/kauth.h>
77#include <sys/file_internal.h>
78#include <sys/vnode_internal.h>
1c79356b
A
79#include <sys/unistd.h>
80#include <sys/buf.h>
81#include <sys/ioctl.h>
55e303ae 82#include <sys/namei.h>
1c79356b
A
83#include <sys/tty.h>
84#include <sys/disklabel.h>
85#include <sys/vm.h>
86#include <sys/sysctl.h>
9bccf70c 87#include <sys/user.h>
55e303ae 88#include <sys/aio_kern.h>
e5568f75
A
89
90#include <bsm/audit_kernel.h>
91
1c79356b
A
92#include <mach/machine.h>
93#include <mach/mach_types.h>
94#include <mach/vm_param.h>
95#include <kern/task.h>
91447636 96#include <kern/lock.h>
1c79356b 97#include <vm/vm_kern.h>
91447636 98#include <vm/vm_map.h>
1c79356b
A
99#include <mach/host_info.h>
100
101extern vm_map_t bsd_pageable_map;
102
91447636 103#include <sys/mount_internal.h>
1c79356b 104#include <sys/kdebug.h>
91447636 105#include <sys/sysproto.h>
1c79356b
A
106
107#include <IOKit/IOPlatformExpert.h>
108#include <pexpert/pexpert.h>
109
55e303ae 110#include <machine/machine_routines.h>
1c79356b 111
91447636
A
112#include <vm/vm_protos.h>
113
1c79356b 114sysctlfn kern_sysctl;
1c79356b
A
115#ifdef DEBUG
116sysctlfn debug_sysctl;
117#endif
118extern sysctlfn vm_sysctl;
119extern sysctlfn vfs_sysctl;
120extern sysctlfn net_sysctl;
121extern sysctlfn cpu_sysctl;
55e303ae
A
122extern int aio_max_requests;
123extern int aio_max_requests_per_process;
124extern int aio_worker_threads;
8f6c56a5 125extern int maxprocperuid;
55e303ae 126extern int maxfilesperproc;
91447636
A
127extern int lowpri_IO_window_msecs;
128extern int lowpri_IO_delay_msecs;
1c79356b 129
91447636
A
130static void
131fill_eproc(struct proc *p, struct eproc *ep);
132static void
133fill_externproc(struct proc *p, struct extern_proc *exp);
134static void
135fill_user_eproc(struct proc *p, struct user_eproc *ep);
136static void
137fill_user_proc(struct proc *p, struct user_kinfo_proc *kp);
138static void
139fill_user_externproc(struct proc *p, struct user_extern_proc *exp);
140extern int
141kdbg_control(int *name, u_int namelen, user_addr_t where, size_t * sizep);
1c79356b 142int
91447636
A
143kdebug_ops(int *name, u_int namelen, user_addr_t where, size_t *sizep, struct proc *p);
144#if NFSCLIENT
145extern int
146netboot_root(void);
147#endif
148int
149pcsamples_ops(int *name, u_int namelen, user_addr_t where, size_t *sizep,
150 struct proc *p);
151__private_extern__ kern_return_t
152reset_vmobjectcache(unsigned int val1, unsigned int val2);
153extern int
154resize_namecache(u_int newsize);
55e303ae 155static int
91447636 156sysctl_aiomax(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, size_t newlen);
55e303ae 157static int
91447636 158sysctl_aioprocmax(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, size_t newlen);
55e303ae 159static int
91447636
A
160sysctl_aiothreads(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, size_t newlen);
161extern int
162sysctl_clockrate(user_addr_t where, size_t *sizep);
163int
164sysctl_doproc(int *name, u_int namelen, user_addr_t where, size_t *sizep);
165int
166sysctl_doprof(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
167 user_addr_t newp, size_t newlen);
168int
169sysctl_file(user_addr_t where, size_t *sizep);
55e303ae
A
170static void
171fill_proc(struct proc *p, struct kinfo_proc *kp);
172static int
91447636
A
173sysctl_maxfilesperproc(user_addr_t oldp, size_t *oldlenp,
174 user_addr_t newp, size_t newlen);
55e303ae 175static int
91447636
A
176sysctl_maxprocperuid(user_addr_t oldp, size_t *oldlenp,
177 user_addr_t newp, size_t newlen);
55e303ae 178static int
91447636
A
179sysctl_maxproc(user_addr_t oldp, size_t *oldlenp,
180 user_addr_t newp, size_t newlen);
181int
182sysctl_procargs(int *name, u_int namelen, user_addr_t where,
183 size_t *sizep, struct proc *cur_proc);
55e303ae 184static int
91447636
A
185sysctl_procargs2(int *name, u_int namelen, user_addr_t where, size_t *sizep,
186 struct proc *cur_proc);
55e303ae 187static int
91447636
A
188sysctl_procargsx(int *name, u_int namelen, user_addr_t where, size_t *sizep,
189 struct proc *cur_proc, int argc_yes);
190int
191sysctl_struct(user_addr_t oldp, size_t *oldlenp, user_addr_t newp,
192 size_t newlen, void *sp, int len);
193extern int
194sysctl_vnode(user_addr_t where, size_t *sizep);
1c79356b
A
195
196
197/*
198 * temporary location for vm_sysctl. This should be machine independant
199 */
91447636
A
200
201extern uint32_t mach_factor[3];
202
203static void
204loadavg32to64(struct loadavg *la32, struct user_loadavg *la64)
205{
206 la64->ldavg[0] = la32->ldavg[0];
207 la64->ldavg[1] = la32->ldavg[1];
208 la64->ldavg[2] = la32->ldavg[2];
209 la64->fscale = (user_long_t)la32->fscale;
210}
211
9bccf70c 212int
91447636
A
213vm_sysctl(int *name, __unused u_int namelen, user_addr_t oldp, size_t *oldlenp,
214 user_addr_t newp, size_t newlen, __unused struct proc *p)
1c79356b 215{
1c79356b
A
216 struct loadavg loadinfo;
217
1c79356b
A
218 switch (name[0]) {
219 case VM_LOADAVG:
91447636
A
220 if (proc_is64bit(p)) {
221 struct user_loadavg loadinfo64;
222 loadavg32to64(&averunnable, &loadinfo64);
223 return (sysctl_struct(oldp, oldlenp, newp, newlen,
224 &loadinfo64, sizeof(loadinfo64)));
225 } else {
226 return (sysctl_struct(oldp, oldlenp, newp, newlen,
9bccf70c 227 &averunnable, sizeof(struct loadavg)));
91447636 228 }
1c79356b
A
229 case VM_MACHFACTOR:
230 loadinfo.ldavg[0] = mach_factor[0];
231 loadinfo.ldavg[1] = mach_factor[1];
232 loadinfo.ldavg[2] = mach_factor[2];
233 loadinfo.fscale = LSCALE;
91447636
A
234 if (proc_is64bit(p)) {
235 struct user_loadavg loadinfo64;
236 loadavg32to64(&loadinfo, &loadinfo64);
237 return (sysctl_struct(oldp, oldlenp, newp, newlen,
238 &loadinfo64, sizeof(loadinfo64)));
239 } else {
240 return (sysctl_struct(oldp, oldlenp, newp, newlen,
9bccf70c 241 &loadinfo, sizeof(struct loadavg)));
91447636
A
242 }
243 case VM_SWAPUSAGE: {
244 int error;
245 uint64_t swap_total;
246 uint64_t swap_avail;
247 uint32_t swap_pagesize;
248 boolean_t swap_encrypted;
249 struct xsw_usage xsu;
250
251 error = macx_swapinfo(&swap_total,
252 &swap_avail,
253 &swap_pagesize,
254 &swap_encrypted);
255 if (error)
256 return error;
257
258 xsu.xsu_total = swap_total;
259 xsu.xsu_avail = swap_avail;
260 xsu.xsu_used = swap_total - swap_avail;
261 xsu.xsu_pagesize = swap_pagesize;
262 xsu.xsu_encrypted = swap_encrypted;
263 return sysctl_struct(oldp, oldlenp, newp, newlen,
264 &xsu, sizeof (struct xsw_usage));
265 }
1c79356b 266 case VM_METER:
91447636 267 return (ENOTSUP);
1c79356b 268 case VM_MAXID:
91447636 269 return (ENOTSUP);
1c79356b 270 default:
91447636 271 return (ENOTSUP);
1c79356b
A
272 }
273 /* NOTREACHED */
91447636 274 return (ENOTSUP);
1c79356b
A
275}
276
277/*
278 * Locking and stats
279 */
280static struct sysctl_lock {
281 int sl_lock;
282 int sl_want;
283 int sl_locked;
284} memlock;
285
1c79356b 286int
91447636 287__sysctl(struct proc *p, struct __sysctl_args *uap, __unused register_t *retval)
1c79356b
A
288{
289 int error, dolock = 1;
91447636
A
290 size_t savelen = 0, oldlen = 0, newlen;
291 sysctlfn *fnp = NULL;
1c79356b
A
292 int name[CTL_MAXNAME];
293 int i;
0b4e3aa0 294 int error1;
1c79356b
A
295
296 /*
297 * all top-level sysctl names are non-terminal
298 */
299 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
300 return (EINVAL);
91447636
A
301 error = copyin(uap->name, &name[0], uap->namelen * sizeof(int));
302 if (error)
1c79356b 303 return (error);
91447636 304
e5568f75
A
305 AUDIT_ARG(ctlname, name, uap->namelen);
306
91447636
A
307 if (proc_is64bit(p)) {
308 /* uap->newlen is a size_t value which grows to 64 bits
309 * when coming from a 64-bit process. since it's doubtful we'll
310 * have a sysctl newp buffer greater than 4GB we shrink it to size_t
311 */
312 newlen = CAST_DOWN(size_t, uap->newlen);
313 }
314 else {
315 newlen = uap->newlen;
316 }
317
1c79356b 318 /* CTL_UNSPEC is used to get oid to AUTO_OID */
91447636
A
319 if (uap->new != USER_ADDR_NULL
320 && ((name[0] == CTL_KERN
321 && !(name[1] == KERN_IPC || name[1] == KERN_PANICINFO || name[1] == KERN_PROCDELAYTERM ||
8f6c56a5 322 name[1] == KERN_PROC_LOW_PRI_IO))
91447636
A
323 || (name[0] == CTL_HW)
324 || (name[0] == CTL_VM)
325 || (name[0] == CTL_VFS))
326 && (error = suser(kauth_cred_get(), &p->p_acflag)))
1c79356b
A
327 return (error);
328
329 switch (name[0]) {
330 case CTL_KERN:
91447636 331 fnp = kern_sysctl;
0b4e3aa0
A
332 if ((name[1] != KERN_VNODE) && (name[1] != KERN_FILE)
333 && (name[1] != KERN_PROC))
1c79356b
A
334 dolock = 0;
335 break;
1c79356b 336 case CTL_VM:
91447636 337 fnp = vm_sysctl;
1c79356b
A
338 break;
339
340 case CTL_VFS:
91447636 341 fnp = vfs_sysctl;
1c79356b 342 break;
1c79356b
A
343#ifdef DEBUG
344 case CTL_DEBUG:
91447636 345 fnp = debug_sysctl;
1c79356b
A
346 break;
347#endif
348 default:
91447636 349 fnp = NULL;
1c79356b
A
350 }
351
91447636
A
352 if (uap->oldlenp != USER_ADDR_NULL) {
353 uint64_t oldlen64 = fuulong(uap->oldlenp);
354
355 oldlen = CAST_DOWN(size_t, oldlen64);
356 /*
357 * If more than 4G, clamp to 4G - useracc() below will catch
358 * with an EFAULT, if it's actually necessary.
359 */
360 if (oldlen64 > 0x00000000ffffffffULL)
361 oldlen = 0xffffffffUL;
362 }
1c79356b 363
91447636
A
364 if (uap->old != USER_ADDR_NULL) {
365 if (!useracc(uap->old, (user_size_t)oldlen, B_WRITE))
1c79356b
A
366 return (EFAULT);
367
368 /* The pc sampling mechanism does not need to take this lock */
9bccf70c
A
369 if ((name[1] != KERN_PCSAMPLES) &&
370 (!((name[1] == KERN_KDEBUG) && (name[2] == KERN_KDGETENTROPY)))) {
1c79356b
A
371 while (memlock.sl_lock) {
372 memlock.sl_want = 1;
373 sleep((caddr_t)&memlock, PRIBIO+1);
374 memlock.sl_locked++;
375 }
376 memlock.sl_lock = 1;
377 }
378
91447636
A
379 if (dolock && oldlen &&
380 (error = vslock(uap->old, (user_size_t)oldlen))) {
9bccf70c
A
381 if ((name[1] != KERN_PCSAMPLES) &&
382 (! ((name[1] == KERN_KDEBUG) && (name[2] == KERN_KDGETENTROPY)))) {
0b4e3aa0
A
383 memlock.sl_lock = 0;
384 if (memlock.sl_want) {
385 memlock.sl_want = 0;
386 wakeup((caddr_t)&memlock);
387 }
388 }
389 return(error);
390 }
1c79356b
A
391 savelen = oldlen;
392 }
393
91447636
A
394 if (fnp) {
395 error = (*fnp)(name + 1, uap->namelen - 1, uap->old,
396 &oldlen, uap->new, newlen, p);
397 }
1c79356b 398 else
91447636 399 error = ENOTSUP;
1c79356b 400
91447636
A
401 if ( (name[0] != CTL_VFS) && (error == ENOTSUP)) {
402 size_t tmp = oldlen;
403 error = userland_sysctl(p, name, uap->namelen, uap->old, &tmp,
404 1, uap->new, newlen, &oldlen);
405 }
1c79356b 406
91447636 407 if (uap->old != USER_ADDR_NULL) {
0b4e3aa0 408 if (dolock && savelen) {
91447636 409 error1 = vsunlock(uap->old, (user_size_t)savelen, B_WRITE);
0b4e3aa0
A
410 if (!error && error1)
411 error = error1;
412 }
1c79356b
A
413 if (name[1] != KERN_PCSAMPLES) {
414 memlock.sl_lock = 0;
415 if (memlock.sl_want) {
416 memlock.sl_want = 0;
417 wakeup((caddr_t)&memlock);
418 }
419 }
420 }
421 if ((error) && (error != ENOMEM))
422 return (error);
423
91447636
A
424 if (uap->oldlenp != USER_ADDR_NULL) {
425 i = suulong(uap->oldlenp, oldlen);
1c79356b
A
426 if (i)
427 return i;
428 }
429
430 return (error);
431}
432
433/*
434 * Attributes stored in the kernel.
435 */
8f6c56a5
A
436extern char classichandler[32];
437extern uint32_t classichandler_fsid;
438extern long classichandler_fileid;
e5568f75 439__private_extern__ char corefilename[MAXPATHLEN+1];
91447636
A
440__private_extern__ int do_coredump;
441__private_extern__ int sugid_coredump;
e5568f75 442
55e303ae 443
1c79356b
A
444#ifdef INSECURE
445int securelevel = -1;
446#else
447int securelevel;
448#endif
449
55e303ae 450static int
91447636
A
451sysctl_affinity(
452 int *name,
453 u_int namelen,
454 user_addr_t oldBuf,
455 size_t *oldSize,
456 user_addr_t newBuf,
457 __unused size_t newSize,
458 struct proc *cur_proc)
55e303ae
A
459{
460 if (namelen < 1)
91447636 461 return (ENOTSUP);
55e303ae
A
462
463 if (name[0] == 0 && 1 == namelen) {
464 return sysctl_rdint(oldBuf, oldSize, newBuf,
91447636 465 (cur_proc->p_flag & P_AFFINITY) ? 1 : 0);
55e303ae
A
466 } else if (name[0] == 1 && 2 == namelen) {
467 if (name[1] == 0) {
468 cur_proc->p_flag &= ~P_AFFINITY;
469 } else {
470 cur_proc->p_flag |= P_AFFINITY;
471 }
472 return 0;
473 }
91447636 474 return (ENOTSUP);
55e303ae
A
475}
476
477static int
8f6c56a5 478sysctl_classic(
91447636
A
479 int *name,
480 u_int namelen,
481 user_addr_t oldBuf,
482 size_t *oldSize,
483 user_addr_t newBuf,
484 __unused size_t newSize,
485 struct proc *cur_proc)
55e303ae 486{
55e303ae
A
487 struct proc *p;
488
489 if (namelen != 1)
91447636 490 return (ENOTSUP);
55e303ae
A
491
492 p = pfind(name[0]);
493 if (p == NULL)
494 return (EINVAL);
495
91447636
A
496 if ((kauth_cred_getuid(p->p_ucred) != kauth_cred_getuid(kauth_cred_get()))
497 && suser(kauth_cred_get(), &cur_proc->p_acflag))
55e303ae
A
498 return (EPERM);
499
500 return sysctl_rdint(oldBuf, oldSize, newBuf,
8f6c56a5 501 (p->p_flag & P_CLASSIC) ? 1 : 0);
55e303ae
A
502}
503
504static int
8f6c56a5 505sysctl_classichandler(
91447636
A
506 __unused int *name,
507 __unused u_int namelen,
508 user_addr_t oldBuf,
509 size_t *oldSize,
510 user_addr_t newBuf,
511 size_t newSize,
512 struct proc *p)
55e303ae
A
513{
514 int error;
91447636 515 size_t len;
55e303ae 516 struct nameidata nd;
91447636 517 struct vnode_attr va;
8f6c56a5 518 char handler[sizeof(classichandler)];
91447636
A
519 struct vfs_context context;
520
521 context.vc_proc = p;
522 context.vc_ucred = kauth_cred_get();
523
524 if (oldSize) {
8f6c56a5 525 len = strlen(classichandler) + 1;
91447636
A
526 if (oldBuf) {
527 if (*oldSize < len)
528 return (ENOMEM);
8f6c56a5 529 error = copyout(classichandler, oldBuf, len);
91447636
A
530 if (error)
531 return (error);
532 }
533 *oldSize = len - 1;
534 }
55e303ae 535 if (newBuf) {
91447636
A
536 error = suser(context.vc_ucred, &p->p_acflag);
537 if (error)
538 return (error);
8f6c56a5 539 if (newSize >= sizeof(classichandler))
91447636 540 return (ENAMETOOLONG);
55e303ae
A
541 error = copyin(newBuf, handler, newSize);
542 if (error)
543 return (error);
544 handler[newSize] = 0;
8f6c56a5
A
545
546 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE32,
547 CAST_USER_ADDR_T(handler), &context);
548 error = namei(&nd);
55e303ae
A
549 if (error)
550 return (error);
8f6c56a5
A
551 nameidone(&nd);
552
553 /* Check mount point */
554 if ((nd.ni_vp->v_mount->mnt_flag & MNT_NOEXEC) ||
555 (nd.ni_vp->v_type != VREG)) {
556 vnode_put(nd.ni_vp);
557 return (EACCES);
558 }
559
560 VATTR_INIT(&va);
561 VATTR_WANTED(&va, va_fsid);
562 VATTR_WANTED(&va, va_fileid);
563 error = vnode_getattr(nd.ni_vp, &va, &context);
564 if (error) {
565 vnode_put(nd.ni_vp);
566 return (error);
567 }
568 vnode_put(nd.ni_vp);
569
570 classichandler_fsid = va.va_fsid;
571 classichandler_fileid = (u_long)va.va_fileid;
572 strcpy(classichandler, handler);
55e303ae 573 }
91447636 574 return 0;
55e303ae
A
575}
576
577
9bccf70c 578extern int get_kernel_symfile( struct proc *, char **);
91447636
A
579__private_extern__ int
580sysctl_dopanicinfo(int *, u_int, user_addr_t, size_t *, user_addr_t,
581 size_t, struct proc *);
1c79356b
A
582
583/*
584 * kernel related system variables.
585 */
9bccf70c 586int
91447636
A
587kern_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
588 user_addr_t newp, size_t newlen, struct proc *p)
1c79356b 589{
e5568f75 590 int error, level, inthostid, tmp;
1c79356b 591 unsigned int oldval=0;
9bccf70c 592 char *str;
9bccf70c
A
593 /* all sysctl names not listed below are terminal at this level */
594 if (namelen != 1
595 && !(name[0] == KERN_PROC
596 || name[0] == KERN_PROF
597 || name[0] == KERN_KDEBUG
598 || name[0] == KERN_PROCARGS
55e303ae 599 || name[0] == KERN_PROCARGS2
9bccf70c
A
600 || name[0] == KERN_PCSAMPLES
601 || name[0] == KERN_IPC
602 || name[0] == KERN_SYSV
55e303ae 603 || name[0] == KERN_AFFINITY
8f6c56a5 604 || name[0] == KERN_CLASSIC
91447636 605 || name[0] == KERN_PANICINFO
8f6c56a5 606 || name[0] == KERN_POSIX)
9bccf70c 607 )
1c79356b
A
608 return (ENOTDIR); /* overloaded */
609
610 switch (name[0]) {
611 case KERN_OSTYPE:
612 return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
613 case KERN_OSRELEASE:
614 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
615 case KERN_OSREV:
616 return (sysctl_rdint(oldp, oldlenp, newp, BSD));
617 case KERN_VERSION:
618 return (sysctl_rdstring(oldp, oldlenp, newp, version));
619 case KERN_MAXVNODES:
620 oldval = desiredvnodes;
621 error = sysctl_int(oldp, oldlenp, newp,
622 newlen, &desiredvnodes);
623 reset_vmobjectcache(oldval, desiredvnodes);
55e303ae 624 resize_namecache(desiredvnodes);
1c79356b
A
625 return(error);
626 case KERN_MAXPROC:
55e303ae 627 return (sysctl_maxproc(oldp, oldlenp, newp, newlen));
1c79356b
A
628 case KERN_MAXFILES:
629 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
55e303ae
A
630 case KERN_MAXPROCPERUID:
631 return( sysctl_maxprocperuid( oldp, oldlenp, newp, newlen ) );
632 case KERN_MAXFILESPERPROC:
633 return( sysctl_maxfilesperproc( oldp, oldlenp, newp, newlen ) );
1c79356b
A
634 case KERN_ARGMAX:
635 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
636 case KERN_SECURELVL:
637 level = securelevel;
638 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
91447636 639 newp == USER_ADDR_NULL)
1c79356b
A
640 return (error);
641 if (level < securelevel && p->p_pid != 1)
642 return (EPERM);
643 securelevel = level;
644 return (0);
645 case KERN_HOSTNAME:
91447636 646 error = sysctl_trstring(oldp, oldlenp, newp, newlen,
1c79356b
A
647 hostname, sizeof(hostname));
648 if (newp && !error)
649 hostnamelen = newlen;
650 return (error);
651 case KERN_DOMAINNAME:
652 error = sysctl_string(oldp, oldlenp, newp, newlen,
653 domainname, sizeof(domainname));
654 if (newp && !error)
655 domainnamelen = newlen;
656 return (error);
657 case KERN_HOSTID:
658 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */
659 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
660 hostid = inthostid;
661 return (error);
662 case KERN_CLOCKRATE:
663 return (sysctl_clockrate(oldp, oldlenp));
664 case KERN_BOOTTIME:
91447636
A
665 {
666 struct timeval t;
667
668 t.tv_sec = boottime_sec();
669 t.tv_usec = 0;
670
671 return (sysctl_rdstruct(oldp, oldlenp, newp, &t,
1c79356b 672 sizeof(struct timeval)));
91447636 673 }
1c79356b
A
674 case KERN_VNODE:
675 return (sysctl_vnode(oldp, oldlenp));
676 case KERN_PROC:
677 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
678 case KERN_FILE:
679 return (sysctl_file(oldp, oldlenp));
680#ifdef GPROF
681 case KERN_PROF:
682 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
683 newp, newlen));
684#endif
685 case KERN_POSIX1:
686 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
687 case KERN_NGROUPS:
688 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
689 case KERN_JOB_CONTROL:
690 return (sysctl_rdint(oldp, oldlenp, newp, 1));
691 case KERN_SAVED_IDS:
692#ifdef _POSIX_SAVED_IDS
693 return (sysctl_rdint(oldp, oldlenp, newp, 1));
694#else
695 return (sysctl_rdint(oldp, oldlenp, newp, 0));
696#endif
1c79356b
A
697 case KERN_KDEBUG:
698 return (kdebug_ops(name + 1, namelen - 1, oldp, oldlenp, p));
699 case KERN_PCSAMPLES:
700 return (pcsamples_ops(name + 1, namelen - 1, oldp, oldlenp, p));
701 case KERN_PROCARGS:
702 /* new one as it does not use kinfo_proc */
9bccf70c 703 return (sysctl_procargs(name + 1, namelen - 1, oldp, oldlenp, p));
55e303ae
A
704 case KERN_PROCARGS2:
705 /* new one as it does not use kinfo_proc */
706 return (sysctl_procargs2(name + 1, namelen - 1, oldp, oldlenp, p));
9bccf70c
A
707 case KERN_SYMFILE:
708 error = get_kernel_symfile( p, &str );
709 if ( error )
710 return error;
711 return (sysctl_rdstring(oldp, oldlenp, newp, str));
91447636 712#if NFSCLIENT
9bccf70c
A
713 case KERN_NETBOOT:
714 return (sysctl_rdint(oldp, oldlenp, newp, netboot_root()));
91447636 715#endif
9bccf70c
A
716 case KERN_PANICINFO:
717 return(sysctl_dopanicinfo(name + 1, namelen - 1, oldp, oldlenp,
718 newp, newlen, p));
55e303ae
A
719 case KERN_AFFINITY:
720 return sysctl_affinity(name+1, namelen-1, oldp, oldlenp,
721 newp, newlen, p);
8f6c56a5
A
722 case KERN_CLASSIC:
723 return sysctl_classic(name+1, namelen-1, oldp, oldlenp,
724 newp, newlen, p);
55e303ae 725 case KERN_CLASSICHANDLER:
8f6c56a5
A
726 return sysctl_classichandler(name+1, namelen-1, oldp, oldlenp,
727 newp, newlen, p);
55e303ae
A
728 case KERN_AIOMAX:
729 return( sysctl_aiomax( oldp, oldlenp, newp, newlen ) );
730 case KERN_AIOPROCMAX:
731 return( sysctl_aioprocmax( oldp, oldlenp, newp, newlen ) );
732 case KERN_AIOTHREADS:
733 return( sysctl_aiothreads( oldp, oldlenp, newp, newlen ) );
91447636
A
734 case KERN_USRSTACK:
735 return (sysctl_rdint(oldp, oldlenp, newp, (uintptr_t)p->user_stack));
736 case KERN_USRSTACK64:
737 return (sysctl_rdquad(oldp, oldlenp, newp, p->user_stack));
e5568f75
A
738 case KERN_COREFILE:
739 error = sysctl_string(oldp, oldlenp, newp, newlen,
740 corefilename, sizeof(corefilename));
741 return (error);
742 case KERN_COREDUMP:
743 tmp = do_coredump;
744 error = sysctl_int(oldp, oldlenp, newp, newlen, &do_coredump);
91447636 745 if (!error && ((do_coredump < 0) || (do_coredump > 1))) {
e5568f75
A
746 do_coredump = tmp;
747 error = EINVAL;
748 }
749 return (error);
750 case KERN_SUGID_COREDUMP:
751 tmp = sugid_coredump;
752 error = sysctl_int(oldp, oldlenp, newp, newlen, &sugid_coredump);
91447636 753 if (!error && ((sugid_coredump < 0) || (sugid_coredump > 1))) {
e5568f75
A
754 sugid_coredump = tmp;
755 error = EINVAL;
756 }
757 return (error);
91447636
A
758 case KERN_PROCDELAYTERM:
759 {
760 int old_value, new_value;
761
762 error = 0;
763 if (oldp && *oldlenp < sizeof(int))
764 return (ENOMEM);
765 if ( newp && newlen != sizeof(int) )
766 return(EINVAL);
767 *oldlenp = sizeof(int);
768 old_value = (p->p_lflag & P_LDELAYTERM)? 1: 0;
769 if (oldp && (error = copyout( &old_value, oldp, sizeof(int))))
770 return(error);
771 if (error == 0 && newp )
772 error = copyin( newp, &new_value, sizeof(int) );
773 if (error == 0 && newp) {
774 if (new_value)
775 p->p_lflag |= P_LDELAYTERM;
776 else
777 p->p_lflag &= ~P_LDELAYTERM;
778 }
779 return(error);
780 }
781 case KERN_PROC_LOW_PRI_IO:
782 {
783 int old_value, new_value;
784
785 error = 0;
786 if (oldp && *oldlenp < sizeof(int))
787 return (ENOMEM);
788 if ( newp && newlen != sizeof(int) )
789 return(EINVAL);
790 *oldlenp = sizeof(int);
791
792 old_value = (p->p_lflag & P_LLOW_PRI_IO)? 0x01: 0;
793 if (p->p_lflag & P_LBACKGROUND_IO)
794 old_value |= 0x02;
795
796 if (oldp && (error = copyout( &old_value, oldp, sizeof(int))))
797 return(error);
798 if (error == 0 && newp )
799 error = copyin( newp, &new_value, sizeof(int) );
800 if (error == 0 && newp) {
801 if (new_value & 0x01)
802 p->p_lflag |= P_LLOW_PRI_IO;
803 else if (new_value & 0x02)
804 p->p_lflag |= P_LBACKGROUND_IO;
805 else if (new_value == 0)
806 p->p_lflag &= ~(P_LLOW_PRI_IO | P_LBACKGROUND_IO);
807 }
808 return(error);
809 }
810 case KERN_LOW_PRI_WINDOW:
811 {
812 int old_value, new_value;
813
814 error = 0;
815 if (oldp && *oldlenp < sizeof(old_value) )
816 return (ENOMEM);
817 if ( newp && newlen != sizeof(new_value) )
818 return(EINVAL);
819 *oldlenp = sizeof(old_value);
820
821 old_value = lowpri_IO_window_msecs;
822
823 if (oldp && (error = copyout( &old_value, oldp, *oldlenp)))
824 return(error);
825 if (error == 0 && newp )
826 error = copyin( newp, &new_value, sizeof(newlen) );
827 if (error == 0 && newp) {
828 lowpri_IO_window_msecs = new_value;
829 }
830 return(error);
831 }
832 case KERN_LOW_PRI_DELAY:
833 {
834 int old_value, new_value;
835
836 error = 0;
837 if (oldp && *oldlenp < sizeof(old_value) )
838 return (ENOMEM);
839 if ( newp && newlen != sizeof(new_value) )
840 return(EINVAL);
841 *oldlenp = sizeof(old_value);
842
843 old_value = lowpri_IO_delay_msecs;
844
845 if (oldp && (error = copyout( &old_value, oldp, *oldlenp)))
846 return(error);
847 if (error == 0 && newp )
848 error = copyin( newp, &new_value, sizeof(newlen) );
849 if (error == 0 && newp) {
850 lowpri_IO_delay_msecs = new_value;
851 }
852 return(error);
853 }
854 case KERN_SHREG_PRIVATIZABLE:
855 /* this kernel does implement shared_region_make_private_np() */
856 return (sysctl_rdint(oldp, oldlenp, newp, 1));
1c79356b 857 default:
91447636 858 return (ENOTSUP);
1c79356b
A
859 }
860 /* NOTREACHED */
861}
862
1c79356b
A
863#ifdef DEBUG
864/*
865 * Debugging related system variables.
866 */
867#if DIAGNOSTIC
868extern
869#endif /* DIAGNOSTIC */
870struct ctldebug debug0, debug1;
871struct ctldebug debug2, debug3, debug4;
872struct ctldebug debug5, debug6, debug7, debug8, debug9;
873struct ctldebug debug10, debug11, debug12, debug13, debug14;
874struct ctldebug debug15, debug16, debug17, debug18, debug19;
875static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
876 &debug0, &debug1, &debug2, &debug3, &debug4,
877 &debug5, &debug6, &debug7, &debug8, &debug9,
878 &debug10, &debug11, &debug12, &debug13, &debug14,
879 &debug15, &debug16, &debug17, &debug18, &debug19,
880};
881int
91447636
A
882debug_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
883 user_addr_t newp, size_t newlen, struct proc *p)
1c79356b
A
884{
885 struct ctldebug *cdp;
886
887 /* all sysctl names at this level are name and field */
888 if (namelen != 2)
889 return (ENOTDIR); /* overloaded */
890 cdp = debugvars[name[0]];
891 if (cdp->debugname == 0)
91447636 892 return (ENOTSUP);
1c79356b
A
893 switch (name[1]) {
894 case CTL_DEBUG_NAME:
895 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
896 case CTL_DEBUG_VALUE:
897 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
898 default:
91447636 899 return (ENOTSUP);
1c79356b
A
900 }
901 /* NOTREACHED */
902}
903#endif /* DEBUG */
904
905/*
906 * Validate parameters and get old / set new parameters
907 * for an integer-valued sysctl function.
908 */
9bccf70c 909int
91447636
A
910sysctl_int(user_addr_t oldp, size_t *oldlenp,
911 user_addr_t newp, size_t newlen, int *valp)
1c79356b
A
912{
913 int error = 0;
914
91447636
A
915 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
916 return (EFAULT);
1c79356b
A
917 if (oldp && *oldlenp < sizeof(int))
918 return (ENOMEM);
919 if (newp && newlen != sizeof(int))
920 return (EINVAL);
921 *oldlenp = sizeof(int);
922 if (oldp)
923 error = copyout(valp, oldp, sizeof(int));
e5568f75 924 if (error == 0 && newp) {
1c79356b 925 error = copyin(newp, valp, sizeof(int));
e5568f75
A
926 AUDIT_ARG(value, *valp);
927 }
1c79356b
A
928 return (error);
929}
930
931/*
932 * As above, but read-only.
933 */
9bccf70c 934int
91447636 935sysctl_rdint(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, int val)
1c79356b
A
936{
937 int error = 0;
938
91447636
A
939 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
940 return (EFAULT);
1c79356b
A
941 if (oldp && *oldlenp < sizeof(int))
942 return (ENOMEM);
943 if (newp)
944 return (EPERM);
945 *oldlenp = sizeof(int);
946 if (oldp)
947 error = copyout((caddr_t)&val, oldp, sizeof(int));
948 return (error);
949}
950
9bccf70c
A
951/*
952 * Validate parameters and get old / set new parameters
953 * for an quad(64bit)-valued sysctl function.
954 */
955int
91447636
A
956sysctl_quad(user_addr_t oldp, size_t *oldlenp,
957 user_addr_t newp, size_t newlen, quad_t *valp)
9bccf70c
A
958{
959 int error = 0;
960
91447636
A
961 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
962 return (EFAULT);
9bccf70c
A
963 if (oldp && *oldlenp < sizeof(quad_t))
964 return (ENOMEM);
965 if (newp && newlen != sizeof(quad_t))
966 return (EINVAL);
967 *oldlenp = sizeof(quad_t);
968 if (oldp)
969 error = copyout(valp, oldp, sizeof(quad_t));
970 if (error == 0 && newp)
971 error = copyin(newp, valp, sizeof(quad_t));
972 return (error);
973}
974
975/*
976 * As above, but read-only.
977 */
978int
979sysctl_rdquad(oldp, oldlenp, newp, val)
980 void *oldp;
981 size_t *oldlenp;
982 void *newp;
983 quad_t val;
984{
985 int error = 0;
986
91447636
A
987 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
988 return (EFAULT);
9bccf70c
A
989 if (oldp && *oldlenp < sizeof(quad_t))
990 return (ENOMEM);
991 if (newp)
992 return (EPERM);
993 *oldlenp = sizeof(quad_t);
994 if (oldp)
91447636
A
995 error = copyout((caddr_t)&val, CAST_USER_ADDR_T(oldp), sizeof(quad_t));
996 return (error);
997}
998
999/*
1000 * Validate parameters and get old / set new parameters
1001 * for a string-valued sysctl function. Unlike sysctl_string, if you
1002 * give it a too small (but larger than 0 bytes) buffer, instead of
1003 * returning ENOMEM, it truncates the returned string to the buffer
1004 * size. This preserves the semantics of some library routines
1005 * implemented via sysctl, which truncate their returned data, rather
1006 * than simply returning an error. The returned string is always NUL
1007 * terminated.
1008 */
1009int
1010sysctl_trstring(user_addr_t oldp, size_t *oldlenp,
1011 user_addr_t newp, size_t newlen, char *str, int maxlen)
1012{
1013 int len, copylen, error = 0;
1014
1015 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1016 return (EFAULT);
1017 copylen = len = strlen(str) + 1;
1018 if (oldp && (len < 0 || *oldlenp < 1))
1019 return (ENOMEM);
1020 if (oldp && (*oldlenp < (size_t)len))
1021 copylen = *oldlenp + 1;
1022 if (newp && (maxlen < 0 || newlen >= (size_t)maxlen))
1023 return (EINVAL);
1024 *oldlenp = copylen - 1; /* deal with NULL strings correctly */
1025 if (oldp) {
1026 error = copyout(str, oldp, copylen);
1027 if (!error) {
1028 unsigned char c = 0;
1029 /* NUL terminate */
1030 oldp += *oldlenp;
1031 error = copyout((void *)&c, oldp, sizeof(char));
1032 }
1033 }
1034 if (error == 0 && newp) {
1035 error = copyin(newp, str, newlen);
1036 str[newlen] = 0;
1037 AUDIT_ARG(text, (char *)str);
1038 }
9bccf70c
A
1039 return (error);
1040}
1041
1c79356b
A
1042/*
1043 * Validate parameters and get old / set new parameters
1044 * for a string-valued sysctl function.
1045 */
9bccf70c 1046int
91447636
A
1047sysctl_string(user_addr_t oldp, size_t *oldlenp,
1048 user_addr_t newp, size_t newlen, char *str, int maxlen)
1c79356b
A
1049{
1050 int len, error = 0;
1051
91447636
A
1052 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1053 return (EFAULT);
1c79356b 1054 len = strlen(str) + 1;
91447636 1055 if (oldp && (len < 0 || *oldlenp < (size_t)len))
1c79356b 1056 return (ENOMEM);
91447636 1057 if (newp && (maxlen < 0 || newlen >= (size_t)maxlen))
1c79356b 1058 return (EINVAL);
9bccf70c 1059 *oldlenp = len -1; /* deal with NULL strings correctly */
1c79356b 1060 if (oldp) {
1c79356b
A
1061 error = copyout(str, oldp, len);
1062 }
1063 if (error == 0 && newp) {
1064 error = copyin(newp, str, newlen);
1065 str[newlen] = 0;
e5568f75 1066 AUDIT_ARG(text, (char *)str);
1c79356b
A
1067 }
1068 return (error);
1069}
1070
1071/*
1072 * As above, but read-only.
1073 */
9bccf70c 1074int
91447636
A
1075sysctl_rdstring(user_addr_t oldp, size_t *oldlenp,
1076 user_addr_t newp, char *str)
1c79356b
A
1077{
1078 int len, error = 0;
1079
91447636
A
1080 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1081 return (EFAULT);
1c79356b 1082 len = strlen(str) + 1;
91447636 1083 if (oldp && *oldlenp < (size_t)len)
1c79356b
A
1084 return (ENOMEM);
1085 if (newp)
1086 return (EPERM);
1087 *oldlenp = len;
1088 if (oldp)
1089 error = copyout(str, oldp, len);
1090 return (error);
1091}
1092
1093/*
1094 * Validate parameters and get old / set new parameters
1095 * for a structure oriented sysctl function.
1096 */
9bccf70c 1097int
91447636
A
1098sysctl_struct(user_addr_t oldp, size_t *oldlenp,
1099 user_addr_t newp, size_t newlen, void *sp, int len)
1c79356b
A
1100{
1101 int error = 0;
1102
91447636
A
1103 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1104 return (EFAULT);
1105 if (oldp && (len < 0 || *oldlenp < (size_t)len))
1c79356b 1106 return (ENOMEM);
91447636 1107 if (newp && (len < 0 || newlen > (size_t)len))
1c79356b
A
1108 return (EINVAL);
1109 if (oldp) {
1110 *oldlenp = len;
1111 error = copyout(sp, oldp, len);
1112 }
1113 if (error == 0 && newp)
1114 error = copyin(newp, sp, len);
1115 return (error);
1116}
1117
1118/*
1119 * Validate parameters and get old parameters
1120 * for a structure oriented sysctl function.
1121 */
9bccf70c 1122int
91447636
A
1123sysctl_rdstruct(user_addr_t oldp, size_t *oldlenp,
1124 user_addr_t newp, void *sp, int len)
1c79356b
A
1125{
1126 int error = 0;
1127
91447636
A
1128 if (oldp != USER_ADDR_NULL && oldlenp == NULL)
1129 return (EFAULT);
1130 if (oldp && (len < 0 || *oldlenp < (size_t)len))
1c79356b
A
1131 return (ENOMEM);
1132 if (newp)
1133 return (EPERM);
1134 *oldlenp = len;
1135 if (oldp)
1136 error = copyout(sp, oldp, len);
1137 return (error);
1138}
1139
1140/*
1141 * Get file structures.
1142 */
9bccf70c 1143int
91447636 1144sysctl_file(user_addr_t where, size_t *sizep)
1c79356b
A
1145{
1146 int buflen, error;
91447636
A
1147 struct fileglob *fg;
1148 user_addr_t start = where;
1149 struct extern_file nef;
1c79356b
A
1150
1151 buflen = *sizep;
91447636 1152 if (where == USER_ADDR_NULL) {
1c79356b
A
1153 /*
1154 * overestimate by 10 files
1155 */
91447636 1156 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct extern_file);
1c79356b
A
1157 return (0);
1158 }
1159
1160 /*
1161 * first copyout filehead
1162 */
91447636 1163 if (buflen < 0 || (size_t)buflen < sizeof(filehead)) {
1c79356b
A
1164 *sizep = 0;
1165 return (0);
1166 }
91447636
A
1167 error = copyout((caddr_t)&filehead, where, sizeof(filehead));
1168 if (error)
1c79356b
A
1169 return (error);
1170 buflen -= sizeof(filehead);
1171 where += sizeof(filehead);
1172
1173 /*
1174 * followed by an array of file structures
1175 */
91447636
A
1176 for (fg = filehead.lh_first; fg != 0; fg = fg->f_list.le_next) {
1177 if (buflen < 0 || (size_t)buflen < sizeof(struct extern_file)) {
1c79356b
A
1178 *sizep = where - start;
1179 return (ENOMEM);
1180 }
91447636
A
1181 nef.f_list.le_next = (struct extern_file *)fg->f_list.le_next;
1182 nef.f_list.le_prev = (struct extern_file **)fg->f_list.le_prev;
1183 nef.f_flag = (fg->fg_flag & FMASK);
1184 nef.f_type = fg->fg_type;
1185 nef.f_count = fg->fg_count;
1186 nef.f_msgcount = fg->fg_msgcount;
1187 nef.f_cred = fg->fg_cred;
1188 nef.f_ops = fg->fg_ops;
1189 nef.f_offset = fg->fg_offset;
1190 nef.f_data = fg->fg_data;
1191 error = copyout((caddr_t)&nef, where, sizeof (struct extern_file));
1192 if (error)
1c79356b 1193 return (error);
91447636
A
1194 buflen -= sizeof(struct extern_file);
1195 where += sizeof(struct extern_file);
1c79356b 1196 }
91447636 1197 *sizep = where - start;
1c79356b
A
1198 return (0);
1199}
1200
1201/*
1202 * try over estimating by 5 procs
1203 */
1204#define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
1205
9bccf70c 1206int
91447636 1207sysctl_doproc(int *name, u_int namelen, user_addr_t where, size_t *sizep)
1c79356b 1208{
91447636
A
1209 struct proc *p;
1210 user_addr_t dp = where;
1211 size_t needed = 0;
1212 int buflen = where != USER_ADDR_NULL ? *sizep : 0;
1c79356b 1213 int doingzomb;
1c79356b 1214 int error = 0;
91447636
A
1215 boolean_t is_64_bit = FALSE;
1216 struct kinfo_proc kproc;
1217 struct user_kinfo_proc user_kproc;
1218 int sizeof_kproc;
1219 caddr_t kprocp;
1c79356b
A
1220
1221 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
1222 return (EINVAL);
1223 p = allproc.lh_first;
1224 doingzomb = 0;
91447636
A
1225 is_64_bit = proc_is64bit(current_proc());
1226 if (is_64_bit) {
1227 sizeof_kproc = sizeof(user_kproc);
1228 kprocp = (caddr_t) &user_kproc;
1229 }
1230 else {
1231 sizeof_kproc = sizeof(kproc);
1232 kprocp = (caddr_t) &kproc;
1233 }
1c79356b
A
1234again:
1235 for (; p != 0; p = p->p_list.le_next) {
1236 /*
1237 * Skip embryonic processes.
1238 */
1239 if (p->p_stat == SIDL)
1240 continue;
1241 /*
1242 * TODO - make more efficient (see notes below).
1243 * do by session.
1244 */
1245 switch (name[0]) {
1246
1247 case KERN_PROC_PID:
1248 /* could do this with just a lookup */
1249 if (p->p_pid != (pid_t)name[1])
1250 continue;
1251 break;
1252
1253 case KERN_PROC_PGRP:
1254 /* could do this by traversing pgrp */
1255 if (p->p_pgrp->pg_id != (pid_t)name[1])
1256 continue;
1257 break;
1258
1259 case KERN_PROC_TTY:
55e303ae
A
1260 if ((p->p_flag & P_CONTROLT) == 0 ||
1261 (p->p_session == NULL) ||
1c79356b
A
1262 p->p_session->s_ttyp == NULL ||
1263 p->p_session->s_ttyp->t_dev != (dev_t)name[1])
1264 continue;
1265 break;
1266
1267 case KERN_PROC_UID:
55e303ae 1268 if ((p->p_ucred == NULL) ||
91447636 1269 (kauth_cred_getuid(p->p_ucred) != (uid_t)name[1]))
1c79356b
A
1270 continue;
1271 break;
1272
1273 case KERN_PROC_RUID:
55e303ae 1274 if ((p->p_ucred == NULL) ||
91447636 1275 (p->p_ucred->cr_ruid != (uid_t)name[1]))
1c79356b
A
1276 continue;
1277 break;
1278 }
91447636
A
1279 if (buflen >= sizeof_kproc) {
1280 bzero(kprocp, sizeof_kproc);
1281 if (is_64_bit) {
1282 fill_user_proc(p, (struct user_kinfo_proc *) kprocp);
1283 }
1284 else {
1285 fill_proc(p, (struct kinfo_proc *) kprocp);
1286 }
1287 error = copyout(kprocp, dp, sizeof_kproc);
1288 if (error)
1c79356b 1289 return (error);
91447636
A
1290 dp += sizeof_kproc;
1291 buflen -= sizeof_kproc;
1c79356b 1292 }
91447636 1293 needed += sizeof_kproc;
1c79356b
A
1294 }
1295 if (doingzomb == 0) {
1296 p = zombproc.lh_first;
1297 doingzomb++;
1298 goto again;
1299 }
91447636
A
1300 if (where != USER_ADDR_NULL) {
1301 *sizep = dp - where;
1c79356b
A
1302 if (needed > *sizep)
1303 return (ENOMEM);
1304 } else {
1305 needed += KERN_PROCSLOP;
1306 *sizep = needed;
1307 }
1308 return (0);
1309}
1310
1c79356b
A
1311/*
1312 * Fill in an eproc structure for the specified process.
1313 */
55e303ae 1314static void
1c79356b
A
1315fill_eproc(p, ep)
1316 register struct proc *p;
1317 register struct eproc *ep;
1318{
1319 register struct tty *tp;
1320
1321 ep->e_paddr = p;
55e303ae
A
1322 if (p->p_pgrp) {
1323 ep->e_sess = p->p_pgrp->pg_session;
1324 ep->e_pgid = p->p_pgrp->pg_id;
1325 ep->e_jobc = p->p_pgrp->pg_jobc;
1326 if (ep->e_sess && ep->e_sess->s_ttyvp)
1327 ep->e_flag = EPROC_CTTY;
1328 } else {
1329 ep->e_sess = (struct session *)0;
1330 ep->e_pgid = 0;
1331 ep->e_jobc = 0;
1332 }
1333 ep->e_ppid = (p->p_pptr) ? p->p_pptr->p_pid : 0;
91447636
A
1334 /* Pre-zero the fake historical pcred */
1335 bzero(&ep->e_pcred, sizeof(struct _pcred));
1336 if (p->p_ucred) {
1337 /* XXX not ref-counted */
1338
1339 /* A fake historical pcred */
1340 ep->e_pcred.p_ruid = p->p_ucred->cr_ruid;
1341 ep->e_pcred.p_svuid = p->p_ucred->cr_svuid;
1342 ep->e_pcred.p_rgid = p->p_ucred->cr_rgid;
1343 ep->e_pcred.p_svgid = p->p_ucred->cr_svgid;
1344
1345 /* A fake historical *kauth_cred_t */
1346 ep->e_ucred.cr_ref = p->p_ucred->cr_ref;
1347 ep->e_ucred.cr_uid = kauth_cred_getuid(p->p_ucred);
1348 ep->e_ucred.cr_ngroups = p->p_ucred->cr_ngroups;
1349 bcopy(p->p_ucred->cr_groups, ep->e_ucred.cr_groups, NGROUPS*sizeof(gid_t));
1350
55e303ae 1351 }
1c79356b 1352 if (p->p_stat == SIDL || p->p_stat == SZOMB) {
1c79356b
A
1353 ep->e_vm.vm_tsize = 0;
1354 ep->e_vm.vm_dsize = 0;
1355 ep->e_vm.vm_ssize = 0;
1c79356b 1356 }
9bccf70c 1357 ep->e_vm.vm_rssize = 0;
55e303ae
A
1358
1359 if ((p->p_flag & P_CONTROLT) && (ep->e_sess) &&
1c79356b
A
1360 (tp = ep->e_sess->s_ttyp)) {
1361 ep->e_tdev = tp->t_dev;
1362 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1363 ep->e_tsess = tp->t_session;
1364 } else
1365 ep->e_tdev = NODEV;
55e303ae 1366
1c79356b
A
1367 if (SESS_LEADER(p))
1368 ep->e_flag |= EPROC_SLEADER;
1369 if (p->p_wmesg)
1370 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
1371 ep->e_xsize = ep->e_xrssize = 0;
1372 ep->e_xccount = ep->e_xswrss = 0;
1373}
55e303ae 1374
91447636
A
1375/*
1376 * Fill in an LP64 version of eproc structure for the specified process.
1377 */
1378static void
1379fill_user_eproc(register struct proc *p, register struct user_eproc *ep)
1380{
1381 register struct tty *tp;
1382 struct session *sessionp = NULL;
1383
1384 ep->e_paddr = CAST_USER_ADDR_T(p);
1385 if (p->p_pgrp) {
1386 sessionp = p->p_pgrp->pg_session;
1387 ep->e_sess = CAST_USER_ADDR_T(sessionp);
1388 ep->e_pgid = p->p_pgrp->pg_id;
1389 ep->e_jobc = p->p_pgrp->pg_jobc;
1390 if (sessionp) {
1391 if (sessionp->s_ttyvp)
1392 ep->e_flag = EPROC_CTTY;
1393 }
1394 } else {
1395 ep->e_sess = USER_ADDR_NULL;
1396 ep->e_pgid = 0;
1397 ep->e_jobc = 0;
1398 }
1399 ep->e_ppid = (p->p_pptr) ? p->p_pptr->p_pid : 0;
1400 /* Pre-zero the fake historical pcred */
1401 bzero(&ep->e_pcred, sizeof(ep->e_pcred));
1402 if (p->p_ucred) {
1403 /* XXX not ref-counted */
1404
1405 /* A fake historical pcred */
1406 ep->e_pcred.p_ruid = p->p_ucred->cr_ruid;
1407 ep->e_pcred.p_svuid = p->p_ucred->cr_svuid;
1408 ep->e_pcred.p_rgid = p->p_ucred->cr_rgid;
1409 ep->e_pcred.p_svgid = p->p_ucred->cr_svgid;
1410
1411 /* A fake historical *kauth_cred_t */
1412 ep->e_ucred.cr_ref = p->p_ucred->cr_ref;
1413 ep->e_ucred.cr_uid = kauth_cred_getuid(p->p_ucred);
1414 ep->e_ucred.cr_ngroups = p->p_ucred->cr_ngroups;
1415 bcopy(p->p_ucred->cr_groups, ep->e_ucred.cr_groups, NGROUPS*sizeof(gid_t));
1416
1417 }
1418 if (p->p_stat == SIDL || p->p_stat == SZOMB) {
1419 ep->e_vm.vm_tsize = 0;
1420 ep->e_vm.vm_dsize = 0;
1421 ep->e_vm.vm_ssize = 0;
1422 }
1423 ep->e_vm.vm_rssize = 0;
1424
1425 if ((p->p_flag & P_CONTROLT) && (sessionp) &&
1426 (tp = sessionp->s_ttyp)) {
1427 ep->e_tdev = tp->t_dev;
1428 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1429 ep->e_tsess = CAST_USER_ADDR_T(tp->t_session);
1430 } else
1431 ep->e_tdev = NODEV;
1432
1433 if (SESS_LEADER(p))
1434 ep->e_flag |= EPROC_SLEADER;
1435 if (p->p_wmesg)
1436 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
1437 ep->e_xsize = ep->e_xrssize = 0;
1438 ep->e_xccount = ep->e_xswrss = 0;
1439}
1440
1c79356b
A
1441/*
1442 * Fill in an eproc structure for the specified process.
1443 */
55e303ae 1444static void
1c79356b
A
1445fill_externproc(p, exp)
1446 register struct proc *p;
1447 register struct extern_proc *exp;
1448{
1449 exp->p_forw = exp->p_back = NULL;
9bccf70c
A
1450 if (p->p_stats)
1451 exp->p_starttime = p->p_stats->p_start;
1c79356b
A
1452 exp->p_vmspace = NULL;
1453 exp->p_sigacts = p->p_sigacts;
1454 exp->p_flag = p->p_flag;
1455 exp->p_stat = p->p_stat ;
1456 exp->p_pid = p->p_pid ;
1457 exp->p_oppid = p->p_oppid ;
1458 exp->p_dupfd = p->p_dupfd ;
1459 /* Mach related */
91447636 1460 exp->user_stack = CAST_DOWN(caddr_t, p->user_stack);
1c79356b
A
1461 exp->exit_thread = p->exit_thread ;
1462 exp->p_debugger = p->p_debugger ;
1463 exp->sigwait = p->sigwait ;
1464 /* scheduling */
1465 exp->p_estcpu = p->p_estcpu ;
1466 exp->p_cpticks = p->p_cpticks ;
1467 exp->p_pctcpu = p->p_pctcpu ;
1468 exp->p_wchan = p->p_wchan ;
1469 exp->p_wmesg = p->p_wmesg ;
1470 exp->p_swtime = p->p_swtime ;
1471 exp->p_slptime = p->p_slptime ;
1472 bcopy(&p->p_realtimer, &exp->p_realtimer,sizeof(struct itimerval));
1473 bcopy(&p->p_rtime, &exp->p_rtime,sizeof(struct timeval));
1474 exp->p_uticks = p->p_uticks ;
1475 exp->p_sticks = p->p_sticks ;
1476 exp->p_iticks = p->p_iticks ;
1477 exp->p_traceflag = p->p_traceflag ;
1478 exp->p_tracep = p->p_tracep ;
9bccf70c 1479 exp->p_siglist = 0 ; /* No longer relevant */
1c79356b
A
1480 exp->p_textvp = p->p_textvp ;
1481 exp->p_holdcnt = 0 ;
9bccf70c 1482 exp->p_sigmask = 0 ; /* no longer avaialable */
1c79356b
A
1483 exp->p_sigignore = p->p_sigignore ;
1484 exp->p_sigcatch = p->p_sigcatch ;
1485 exp->p_priority = p->p_priority ;
1486 exp->p_usrpri = p->p_usrpri ;
1487 exp->p_nice = p->p_nice ;
1488 bcopy(&p->p_comm, &exp->p_comm,MAXCOMLEN);
1489 exp->p_comm[MAXCOMLEN] = '\0';
1490 exp->p_pgrp = p->p_pgrp ;
1491 exp->p_addr = NULL;
1492 exp->p_xstat = p->p_xstat ;
1493 exp->p_acflag = p->p_acflag ;
91447636
A
1494 exp->p_ru = p->p_ru ; /* XXX may be NULL */
1495}
1496
1497/*
1498 * Fill in an LP64 version of extern_proc structure for the specified process.
1499 */
1500static void
1501fill_user_externproc(register struct proc *p, register struct user_extern_proc *exp)
1502{
1503 exp->p_forw = exp->p_back = USER_ADDR_NULL;
1504 if (p->p_stats) {
1505 exp->p_starttime.tv_sec = p->p_stats->p_start.tv_sec;
1506 exp->p_starttime.tv_usec = p->p_stats->p_start.tv_usec;
1507 }
1508 exp->p_vmspace = USER_ADDR_NULL;
1509 exp->p_sigacts = CAST_USER_ADDR_T(p->p_sigacts);
1510 exp->p_flag = p->p_flag;
1511 exp->p_stat = p->p_stat ;
1512 exp->p_pid = p->p_pid ;
1513 exp->p_oppid = p->p_oppid ;
1514 exp->p_dupfd = p->p_dupfd ;
1515 /* Mach related */
1516 exp->user_stack = p->user_stack;
1517 exp->exit_thread = CAST_USER_ADDR_T(p->exit_thread);
1518 exp->p_debugger = p->p_debugger ;
1519 exp->sigwait = p->sigwait ;
1520 /* scheduling */
1521 exp->p_estcpu = p->p_estcpu ;
1522 exp->p_cpticks = p->p_cpticks ;
1523 exp->p_pctcpu = p->p_pctcpu ;
1524 exp->p_wchan = CAST_USER_ADDR_T(p->p_wchan);
1525 exp->p_wmesg = CAST_USER_ADDR_T(p->p_wmesg);
1526 exp->p_swtime = p->p_swtime ;
1527 exp->p_slptime = p->p_slptime ;
1528 exp->p_realtimer.it_interval.tv_sec = p->p_realtimer.it_interval.tv_sec;
1529 exp->p_realtimer.it_interval.tv_usec = p->p_realtimer.it_interval.tv_usec;
1530 exp->p_realtimer.it_value.tv_sec = p->p_realtimer.it_value.tv_sec;
1531 exp->p_realtimer.it_value.tv_usec = p->p_realtimer.it_value.tv_usec;
1532 exp->p_rtime.tv_sec = p->p_rtime.tv_sec;
1533 exp->p_rtime.tv_usec = p->p_rtime.tv_usec;
1534 exp->p_uticks = p->p_uticks ;
1535 exp->p_sticks = p->p_sticks ;
1536 exp->p_iticks = p->p_iticks ;
1537 exp->p_traceflag = p->p_traceflag ;
1538 exp->p_tracep = CAST_USER_ADDR_T(p->p_tracep);
1539 exp->p_siglist = 0 ; /* No longer relevant */
1540 exp->p_textvp = CAST_USER_ADDR_T(p->p_textvp);
1541 exp->p_holdcnt = 0 ;
1542 exp->p_sigmask = 0 ; /* no longer avaialable */
1543 exp->p_sigignore = p->p_sigignore ;
1544 exp->p_sigcatch = p->p_sigcatch ;
1545 exp->p_priority = p->p_priority ;
1546 exp->p_usrpri = p->p_usrpri ;
1547 exp->p_nice = p->p_nice ;
1548 bcopy(&p->p_comm, &exp->p_comm,MAXCOMLEN);
1549 exp->p_comm[MAXCOMLEN] = '\0';
1550 exp->p_pgrp = CAST_USER_ADDR_T(p->p_pgrp);
1551 exp->p_addr = USER_ADDR_NULL;
1552 exp->p_xstat = p->p_xstat ;
1553 exp->p_acflag = p->p_acflag ;
1554 exp->p_ru = CAST_USER_ADDR_T(p->p_ru); /* XXX may be NULL */
1c79356b
A
1555}
1556
55e303ae
A
1557static void
1558fill_proc(p, kp)
1559 register struct proc *p;
1560 register struct kinfo_proc *kp;
1561{
1562 fill_externproc(p, &kp->kp_proc);
1563 fill_eproc(p, &kp->kp_eproc);
1564}
1565
91447636
A
1566static void
1567fill_user_proc(register struct proc *p, register struct user_kinfo_proc *kp)
1568{
1569 fill_user_externproc(p, &kp->kp_proc);
1570 fill_user_eproc(p, &kp->kp_eproc);
1571}
1572
9bccf70c 1573int
91447636
A
1574kdebug_ops(int *name, u_int namelen, user_addr_t where,
1575 size_t *sizep, struct proc *p)
1c79356b 1576{
9bccf70c 1577 int ret=0;
1c79356b 1578
91447636
A
1579 ret = suser(kauth_cred_get(), &p->p_acflag);
1580 if (ret)
9bccf70c 1581 return(ret);
1c79356b
A
1582
1583 switch(name[0]) {
1584 case KERN_KDEFLAGS:
1585 case KERN_KDDFLAGS:
1586 case KERN_KDENABLE:
1587 case KERN_KDGETBUF:
1588 case KERN_KDSETUP:
1589 case KERN_KDREMOVE:
1590 case KERN_KDSETREG:
1591 case KERN_KDGETREG:
1592 case KERN_KDREADTR:
1593 case KERN_KDPIDTR:
1594 case KERN_KDTHRMAP:
1595 case KERN_KDPIDEX:
1596 case KERN_KDSETRTCDEC:
1597 case KERN_KDSETBUF:
9bccf70c 1598 case KERN_KDGETENTROPY:
1c79356b
A
1599 ret = kdbg_control(name, namelen, where, sizep);
1600 break;
1601 default:
91447636 1602 ret= ENOTSUP;
1c79356b
A
1603 break;
1604 }
1605 return(ret);
1606}
1607
91447636
A
1608extern int pcsamples_control(int *name, u_int namelen, user_addr_t where,
1609 size_t * sizep);
1610
9bccf70c 1611int
91447636
A
1612pcsamples_ops(int *name, u_int namelen, user_addr_t where,
1613 size_t *sizep, struct proc *p)
1c79356b 1614{
9bccf70c 1615 int ret=0;
1c79356b 1616
91447636
A
1617 ret = suser(kauth_cred_get(), &p->p_acflag);
1618 if (ret)
9bccf70c 1619 return(ret);
1c79356b
A
1620
1621 switch(name[0]) {
1622 case KERN_PCDISABLE:
1623 case KERN_PCGETBUF:
1624 case KERN_PCSETUP:
1625 case KERN_PCREMOVE:
1626 case KERN_PCREADBUF:
1627 case KERN_PCSETREG:
1628 case KERN_PCSETBUF:
1629 case KERN_PCCOMM:
1630 ret = pcsamples_control(name, namelen, where, sizep);
1631 break;
1632 default:
91447636 1633 ret= ENOTSUP;
1c79356b
A
1634 break;
1635 }
1636 return(ret);
1637}
1638
1639/*
55e303ae
A
1640 * Return the top *sizep bytes of the user stack, or the entire area of the
1641 * user stack down through the saved exec_path, whichever is smaller.
1c79356b 1642 */
9bccf70c 1643int
91447636
A
1644sysctl_procargs(int *name, u_int namelen, user_addr_t where,
1645 size_t *sizep, struct proc *cur_proc)
55e303ae
A
1646{
1647 return sysctl_procargsx( name, namelen, where, sizep, cur_proc, 0);
1648}
1649
1650static int
91447636
A
1651sysctl_procargs2(int *name, u_int namelen, user_addr_t where,
1652 size_t *sizep, struct proc *cur_proc)
55e303ae
A
1653{
1654 return sysctl_procargsx( name, namelen, where, sizep, cur_proc, 1);
1655}
1656
1657static int
91447636
A
1658sysctl_procargsx(int *name, __unused u_int namelen, user_addr_t where,
1659 size_t *sizep, struct proc *cur_proc, int argc_yes)
1c79356b 1660{
91447636
A
1661 struct proc *p;
1662 int buflen = where != USER_ADDR_NULL ? *sizep : 0;
1c79356b
A
1663 int error = 0;
1664 struct vm_map *proc_map;
1665 struct task * task;
1666 vm_map_copy_t tmp;
91447636
A
1667 user_addr_t arg_addr;
1668 size_t arg_size;
1c79356b 1669 caddr_t data;
91447636 1670 int size;
1c79356b 1671 vm_offset_t copy_start, copy_end;
1c79356b
A
1672 kern_return_t ret;
1673 int pid;
1674
55e303ae 1675 if (argc_yes)
91447636 1676 buflen -= sizeof(int); /* reserve first word to return argc */
1c79356b 1677
91447636
A
1678 /* we only care about buflen when where (oldp from sysctl) is not NULL. */
1679 /* when where (oldp from sysctl) is NULL and sizep (oldlenp from sysctl */
1680 /* is not NULL then the caller wants us to return the length needed to */
1681 /* hold the data we would return */
1682 if (where != USER_ADDR_NULL && (buflen <= 0 || buflen > ARG_MAX)) {
1c79356b
A
1683 return(EINVAL);
1684 }
1685 arg_size = buflen;
1686
1687 /*
1688 * Lookup process by pid
1689 */
1690 pid = name[0];
1c79356b
A
1691 p = pfind(pid);
1692 if (p == NULL) {
1693 return(EINVAL);
1694 }
1695
1696 /*
1697 * Copy the top N bytes of the stack.
1698 * On all machines we have so far, the stack grows
1699 * downwards.
1700 *
1701 * If the user expects no more than N bytes of
1702 * argument list, use that as a guess for the
1703 * size.
1704 */
1705
1706 if (!p->user_stack)
1707 return(EINVAL);
1708
91447636
A
1709 if (where == USER_ADDR_NULL) {
1710 /* caller only wants to know length of proc args data */
1711 if (sizep == NULL)
1712 return(EFAULT);
1713
1714 size = p->p_argslen;
1715 if (argc_yes) {
1716 size += sizeof(int);
1717 }
1718 else {
1719 /*
1720 * old PROCARGS will return the executable's path and plus some
1721 * extra space for work alignment and data tags
1722 */
1723 size += PATH_MAX + (6 * sizeof(int));
1724 }
1725 size += (size & (sizeof(int) - 1)) ? (sizeof(int) - (size & (sizeof(int) - 1))) : 0;
1726 *sizep = size;
1727 return (0);
1728 }
1729
1730 if ((kauth_cred_getuid(p->p_ucred) != kauth_cred_getuid(kauth_cred_get()))
1731 && suser(kauth_cred_get(), &cur_proc->p_acflag))
9bccf70c 1732 return (EINVAL);
91447636
A
1733
1734 if ((u_int)arg_size > p->p_argslen)
1735 arg_size = round_page(p->p_argslen);
1736
1737 arg_addr = p->user_stack - arg_size;
1c79356b
A
1738
1739
1740 /*
1741 * Before we can block (any VM code), make another
1742 * reference to the map to keep it alive. We do
1743 * that by getting a reference on the task itself.
1744 */
1745 task = p->task;
1746 if (task == NULL)
1747 return(EINVAL);
1748
0b4e3aa0 1749 /*
91447636
A
1750 * Once we have a task reference we can convert that into a
1751 * map reference, which we will use in the calls below. The
1752 * task/process may change its map after we take this reference
1753 * (see execve), but the worst that will happen then is a return
1754 * of stale info (which is always a possibility).
0b4e3aa0 1755 */
91447636
A
1756 task_reference(task);
1757 proc_map = get_task_map_reference(task);
1758 task_deallocate(task);
1759 if (proc_map == NULL)
1760 return(EINVAL);
1c79356b 1761
91447636
A
1762
1763 ret = kmem_alloc(kernel_map, &copy_start, round_page(arg_size));
1c79356b 1764 if (ret != KERN_SUCCESS) {
91447636 1765 vm_map_deallocate(proc_map);
1c79356b
A
1766 return(ENOMEM);
1767 }
1768
91447636 1769 copy_end = round_page(copy_start + arg_size);
1c79356b 1770
91447636
A
1771 if( vm_map_copyin(proc_map, (vm_map_address_t)arg_addr,
1772 (vm_map_size_t)arg_size, FALSE, &tmp) != KERN_SUCCESS) {
1773 vm_map_deallocate(proc_map);
1c79356b 1774 kmem_free(kernel_map, copy_start,
91447636 1775 round_page(arg_size));
1c79356b
A
1776 return (EIO);
1777 }
1778
1779 /*
1780 * Now that we've done the copyin from the process'
1781 * map, we can release the reference to it.
1782 */
91447636 1783 vm_map_deallocate(proc_map);
1c79356b 1784
91447636
A
1785 if( vm_map_copy_overwrite(kernel_map,
1786 (vm_map_address_t)copy_start,
1787 tmp, FALSE) != KERN_SUCCESS) {
1c79356b 1788 kmem_free(kernel_map, copy_start,
91447636 1789 round_page(arg_size));
1c79356b
A
1790 return (EIO);
1791 }
1792
91447636
A
1793 if (arg_size > p->p_argslen) {
1794 data = (caddr_t) (copy_end - p->p_argslen);
55e303ae
A
1795 size = p->p_argslen;
1796 } else {
91447636
A
1797 data = (caddr_t) (copy_end - arg_size);
1798 size = arg_size;
55e303ae 1799 }
1c79356b 1800
55e303ae
A
1801 if (argc_yes) {
1802 /* Put processes argc as the first word in the copyout buffer */
1803 suword(where, p->p_argc);
91447636
A
1804 error = copyout(data, (where + sizeof(int)), size);
1805 size += sizeof(int);
55e303ae
A
1806 } else {
1807 error = copyout(data, where, size);
1808
1809 /*
1810 * Make the old PROCARGS work to return the executable's path
1811 * But, only if there is enough space in the provided buffer
1812 *
1813 * on entry: data [possibily] points to the beginning of the path
1814 *
1815 * Note: we keep all pointers&sizes aligned to word boundries
1816 */
91447636 1817 if ( (! error) && (buflen > 0 && (u_int)buflen > p->p_argslen) )
55e303ae 1818 {
91447636 1819 int binPath_sz, alignedBinPath_sz = 0;
55e303ae 1820 int extraSpaceNeeded, addThis;
91447636 1821 user_addr_t placeHere;
55e303ae 1822 char * str = (char *) data;
91447636 1823 int max_len = size;
55e303ae
A
1824
1825 /* Some apps are really bad about messing up their stacks
1826 So, we have to be extra careful about getting the length
1827 of the executing binary. If we encounter an error, we bail.
1828 */
1829
1830 /* Limit ourselves to PATH_MAX paths */
1831 if ( max_len > PATH_MAX ) max_len = PATH_MAX;
1832
1833 binPath_sz = 0;
1834
1835 while ( (binPath_sz < max_len-1) && (*str++ != 0) )
1836 binPath_sz++;
1837
91447636 1838 /* If we have a NUL terminator, copy it, too */
55e303ae
A
1839 if (binPath_sz < max_len-1) binPath_sz += 1;
1840
1841 /* Pre-Flight the space requiremnts */
1842
1843 /* Account for the padding that fills out binPath to the next word */
91447636 1844 alignedBinPath_sz += (binPath_sz & (sizeof(int)-1)) ? (sizeof(int)-(binPath_sz & (sizeof(int)-1))) : 0;
55e303ae
A
1845
1846 placeHere = where + size;
1847
1848 /* Account for the bytes needed to keep placeHere word aligned */
91447636 1849 addThis = (placeHere & (sizeof(int)-1)) ? (sizeof(int)-(placeHere & (sizeof(int)-1))) : 0;
55e303ae
A
1850
1851 /* Add up all the space that is needed */
91447636 1852 extraSpaceNeeded = alignedBinPath_sz + addThis + binPath_sz + (4 * sizeof(int));
55e303ae
A
1853
1854 /* is there is room to tack on argv[0]? */
91447636 1855 if ( (buflen & ~(sizeof(int)-1)) >= ( p->p_argslen + extraSpaceNeeded ))
55e303ae
A
1856 {
1857 placeHere += addThis;
1858 suword(placeHere, 0);
91447636 1859 placeHere += sizeof(int);
55e303ae 1860 suword(placeHere, 0xBFFF0000);
91447636 1861 placeHere += sizeof(int);
55e303ae 1862 suword(placeHere, 0);
91447636 1863 placeHere += sizeof(int);
55e303ae
A
1864 error = copyout(data, placeHere, binPath_sz);
1865 if ( ! error )
1866 {
1867 placeHere += binPath_sz;
1868 suword(placeHere, 0);
1869 size += extraSpaceNeeded;
1870 }
1871 }
1872 }
1873 }
1874
1875 if (copy_start != (vm_offset_t) 0) {
1876 kmem_free(kernel_map, copy_start, copy_end - copy_start);
1c79356b
A
1877 }
1878 if (error) {
1879 return(error);
1880 }
1881
91447636 1882 if (where != USER_ADDR_NULL)
1c79356b
A
1883 *sizep = size;
1884 return (0);
1885}
55e303ae
A
1886
1887
1888/*
1889 * Validate parameters and get old / set new parameters
1890 * for max number of concurrent aio requests. Makes sure
1891 * the system wide limit is greater than the per process
1892 * limit.
1893 */
1894static int
91447636 1895sysctl_aiomax(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, size_t newlen)
55e303ae
A
1896{
1897 int error = 0;
1898 int new_value;
1899
1900 if ( oldp && *oldlenp < sizeof(int) )
1901 return (ENOMEM);
1902 if ( newp && newlen != sizeof(int) )
1903 return (EINVAL);
1904
1905 *oldlenp = sizeof(int);
1906 if ( oldp )
1907 error = copyout( &aio_max_requests, oldp, sizeof(int) );
1908 if ( error == 0 && newp )
1909 error = copyin( newp, &new_value, sizeof(int) );
1910 if ( error == 0 && newp ) {
1911 if ( new_value >= aio_max_requests_per_process )
1912 aio_max_requests = new_value;
1913 else
1914 error = EINVAL;
1915 }
1916 return( error );
1917
1918} /* sysctl_aiomax */
1919
1920
1921/*
1922 * Validate parameters and get old / set new parameters
1923 * for max number of concurrent aio requests per process.
1924 * Makes sure per process limit is less than the system wide
1925 * limit.
1926 */
1927static int
91447636 1928sysctl_aioprocmax(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, size_t newlen )
55e303ae
A
1929{
1930 int error = 0;
1931 int new_value = 0;
1932
1933 if ( oldp && *oldlenp < sizeof(int) )
1934 return (ENOMEM);
1935 if ( newp && newlen != sizeof(int) )
1936 return (EINVAL);
1937
1938 *oldlenp = sizeof(int);
1939 if ( oldp )
1940 error = copyout( &aio_max_requests_per_process, oldp, sizeof(int) );
1941 if ( error == 0 && newp )
1942 error = copyin( newp, &new_value, sizeof(int) );
1943 if ( error == 0 && newp ) {
1944 if ( new_value <= aio_max_requests && new_value >= AIO_LISTIO_MAX )
1945 aio_max_requests_per_process = new_value;
1946 else
1947 error = EINVAL;
1948 }
1949 return( error );
1950
1951} /* sysctl_aioprocmax */
1952
1953
1954/*
1955 * Validate parameters and get old / set new parameters
1956 * for max number of async IO worker threads.
1957 * We only allow an increase in the number of worker threads.
1958 */
1959static int
91447636 1960sysctl_aiothreads(user_addr_t oldp, size_t *oldlenp, user_addr_t newp, size_t newlen)
55e303ae
A
1961{
1962 int error = 0;
1963 int new_value;
1964
1965 if ( oldp && *oldlenp < sizeof(int) )
1966 return (ENOMEM);
1967 if ( newp && newlen != sizeof(int) )
1968 return (EINVAL);
1969
1970 *oldlenp = sizeof(int);
1971 if ( oldp )
1972 error = copyout( &aio_worker_threads, oldp, sizeof(int) );
1973 if ( error == 0 && newp )
1974 error = copyin( newp, &new_value, sizeof(int) );
1975 if ( error == 0 && newp ) {
1976 if (new_value > aio_worker_threads ) {
1977 _aio_create_worker_threads( (new_value - aio_worker_threads) );
1978 aio_worker_threads = new_value;
1979 }
1980 else
1981 error = EINVAL;
1982 }
1983 return( error );
1984
1985} /* sysctl_aiothreads */
1986
1987
1988/*
1989 * Validate parameters and get old / set new parameters
1990 * for max number of processes per UID.
1991 * Makes sure per UID limit is less than the system wide limit.
1992 */
1993static int
91447636
A
1994sysctl_maxprocperuid(user_addr_t oldp, size_t *oldlenp,
1995 user_addr_t newp, size_t newlen)
55e303ae
A
1996{
1997 int error = 0;
1998 int new_value;
1999
91447636 2000 if ( oldp != USER_ADDR_NULL && *oldlenp < sizeof(int) )
55e303ae 2001 return (ENOMEM);
91447636 2002 if ( newp != USER_ADDR_NULL && newlen != sizeof(int) )
55e303ae
A
2003 return (EINVAL);
2004
2005 *oldlenp = sizeof(int);
91447636 2006 if ( oldp != USER_ADDR_NULL )
55e303ae 2007 error = copyout( &maxprocperuid, oldp, sizeof(int) );
91447636 2008 if ( error == 0 && newp != USER_ADDR_NULL ) {
55e303ae 2009 error = copyin( newp, &new_value, sizeof(int) );
e5568f75
A
2010 if ( error == 0 ) {
2011 AUDIT_ARG(value, new_value);
2012 if ( new_value <= maxproc && new_value > 0 )
2013 maxprocperuid = new_value;
2014 else
2015 error = EINVAL;
2016 }
91447636 2017 else
55e303ae
A
2018 error = EINVAL;
2019 }
2020 return( error );
2021
2022} /* sysctl_maxprocperuid */
2023
2024
2025/*
2026 * Validate parameters and get old / set new parameters
2027 * for max number of files per process.
2028 * Makes sure per process limit is less than the system-wide limit.
2029 */
2030static int
91447636
A
2031sysctl_maxfilesperproc(user_addr_t oldp, size_t *oldlenp,
2032 user_addr_t newp, size_t newlen)
55e303ae
A
2033{
2034 int error = 0;
2035 int new_value;
2036
91447636 2037 if ( oldp != USER_ADDR_NULL && *oldlenp < sizeof(int) )
55e303ae 2038 return (ENOMEM);
91447636 2039 if ( newp != USER_ADDR_NULL && newlen != sizeof(int) )
55e303ae
A
2040 return (EINVAL);
2041
2042 *oldlenp = sizeof(int);
91447636 2043 if ( oldp != USER_ADDR_NULL )
55e303ae 2044 error = copyout( &maxfilesperproc, oldp, sizeof(int) );
91447636 2045 if ( error == 0 && newp != USER_ADDR_NULL ) {
55e303ae 2046 error = copyin( newp, &new_value, sizeof(int) );
e5568f75
A
2047 if ( error == 0 ) {
2048 AUDIT_ARG(value, new_value);
2049 if ( new_value < maxfiles && new_value > 0 )
2050 maxfilesperproc = new_value;
2051 else
2052 error = EINVAL;
2053 }
55e303ae
A
2054 else
2055 error = EINVAL;
2056 }
2057 return( error );
2058
2059} /* sysctl_maxfilesperproc */
2060
2061
2062/*
2063 * Validate parameters and get old / set new parameters
2064 * for the system-wide limit on the max number of processes.
2065 * Makes sure the system-wide limit is less than the configured hard
2066 * limit set at kernel compilation.
2067 */
2068static int
91447636
A
2069sysctl_maxproc(user_addr_t oldp, size_t *oldlenp,
2070 user_addr_t newp, size_t newlen )
55e303ae
A
2071{
2072 int error = 0;
2073 int new_value;
2074
91447636 2075 if ( oldp != USER_ADDR_NULL && *oldlenp < sizeof(int) )
55e303ae 2076 return (ENOMEM);
91447636 2077 if ( newp != USER_ADDR_NULL && newlen != sizeof(int) )
55e303ae
A
2078 return (EINVAL);
2079
2080 *oldlenp = sizeof(int);
91447636 2081 if ( oldp != USER_ADDR_NULL )
55e303ae 2082 error = copyout( &maxproc, oldp, sizeof(int) );
91447636 2083 if ( error == 0 && newp != USER_ADDR_NULL ) {
55e303ae 2084 error = copyin( newp, &new_value, sizeof(int) );
e5568f75
A
2085 if ( error == 0 ) {
2086 AUDIT_ARG(value, new_value);
2087 if ( new_value <= hard_maxproc && new_value > 0 )
91447636 2088 maxproc = new_value;
e5568f75
A
2089 else
2090 error = EINVAL;
2091 }
55e303ae
A
2092 else
2093 error = EINVAL;
2094 }
2095 return( error );
2096
2097} /* sysctl_maxproc */