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