]> git.saurik.com Git - apple/xnu.git/blame_incremental - bsd/kern/kern_sysctl.c
xnu-517.9.4.tar.gz
[apple/xnu.git] / bsd / kern / kern_sysctl.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23/*-
24 * Copyright (c) 1982, 1986, 1989, 1993
25 * The Regents of the University of California. All rights reserved.
26 *
27 * This code is derived from software contributed to Berkeley by
28 * Mike Karels at Berkeley Software Design, Inc.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the University of
41 * California, Berkeley and its contributors.
42 * 4. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 *
58 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
59 */
60
61/*
62 * sysctl system call.
63 */
64
65#include <sys/param.h>
66#include <sys/systm.h>
67#include <sys/kernel.h>
68#include <sys/malloc.h>
69#include <sys/proc.h>
70#include <sys/file.h>
71#include <sys/vnode.h>
72#include <sys/unistd.h>
73#include <sys/buf.h>
74#include <sys/ioctl.h>
75#include <sys/namei.h>
76#include <sys/tty.h>
77#include <sys/disklabel.h>
78#include <sys/vm.h>
79#include <sys/sysctl.h>
80#include <sys/user.h>
81#include <sys/aio_kern.h>
82
83#include <bsm/audit_kernel.h>
84
85#include <mach/machine.h>
86#include <mach/mach_types.h>
87#include <mach/vm_param.h>
88#include <kern/task.h>
89#include <vm/vm_kern.h>
90#include <mach/host_info.h>
91
92extern vm_map_t bsd_pageable_map;
93
94#include <sys/mount.h>
95#include <sys/kdebug.h>
96
97#include <IOKit/IOPlatformExpert.h>
98#include <pexpert/pexpert.h>
99
100#include <machine/machine_routines.h>
101
102sysctlfn kern_sysctl;
103#ifdef DEBUG
104sysctlfn debug_sysctl;
105#endif
106extern sysctlfn vm_sysctl;
107extern sysctlfn vfs_sysctl;
108extern sysctlfn net_sysctl;
109extern sysctlfn cpu_sysctl;
110extern int aio_max_requests;
111extern int aio_max_requests_per_process;
112extern int aio_worker_threads;
113extern int maxprocperuid;
114extern int maxfilesperproc;
115
116
117int
118userland_sysctl(struct proc *p, int *name, u_int namelen, void *old, size_t
119 *oldlenp, int inkernel, void *new, size_t newlen, size_t *retval);
120
121static int
122sysctl_aiomax( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
123static int
124sysctl_aioprocmax( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
125static int
126sysctl_aiothreads( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
127static void
128fill_proc(struct proc *p, struct kinfo_proc *kp);
129static int
130sysctl_maxfilesperproc( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
131static int
132sysctl_maxprocperuid( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
133static int
134sysctl_maxproc( void *oldp, size_t *oldlenp, void *newp, size_t newlen );
135static int
136sysctl_procargs2( int *name, u_int namelen, char *where, size_t *sizep, struct proc *cur_proc);
137static int
138sysctl_procargsx( int *name, u_int namelen, char *where, size_t *sizep, struct proc *cur_proc, int argc_yes);
139
140
141/*
142 * temporary location for vm_sysctl. This should be machine independant
143 */
144int
145vm_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
146 int *name;
147 u_int namelen;
148 void *oldp;
149 size_t *oldlenp;
150 void *newp;
151 size_t newlen;
152 struct proc *p;
153{
154 extern uint32_t mach_factor[3];
155 struct loadavg loadinfo;
156
157 switch (name[0]) {
158 case VM_LOADAVG:
159 return (sysctl_struct(oldp, oldlenp, newp, newlen,
160 &averunnable, sizeof(struct loadavg)));
161 case VM_MACHFACTOR:
162 loadinfo.ldavg[0] = mach_factor[0];
163 loadinfo.ldavg[1] = mach_factor[1];
164 loadinfo.ldavg[2] = mach_factor[2];
165 loadinfo.fscale = LSCALE;
166 return (sysctl_struct(oldp, oldlenp, newp, newlen,
167 &loadinfo, sizeof(struct loadavg)));
168 case VM_METER:
169 return (EOPNOTSUPP);
170 case VM_MAXID:
171 return (EOPNOTSUPP);
172 default:
173 return (EOPNOTSUPP);
174 }
175 /* NOTREACHED */
176 return (EOPNOTSUPP);
177}
178
179/*
180 * Locking and stats
181 */
182static struct sysctl_lock {
183 int sl_lock;
184 int sl_want;
185 int sl_locked;
186} memlock;
187
188struct __sysctl_args {
189 int *name;
190 u_int namelen;
191 void *old;
192 size_t *oldlenp;
193 void *new;
194 size_t newlen;
195};
196int
197__sysctl(p, uap, retval)
198 struct proc *p;
199 register struct __sysctl_args *uap;
200 register_t *retval;
201{
202 int error, dolock = 1;
203 size_t savelen, oldlen = 0;
204 sysctlfn *fn;
205 int name[CTL_MAXNAME];
206 int i;
207 int error1;
208
209 /*
210 * all top-level sysctl names are non-terminal
211 */
212 if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
213 return (EINVAL);
214 if (error =
215 copyin(uap->name, &name, uap->namelen * sizeof(int)))
216 return (error);
217
218 AUDIT_ARG(ctlname, name, uap->namelen);
219
220 /* CTL_UNSPEC is used to get oid to AUTO_OID */
221 if (uap->new != NULL
222 && ((name[0] == CTL_KERN
223 && !(name[1] == KERN_IPC || name[1] == KERN_PANICINFO))
224 || (name[0] == CTL_HW)
225 || (name[0] == CTL_VM)
226 || (name[0] == CTL_VFS))
227 && (error = suser(p->p_ucred, &p->p_acflag)))
228 return (error);
229
230 switch (name[0]) {
231 case CTL_KERN:
232 fn = kern_sysctl;
233 if ((name[1] != KERN_VNODE) && (name[1] != KERN_FILE)
234 && (name[1] != KERN_PROC))
235 dolock = 0;
236 break;
237 case CTL_VM:
238 fn = vm_sysctl;
239 break;
240
241 case CTL_VFS:
242 fn = vfs_sysctl;
243 break;
244#ifdef DEBUG
245 case CTL_DEBUG:
246 fn = debug_sysctl;
247 break;
248#endif
249 default:
250 fn = 0;
251 }
252
253 if (uap->oldlenp &&
254 (error = copyin(uap->oldlenp, &oldlen, sizeof(oldlen))))
255 return (error);
256
257 if (uap->old != NULL) {
258 if (!useracc(uap->old, oldlen, B_WRITE))
259 return (EFAULT);
260
261 /* The pc sampling mechanism does not need to take this lock */
262 if ((name[1] != KERN_PCSAMPLES) &&
263 (!((name[1] == KERN_KDEBUG) && (name[2] == KERN_KDGETENTROPY)))) {
264 while (memlock.sl_lock) {
265 memlock.sl_want = 1;
266 sleep((caddr_t)&memlock, PRIBIO+1);
267 memlock.sl_locked++;
268 }
269 memlock.sl_lock = 1;
270 }
271
272 if (dolock && oldlen && (error = vslock(uap->old, oldlen))) {
273 if ((name[1] != KERN_PCSAMPLES) &&
274 (! ((name[1] == KERN_KDEBUG) && (name[2] == KERN_KDGETENTROPY)))) {
275 memlock.sl_lock = 0;
276 if (memlock.sl_want) {
277 memlock.sl_want = 0;
278 wakeup((caddr_t)&memlock);
279 }
280 }
281 return(error);
282 }
283 savelen = oldlen;
284 }
285
286 if (fn)
287 error = (*fn)(name + 1, uap->namelen - 1, uap->old,
288 &oldlen, uap->new, uap->newlen, p);
289 else
290 error = EOPNOTSUPP;
291
292 if ( (name[0] != CTL_VFS) && (error == EOPNOTSUPP))
293 error = userland_sysctl(p, name, uap->namelen,
294 uap->old, uap->oldlenp, 0,
295 uap->new, uap->newlen, &oldlen);
296
297 if (uap->old != NULL) {
298 if (dolock && savelen) {
299 error1 = vsunlock(uap->old, savelen, B_WRITE);
300 if (!error && error1)
301 error = error1;
302 }
303 if (name[1] != KERN_PCSAMPLES) {
304 memlock.sl_lock = 0;
305 if (memlock.sl_want) {
306 memlock.sl_want = 0;
307 wakeup((caddr_t)&memlock);
308 }
309 }
310 }
311 if ((error) && (error != ENOMEM))
312 return (error);
313
314 if (uap->oldlenp) {
315 i = copyout(&oldlen, uap->oldlenp, sizeof(oldlen));
316 if (i)
317 return i;
318 }
319
320 return (error);
321}
322
323/*
324 * Attributes stored in the kernel.
325 */
326extern char hostname[MAXHOSTNAMELEN]; /* defined in bsd/kern/init_main.c */
327extern int hostnamelen;
328extern char domainname[MAXHOSTNAMELEN];
329extern int domainnamelen;
330extern char classichandler[32];
331extern long classichandler_fsid;
332extern long classichandler_fileid;
333__private_extern__ char corefilename[MAXPATHLEN+1];
334__private_extern__ do_coredump;
335__private_extern__ sugid_coredump;
336
337
338extern long hostid;
339#ifdef INSECURE
340int securelevel = -1;
341#else
342int securelevel;
343#endif
344
345static int
346sysctl_affinity(name, namelen, oldBuf, oldSize, newBuf, newSize, cur_proc)
347 int *name;
348 u_int namelen;
349 char *oldBuf;
350 size_t *oldSize;
351 char *newBuf;
352 size_t newSize;
353 struct proc *cur_proc;
354{
355 if (namelen < 1)
356 return (EOPNOTSUPP);
357
358 if (name[0] == 0 && 1 == namelen) {
359 return sysctl_rdint(oldBuf, oldSize, newBuf,
360 (cur_proc->p_flag & P_AFFINITY) ? 1 : 0);
361 } else if (name[0] == 1 && 2 == namelen) {
362 if (name[1] == 0) {
363 cur_proc->p_flag &= ~P_AFFINITY;
364 } else {
365 cur_proc->p_flag |= P_AFFINITY;
366 }
367 return 0;
368 }
369 return (EOPNOTSUPP);
370}
371
372static int
373sysctl_classic(name, namelen, oldBuf, oldSize, newBuf, newSize, cur_proc)
374 int *name;
375 u_int namelen;
376 char *oldBuf;
377 size_t *oldSize;
378 char *newBuf;
379 size_t newSize;
380 struct proc *cur_proc;
381{
382 int newVal;
383 int err;
384 struct proc *p;
385
386 if (namelen != 1)
387 return (EOPNOTSUPP);
388
389 p = pfind(name[0]);
390 if (p == NULL)
391 return (EINVAL);
392
393 if ((p->p_ucred->cr_uid != cur_proc->p_ucred->cr_uid)
394 && suser(cur_proc->p_ucred, &cur_proc->p_acflag))
395 return (EPERM);
396
397 return sysctl_rdint(oldBuf, oldSize, newBuf,
398 (p->p_flag & P_CLASSIC) ? 1 : 0);
399}
400
401static int
402sysctl_classichandler(name, namelen, oldBuf, oldSize, newBuf, newSize, p)
403 int *name;
404 u_int namelen;
405 char *oldBuf;
406 size_t *oldSize;
407 char *newBuf;
408 size_t newSize;
409 struct proc *p;
410{
411 int error;
412 int len;
413 struct nameidata nd;
414 struct vattr vattr;
415 char handler[sizeof(classichandler)];
416
417 if ((error = suser(p->p_ucred, &p->p_acflag)))
418 return (error);
419 len = strlen(classichandler) + 1;
420 if (oldBuf && *oldSize < len)
421 return (ENOMEM);
422 if (newBuf && newSize >= sizeof(classichandler))
423 return (ENAMETOOLONG);
424 *oldSize = len - 1;
425 if (newBuf) {
426 error = copyin(newBuf, handler, newSize);
427 if (error)
428 return (error);
429 handler[newSize] = 0;
430
431 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
432 handler, p);
433 error = namei(&nd);
434 if (error)
435 return (error);
436 /* Check mount point */
437 if ((nd.ni_vp->v_mount->mnt_flag & MNT_NOEXEC) ||
438 (nd.ni_vp->v_type != VREG)) {
439 vput(nd.ni_vp);
440 return (EACCES);
441 }
442 error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p);
443 if (error) {
444 vput(nd.ni_vp);
445 return (error);
446 }
447 classichandler_fsid = vattr.va_fsid;
448 classichandler_fileid = vattr.va_fileid;
449 vput(nd.ni_vp);
450 }
451 if (oldBuf) {
452 error = copyout(classichandler, oldBuf, len);
453 if (error)
454 return (error);
455 }
456 if (newBuf) {
457 strcpy(classichandler, handler);
458 }
459 return (error);
460}
461
462
463extern int get_kernel_symfile( struct proc *, char **);
464extern int sysctl_dopanicinfo(int *, u_int, void *, size_t *,
465 void *, size_t, struct proc *);
466
467/*
468 * kernel related system variables.
469 */
470int
471kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
472 int *name;
473 u_int namelen;
474 void *oldp;
475 size_t *oldlenp;
476 void *newp;
477 size_t newlen;
478 struct proc *p;
479{
480 int error, level, inthostid, tmp;
481 unsigned int oldval=0;
482 char *str;
483 extern char ostype[], osrelease[], version[];
484 extern int netboot_root();
485
486 /* all sysctl names not listed below are terminal at this level */
487 if (namelen != 1
488 && !(name[0] == KERN_PROC
489 || name[0] == KERN_PROF
490 || name[0] == KERN_KDEBUG
491 || name[0] == KERN_PROCARGS
492 || name[0] == KERN_PROCARGS2
493 || name[0] == KERN_PCSAMPLES
494 || name[0] == KERN_IPC
495 || name[0] == KERN_SYSV
496 || name[0] == KERN_AFFINITY
497 || name[0] == KERN_CLASSIC
498 || name[0] == KERN_PANICINFO)
499 )
500 return (ENOTDIR); /* overloaded */
501
502 switch (name[0]) {
503 case KERN_OSTYPE:
504 return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
505 case KERN_OSRELEASE:
506 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
507 case KERN_OSREV:
508 return (sysctl_rdint(oldp, oldlenp, newp, BSD));
509 case KERN_VERSION:
510 return (sysctl_rdstring(oldp, oldlenp, newp, version));
511 case KERN_MAXVNODES:
512 oldval = desiredvnodes;
513 error = sysctl_int(oldp, oldlenp, newp,
514 newlen, &desiredvnodes);
515 reset_vmobjectcache(oldval, desiredvnodes);
516 resize_namecache(desiredvnodes);
517 return(error);
518 case KERN_MAXPROC:
519 return (sysctl_maxproc(oldp, oldlenp, newp, newlen));
520 case KERN_MAXFILES:
521 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
522 case KERN_MAXPROCPERUID:
523 return( sysctl_maxprocperuid( oldp, oldlenp, newp, newlen ) );
524 case KERN_MAXFILESPERPROC:
525 return( sysctl_maxfilesperproc( oldp, oldlenp, newp, newlen ) );
526 case KERN_ARGMAX:
527 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
528 case KERN_SECURELVL:
529 level = securelevel;
530 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
531 newp == NULL)
532 return (error);
533 if (level < securelevel && p->p_pid != 1)
534 return (EPERM);
535 securelevel = level;
536 return (0);
537 case KERN_HOSTNAME:
538 error = sysctl_string(oldp, oldlenp, newp, newlen,
539 hostname, sizeof(hostname));
540 if (newp && !error)
541 hostnamelen = newlen;
542 return (error);
543 case KERN_DOMAINNAME:
544 error = sysctl_string(oldp, oldlenp, newp, newlen,
545 domainname, sizeof(domainname));
546 if (newp && !error)
547 domainnamelen = newlen;
548 return (error);
549 case KERN_HOSTID:
550 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */
551 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
552 hostid = inthostid;
553 return (error);
554 case KERN_CLOCKRATE:
555 return (sysctl_clockrate(oldp, oldlenp));
556 case KERN_BOOTTIME:
557 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
558 sizeof(struct timeval)));
559 case KERN_VNODE:
560 return (sysctl_vnode(oldp, oldlenp));
561 case KERN_PROC:
562 return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
563 case KERN_FILE:
564 return (sysctl_file(oldp, oldlenp));
565#ifdef GPROF
566 case KERN_PROF:
567 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
568 newp, newlen));
569#endif
570 case KERN_POSIX1:
571 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
572 case KERN_NGROUPS:
573 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
574 case KERN_JOB_CONTROL:
575 return (sysctl_rdint(oldp, oldlenp, newp, 1));
576 case KERN_SAVED_IDS:
577#ifdef _POSIX_SAVED_IDS
578 return (sysctl_rdint(oldp, oldlenp, newp, 1));
579#else
580 return (sysctl_rdint(oldp, oldlenp, newp, 0));
581#endif
582 case KERN_KDEBUG:
583 return (kdebug_ops(name + 1, namelen - 1, oldp, oldlenp, p));
584 case KERN_PCSAMPLES:
585 return (pcsamples_ops(name + 1, namelen - 1, oldp, oldlenp, p));
586 case KERN_PROCARGS:
587 /* new one as it does not use kinfo_proc */
588 return (sysctl_procargs(name + 1, namelen - 1, oldp, oldlenp, p));
589 case KERN_PROCARGS2:
590 /* new one as it does not use kinfo_proc */
591 return (sysctl_procargs2(name + 1, namelen - 1, oldp, oldlenp, p));
592 case KERN_SYMFILE:
593 error = get_kernel_symfile( p, &str );
594 if ( error )
595 return error;
596 return (sysctl_rdstring(oldp, oldlenp, newp, str));
597 case KERN_NETBOOT:
598 return (sysctl_rdint(oldp, oldlenp, newp, netboot_root()));
599 case KERN_PANICINFO:
600 return(sysctl_dopanicinfo(name + 1, namelen - 1, oldp, oldlenp,
601 newp, newlen, p));
602 case KERN_AFFINITY:
603 return sysctl_affinity(name+1, namelen-1, oldp, oldlenp,
604 newp, newlen, p);
605 case KERN_CLASSIC:
606 return sysctl_classic(name+1, namelen-1, oldp, oldlenp,
607 newp, newlen, p);
608 case KERN_CLASSICHANDLER:
609 return sysctl_classichandler(name+1, namelen-1, oldp, oldlenp,
610 newp, newlen, p);
611 case KERN_AIOMAX:
612 return( sysctl_aiomax( oldp, oldlenp, newp, newlen ) );
613 case KERN_AIOPROCMAX:
614 return( sysctl_aioprocmax( oldp, oldlenp, newp, newlen ) );
615 case KERN_AIOTHREADS:
616 return( sysctl_aiothreads( oldp, oldlenp, newp, newlen ) );
617 case KERN_COREFILE:
618 error = sysctl_string(oldp, oldlenp, newp, newlen,
619 corefilename, sizeof(corefilename));
620 return (error);
621 case KERN_COREDUMP:
622 tmp = do_coredump;
623 error = sysctl_int(oldp, oldlenp, newp, newlen, &do_coredump);
624 if (!error && (do_coredump < 0) || (do_coredump > 1)) {
625 do_coredump = tmp;
626 error = EINVAL;
627 }
628 return (error);
629 case KERN_SUGID_COREDUMP:
630 tmp = sugid_coredump;
631 error = sysctl_int(oldp, oldlenp, newp, newlen, &sugid_coredump);
632 if (!error && (sugid_coredump < 0) || (sugid_coredump > 1)) {
633 sugid_coredump = tmp;
634 error = EINVAL;
635 }
636 return (error);
637 default:
638 return (EOPNOTSUPP);
639 }
640 /* NOTREACHED */
641}
642
643#ifdef DEBUG
644/*
645 * Debugging related system variables.
646 */
647#if DIAGNOSTIC
648extern
649#endif /* DIAGNOSTIC */
650struct ctldebug debug0, debug1;
651struct ctldebug debug2, debug3, debug4;
652struct ctldebug debug5, debug6, debug7, debug8, debug9;
653struct ctldebug debug10, debug11, debug12, debug13, debug14;
654struct ctldebug debug15, debug16, debug17, debug18, debug19;
655static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
656 &debug0, &debug1, &debug2, &debug3, &debug4,
657 &debug5, &debug6, &debug7, &debug8, &debug9,
658 &debug10, &debug11, &debug12, &debug13, &debug14,
659 &debug15, &debug16, &debug17, &debug18, &debug19,
660};
661int
662debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
663 int *name;
664 u_int namelen;
665 void *oldp;
666 size_t *oldlenp;
667 void *newp;
668 size_t newlen;
669 struct proc *p;
670{
671 struct ctldebug *cdp;
672
673 /* all sysctl names at this level are name and field */
674 if (namelen != 2)
675 return (ENOTDIR); /* overloaded */
676 cdp = debugvars[name[0]];
677 if (cdp->debugname == 0)
678 return (EOPNOTSUPP);
679 switch (name[1]) {
680 case CTL_DEBUG_NAME:
681 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
682 case CTL_DEBUG_VALUE:
683 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
684 default:
685 return (EOPNOTSUPP);
686 }
687 /* NOTREACHED */
688}
689#endif /* DEBUG */
690
691/*
692 * Validate parameters and get old / set new parameters
693 * for an integer-valued sysctl function.
694 */
695int
696sysctl_int(oldp, oldlenp, newp, newlen, valp)
697 void *oldp;
698 size_t *oldlenp;
699 void *newp;
700 size_t newlen;
701 int *valp;
702{
703 int error = 0;
704
705 if (oldp && *oldlenp < sizeof(int))
706 return (ENOMEM);
707 if (newp && newlen != sizeof(int))
708 return (EINVAL);
709 *oldlenp = sizeof(int);
710 if (oldp)
711 error = copyout(valp, oldp, sizeof(int));
712 if (error == 0 && newp) {
713 error = copyin(newp, valp, sizeof(int));
714 AUDIT_ARG(value, *valp);
715 }
716 return (error);
717}
718
719/*
720 * As above, but read-only.
721 */
722int
723sysctl_rdint(oldp, oldlenp, newp, val)
724 void *oldp;
725 size_t *oldlenp;
726 void *newp;
727 int val;
728{
729 int error = 0;
730
731 if (oldp && *oldlenp < sizeof(int))
732 return (ENOMEM);
733 if (newp)
734 return (EPERM);
735 *oldlenp = sizeof(int);
736 if (oldp)
737 error = copyout((caddr_t)&val, oldp, sizeof(int));
738 return (error);
739}
740
741/*
742 * Validate parameters and get old / set new parameters
743 * for an quad(64bit)-valued sysctl function.
744 */
745int
746sysctl_quad(oldp, oldlenp, newp, newlen, valp)
747 void *oldp;
748 size_t *oldlenp;
749 void *newp;
750 size_t newlen;
751 quad_t *valp;
752{
753 int error = 0;
754
755 if (oldp && *oldlenp < sizeof(quad_t))
756 return (ENOMEM);
757 if (newp && newlen != sizeof(quad_t))
758 return (EINVAL);
759 *oldlenp = sizeof(quad_t);
760 if (oldp)
761 error = copyout(valp, oldp, sizeof(quad_t));
762 if (error == 0 && newp)
763 error = copyin(newp, valp, sizeof(quad_t));
764 return (error);
765}
766
767/*
768 * As above, but read-only.
769 */
770int
771sysctl_rdquad(oldp, oldlenp, newp, val)
772 void *oldp;
773 size_t *oldlenp;
774 void *newp;
775 quad_t val;
776{
777 int error = 0;
778
779 if (oldp && *oldlenp < sizeof(quad_t))
780 return (ENOMEM);
781 if (newp)
782 return (EPERM);
783 *oldlenp = sizeof(quad_t);
784 if (oldp)
785 error = copyout((caddr_t)&val, oldp, sizeof(quad_t));
786 return (error);
787}
788
789/*
790 * Validate parameters and get old / set new parameters
791 * for a string-valued sysctl function.
792 */
793int
794sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
795 void *oldp;
796 size_t *oldlenp;
797 void *newp;
798 size_t newlen;
799 char *str;
800 int maxlen;
801{
802 int len, error = 0;
803
804 len = strlen(str) + 1;
805 if (oldp && *oldlenp < len)
806 return (ENOMEM);
807 if (newp && newlen >= maxlen)
808 return (EINVAL);
809 *oldlenp = len -1; /* deal with NULL strings correctly */
810 if (oldp) {
811 error = copyout(str, oldp, len);
812 }
813 if (error == 0 && newp) {
814 error = copyin(newp, str, newlen);
815 str[newlen] = 0;
816 AUDIT_ARG(text, (char *)str);
817 }
818 return (error);
819}
820
821/*
822 * As above, but read-only.
823 */
824int
825sysctl_rdstring(oldp, oldlenp, newp, str)
826 void *oldp;
827 size_t *oldlenp;
828 void *newp;
829 char *str;
830{
831 int len, error = 0;
832
833 len = strlen(str) + 1;
834 if (oldp && *oldlenp < len)
835 return (ENOMEM);
836 if (newp)
837 return (EPERM);
838 *oldlenp = len;
839 if (oldp)
840 error = copyout(str, oldp, len);
841 return (error);
842}
843
844/*
845 * Validate parameters and get old / set new parameters
846 * for a structure oriented sysctl function.
847 */
848int
849sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
850 void *oldp;
851 size_t *oldlenp;
852 void *newp;
853 size_t newlen;
854 void *sp;
855 int len;
856{
857 int error = 0;
858
859 if (oldp && *oldlenp < len)
860 return (ENOMEM);
861 if (newp && newlen > len)
862 return (EINVAL);
863 if (oldp) {
864 *oldlenp = len;
865 error = copyout(sp, oldp, len);
866 }
867 if (error == 0 && newp)
868 error = copyin(newp, sp, len);
869 return (error);
870}
871
872/*
873 * Validate parameters and get old parameters
874 * for a structure oriented sysctl function.
875 */
876int
877sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
878 void *oldp;
879 size_t *oldlenp;
880 void *newp, *sp;
881 int len;
882{
883 int error = 0;
884
885 if (oldp && *oldlenp < len)
886 return (ENOMEM);
887 if (newp)
888 return (EPERM);
889 *oldlenp = len;
890 if (oldp)
891 error = copyout(sp, oldp, len);
892 return (error);
893}
894
895/*
896 * Get file structures.
897 */
898int
899sysctl_file(where, sizep)
900 char *where;
901 size_t *sizep;
902{
903 int buflen, error;
904 struct file *fp;
905 char *start = where;
906
907 buflen = *sizep;
908 if (where == NULL) {
909 /*
910 * overestimate by 10 files
911 */
912 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
913 return (0);
914 }
915
916 /*
917 * first copyout filehead
918 */
919 if (buflen < sizeof(filehead)) {
920 *sizep = 0;
921 return (0);
922 }
923 if (error = copyout((caddr_t)&filehead, where, sizeof(filehead)))
924 return (error);
925 buflen -= sizeof(filehead);
926 where += sizeof(filehead);
927
928 /*
929 * followed by an array of file structures
930 */
931 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) {
932 if (buflen < sizeof(struct file)) {
933 *sizep = where - start;
934 return (ENOMEM);
935 }
936 if (error = copyout((caddr_t)fp, where, sizeof (struct file)))
937 return (error);
938 buflen -= sizeof(struct file);
939 where += sizeof(struct file);
940 }
941 *sizep = where - start;
942 return (0);
943}
944
945/*
946 * try over estimating by 5 procs
947 */
948#define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
949
950int
951sysctl_doproc(name, namelen, where, sizep)
952 int *name;
953 u_int namelen;
954 char *where;
955 size_t *sizep;
956{
957 register struct proc *p;
958 register struct kinfo_proc *dp = (struct kinfo_proc *)where;
959 register int needed = 0;
960 int buflen = where != NULL ? *sizep : 0;
961 int doingzomb;
962 struct kinfo_proc kproc;
963 int error = 0;
964
965 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
966 return (EINVAL);
967 p = allproc.lh_first;
968 doingzomb = 0;
969again:
970 for (; p != 0; p = p->p_list.le_next) {
971 /*
972 * Skip embryonic processes.
973 */
974 if (p->p_stat == SIDL)
975 continue;
976 /*
977 * TODO - make more efficient (see notes below).
978 * do by session.
979 */
980 switch (name[0]) {
981
982 case KERN_PROC_PID:
983 /* could do this with just a lookup */
984 if (p->p_pid != (pid_t)name[1])
985 continue;
986 break;
987
988 case KERN_PROC_PGRP:
989 /* could do this by traversing pgrp */
990 if (p->p_pgrp->pg_id != (pid_t)name[1])
991 continue;
992 break;
993
994 case KERN_PROC_TTY:
995 if ((p->p_flag & P_CONTROLT) == 0 ||
996 (p->p_session == NULL) ||
997 p->p_session->s_ttyp == NULL ||
998 p->p_session->s_ttyp->t_dev != (dev_t)name[1])
999 continue;
1000 break;
1001
1002 case KERN_PROC_UID:
1003 if ((p->p_ucred == NULL) ||
1004 (p->p_ucred->cr_uid != (uid_t)name[1]))
1005 continue;
1006 break;
1007
1008 case KERN_PROC_RUID:
1009 if ((p->p_ucred == NULL) ||
1010 (p->p_cred->p_ruid != (uid_t)name[1]))
1011 continue;
1012 break;
1013 }
1014 if (buflen >= sizeof(struct kinfo_proc)) {
1015 bzero(&kproc, sizeof(struct kinfo_proc));
1016 fill_proc(p, &kproc);
1017 if (error = copyout((caddr_t)&kproc, &dp->kp_proc,
1018 sizeof(struct kinfo_proc)))
1019 return (error);
1020 dp++;
1021 buflen -= sizeof(struct kinfo_proc);
1022 }
1023 needed += sizeof(struct kinfo_proc);
1024 }
1025 if (doingzomb == 0) {
1026 p = zombproc.lh_first;
1027 doingzomb++;
1028 goto again;
1029 }
1030 if (where != NULL) {
1031 *sizep = (caddr_t)dp - where;
1032 if (needed > *sizep)
1033 return (ENOMEM);
1034 } else {
1035 needed += KERN_PROCSLOP;
1036 *sizep = needed;
1037 }
1038 return (0);
1039}
1040
1041/*
1042 * Fill in an eproc structure for the specified process.
1043 */
1044static void
1045fill_eproc(p, ep)
1046 register struct proc *p;
1047 register struct eproc *ep;
1048{
1049 register struct tty *tp;
1050
1051 ep->e_paddr = p;
1052 if (p->p_pgrp) {
1053 ep->e_sess = p->p_pgrp->pg_session;
1054 ep->e_pgid = p->p_pgrp->pg_id;
1055 ep->e_jobc = p->p_pgrp->pg_jobc;
1056 if (ep->e_sess && ep->e_sess->s_ttyvp)
1057 ep->e_flag = EPROC_CTTY;
1058 } else {
1059 ep->e_sess = (struct session *)0;
1060 ep->e_pgid = 0;
1061 ep->e_jobc = 0;
1062 }
1063 ep->e_ppid = (p->p_pptr) ? p->p_pptr->p_pid : 0;
1064 if (p->p_cred) {
1065 ep->e_pcred = *p->p_cred;
1066 if (p->p_ucred)
1067 ep->e_ucred = *p->p_ucred;
1068 }
1069 if (p->p_stat == SIDL || p->p_stat == SZOMB) {
1070 ep->e_vm.vm_tsize = 0;
1071 ep->e_vm.vm_dsize = 0;
1072 ep->e_vm.vm_ssize = 0;
1073 }
1074 ep->e_vm.vm_rssize = 0;
1075
1076 if ((p->p_flag & P_CONTROLT) && (ep->e_sess) &&
1077 (tp = ep->e_sess->s_ttyp)) {
1078 ep->e_tdev = tp->t_dev;
1079 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1080 ep->e_tsess = tp->t_session;
1081 } else
1082 ep->e_tdev = NODEV;
1083
1084 if (SESS_LEADER(p))
1085 ep->e_flag |= EPROC_SLEADER;
1086 if (p->p_wmesg)
1087 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
1088 ep->e_xsize = ep->e_xrssize = 0;
1089 ep->e_xccount = ep->e_xswrss = 0;
1090}
1091
1092/*
1093 * Fill in an eproc structure for the specified process.
1094 */
1095static void
1096fill_externproc(p, exp)
1097 register struct proc *p;
1098 register struct extern_proc *exp;
1099{
1100 exp->p_forw = exp->p_back = NULL;
1101 if (p->p_stats)
1102 exp->p_starttime = p->p_stats->p_start;
1103 exp->p_vmspace = NULL;
1104 exp->p_sigacts = p->p_sigacts;
1105 exp->p_flag = p->p_flag;
1106 exp->p_stat = p->p_stat ;
1107 exp->p_pid = p->p_pid ;
1108 exp->p_oppid = p->p_oppid ;
1109 exp->p_dupfd = p->p_dupfd ;
1110 /* Mach related */
1111 exp->user_stack = p->user_stack ;
1112 exp->exit_thread = p->exit_thread ;
1113 exp->p_debugger = p->p_debugger ;
1114 exp->sigwait = p->sigwait ;
1115 /* scheduling */
1116 exp->p_estcpu = p->p_estcpu ;
1117 exp->p_cpticks = p->p_cpticks ;
1118 exp->p_pctcpu = p->p_pctcpu ;
1119 exp->p_wchan = p->p_wchan ;
1120 exp->p_wmesg = p->p_wmesg ;
1121 exp->p_swtime = p->p_swtime ;
1122 exp->p_slptime = p->p_slptime ;
1123 bcopy(&p->p_realtimer, &exp->p_realtimer,sizeof(struct itimerval));
1124 bcopy(&p->p_rtime, &exp->p_rtime,sizeof(struct timeval));
1125 exp->p_uticks = p->p_uticks ;
1126 exp->p_sticks = p->p_sticks ;
1127 exp->p_iticks = p->p_iticks ;
1128 exp->p_traceflag = p->p_traceflag ;
1129 exp->p_tracep = p->p_tracep ;
1130 exp->p_siglist = 0 ; /* No longer relevant */
1131 exp->p_textvp = p->p_textvp ;
1132 exp->p_holdcnt = 0 ;
1133 exp->p_sigmask = 0 ; /* no longer avaialable */
1134 exp->p_sigignore = p->p_sigignore ;
1135 exp->p_sigcatch = p->p_sigcatch ;
1136 exp->p_priority = p->p_priority ;
1137 exp->p_usrpri = p->p_usrpri ;
1138 exp->p_nice = p->p_nice ;
1139 bcopy(&p->p_comm, &exp->p_comm,MAXCOMLEN);
1140 exp->p_comm[MAXCOMLEN] = '\0';
1141 exp->p_pgrp = p->p_pgrp ;
1142 exp->p_addr = NULL;
1143 exp->p_xstat = p->p_xstat ;
1144 exp->p_acflag = p->p_acflag ;
1145 exp->p_ru = p->p_ru ;
1146}
1147
1148static void
1149fill_proc(p, kp)
1150 register struct proc *p;
1151 register struct kinfo_proc *kp;
1152{
1153 fill_externproc(p, &kp->kp_proc);
1154 fill_eproc(p, &kp->kp_eproc);
1155}
1156
1157int
1158kdebug_ops(name, namelen, where, sizep, p)
1159int *name;
1160u_int namelen;
1161char *where;
1162size_t *sizep;
1163struct proc *p;
1164{
1165 int size=*sizep;
1166 int ret=0;
1167 extern int kdbg_control(int *name, u_int namelen,
1168 char * where,size_t * sizep);
1169
1170 if (ret = suser(p->p_ucred, &p->p_acflag))
1171 return(ret);
1172
1173 switch(name[0]) {
1174 case KERN_KDEFLAGS:
1175 case KERN_KDDFLAGS:
1176 case KERN_KDENABLE:
1177 case KERN_KDGETBUF:
1178 case KERN_KDSETUP:
1179 case KERN_KDREMOVE:
1180 case KERN_KDSETREG:
1181 case KERN_KDGETREG:
1182 case KERN_KDREADTR:
1183 case KERN_KDPIDTR:
1184 case KERN_KDTHRMAP:
1185 case KERN_KDPIDEX:
1186 case KERN_KDSETRTCDEC:
1187 case KERN_KDSETBUF:
1188 case KERN_KDGETENTROPY:
1189 ret = kdbg_control(name, namelen, where, sizep);
1190 break;
1191 default:
1192 ret= EOPNOTSUPP;
1193 break;
1194 }
1195 return(ret);
1196}
1197
1198int
1199pcsamples_ops(name, namelen, where, sizep, p)
1200int *name;
1201u_int namelen;
1202char *where;
1203size_t *sizep;
1204struct proc *p;
1205{
1206 int ret=0;
1207 extern int pcsamples_control(int *name, u_int namelen,
1208 char * where,size_t * sizep);
1209
1210 if (ret = suser(p->p_ucred, &p->p_acflag))
1211 return(ret);
1212
1213 switch(name[0]) {
1214 case KERN_PCDISABLE:
1215 case KERN_PCGETBUF:
1216 case KERN_PCSETUP:
1217 case KERN_PCREMOVE:
1218 case KERN_PCREADBUF:
1219 case KERN_PCSETREG:
1220 case KERN_PCSETBUF:
1221 case KERN_PCCOMM:
1222 ret = pcsamples_control(name, namelen, where, sizep);
1223 break;
1224 default:
1225 ret= EOPNOTSUPP;
1226 break;
1227 }
1228 return(ret);
1229}
1230
1231/*
1232 * Return the top *sizep bytes of the user stack, or the entire area of the
1233 * user stack down through the saved exec_path, whichever is smaller.
1234 */
1235int
1236sysctl_procargs(name, namelen, where, sizep, cur_proc)
1237 int *name;
1238 u_int namelen;
1239 char *where;
1240 size_t *sizep;
1241 struct proc *cur_proc;
1242{
1243 return sysctl_procargsx( name, namelen, where, sizep, cur_proc, 0);
1244}
1245
1246static int
1247sysctl_procargs2(name, namelen, where, sizep, cur_proc)
1248 int *name;
1249 u_int namelen;
1250 char *where;
1251 size_t *sizep;
1252 struct proc *cur_proc;
1253{
1254 return sysctl_procargsx( name, namelen, where, sizep, cur_proc, 1);
1255}
1256
1257static int
1258sysctl_procargsx(name, namelen, where, sizep, cur_proc, argc_yes)
1259 int *name;
1260 u_int namelen;
1261 char *where;
1262 size_t *sizep;
1263 struct proc *cur_proc;
1264 int argc_yes;
1265{
1266 register struct proc *p;
1267 register int needed = 0;
1268 int buflen = where != NULL ? *sizep : 0;
1269 int error = 0;
1270 struct vm_map *proc_map;
1271 struct task * task;
1272 vm_map_copy_t tmp;
1273 vm_offset_t arg_addr;
1274 vm_size_t arg_size;
1275 caddr_t data;
1276 unsigned size;
1277 vm_offset_t copy_start, copy_end;
1278 int *ip;
1279 kern_return_t ret;
1280 int pid;
1281
1282 if (argc_yes)
1283 buflen -= NBPW; /* reserve first word to return argc */
1284
1285 if ((buflen <= 0) || (buflen > ARG_MAX)) {
1286 return(EINVAL);
1287 }
1288 arg_size = buflen;
1289
1290 /*
1291 * Lookup process by pid
1292 */
1293 pid = name[0];
1294
1295 restart:
1296 p = pfind(pid);
1297 if (p == NULL) {
1298 return(EINVAL);
1299 }
1300
1301 /*
1302 * Copy the top N bytes of the stack.
1303 * On all machines we have so far, the stack grows
1304 * downwards.
1305 *
1306 * If the user expects no more than N bytes of
1307 * argument list, use that as a guess for the
1308 * size.
1309 */
1310
1311 if (!p->user_stack)
1312 return(EINVAL);
1313
1314 if ((p->p_ucred->cr_uid != cur_proc->p_ucred->cr_uid)
1315 && suser(cur_proc->p_ucred, &cur_proc->p_acflag))
1316 return (EINVAL);
1317 arg_addr = (vm_offset_t)(p->user_stack - arg_size);
1318
1319
1320 /*
1321 * Before we can block (any VM code), make another
1322 * reference to the map to keep it alive. We do
1323 * that by getting a reference on the task itself.
1324 */
1325 task = p->task;
1326 if (task == NULL)
1327 return(EINVAL);
1328
1329 /*
1330 * A regular task_reference call can block, causing the funnel
1331 * to be dropped and allowing the proc/task to get freed.
1332 * Instead, we issue a non-blocking attempt at the task reference,
1333 * and look up the proc/task all over again if that fails.
1334 */
1335 if (!task_reference_try(task)) {
1336 mutex_pause();
1337 goto restart;
1338 }
1339
1340 ret = kmem_alloc(kernel_map, &copy_start, round_page_32(arg_size));
1341 if (ret != KERN_SUCCESS) {
1342 task_deallocate(task);
1343 return(ENOMEM);
1344 }
1345
1346 proc_map = get_task_map(task);
1347 copy_end = round_page_32(copy_start + arg_size);
1348
1349 if( vm_map_copyin(proc_map, trunc_page(arg_addr), round_page_32(arg_size),
1350 FALSE, &tmp) != KERN_SUCCESS) {
1351 task_deallocate(task);
1352 kmem_free(kernel_map, copy_start,
1353 round_page_32(arg_size));
1354 return (EIO);
1355 }
1356
1357 /*
1358 * Now that we've done the copyin from the process'
1359 * map, we can release the reference to it.
1360 */
1361 task_deallocate(task);
1362
1363 if( vm_map_copy_overwrite(kernel_map, copy_start,
1364 tmp, FALSE) != KERN_SUCCESS) {
1365 kmem_free(kernel_map, copy_start,
1366 round_page_32(arg_size));
1367 return (EIO);
1368 }
1369
1370 data = (caddr_t) (copy_end - arg_size);
1371
1372 if (buflen > p->p_argslen) {
1373 data = &data[buflen - p->p_argslen];
1374 size = p->p_argslen;
1375 } else {
1376 size = buflen;
1377 }
1378
1379 if (argc_yes) {
1380 /* Put processes argc as the first word in the copyout buffer */
1381 suword(where, p->p_argc);
1382 error = copyout(data, where + NBPW, size);
1383 } else {
1384 error = copyout(data, where, size);
1385
1386 /*
1387 * Make the old PROCARGS work to return the executable's path
1388 * But, only if there is enough space in the provided buffer
1389 *
1390 * on entry: data [possibily] points to the beginning of the path
1391 *
1392 * Note: we keep all pointers&sizes aligned to word boundries
1393 */
1394
1395 if ( (! error) && (buflen > p->p_argslen) )
1396 {
1397 int binPath_sz;
1398 int extraSpaceNeeded, addThis;
1399 char * placeHere;
1400 char * str = (char *) data;
1401 unsigned int max_len = size;
1402
1403 /* Some apps are really bad about messing up their stacks
1404 So, we have to be extra careful about getting the length
1405 of the executing binary. If we encounter an error, we bail.
1406 */
1407
1408 /* Limit ourselves to PATH_MAX paths */
1409 if ( max_len > PATH_MAX ) max_len = PATH_MAX;
1410
1411 binPath_sz = 0;
1412
1413 while ( (binPath_sz < max_len-1) && (*str++ != 0) )
1414 binPath_sz++;
1415
1416 if (binPath_sz < max_len-1) binPath_sz += 1;
1417
1418 /* Pre-Flight the space requiremnts */
1419
1420 /* Account for the padding that fills out binPath to the next word */
1421 binPath_sz += (binPath_sz & (NBPW-1)) ? (NBPW-(binPath_sz & (NBPW-1))) : 0;
1422
1423 placeHere = where + size;
1424
1425 /* Account for the bytes needed to keep placeHere word aligned */
1426 addThis = ((unsigned long)placeHere & (NBPW-1)) ? (NBPW-((unsigned long)placeHere & (NBPW-1))) : 0;
1427
1428 /* Add up all the space that is needed */
1429 extraSpaceNeeded = binPath_sz + addThis + (4 * NBPW);
1430
1431 /* is there is room to tack on argv[0]? */
1432 if ( (buflen & ~(NBPW-1)) >= ( p->p_argslen + extraSpaceNeeded ))
1433 {
1434 placeHere += addThis;
1435 suword(placeHere, 0);
1436 placeHere += NBPW;
1437 suword(placeHere, 0xBFFF0000);
1438 placeHere += NBPW;
1439 suword(placeHere, 0);
1440 placeHere += NBPW;
1441 error = copyout(data, placeHere, binPath_sz);
1442 if ( ! error )
1443 {
1444 placeHere += binPath_sz;
1445 suword(placeHere, 0);
1446 size += extraSpaceNeeded;
1447 }
1448 }
1449 }
1450 }
1451
1452 if (copy_start != (vm_offset_t) 0) {
1453 kmem_free(kernel_map, copy_start, copy_end - copy_start);
1454 }
1455 if (error) {
1456 return(error);
1457 }
1458
1459 if (where != NULL)
1460 *sizep = size;
1461 return (0);
1462}
1463
1464
1465/*
1466 * Validate parameters and get old / set new parameters
1467 * for max number of concurrent aio requests. Makes sure
1468 * the system wide limit is greater than the per process
1469 * limit.
1470 */
1471static int
1472sysctl_aiomax( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
1473{
1474 int error = 0;
1475 int new_value;
1476
1477 if ( oldp && *oldlenp < sizeof(int) )
1478 return (ENOMEM);
1479 if ( newp && newlen != sizeof(int) )
1480 return (EINVAL);
1481
1482 *oldlenp = sizeof(int);
1483 if ( oldp )
1484 error = copyout( &aio_max_requests, oldp, sizeof(int) );
1485 if ( error == 0 && newp )
1486 error = copyin( newp, &new_value, sizeof(int) );
1487 if ( error == 0 && newp ) {
1488 if ( new_value >= aio_max_requests_per_process )
1489 aio_max_requests = new_value;
1490 else
1491 error = EINVAL;
1492 }
1493 return( error );
1494
1495} /* sysctl_aiomax */
1496
1497
1498/*
1499 * Validate parameters and get old / set new parameters
1500 * for max number of concurrent aio requests per process.
1501 * Makes sure per process limit is less than the system wide
1502 * limit.
1503 */
1504static int
1505sysctl_aioprocmax( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
1506{
1507 int error = 0;
1508 int new_value = 0;
1509
1510 if ( oldp && *oldlenp < sizeof(int) )
1511 return (ENOMEM);
1512 if ( newp && newlen != sizeof(int) )
1513 return (EINVAL);
1514
1515 *oldlenp = sizeof(int);
1516 if ( oldp )
1517 error = copyout( &aio_max_requests_per_process, oldp, sizeof(int) );
1518 if ( error == 0 && newp )
1519 error = copyin( newp, &new_value, sizeof(int) );
1520 if ( error == 0 && newp ) {
1521 if ( new_value <= aio_max_requests && new_value >= AIO_LISTIO_MAX )
1522 aio_max_requests_per_process = new_value;
1523 else
1524 error = EINVAL;
1525 }
1526 return( error );
1527
1528} /* sysctl_aioprocmax */
1529
1530
1531/*
1532 * Validate parameters and get old / set new parameters
1533 * for max number of async IO worker threads.
1534 * We only allow an increase in the number of worker threads.
1535 */
1536static int
1537sysctl_aiothreads( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
1538{
1539 int error = 0;
1540 int new_value;
1541
1542 if ( oldp && *oldlenp < sizeof(int) )
1543 return (ENOMEM);
1544 if ( newp && newlen != sizeof(int) )
1545 return (EINVAL);
1546
1547 *oldlenp = sizeof(int);
1548 if ( oldp )
1549 error = copyout( &aio_worker_threads, oldp, sizeof(int) );
1550 if ( error == 0 && newp )
1551 error = copyin( newp, &new_value, sizeof(int) );
1552 if ( error == 0 && newp ) {
1553 if (new_value > aio_worker_threads ) {
1554 _aio_create_worker_threads( (new_value - aio_worker_threads) );
1555 aio_worker_threads = new_value;
1556 }
1557 else
1558 error = EINVAL;
1559 }
1560 return( error );
1561
1562} /* sysctl_aiothreads */
1563
1564
1565/*
1566 * Validate parameters and get old / set new parameters
1567 * for max number of processes per UID.
1568 * Makes sure per UID limit is less than the system wide limit.
1569 */
1570static int
1571sysctl_maxprocperuid( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
1572{
1573 int error = 0;
1574 int new_value;
1575
1576 if ( oldp != NULL && *oldlenp < sizeof(int) )
1577 return (ENOMEM);
1578 if ( newp != NULL && newlen != sizeof(int) )
1579 return (EINVAL);
1580
1581 *oldlenp = sizeof(int);
1582 if ( oldp != NULL )
1583 error = copyout( &maxprocperuid, oldp, sizeof(int) );
1584 if ( error == 0 && newp != NULL ) {
1585 error = copyin( newp, &new_value, sizeof(int) );
1586 if ( error == 0 ) {
1587 AUDIT_ARG(value, new_value);
1588 if ( new_value <= maxproc && new_value > 0 )
1589 maxprocperuid = new_value;
1590 else
1591 error = EINVAL;
1592 }
1593 else
1594 error = EINVAL;
1595 }
1596 return( error );
1597
1598} /* sysctl_maxprocperuid */
1599
1600
1601/*
1602 * Validate parameters and get old / set new parameters
1603 * for max number of files per process.
1604 * Makes sure per process limit is less than the system-wide limit.
1605 */
1606static int
1607sysctl_maxfilesperproc( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
1608{
1609 int error = 0;
1610 int new_value;
1611
1612 if ( oldp != NULL && *oldlenp < sizeof(int) )
1613 return (ENOMEM);
1614 if ( newp != NULL && newlen != sizeof(int) )
1615 return (EINVAL);
1616
1617 *oldlenp = sizeof(int);
1618 if ( oldp != NULL )
1619 error = copyout( &maxfilesperproc, oldp, sizeof(int) );
1620 if ( error == 0 && newp != NULL ) {
1621 error = copyin( newp, &new_value, sizeof(int) );
1622 if ( error == 0 ) {
1623 AUDIT_ARG(value, new_value);
1624 if ( new_value < maxfiles && new_value > 0 )
1625 maxfilesperproc = new_value;
1626 else
1627 error = EINVAL;
1628 }
1629 else
1630 error = EINVAL;
1631 }
1632 return( error );
1633
1634} /* sysctl_maxfilesperproc */
1635
1636
1637/*
1638 * Validate parameters and get old / set new parameters
1639 * for the system-wide limit on the max number of processes.
1640 * Makes sure the system-wide limit is less than the configured hard
1641 * limit set at kernel compilation.
1642 */
1643static int
1644sysctl_maxproc( void *oldp, size_t *oldlenp, void *newp, size_t newlen )
1645{
1646 int error = 0;
1647 int new_value;
1648
1649 if ( oldp != NULL && *oldlenp < sizeof(int) )
1650 return (ENOMEM);
1651 if ( newp != NULL && newlen != sizeof(int) )
1652 return (EINVAL);
1653
1654 *oldlenp = sizeof(int);
1655 if ( oldp != NULL )
1656 error = copyout( &maxproc, oldp, sizeof(int) );
1657 if ( error == 0 && newp != NULL ) {
1658 error = copyin( newp, &new_value, sizeof(int) );
1659 if ( error == 0 ) {
1660 AUDIT_ARG(value, new_value);
1661 if ( new_value <= hard_maxproc && new_value > 0 )
1662 maxproc = new_value;
1663 else
1664 error = EINVAL;
1665 }
1666 else
1667 error = EINVAL;
1668 }
1669 return( error );
1670
1671} /* sysctl_maxproc */