kern_sysctl.c revision 1.53 1 /* $NetBSD: kern_sysctl.c,v 1.53 1999/11/03 09:12:15 jdolecek Exp $ */
2
3 /*-
4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Mike Karels at Berkeley Software Design, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)kern_sysctl.c 8.9 (Berkeley) 5/20/95
39 */
40
41 /*
42 * sysctl system call.
43 */
44
45 #include "opt_ddb.h"
46 #include "opt_insecure.h"
47 #include "opt_defcorename.h"
48 #include "opt_sysv.h"
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/kernel.h>
53 #include <sys/malloc.h>
54 #include <sys/pool.h>
55 #include <sys/proc.h>
56 #include <sys/file.h>
57 #include <sys/vnode.h>
58 #include <sys/unistd.h>
59 #include <sys/buf.h>
60 #include <sys/ioctl.h>
61 #include <sys/tty.h>
62 #include <sys/disklabel.h>
63 #include <sys/device.h>
64 #include <vm/vm.h>
65 #include <sys/sysctl.h>
66 #include <sys/msgbuf.h>
67
68 #include <uvm/uvm_extern.h>
69
70 #include <sys/mount.h>
71 #include <sys/syscallargs.h>
72 #include <sys/resource.h>
73 #include <sys/resourcevar.h>
74
75
76 #if defined(DDB)
77 #include <ddb/ddbvar.h>
78 #endif
79
80 /*
81 * Locking and stats
82 */
83 static struct sysctl_lock {
84 int sl_lock;
85 int sl_want;
86 int sl_locked;
87 } memlock;
88
89 int
90 sys___sysctl(p, v, retval)
91 struct proc *p;
92 void *v;
93 register_t *retval;
94 {
95 register struct sys___sysctl_args /* {
96 syscallarg(int *) name;
97 syscallarg(u_int) namelen;
98 syscallarg(void *) old;
99 syscallarg(size_t *) oldlenp;
100 syscallarg(void *) new;
101 syscallarg(size_t) newlen;
102 } */ *uap = v;
103 int error, dolock = 1;
104 size_t savelen = 0, oldlen = 0;
105 sysctlfn *fn;
106 int name[CTL_MAXNAME];
107
108 /*
109 * all top-level sysctl names are non-terminal
110 */
111 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2)
112 return (EINVAL);
113 error = copyin(SCARG(uap, name), &name,
114 SCARG(uap, namelen) * sizeof(int));
115 if (error)
116 return (error);
117
118 /*
119 * For all but CTL_PROC, must be root to change a value.
120 * For CTL_PROC, must be root, or owner of the proc (and not suid),
121 * this is checked in proc_sysctl() (once we know the targer proc).
122 */
123 if (SCARG(uap, new) != NULL && name[0] != CTL_PROC &&
124 (error = suser(p->p_ucred, &p->p_acflag)))
125 return error;
126
127 switch (name[0]) {
128 case CTL_KERN:
129 fn = kern_sysctl;
130 if (name[2] != KERN_VNODE) /* XXX */
131 dolock = 0;
132 break;
133 case CTL_HW:
134 fn = hw_sysctl;
135 break;
136 case CTL_VM:
137 fn = uvm_sysctl;
138 break;
139 case CTL_NET:
140 fn = net_sysctl;
141 break;
142 case CTL_VFS:
143 fn = vfs_sysctl;
144 break;
145 case CTL_MACHDEP:
146 fn = cpu_sysctl;
147 break;
148 #ifdef DEBUG
149 case CTL_DEBUG:
150 fn = debug_sysctl;
151 break;
152 #endif
153 #ifdef DDB
154 case CTL_DDB:
155 fn = ddb_sysctl;
156 break;
157 #endif
158 case CTL_PROC:
159 fn = proc_sysctl;
160 break;
161 default:
162 return (EOPNOTSUPP);
163 }
164
165 if (SCARG(uap, oldlenp) &&
166 (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
167 return (error);
168 if (SCARG(uap, old) != NULL) {
169 if (!uvm_useracc(SCARG(uap, old), oldlen, B_WRITE))
170 return (EFAULT);
171 while (memlock.sl_lock) {
172 memlock.sl_want = 1;
173 sleep((caddr_t)&memlock, PRIBIO+1);
174 memlock.sl_locked++;
175 }
176 memlock.sl_lock = 1;
177 if (dolock) {
178 /*
179 * XXX Um, this is kind of evil. What should we
180 * XXX be passing here?
181 */
182 if (uvm_vslock(p, SCARG(uap, old), oldlen,
183 VM_PROT_NONE) != KERN_SUCCESS) {
184 memlock.sl_lock = 0;
185 if (memlock.sl_want) {
186 memlock.sl_want = 0;
187 wakeup((caddr_t)&memlock);
188 return (EFAULT);
189 }
190 }
191 }
192 savelen = oldlen;
193 }
194 error = (*fn)(name + 1, SCARG(uap, namelen) - 1, SCARG(uap, old),
195 &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
196 if (SCARG(uap, old) != NULL) {
197 if (dolock)
198 uvm_vsunlock(p, SCARG(uap, old), savelen);
199 memlock.sl_lock = 0;
200 if (memlock.sl_want) {
201 memlock.sl_want = 0;
202 wakeup((caddr_t)&memlock);
203 }
204 }
205 if (error)
206 return (error);
207 if (SCARG(uap, oldlenp))
208 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen));
209 return (error);
210 }
211
212 /*
213 * Attributes stored in the kernel.
214 */
215 char hostname[MAXHOSTNAMELEN];
216 int hostnamelen;
217 char domainname[MAXHOSTNAMELEN];
218 int domainnamelen;
219 long hostid;
220 #ifdef INSECURE
221 int securelevel = -1;
222 #else
223 int securelevel = 0;
224 #endif
225 #ifdef DEFCORENAME
226 char defcorename[MAXPATHLEN] = DEFCORENAME;
227 int defcorenamelen = sizeof(DEFCORENAME);
228 #else
229 char defcorename[MAXPATHLEN] = "%n.core";
230 int defcorenamelen = sizeof("%n.core");
231 #endif
232
233 /*
234 * kernel related system variables.
235 */
236 int
237 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
238 int *name;
239 u_int namelen;
240 void *oldp;
241 size_t *oldlenp;
242 void *newp;
243 size_t newlen;
244 struct proc *p;
245 {
246 int error, level, inthostid;
247 int old_autonicetime;
248 int old_vnodes;
249 extern char ostype[], osrelease[], version[];
250
251 /* All sysctl names at this level, except for a few, are terminal. */
252 switch (name[0]) {
253 case KERN_PROC:
254 case KERN_PROF:
255 case KERN_MBUF:
256 /* Not terminal. */
257 break;
258 default:
259 if (namelen != 1)
260 return (ENOTDIR); /* overloaded */
261 }
262
263 switch (name[0]) {
264 case KERN_OSTYPE:
265 return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
266 case KERN_OSRELEASE:
267 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
268 case KERN_OSREV:
269 return (sysctl_rdint(oldp, oldlenp, newp, NetBSD));
270 case KERN_VERSION:
271 return (sysctl_rdstring(oldp, oldlenp, newp, version));
272 case KERN_MAXVNODES:
273 old_vnodes = desiredvnodes;
274 error = sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes);
275 if (old_vnodes > desiredvnodes) {
276 desiredvnodes = old_vnodes;
277 return (EINVAL);
278 }
279 return (error);
280 case KERN_MAXPROC:
281 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
282 case KERN_MAXFILES:
283 return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
284 case KERN_ARGMAX:
285 return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
286 case KERN_SECURELVL:
287 level = securelevel;
288 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
289 newp == NULL)
290 return (error);
291 if (level < securelevel && p->p_pid != 1)
292 return (EPERM);
293 securelevel = level;
294 return (0);
295 case KERN_HOSTNAME:
296 error = sysctl_string(oldp, oldlenp, newp, newlen,
297 hostname, sizeof(hostname));
298 if (newp && !error)
299 hostnamelen = newlen;
300 return (error);
301 case KERN_DOMAINNAME:
302 error = sysctl_string(oldp, oldlenp, newp, newlen,
303 domainname, sizeof(domainname));
304 if (newp && !error)
305 domainnamelen = newlen;
306 return (error);
307 case KERN_HOSTID:
308 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */
309 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
310 hostid = inthostid;
311 return (error);
312 case KERN_CLOCKRATE:
313 return (sysctl_clockrate(oldp, oldlenp));
314 case KERN_BOOTTIME:
315 return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
316 sizeof(struct timeval)));
317 case KERN_VNODE:
318 return (sysctl_vnode(oldp, oldlenp, p));
319 case KERN_PROC:
320 return (sysctl_doeproc(name + 1, namelen - 1, oldp, oldlenp));
321 case KERN_FILE:
322 return (sysctl_file(oldp, oldlenp));
323 #ifdef GPROF
324 case KERN_PROF:
325 return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
326 newp, newlen));
327 #endif
328 case KERN_POSIX1:
329 return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
330 case KERN_NGROUPS:
331 return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
332 case KERN_JOB_CONTROL:
333 return (sysctl_rdint(oldp, oldlenp, newp, 1));
334 case KERN_SAVED_IDS:
335 #ifdef _POSIX_SAVED_IDS
336 return (sysctl_rdint(oldp, oldlenp, newp, 1));
337 #else
338 return (sysctl_rdint(oldp, oldlenp, newp, 0));
339 #endif
340 case KERN_MAXPARTITIONS:
341 return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
342 case KERN_RAWPARTITION:
343 return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART));
344 #ifdef NTP
345 case KERN_NTPTIME:
346 return (sysctl_ntptime(oldp, oldlenp));
347 #endif
348 case KERN_AUTONICETIME:
349 old_autonicetime = autonicetime;
350 error = sysctl_int(oldp, oldlenp, newp, newlen, &autonicetime);
351 if (autonicetime < 0)
352 autonicetime = old_autonicetime;
353 return (error);
354 case KERN_AUTONICEVAL:
355 error = sysctl_int(oldp, oldlenp, newp, newlen, &autoniceval);
356 if (autoniceval < PRIO_MIN)
357 autoniceval = PRIO_MIN;
358 if (autoniceval > PRIO_MAX)
359 autoniceval = PRIO_MAX;
360 return (error);
361 case KERN_RTC_OFFSET:
362 return (sysctl_rdint(oldp, oldlenp, newp, rtc_offset));
363 case KERN_ROOT_DEVICE:
364 return (sysctl_rdstring(oldp, oldlenp, newp,
365 root_device->dv_xname));
366 case KERN_MSGBUFSIZE:
367 /*
368 * deal with cases where the message buffer has
369 * become corrupted.
370 */
371 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
372 msgbufenabled = 0;
373 return (ENXIO);
374 }
375 return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs));
376 case KERN_FSYNC:
377 return (sysctl_rdint(oldp, oldlenp, newp, 1));
378 case KERN_SYSVMSG:
379 #ifdef SYSVMSG
380 return (sysctl_rdint(oldp, oldlenp, newp, 1));
381 #else
382 return (sysctl_rdint(oldp, oldlenp, newp, 0));
383 #endif
384 case KERN_SYSVSEM:
385 #ifdef SYSVSEM
386 return (sysctl_rdint(oldp, oldlenp, newp, 1));
387 #else
388 return (sysctl_rdint(oldp, oldlenp, newp, 0));
389 #endif
390 case KERN_SYSVSHM:
391 #ifdef SYSVSHM
392 return (sysctl_rdint(oldp, oldlenp, newp, 1));
393 #else
394 return (sysctl_rdint(oldp, oldlenp, newp, 0));
395 #endif
396 case KERN_DEFCORENAME:
397 if (newp && newlen < 1)
398 return (EINVAL);
399 error = sysctl_string(oldp, oldlenp, newp, newlen,
400 defcorename, sizeof(defcorename));
401 if (newp && !error)
402 defcorenamelen = newlen;
403 return (error);
404 case KERN_SYNCHRONIZED_IO:
405 return (sysctl_rdint(oldp, oldlenp, newp, 1));
406 case KERN_IOV_MAX:
407 return (sysctl_rdint(oldp, oldlenp, newp, IOV_MAX));
408 case KERN_MBUF:
409 return (sysctl_dombuf(name + 1, namelen - 1, oldp, oldlenp,
410 newp, newlen));
411 case KERN_MAPPED_FILES:
412 return (sysctl_rdint(oldp, oldlenp, newp, 1));
413 case KERN_MEMLOCK:
414 return (sysctl_rdint(oldp, oldlenp, newp, 1));
415 case KERN_MEMLOCK_RANGE:
416 return (sysctl_rdint(oldp, oldlenp, newp, 1));
417 case KERN_MEMORY_PROTECTION:
418 return (sysctl_rdint(oldp, oldlenp, newp, 1));
419 case KERN_LOGIN_NAME_MAX:
420 return (sysctl_rdint(oldp, oldlenp, newp, LOGIN_NAME_MAX));
421 default:
422 return (EOPNOTSUPP);
423 }
424 /* NOTREACHED */
425 }
426
427 /*
428 * hardware related system variables.
429 */
430 int
431 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
432 int *name;
433 u_int namelen;
434 void *oldp;
435 size_t *oldlenp;
436 void *newp;
437 size_t newlen;
438 struct proc *p;
439 {
440 extern char machine[], machine_arch[], cpu_model[];
441
442 /* all sysctl names at this level are terminal */
443 if (namelen != 1)
444 return (ENOTDIR); /* overloaded */
445
446 switch (name[0]) {
447 case HW_MACHINE:
448 return (sysctl_rdstring(oldp, oldlenp, newp, machine));
449 case HW_MACHINE_ARCH:
450 return (sysctl_rdstring(oldp, oldlenp, newp, machine_arch));
451 case HW_MODEL:
452 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
453 case HW_NCPU:
454 return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */
455 case HW_BYTEORDER:
456 return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
457 case HW_PHYSMEM:
458 return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
459 case HW_USERMEM:
460 return (sysctl_rdint(oldp, oldlenp, newp,
461 ctob(physmem - uvmexp.wired)));
462 case HW_PAGESIZE:
463 return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
464 default:
465 return (EOPNOTSUPP);
466 }
467 /* NOTREACHED */
468 }
469
470 #ifdef DEBUG
471 /*
472 * Debugging related system variables.
473 */
474 struct ctldebug debug0, debug1, debug2, debug3, debug4;
475 struct ctldebug debug5, debug6, debug7, debug8, debug9;
476 struct ctldebug debug10, debug11, debug12, debug13, debug14;
477 struct ctldebug debug15, debug16, debug17, debug18, debug19;
478 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
479 &debug0, &debug1, &debug2, &debug3, &debug4,
480 &debug5, &debug6, &debug7, &debug8, &debug9,
481 &debug10, &debug11, &debug12, &debug13, &debug14,
482 &debug15, &debug16, &debug17, &debug18, &debug19,
483 };
484 int
485 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
486 int *name;
487 u_int namelen;
488 void *oldp;
489 size_t *oldlenp;
490 void *newp;
491 size_t newlen;
492 struct proc *p;
493 {
494 struct ctldebug *cdp;
495
496 /* all sysctl names at this level are name and field */
497 if (namelen != 2)
498 return (ENOTDIR); /* overloaded */
499 cdp = debugvars[name[0]];
500 if (name[0] >= CTL_DEBUG_MAXID || cdp->debugname == 0)
501 return (EOPNOTSUPP);
502 switch (name[1]) {
503 case CTL_DEBUG_NAME:
504 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
505 case CTL_DEBUG_VALUE:
506 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
507 default:
508 return (EOPNOTSUPP);
509 }
510 /* NOTREACHED */
511 }
512 #endif /* DEBUG */
513
514 int
515 proc_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
516 int *name;
517 u_int namelen;
518 void *oldp;
519 size_t *oldlenp;
520 void *newp;
521 size_t newlen;
522 struct proc *p;
523 {
524 struct proc *ptmp=NULL;
525 const struct proclist_desc *pd;
526 int error = 0;
527 struct rlimit alim;
528 struct plimit *newplim;
529 char *tmps = NULL;
530 int i, curlen, len;
531
532 if (namelen < 2)
533 return EINVAL;
534
535 if (name[0] == PROC_CURPROC) {
536 ptmp = p;
537 } else {
538 proclist_lock_read();
539 for (pd = proclists; pd->pd_list != NULL; pd++) {
540 for (ptmp = LIST_FIRST(pd->pd_list); ptmp != NULL;
541 ptmp = LIST_NEXT(ptmp, p_list)) {
542 /* Skip embryonic processes. */
543 if (ptmp->p_stat == SIDL)
544 continue;
545 if (ptmp->p_pid == (pid_t)name[0])
546 break;
547 }
548 if (ptmp != NULL)
549 break;
550 }
551 proclist_unlock_read();
552 if (ptmp == NULL)
553 return(ESRCH);
554 if (p->p_ucred->cr_uid != 0) {
555 if(p->p_cred->p_ruid != ptmp->p_cred->p_ruid ||
556 p->p_cred->p_ruid != ptmp->p_cred->p_svuid)
557 return EPERM;
558 if (ptmp->p_cred->p_rgid != ptmp->p_cred->p_svgid)
559 return EPERM; /* sgid proc */
560 for (i = 0; i < p->p_ucred->cr_ngroups; i++) {
561 if (p->p_ucred->cr_groups[i] ==
562 ptmp->p_cred->p_rgid)
563 break;
564 }
565 if (i == p->p_ucred->cr_ngroups)
566 return EPERM;
567 }
568 }
569 if (name[1] == PROC_PID_CORENAME) {
570 if (namelen != 2)
571 return EINVAL;
572 /*
573 * Can't use sysctl_string() here because we may malloc a new
574 * area during the process, so we have to do it by hand.
575 */
576 curlen = strlen(ptmp->p_limit->pl_corename) + 1;
577 if (oldp && *oldlenp < curlen)
578 return (ENOMEM);
579 if (newp) {
580 if (securelevel > 2)
581 return EPERM;
582 if (newlen > MAXPATHLEN)
583 return ENAMETOOLONG;
584 tmps = malloc(newlen + 1, M_TEMP, M_WAITOK);
585 if (tmps == NULL)
586 return ENOMEM;
587 error = copyin(newp, tmps, newlen + 1);
588 tmps[newlen] = '\0';
589 if (error)
590 goto cleanup;
591 /* Enforce to be either 'core' for end with '.core' */
592 if (newlen < 4) { /* c.o.r.e */
593 error = EINVAL;
594 goto cleanup;
595 }
596 len = newlen - 4;
597 if (len > 0) {
598 if (tmps[len - 1] != '.' &&
599 tmps[len - 1] != '/') {
600 error = EINVAL;
601 goto cleanup;
602 }
603 }
604 if (strcmp(&tmps[len], "core") != 0) {
605 error = EINVAL;
606 goto cleanup;
607 }
608 }
609 if (oldp) {
610 *oldlenp = curlen;
611 error = copyout(ptmp->p_limit->pl_corename, oldp,
612 curlen);
613 }
614 if (newp && error == 0) {
615 /* if the 2 strings are identical, don't limcopy() */
616 if (strcmp(tmps, ptmp->p_limit->pl_corename) == 0) {
617 error = 0;
618 goto cleanup;
619 }
620 if (ptmp->p_limit->p_refcnt > 1 &&
621 (ptmp->p_limit->p_lflags & PL_SHAREMOD) == 0) {
622 newplim = limcopy(ptmp->p_limit);
623 limfree(ptmp->p_limit);
624 ptmp->p_limit = newplim;
625 } else if (ptmp->p_limit->pl_corename != defcorename) {
626 free(ptmp->p_limit->pl_corename, M_TEMP);
627 }
628 ptmp->p_limit->pl_corename = tmps;
629 return (0);
630 }
631 cleanup:
632 if (tmps)
633 free(tmps, M_TEMP);
634 return (error);
635 }
636 if (name[1] == PROC_PID_LIMIT) {
637 if (namelen != 4 || name[2] >= PROC_PID_LIMIT_MAXID)
638 return EINVAL;
639 memcpy(&alim, &ptmp->p_rlimit[name[2] - 1], sizeof(alim));
640 if (name[3] == PROC_PID_LIMIT_TYPE_HARD)
641 error = sysctl_quad(oldp, oldlenp, newp, newlen,
642 &alim.rlim_max);
643 else if (name[3] == PROC_PID_LIMIT_TYPE_SOFT)
644 error = sysctl_quad(oldp, oldlenp, newp, newlen,
645 &alim.rlim_cur);
646 else
647 error = EINVAL;
648
649 if (error)
650 return error;
651
652 if (newp)
653 error = dosetrlimit(ptmp, p->p_cred,
654 name[2] - 1, &alim);
655 return error;
656 }
657 return (EINVAL);
658 }
659
660 /*
661 * Validate parameters and get old / set new parameters
662 * for an integer-valued sysctl function.
663 */
664 int
665 sysctl_int(oldp, oldlenp, newp, newlen, valp)
666 void *oldp;
667 size_t *oldlenp;
668 void *newp;
669 size_t newlen;
670 int *valp;
671 {
672 int error = 0;
673
674 if (oldp && *oldlenp < sizeof(int))
675 return (ENOMEM);
676 if (newp && newlen != sizeof(int))
677 return (EINVAL);
678 *oldlenp = sizeof(int);
679 if (oldp)
680 error = copyout(valp, oldp, sizeof(int));
681 if (error == 0 && newp)
682 error = copyin(newp, valp, sizeof(int));
683 return (error);
684 }
685
686 /*
687 * As above, but read-only.
688 */
689 int
690 sysctl_rdint(oldp, oldlenp, newp, val)
691 void *oldp;
692 size_t *oldlenp;
693 void *newp;
694 int val;
695 {
696 int error = 0;
697
698 if (oldp && *oldlenp < sizeof(int))
699 return (ENOMEM);
700 if (newp)
701 return (EPERM);
702 *oldlenp = sizeof(int);
703 if (oldp)
704 error = copyout((caddr_t)&val, oldp, sizeof(int));
705 return (error);
706 }
707
708 /*
709 * Validate parameters and get old / set new parameters
710 * for an quad-valued sysctl function.
711 */
712 int
713 sysctl_quad(oldp, oldlenp, newp, newlen, valp)
714 void *oldp;
715 size_t *oldlenp;
716 void *newp;
717 size_t newlen;
718 quad_t *valp;
719 {
720 int error = 0;
721
722 if (oldp && *oldlenp < sizeof(quad_t))
723 return (ENOMEM);
724 if (newp && newlen != sizeof(quad_t))
725 return (EINVAL);
726 *oldlenp = sizeof(quad_t);
727 if (oldp)
728 error = copyout(valp, oldp, sizeof(quad_t));
729 if (error == 0 && newp)
730 error = copyin(newp, valp, sizeof(quad_t));
731 return (error);
732 }
733
734 /*
735 * As above, but read-only.
736 */
737 int
738 sysctl_rdquad(oldp, oldlenp, newp, val)
739 void *oldp;
740 size_t *oldlenp;
741 void *newp;
742 quad_t val;
743 {
744 int error = 0;
745
746 if (oldp && *oldlenp < sizeof(quad_t))
747 return (ENOMEM);
748 if (newp)
749 return (EPERM);
750 *oldlenp = sizeof(quad_t);
751 if (oldp)
752 error = copyout((caddr_t)&val, oldp, sizeof(quad_t));
753 return (error);
754 }
755
756
757 /*
758 * Validate parameters and get old / set new parameters
759 * for a string-valued sysctl function.
760 */
761 int
762 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
763 void *oldp;
764 size_t *oldlenp;
765 void *newp;
766 size_t newlen;
767 char *str;
768 int maxlen;
769 {
770 int len, error = 0;
771
772 len = strlen(str) + 1;
773 if (oldp && *oldlenp < len)
774 return (ENOMEM);
775 if (newp && newlen >= maxlen)
776 return (EINVAL);
777 if (oldp) {
778 *oldlenp = len;
779 error = copyout(str, oldp, len);
780 }
781 if (error == 0 && newp) {
782 error = copyin(newp, str, newlen);
783 str[newlen] = 0;
784 }
785 return (error);
786 }
787
788 /*
789 * As above, but read-only.
790 */
791 int
792 sysctl_rdstring(oldp, oldlenp, newp, str)
793 void *oldp;
794 size_t *oldlenp;
795 void *newp;
796 char *str;
797 {
798 int len, error = 0;
799
800 len = strlen(str) + 1;
801 if (oldp && *oldlenp < len)
802 return (ENOMEM);
803 if (newp)
804 return (EPERM);
805 *oldlenp = len;
806 if (oldp)
807 error = copyout(str, oldp, len);
808 return (error);
809 }
810
811 /*
812 * Validate parameters and get old / set new parameters
813 * for a structure oriented sysctl function.
814 */
815 int
816 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
817 void *oldp;
818 size_t *oldlenp;
819 void *newp;
820 size_t newlen;
821 void *sp;
822 int len;
823 {
824 int error = 0;
825
826 if (oldp && *oldlenp < len)
827 return (ENOMEM);
828 if (newp && newlen > len)
829 return (EINVAL);
830 if (oldp) {
831 *oldlenp = len;
832 error = copyout(sp, oldp, len);
833 }
834 if (error == 0 && newp)
835 error = copyin(newp, sp, len);
836 return (error);
837 }
838
839 /*
840 * Validate parameters and get old parameters
841 * for a structure oriented sysctl function.
842 */
843 int
844 sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
845 void *oldp;
846 size_t *oldlenp;
847 void *newp, *sp;
848 int len;
849 {
850 int error = 0;
851
852 if (oldp && *oldlenp < len)
853 return (ENOMEM);
854 if (newp)
855 return (EPERM);
856 *oldlenp = len;
857 if (oldp)
858 error = copyout(sp, oldp, len);
859 return (error);
860 }
861
862 /*
863 * Get file structures.
864 */
865 int
866 sysctl_file(where, sizep)
867 char *where;
868 size_t *sizep;
869 {
870 int buflen, error;
871 struct file *fp;
872 char *start = where;
873
874 buflen = *sizep;
875 if (where == NULL) {
876 /*
877 * overestimate by 10 files
878 */
879 *sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
880 return (0);
881 }
882
883 /*
884 * first copyout filehead
885 */
886 if (buflen < sizeof(filehead)) {
887 *sizep = 0;
888 return (0);
889 }
890 error = copyout((caddr_t)&filehead, where, sizeof(filehead));
891 if (error)
892 return (error);
893 buflen -= sizeof(filehead);
894 where += sizeof(filehead);
895
896 /*
897 * followed by an array of file structures
898 */
899 for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) {
900 if (buflen < sizeof(struct file)) {
901 *sizep = where - start;
902 return (ENOMEM);
903 }
904 error = copyout((caddr_t)fp, where, sizeof(struct file));
905 if (error)
906 return (error);
907 buflen -= sizeof(struct file);
908 where += sizeof(struct file);
909 }
910 *sizep = where - start;
911 return (0);
912 }
913
914 /*
915 * try over estimating by 5 procs
916 */
917 #define KERN_PROCSLOP (5 * sizeof(struct kinfo_proc))
918
919 int
920 sysctl_doeproc(name, namelen, where, sizep)
921 int *name;
922 u_int namelen;
923 char *where;
924 size_t *sizep;
925 {
926 register struct proc *p;
927 register struct kinfo_proc *dp = (struct kinfo_proc *)where;
928 register int needed = 0;
929 int buflen = where != NULL ? *sizep : 0;
930 const struct proclist_desc *pd;
931 struct eproc eproc;
932 int error = 0;
933
934 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
935 return (EINVAL);
936
937 proclist_lock_read();
938
939 pd = proclists;
940 again:
941 for (p = LIST_FIRST(pd->pd_list); p != NULL;
942 p = LIST_NEXT(p, p_list)) {
943 /*
944 * Skip embryonic processes.
945 */
946 if (p->p_stat == SIDL)
947 continue;
948 /*
949 * TODO - make more efficient (see notes below).
950 * do by session.
951 */
952 switch (name[0]) {
953
954 case KERN_PROC_PID:
955 /* could do this with just a lookup */
956 if (p->p_pid != (pid_t)name[1])
957 continue;
958 break;
959
960 case KERN_PROC_PGRP:
961 /* could do this by traversing pgrp */
962 if (p->p_pgrp->pg_id != (pid_t)name[1])
963 continue;
964 break;
965
966 case KERN_PROC_TTY:
967 if ((p->p_flag & P_CONTROLT) == 0 ||
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:
974 if (p->p_ucred->cr_uid != (uid_t)name[1])
975 continue;
976 break;
977
978 case KERN_PROC_RUID:
979 if (p->p_cred->p_ruid != (uid_t)name[1])
980 continue;
981 break;
982 }
983 if (buflen >= sizeof(struct kinfo_proc)) {
984 fill_eproc(p, &eproc);
985 error = copyout((caddr_t)p, &dp->kp_proc,
986 sizeof(struct proc));
987 if (error)
988 return (error);
989 error = copyout((caddr_t)&eproc, &dp->kp_eproc,
990 sizeof(eproc));
991 if (error)
992 return (error);
993 dp++;
994 buflen -= sizeof(struct kinfo_proc);
995 }
996 needed += sizeof(struct kinfo_proc);
997 }
998 pd++;
999 if (pd->pd_list != NULL)
1000 goto again;
1001 proclist_unlock_read();
1002
1003 if (where != NULL) {
1004 *sizep = (caddr_t)dp - where;
1005 if (needed > *sizep)
1006 return (ENOMEM);
1007 } else {
1008 needed += KERN_PROCSLOP;
1009 *sizep = needed;
1010 }
1011 return (0);
1012 }
1013
1014 /*
1015 * Fill in an eproc structure for the specified process.
1016 */
1017 void
1018 fill_eproc(p, ep)
1019 register struct proc *p;
1020 register struct eproc *ep;
1021 {
1022 register struct tty *tp;
1023
1024 ep->e_paddr = p;
1025 ep->e_sess = p->p_pgrp->pg_session;
1026 ep->e_pcred = *p->p_cred;
1027 ep->e_ucred = *p->p_ucred;
1028 if (p->p_stat == SIDL || P_ZOMBIE(p)) {
1029 ep->e_vm.vm_rssize = 0;
1030 ep->e_vm.vm_tsize = 0;
1031 ep->e_vm.vm_dsize = 0;
1032 ep->e_vm.vm_ssize = 0;
1033 /* ep->e_vm.vm_pmap = XXX; */
1034 } else {
1035 register struct vmspace *vm = p->p_vmspace;
1036
1037 ep->e_vm.vm_rssize = vm_resident_count(vm);
1038 ep->e_vm.vm_tsize = vm->vm_tsize;
1039 ep->e_vm.vm_dsize = vm->vm_dsize;
1040 ep->e_vm.vm_ssize = vm->vm_ssize;
1041 }
1042 if (p->p_pptr)
1043 ep->e_ppid = p->p_pptr->p_pid;
1044 else
1045 ep->e_ppid = 0;
1046 ep->e_pgid = p->p_pgrp->pg_id;
1047 ep->e_sid = ep->e_sess->s_sid;
1048 ep->e_jobc = p->p_pgrp->pg_jobc;
1049 if ((p->p_flag & P_CONTROLT) &&
1050 (tp = ep->e_sess->s_ttyp)) {
1051 ep->e_tdev = tp->t_dev;
1052 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1053 ep->e_tsess = tp->t_session;
1054 } else
1055 ep->e_tdev = NODEV;
1056 if (p->p_wmesg)
1057 strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
1058 ep->e_xsize = ep->e_xrssize = 0;
1059 ep->e_xccount = ep->e_xswrss = 0;
1060 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
1061 if (SESS_LEADER(p))
1062 ep->e_flag |= EPROC_SLEADER;
1063 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME);
1064 }
1065