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