1 /**	$MirOS: src/sys/kern/kern_sysctl.c,v 1.18 2010/09/19 18:55:40 tg Exp $ */
2 /*	$NetBSD: kern_sysctl.c,v 1.146 2003/09/28 13:24:48 dsl Exp $	*/
3 /*	$OpenBSD: kern_sysctl.c,v 1.126 2005/06/04 05:10:40 tedu Exp $	*/
4 /*	$NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $	*/
5 
6 /*-
7  * Copyright (c) 2006, 2007
8  *	Thorsten “mirabilos” Glaser <tg@mirbsd.de>
9  * Copyright (c) 1982, 1986, 1989, 1993
10  *	The Regents of the University of California.  All rights reserved.
11  *
12  * This code is derived from software contributed to Berkeley by
13  * Mike Karels at Berkeley Software Design, Inc.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  * 3. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  *	@(#)kern_sysctl.c	8.4 (Berkeley) 4/14/94
40  */
41 
42 /*
43  * sysctl system call.
44  */
45 
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
49 #include <sys/malloc.h>
50 #include <sys/proc.h>
51 #include <sys/resourcevar.h>
52 #include <sys/file.h>
53 #include <sys/vnode.h>
54 #include <sys/unistd.h>
55 #include <sys/buf.h>
56 #include <sys/ioctl.h>
57 #include <sys/tty.h>
58 #include <sys/disklabel.h>
59 #include <sys/disk.h>
60 #include <uvm/uvm_extern.h>
61 #include <sys/sysctl.h>
62 #include <sys/msgbuf.h>
63 #include <sys/dkstat.h>
64 #include <sys/vmmeter.h>
65 #include <sys/namei.h>
66 #include <sys/exec.h>
67 #include <sys/mbuf.h>
68 #include <sys/sensors.h>
69 #include <sys/conf.h>
70 #ifdef __HAVE_TIMECOUNTER
71 #include <sys/timetc.h>
72 #endif
73 #ifdef __HAVE_EVCOUNT
74 #include <sys/evcount.h>
75 #endif
76 
77 #include <sys/mount.h>
78 #include <sys/syscallargs.h>
79 #include <dev/rndvar.h>
80 
81 #ifdef DDB
82 #include <ddb/db_var.h>
83 #endif
84 
85 #ifdef SYSVMSG
86 #include <sys/msg.h>
87 #endif
88 #ifdef SYSVSEM
89 #include <sys/sem.h>
90 #endif
91 #ifdef SYSVSHM
92 #include <sys/shm.h>
93 #endif
94 
95 #define	PTRTOINT64(_x)	((u_int64_t)(u_long)(_x))
96 
97 extern struct forkstat forkstat;
98 extern struct nchstats nchstats;
99 extern int nselcoll, fscale;
100 extern struct disklist_head disklist;
101 extern fixpt_t ccpu;
102 extern long numvnodes;
103 
104 extern void nmbclust_update(void);
105 
106 int sysctl_diskinit(int, struct proc *);
107 int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *);
108 int sysctl_intrcnt(int *, u_int, void *, size_t *);
109 int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t);
110 int sysctl_emul(int *, u_int, void *, size_t *, void *, size_t);
111 
112 int (*cpu_cpuspeed)(int *);
113 int (*cpu_setperf)(int);
114 static int do_cpu_setperf(int);
115 int perflevel = 100;
116 
117 extern char root_devname[];
118 
119 /*
120  * Lock to avoid too many processes vslocking a large amount of memory
121  * at the same time.
122  */
123 struct lock sysctl_lock, sysctl_disklock;
124 
125 #if defined(KMEMSTATS) || defined(DIAGNOSTIC) || defined(FFS_SOFTUPDATES)
126 struct lock sysctl_kmemlock;
127 #endif
128 
129 const char machine_arch[] = MACHINE_ARCH;
130 
131 void sysctl_init_values(void);
132 
133 static int
do_cpu_setperf(int newspeed)134 do_cpu_setperf(int newspeed)
135 {
136 	int rv = EOPNOTSUPP;
137 	if (cpu_setperf) {
138 		rv = cpu_setperf(newspeed);
139 		if (!rv)
140 			__do_calibrate_cyclecounter(&rv);
141 	}
142 	return (rv);
143 }
144 
145 void
sysctl_init()146 sysctl_init()
147 {
148 	sysctl_init_values();
149 
150 	lockinit(&sysctl_lock, PLOCK|PCATCH, "sysctl", 0, 0);
151 	lockinit(&sysctl_disklock, PLOCK|PCATCH, "sysctl_disklock", 0, 0);
152 
153 #if defined(KMEMSTATS) || defined(DIAGNOSTIC) || defined(FFS_SOFTUPDATES)
154 	lockinit(&sysctl_kmemlock, PLOCK|PCATCH, "sysctl_kmemlock", 0, 0);
155 #endif
156 }
157 
158 int
sys___sysctl(p,v,retval)159 sys___sysctl(p, v, retval)
160 	struct proc *p;
161 	void *v;
162 	register_t *retval;
163 {
164 	register struct sys___sysctl_args /* {
165 		syscallarg(int *) name;
166 		syscallarg(u_int) namelen;
167 		syscallarg(void *) old;
168 		syscallarg(size_t *) oldlenp;
169 		syscallarg(void *) new;
170 		syscallarg(size_t) newlen;
171 	} */ *uap = v;
172 	int error, dolock = 1, canwrite = 0;
173 	size_t savelen = 0, oldlen = 0;
174 	sysctlfn *fn;
175 	int name[CTL_MAXNAME];
176 
177 	/*
178 	 * all top-level sysctl names are non-terminal
179 	 */
180 	if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2)
181 		return (EINVAL);
182 	error = copyin(SCARG(uap, name), name,
183 		       SCARG(uap, namelen) * sizeof(int));
184 	if (error)
185 		return (error);
186 
187 	switch (name[0]) {
188 	case CTL_KERN:
189 		fn = kern_sysctl;
190 		if (name[1] == KERN_VNODE)	/* XXX */
191 			dolock = 0;
192 		if (name[1] == KERN_ARND)	/* non-root write access */
193 			canwrite = 1;
194 		break;
195 	case CTL_HW:
196 		fn = hw_sysctl;
197 		break;
198 	case CTL_VM:
199 		fn = uvm_sysctl;
200 		break;
201 	case CTL_NET:
202 		fn = net_sysctl;
203 		break;
204 	case CTL_FS:
205 		fn = fs_sysctl;
206 		break;
207 	case CTL_VFS:
208 		fn = vfs_sysctl;
209 		break;
210 	case CTL_MACHDEP:
211 		fn = cpu_sysctl;
212 		break;
213 #ifdef DEBUG
214 	case CTL_DEBUG:
215 		fn = debug_sysctl;
216 		break;
217 #endif
218 #ifdef DDB
219 	case CTL_DDB:
220 		fn = ddb_sysctl;
221 		break;
222 #endif
223 	default:
224 		return (EOPNOTSUPP);
225 	}
226 
227 	if (SCARG(uap, new) != NULL && !canwrite &&
228 	    (error = suser(p, 0)))
229 		return (error);
230 
231 	if (SCARG(uap, oldlenp) &&
232 	    (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
233 		return (error);
234 	if (SCARG(uap, old) != NULL) {
235 		if ((error = lockmgr(&sysctl_lock, LK_EXCLUSIVE, NULL, p)) != 0)
236 			return (error);
237 		if (dolock) {
238 			error = uvm_vslock(p, SCARG(uap, old), oldlen,
239 			    VM_PROT_READ|VM_PROT_WRITE);
240 			if (error) {
241 				lockmgr(&sysctl_lock, LK_RELEASE, NULL, p);
242 				return (error);
243 			}
244 		}
245 		savelen = oldlen;
246 	}
247 	error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old),
248 	    &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
249 	if (SCARG(uap, old) != NULL) {
250 		if (dolock)
251 			uvm_vsunlock(p, SCARG(uap, old), savelen);
252 		lockmgr(&sysctl_lock, LK_RELEASE, NULL, p);
253 	}
254 	if (error)
255 		return (error);
256 	if (SCARG(uap, oldlenp))
257 		error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen));
258 	return (error);
259 }
260 
261 /*
262  * Attributes stored in the kernel.
263  */
264 char hostname[MAXHOSTNAMELEN];
265 int hostnamelen;
266 char domainname[1] = "";
267 int domainnamelen;
268 long hostid;
269 char *disknames = NULL;
270 struct diskstats *diskstats = NULL;
271 #ifdef INSECURE
272 int securelevel = -1;
273 #else
274 int securelevel;
275 #endif
276 int allowpsa = 1, allowpse = 1;
277 #define	MAXEMULUNAMELEN 65
278 char emul_uname[MAXEMULUNAMELEN];
279 
280 /*
281  * kernel related system variables.
282  */
283 int
kern_sysctl(name,namelen,oldp,oldlenp,newp,newlen,p)284 kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
285 	int *name;
286 	u_int namelen;
287 	void *oldp;
288 	size_t *oldlenp;
289 	void *newp;
290 	size_t newlen;
291 	struct proc *p;
292 {
293 	int error, level, inthostid, stackgap;
294 	extern int somaxconn, sominconn;
295 	extern int usermount, nosuidcoredump;
296 	extern long cp_time[CPUSTATES];
297 	extern int stackgap_random;
298 #ifdef CRYPTO
299 	extern int usercrypto;
300 	extern int userasymcrypto;
301 	extern int cryptodevallowsoft;
302 #endif
303 
304 	/* all sysctl names at this level are terminal except a ton of them */
305 	if (namelen != 1) {
306 		switch (name[0]) {
307 		case KERN_PROC:
308 		case KERN_PROC2:
309 		case KERN_MALLOCSTATS:
310 		case KERN_TTY:
311 		case KERN_POOL:
312 		case KERN_PROC_ARGS:
313 		case KERN_SYSVIPC_INFO:
314 		case KERN_SEMINFO:
315 		case KERN_SHMINFO:
316 		case KERN_INTRCNT:
317 		case KERN_WATCHDOG:
318 		case KERN_EMUL:
319 #ifdef __HAVE_EVCOUNT
320 		case KERN_EVCOUNT:
321 #endif
322 #ifdef __HAVE_TIMECOUNTER
323 		case KERN_TIMECOUNTER:
324 #endif
325 			break;
326 		default:
327 			return (ENOTDIR);	/* overloaded */
328 		}
329 	}
330 
331 	switch (name[0]) {
332 	case KERN_OSTYPE:
333 		return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
334 	case KERN_OSRELEASE:
335 		return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
336 	case KERN_OSPATCHLEVEL:
337 		return (sysctl_rdstring(oldp, oldlenp, newp, ospatchlevel));
338 	case KERN_OSREV:
339 		return (sysctl_rdint(oldp, oldlenp, newp, MirBSD));
340 	case KERN_OSVERSION:
341 		return (sysctl_rdstring(oldp, oldlenp, newp, osversion));
342 	case KERN_VERSION:
343 		return (sysctl_rdstring(oldp, oldlenp, newp, version));
344 	case KERN_MAXVNODES:
345 		return(sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes));
346 	case KERN_MAXPROC:
347 		return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
348 	case KERN_MAXFILES:
349 		return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
350 	case KERN_NFILES:
351 		return (sysctl_rdint(oldp, oldlenp, newp, nfiles));
352 	case KERN_TTYCOUNT:
353 		return (sysctl_rdint(oldp, oldlenp, newp, tty_count));
354 	case KERN_NUMVNODES:
355 		return (sysctl_rdint(oldp, oldlenp, newp, numvnodes));
356 	case KERN_ARGMAX:
357 		return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
358 	case KERN_NSELCOLL:
359 		return (sysctl_rdint(oldp, oldlenp, newp, nselcoll));
360 	case KERN_SECURELVL:
361 		level = securelevel;
362 		if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
363 		    newp == NULL)
364 			return (error);
365 		if ((securelevel > 0 || level < -1) &&
366 		    level < securelevel && p->p_pid != 1)
367 			return (EPERM);
368 		securelevel = level;
369 		return (0);
370 	case KERN_HOSTNAME:
371 		error = sysctl_tstring(oldp, oldlenp, newp, newlen,
372 		    hostname, sizeof(hostname));
373 		if (newp && !error)
374 			hostnamelen = newlen;
375 		return (error);
376 	case KERN_DOMAINNAME:
377 		error = sysctl_rdstring(oldp, oldlenp, newp, domainname);
378 		return (error);
379 	case KERN_HOSTID:
380 		inthostid = hostid;  /* XXX assumes sizeof long <= sizeof int */
381 		error =  sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
382 		hostid = inthostid;
383 		return (error);
384 	case KERN_CLOCKRATE:
385 		return (sysctl_clockrate(oldp, oldlenp));
386 	case KERN_BOOTTIME:
387 		return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
388 		    sizeof(struct timeval)));
389 	case KERN_VNODE:
390 		return (sysctl_vnode(oldp, oldlenp, p));
391 	case KERN_PROC:
392 	case KERN_PROC2:
393 		return (sysctl_doproc(name, namelen, oldp, oldlenp));
394 	case KERN_PROC_ARGS:
395 		return (sysctl_proc_args(name + 1, namelen - 1, oldp, oldlenp,
396 		     p));
397 	case KERN_FILE:
398 		return (sysctl_file(oldp, oldlenp));
399 	case KERN_MBSTAT:
400 		return (sysctl_rdstruct(oldp, oldlenp, newp, &mbstat,
401 		    sizeof(mbstat)));
402 	case KERN_POSIX1:
403 		return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
404 	case KERN_NGROUPS:
405 		return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
406 	case KERN_JOB_CONTROL:
407 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
408 	case KERN_SAVED_IDS:
409 #ifdef _POSIX_SAVED_IDS
410 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
411 #else
412 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
413 #endif
414 	case KERN_MAXPARTITIONS:
415 		return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
416 	case KERN_RAWPARTITION:
417 		return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART));
418 	case KERN_SOMAXCONN:
419 		return (sysctl_int(oldp, oldlenp, newp, newlen, &somaxconn));
420 	case KERN_SOMINCONN:
421 		return (sysctl_int(oldp, oldlenp, newp, newlen, &sominconn));
422 	case KERN_USERMOUNT:
423 		return (sysctl_int(oldp, oldlenp, newp, newlen, &usermount));
424 	case KERN_RND:
425 		return (sysctl_rdstruct(oldp, oldlenp, newp, &rndstats,
426 		    sizeof(rndstats)));
427 	case KERN_ARND: {
428 		size_t n, o = 0;
429 		/* typical userspace writes are 256 bytes */
430 		uint8_t buf[256];
431 
432 		if (newp) while (newlen) {
433 			n = min(newlen, sizeof(buf));
434 			if ((error = copyin(newp + o, buf, n)))
435 				return (error);
436 			rnd_lopool_add(buf, n);
437 			o += n;
438 			newlen -= n;
439 		}
440 
441 		if (oldp) {
442 			newlen = *oldlenp;
443 			o = 0;
444 			while (newlen) {
445 				n = min(newlen, sizeof(buf));
446 				arc4random_buf(buf, n);
447 				if ((error = copyout(buf, oldp + o, n)))
448 					return (error);
449 				o += n;
450 				newlen -= n;
451 			}
452 		}
453 		return (0);
454 	}
455 	case KERN_NOSUIDCOREDUMP:
456 		return (sysctl_int(oldp, oldlenp, newp, newlen, &nosuidcoredump));
457 	case KERN_FSYNC:
458 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
459 	case KERN_SYSVMSG:
460 #ifdef SYSVMSG
461 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
462 #else
463 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
464 #endif
465 	case KERN_SYSVSEM:
466 #ifdef SYSVSEM
467 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
468 #else
469 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
470 #endif
471 	case KERN_SYSVSHM:
472 #ifdef SYSVSHM
473 		return (sysctl_rdint(oldp, oldlenp, newp, 1));
474 #else
475 		return (sysctl_rdint(oldp, oldlenp, newp, 0));
476 #endif
477 	case KERN_MSGBUFSIZE:
478 		/*
479 		 * deal with cases where the message buffer has
480 		 * become corrupted.
481 		 */
482 		if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC)
483 			return (ENXIO);
484 		return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs));
485 	case KERN_MSGBUF:
486 		/* see note above */
487 		if (!msgbufp || msgbufp->msg_magic != MSG_MAGIC)
488 			return (ENXIO);
489 		return (sysctl_rdstruct(oldp, oldlenp, newp, msgbufp,
490 		    msgbufp->msg_bufs + offsetof(struct msgbuf, msg_bufc)));
491 	case KERN_MALLOCSTATS:
492 		return (sysctl_malloc(name + 1, namelen - 1, oldp, oldlenp,
493 		    newp, newlen, p));
494 	case KERN_CPTIME:
495 #ifdef __HAVE_CPUINFO
496 	{
497 		CPU_INFO_ITERATOR cii;
498 		struct cpu_info *ci;
499 		int i;
500 
501 		bzero(cp_time, sizeof(cp_time));
502 
503 		for (CPU_INFO_FOREACH(cii, ci)) {
504 			for (i = 0; i < CPUSTATES; i++)
505 				cp_time[i] += ci->ci_schedstate.spc_cp_time[i];
506 		}
507 	}
508 #endif
509 		return (sysctl_rdstruct(oldp, oldlenp, newp, &cp_time,
510 		    sizeof(cp_time)));
511 	case KERN_NCHSTATS:
512 		return (sysctl_rdstruct(oldp, oldlenp, newp, &nchstats,
513 		    sizeof(struct nchstats)));
514 	case KERN_FORKSTAT:
515 		return (sysctl_rdstruct(oldp, oldlenp, newp, &forkstat,
516 		    sizeof(struct forkstat)));
517 	case KERN_TTY:
518 		return (sysctl_tty(name + 1, namelen - 1, oldp, oldlenp,
519 		    newp, newlen));
520 	case KERN_FSCALE:
521 		return (sysctl_rdint(oldp, oldlenp, newp, fscale));
522 	case KERN_CCPU:
523 		return (sysctl_rdint(oldp, oldlenp, newp, ccpu));
524 	case KERN_NPROCS:
525 		return (sysctl_rdint(oldp, oldlenp, newp, nprocs));
526 	case KERN_POOL:
527 		return (sysctl_dopool(name + 1, namelen - 1, oldp, oldlenp));
528 	case KERN_STACKGAPRANDOM:
529 		stackgap = stackgap_random;
530 		error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap);
531 		if (error)
532 			return (error);
533 		/*
534 		 * Safety harness.
535 		 */
536 		if ((stackgap < ALIGNBYTES && stackgap != 0) ||
537 		    !powerof2(stackgap) || stackgap >= MAXSSIZ)
538 			return (EINVAL);
539 		stackgap_random = stackgap;
540 		return (0);
541 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
542 	case KERN_SYSVIPC_INFO:
543 		return (sysctl_sysvipc(name + 1, namelen - 1, oldp, oldlenp));
544 #endif
545 #ifdef CRYPTO
546 	case KERN_USERCRYPTO:
547 		return (sysctl_int(oldp, oldlenp, newp, newlen, &usercrypto));
548 	case KERN_USERASYMCRYPTO:
549 		return (sysctl_int(oldp, oldlenp, newp, newlen,
550 			    &userasymcrypto));
551 	case KERN_CRYPTODEVALLOWSOFT:
552 		return (sysctl_int(oldp, oldlenp, newp, newlen,
553 			    &cryptodevallowsoft));
554 #endif
555 	case KERN_SPLASSERT:
556 		return (sysctl_int(oldp, oldlenp, newp, newlen,
557 		    &splassert_ctl));
558 #ifdef SYSVSEM
559 	case KERN_SEMINFO:
560 		return (sysctl_sysvsem(name + 1, namelen - 1, oldp, oldlenp,
561 		    newp, newlen));
562 #endif
563 #ifdef SYSVSHM
564 	case KERN_SHMINFO:
565 		return (sysctl_sysvshm(name + 1, namelen - 1, oldp, oldlenp,
566 		    newp, newlen));
567 #endif
568 	case KERN_INTRCNT:
569 		return (sysctl_intrcnt(name + 1, namelen - 1, oldp, oldlenp));
570 #ifndef SMALL_KERNEL
571 	case KERN_WATCHDOG:
572 		return (sysctl_wdog(name + 1, namelen - 1, oldp, oldlenp,
573 		    newp, newlen));
574 #endif
575 	case KERN_ALLOWPSA:
576 		return sysctl_int(oldp, oldlenp, newp, newlen,
577 		    &allowpsa);
578 	case KERN_ALLOWPSE:
579 		return sysctl_int(oldp, oldlenp, newp, newlen,
580 		    &allowpse);
581 	case KERN_EMUL:
582 		return (sysctl_emul(name + 1, namelen - 1, oldp, oldlenp,
583 		    newp, newlen));
584  	case KERN_ROOT_DEVICE:
585 		return sysctl_rdstring(oldp, oldlenp, newp,
586 		    root_devname);
587 	case KERN_ROOT_PARTITION:
588 		return sysctl_rdint(oldp, oldlenp, newp, DISKPART(rootdev));
589 	case KERN_MAXCLUSTERS:
590 		error = sysctl_int(oldp, oldlenp, newp, newlen, &nmbclust);
591 		if (!error)
592 			nmbclust_update();
593 		return (error);
594 	case KERN_EMULUNAME:
595 		error = sysctl_tstring(oldp, oldlenp, newp, newlen,
596 		    emul_uname, MAXEMULUNAMELEN);
597 		return (error);
598 #ifdef __HAVE_EVCOUNT
599 	case KERN_EVCOUNT:
600 		return (evcount_sysctl(name + 1, namelen - 1, oldp, oldlenp,
601 		    newp, newlen));
602 #endif
603 #ifdef __HAVE_TIMECOUNTER
604 	case KERN_TIMECOUNTER:
605 		return (sysctl_tc(name + 1, namelen - 1, oldp, oldlenp,
606 		    newp, newlen));
607 #endif
608 	default:
609 		return (EOPNOTSUPP);
610 	}
611 	/* NOTREACHED */
612 }
613 
614 /*
615  * hardware related system variables.
616  */
617 int
hw_sysctl(name,namelen,oldp,oldlenp,newp,newlen,p)618 hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
619 	int *name;
620 	u_int namelen;
621 	void *oldp;
622 	size_t *oldlenp;
623 	void *newp;
624 	size_t newlen;
625 	struct proc *p;
626 {
627 	extern char machine[], cpu_model[];
628 	int err;
629 	int cpuspeed;
630 
631 	/* all sysctl names at this level except sensors are terminal */
632 	if (name[0] != HW_SENSORS && namelen != 1)
633 		return (ENOTDIR);		/* overloaded */
634 
635 	switch (name[0]) {
636 	case HW_MACHINE:
637 		return (sysctl_rdstring(oldp, oldlenp, newp, machine));
638 	case HW_MODEL:
639 		return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
640 	case HW_NCPU:
641 		return (sysctl_rdint(oldp, oldlenp, newp, 1));	/* XXX */
642 	case HW_BYTEORDER:
643 		return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
644 	case HW_PHYSMEM:
645 		return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
646 	case HW_USERMEM:
647 		return (sysctl_rdint(oldp, oldlenp, newp,
648 		    ctob(physmem - uvmexp.wired)));
649 	case HW_PAGESIZE:
650 		return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
651 	case HW_DISKNAMES:
652 		err = sysctl_diskinit(0, p);
653 		if (err)
654 			return err;
655 		if (disknames)
656 			return (sysctl_rdstring(oldp, oldlenp, newp,
657 			    disknames));
658 		else
659 			return (sysctl_rdstring(oldp, oldlenp, newp, ""));
660 	case HW_DISKSTATS:
661 		err = sysctl_diskinit(1, p);
662 		if (err)
663 			return err;
664 		return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats,
665 		    disk_count * sizeof(struct diskstats)));
666 	case HW_DISKCOUNT:
667 		return (sysctl_rdint(oldp, oldlenp, newp, disk_count));
668 	case HW_SENSORS:
669 		return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp,
670 		    newp, newlen));
671 	case HW_CPUSPEED:
672 		if (!cpu_cpuspeed)
673 			return (EOPNOTSUPP);
674 		err = cpu_cpuspeed(&cpuspeed);
675 		if (err)
676 			return err;
677 		return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed));
678 	case HW_SETPERF:
679 		if (!cpu_setperf)
680 			return (EOPNOTSUPP);
681 		err = sysctl_int(oldp, oldlenp, newp, newlen, &perflevel);
682 		if (err)
683 			return err;
684 		if (perflevel > 100)
685 			perflevel = 100;
686 		if (perflevel < 0)
687 			perflevel = 0;
688 		if (newp)
689 			return (do_cpu_setperf(perflevel));
690 		else
691 			return (0);
692 	case HW_MACHINE_ARCH:
693 		return (sysctl_rdstring(oldp, oldlenp, newp, machine_arch));
694 	default:
695 		return (EOPNOTSUPP);
696 	}
697 	/* NOTREACHED */
698 }
699 
700 #ifdef DEBUG
701 /*
702  * Debugging related system variables.
703  */
704 extern struct ctldebug debug0, debug1;
705 struct ctldebug debug2, debug3, debug4;
706 struct ctldebug debug5, debug6, debug7, debug8, debug9;
707 struct ctldebug debug10, debug11, debug12, debug13, debug14;
708 struct ctldebug debug15, debug16, debug17, debug18, debug19;
709 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
710 	&debug0, &debug1, &debug2, &debug3, &debug4,
711 	&debug5, &debug6, &debug7, &debug8, &debug9,
712 	&debug10, &debug11, &debug12, &debug13, &debug14,
713 	&debug15, &debug16, &debug17, &debug18, &debug19,
714 };
715 int
debug_sysctl(name,namelen,oldp,oldlenp,newp,newlen,p)716 debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
717 	int *name;
718 	u_int namelen;
719 	void *oldp;
720 	size_t *oldlenp;
721 	void *newp;
722 	size_t newlen;
723 	struct proc *p;
724 {
725 	struct ctldebug *cdp;
726 
727 	/* all sysctl names at this level are name and field */
728 	if (namelen != 2)
729 		return (ENOTDIR);		/* overloaded */
730 	cdp = debugvars[name[0]];
731 	if (cdp->debugname == 0)
732 		return (EOPNOTSUPP);
733 	switch (name[1]) {
734 	case CTL_DEBUG_NAME:
735 		return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
736 	case CTL_DEBUG_VALUE:
737 		return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
738 	default:
739 		return (EOPNOTSUPP);
740 	}
741 	/* NOTREACHED */
742 }
743 #endif /* DEBUG */
744 
745 /*
746  * Validate parameters and get old / set new parameters
747  * for an integer-valued sysctl function.
748  */
749 int
sysctl_int(oldp,oldlenp,newp,newlen,valp)750 sysctl_int(oldp, oldlenp, newp, newlen, valp)
751 	void *oldp;
752 	size_t *oldlenp;
753 	void *newp;
754 	size_t newlen;
755 	int *valp;
756 {
757 	int error = 0;
758 
759 	if (oldp && *oldlenp < sizeof(int))
760 		return (ENOMEM);
761 	if (newp && newlen != sizeof(int))
762 		return (EINVAL);
763 	*oldlenp = sizeof(int);
764 	if (oldp)
765 		error = copyout(valp, oldp, sizeof(int));
766 	if (error == 0 && newp)
767 		error = copyin(newp, valp, sizeof(int));
768 	return (error);
769 }
770 
771 /*
772  * As above, but read-only.
773  */
774 int
sysctl_rdint(oldp,oldlenp,newp,val)775 sysctl_rdint(oldp, oldlenp, newp, val)
776 	void *oldp;
777 	size_t *oldlenp;
778 	void *newp;
779 	int val;
780 {
781 	int error = 0;
782 
783 	if (oldp && *oldlenp < sizeof(int))
784 		return (ENOMEM);
785 	if (newp)
786 		return (EPERM);
787 	*oldlenp = sizeof(int);
788 	if (oldp)
789 		error = copyout((caddr_t)&val, oldp, sizeof(int));
790 	return (error);
791 }
792 
793 /*
794  * Array of integer values.
795  */
796 int
sysctl_int_arr(valpp,name,namelen,oldp,oldlenp,newp,newlen)797 sysctl_int_arr(valpp, name, namelen, oldp, oldlenp, newp, newlen)
798 	int **valpp;
799 	int *name;
800 	u_int namelen;
801 	void *oldp;
802 	size_t *oldlenp;
803 	void *newp;
804 	size_t newlen;
805 {
806 	if (namelen > 1)
807 		return (ENOTDIR);
808 	if (name[0] < 0 || valpp[name[0]] == NULL)
809 		return (EOPNOTSUPP);
810 	return (sysctl_int(oldp, oldlenp, newp, newlen, valpp[name[0]]));
811 }
812 
813 /*
814  * Validate parameters and get old / set new parameters
815  * for an integer-valued sysctl function.
816  */
817 int
sysctl_quad(oldp,oldlenp,newp,newlen,valp)818 sysctl_quad(oldp, oldlenp, newp, newlen, valp)
819 	void *oldp;
820 	size_t *oldlenp;
821 	void *newp;
822 	size_t newlen;
823 	int64_t *valp;
824 {
825 	int error = 0;
826 
827 	if (oldp && *oldlenp < sizeof(int64_t))
828 		return (ENOMEM);
829 	if (newp && newlen != sizeof(int64_t))
830 		return (EINVAL);
831 	*oldlenp = sizeof(int64_t);
832 	if (oldp)
833 		error = copyout(valp, oldp, sizeof(int64_t));
834 	if (error == 0 && newp)
835 		error = copyin(newp, valp, sizeof(int64_t));
836 	return (error);
837 }
838 
839 /*
840  * As above, but read-only.
841  */
842 int
sysctl_rdquad(oldp,oldlenp,newp,val)843 sysctl_rdquad(oldp, oldlenp, newp, val)
844 	void *oldp;
845 	size_t *oldlenp;
846 	void *newp;
847 	int64_t val;
848 {
849 	int error = 0;
850 
851 	if (oldp && *oldlenp < sizeof(int64_t))
852 		return (ENOMEM);
853 	if (newp)
854 		return (EPERM);
855 	*oldlenp = sizeof(int64_t);
856 	if (oldp)
857 		error = copyout((caddr_t)&val, oldp, sizeof(int64_t));
858 	return (error);
859 }
860 
861 /*
862  * Validate parameters and get old / set new parameters
863  * for a string-valued sysctl function.
864  */
865 int
sysctl_string(oldp,oldlenp,newp,newlen,str,maxlen)866 sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
867 	void *oldp;
868 	size_t *oldlenp;
869 	void *newp;
870 	size_t newlen;
871 	char *str;
872 	int maxlen;
873 {
874 	return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0);
875 }
876 
877 int
sysctl_tstring(oldp,oldlenp,newp,newlen,str,maxlen)878 sysctl_tstring(oldp, oldlenp, newp, newlen, str, maxlen)
879 	void *oldp;
880 	size_t *oldlenp;
881 	void *newp;
882 	size_t newlen;
883 	char *str;
884 	int maxlen;
885 {
886 	return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1);
887 }
888 
889 int
sysctl__string(oldp,oldlenp,newp,newlen,str,maxlen,trunc)890 sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, trunc)
891 	void *oldp;
892 	size_t *oldlenp;
893 	void *newp;
894 	size_t newlen;
895 	char *str;
896 	int maxlen;
897 	int trunc;
898 {
899 	int len, error = 0;
900 	char c;
901 
902 	len = strlen(str) + 1;
903 	if (oldp && *oldlenp < len) {
904 		if (trunc == 0 || *oldlenp == 0)
905 			return (ENOMEM);
906 	}
907 	if (newp && newlen >= maxlen)
908 		return (EINVAL);
909 	if (oldp) {
910 		if (trunc && *oldlenp < len) {
911 			/* save & zap NUL terminator while copying */
912 			c = str[*oldlenp-1];
913 			str[*oldlenp-1] = '\0';
914 			error = copyout(str, oldp, *oldlenp);
915 			str[*oldlenp-1] = c;
916 		} else {
917 			*oldlenp = len;
918 			error = copyout(str, oldp, len);
919 		}
920 	}
921 	if (error == 0 && newp) {
922 		error = copyin(newp, str, newlen);
923 		str[newlen] = 0;
924 	}
925 	return (error);
926 }
927 
928 /*
929  * As above, but read-only.
930  */
931 int
sysctl_rdstring(oldp,oldlenp,newp,str)932 sysctl_rdstring(oldp, oldlenp, newp, str)
933 	void *oldp;
934 	size_t *oldlenp;
935 	void *newp;
936 	const char *str;
937 {
938 	int len, error = 0;
939 
940 	len = strlen(str) + 1;
941 	if (oldp && *oldlenp < len)
942 		return (ENOMEM);
943 	if (newp)
944 		return (EPERM);
945 	*oldlenp = len;
946 	if (oldp)
947 		error = copyout(str, oldp, len);
948 	return (error);
949 }
950 
951 /*
952  * Validate parameters and get old / set new parameters
953  * for a structure oriented sysctl function.
954  */
955 int
sysctl_struct(oldp,oldlenp,newp,newlen,sp,len)956 sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
957 	void *oldp;
958 	size_t *oldlenp;
959 	void *newp;
960 	size_t newlen;
961 	void *sp;
962 	int len;
963 {
964 	int error = 0;
965 
966 	if (oldp && *oldlenp < len)
967 		return (ENOMEM);
968 	if (newp && newlen > len)
969 		return (EINVAL);
970 	if (oldp) {
971 		*oldlenp = len;
972 		error = copyout(sp, oldp, len);
973 	}
974 	if (error == 0 && newp)
975 		error = copyin(newp, sp, len);
976 	return (error);
977 }
978 
979 /*
980  * Validate parameters and get old parameters
981  * for a structure oriented sysctl function.
982  */
983 int
sysctl_rdstruct(oldp,oldlenp,newp,sp,len)984 sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
985 	void *oldp;
986 	size_t *oldlenp;
987 	void *newp;
988 	const void *sp;
989 	int len;
990 {
991 	int error = 0;
992 
993 	if (oldp && *oldlenp < len)
994 		return (ENOMEM);
995 	if (newp)
996 		return (EPERM);
997 	*oldlenp = len;
998 	if (oldp)
999 		error = copyout(sp, oldp, len);
1000 	return (error);
1001 }
1002 
1003 /*
1004  * Get file structures.
1005  */
1006 int
sysctl_file(where,sizep)1007 sysctl_file(where, sizep)
1008 	char *where;
1009 	size_t *sizep;
1010 {
1011 	int buflen, error;
1012 	struct file *fp;
1013 	char *start = where;
1014 
1015 	buflen = *sizep;
1016 	if (where == NULL) {
1017 		/*
1018 		 * overestimate by 10 files
1019 		 */
1020 		*sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
1021 		return (0);
1022 	}
1023 
1024 	/*
1025 	 * first copyout filehead
1026 	 */
1027 	if (buflen < sizeof(filehead)) {
1028 		*sizep = 0;
1029 		return (0);
1030 	}
1031 	error = copyout((caddr_t)&filehead, where, sizeof(filehead));
1032 	if (error)
1033 		return (error);
1034 	buflen -= sizeof(filehead);
1035 	where += sizeof(filehead);
1036 
1037 	/*
1038 	 * followed by an array of file structures
1039 	 */
1040 	LIST_FOREACH(fp, &filehead, f_list) {
1041 		if (buflen < sizeof(struct file)) {
1042 			*sizep = where - start;
1043 			return (ENOMEM);
1044 		}
1045 		error = copyout((caddr_t)fp, where, sizeof (struct file));
1046 		if (error)
1047 			return (error);
1048 		buflen -= sizeof(struct file);
1049 		where += sizeof(struct file);
1050 	}
1051 	*sizep = where - start;
1052 	return (0);
1053 }
1054 
1055 /*
1056  * try over estimating by 5 procs
1057  */
1058 #define KERN_PROCSLOP	(5 * sizeof (struct kinfo_proc))
1059 
1060 int
sysctl_doproc(name,namelen,where,sizep)1061 sysctl_doproc(name, namelen, where, sizep)
1062 	int *name;
1063 	u_int namelen;
1064 	char *where;
1065 	size_t *sizep;
1066 {
1067 	struct kinfo_proc2 kproc2;
1068 	struct eproc eproc;
1069 	struct proc *p;
1070 	char *dp;
1071 	int arg, buflen, doingzomb, elem_size, elem_count;
1072 	int error, needed, type, op;
1073 
1074 	dp = where;
1075 	buflen = where != NULL ? *sizep : 0;
1076 	needed = error = 0;
1077 	type = name[0];
1078 
1079 	if (type == KERN_PROC) {
1080 		if (namelen != 3 && !(namelen == 2 &&
1081 		    (name[1] == KERN_PROC_ALL || name[1] == KERN_PROC_KTHREAD)))
1082 			return (EINVAL);
1083 		op = name[1];
1084 		arg = op == KERN_PROC_ALL ? 0 : name[2];
1085 		elem_size = elem_count = 0;
1086 	} else /* if (type == KERN_PROC2) */ {
1087 		if (namelen != 5 || name[3] < 0 || name[4] < 0)
1088 			return (EINVAL);
1089 		op = name[1];
1090 		arg = name[2];
1091 		elem_size = name[3];
1092 		elem_count = name[4];
1093 	}
1094 	p = LIST_FIRST(&allproc);
1095 	doingzomb = 0;
1096 again:
1097 	for (; p != 0; p = LIST_NEXT(p, p_list)) {
1098 		/*
1099 		 * Skip embryonic processes.
1100 		 */
1101 		if (p->p_stat == SIDL)
1102 			continue;
1103 		/*
1104 		 * Skip processes with different real uid
1105 		 */
1106 		if ((!allowpsa) &&
1107 		    (curproc->p_cred->p_ruid != p->p_cred->p_ruid) &&
1108 		    (curproc->p_cred->p_rgid))
1109 			continue;
1110 
1111 		/*
1112 		 * TODO - make more efficient (see notes below).
1113 		 */
1114 		switch (op) {
1115 
1116 		case KERN_PROC_PID:
1117 			/* could do this with just a lookup */
1118 			if (p->p_pid != (pid_t)arg)
1119 				continue;
1120 			break;
1121 
1122 		case KERN_PROC_PGRP:
1123 			/* could do this by traversing pgrp */
1124 			if (p->p_pgrp->pg_id != (pid_t)arg)
1125 				continue;
1126 			break;
1127 
1128 		case KERN_PROC_SESSION:
1129 			if (p->p_session->s_leader == NULL ||
1130 			    p->p_session->s_leader->p_pid != (pid_t)arg)
1131 				continue;
1132 			break;
1133 
1134 		case KERN_PROC_TTY:
1135 			if ((p->p_flag & P_CONTROLT) == 0 ||
1136 			    p->p_session->s_ttyp == NULL ||
1137 			    p->p_session->s_ttyp->t_dev != (dev_t)arg)
1138 				continue;
1139 			break;
1140 
1141 		case KERN_PROC_UID:
1142 			if (p->p_ucred->cr_uid != (uid_t)arg)
1143 				continue;
1144 			break;
1145 
1146 		case KERN_PROC_RUID:
1147 			if (p->p_cred->p_ruid != (uid_t)arg)
1148 				continue;
1149 			break;
1150 
1151 		case KERN_PROC_ALL:
1152 			if (p->p_flag & P_SYSTEM)
1153 				continue;
1154 			break;
1155 		case KERN_PROC_KTHREAD:
1156 			/* no filtering */
1157 			break;
1158 		default:
1159 			return (EINVAL);
1160 		}
1161 		if (type == KERN_PROC) {
1162 			if (buflen >= sizeof(struct kinfo_proc)) {
1163 				fill_eproc(p, &eproc);
1164 				error = copyout((caddr_t)p,
1165 				    &((struct kinfo_proc *)dp)->kp_proc,
1166 				    sizeof(struct proc));
1167 				if (error)
1168 					return (error);
1169 				error = copyout((caddr_t)&eproc,
1170 				    &((struct kinfo_proc *)dp)->kp_eproc,
1171 				    sizeof(eproc));
1172 				if (error)
1173 					return (error);
1174 				dp += sizeof(struct kinfo_proc);
1175 				buflen -= sizeof(struct kinfo_proc);
1176 			}
1177 			needed += sizeof(struct kinfo_proc);
1178 		} else /* if (type == KERN_PROC2) */ {
1179 			if (buflen >= elem_size && elem_count > 0) {
1180 				fill_kproc2(p, &kproc2);
1181 				/*
1182 				 * Copy out elem_size, but not larger than
1183 				 * the size of a struct kinfo_proc2.
1184 				 */
1185 				error = copyout(&kproc2, dp,
1186 				    min(sizeof(kproc2), elem_size));
1187 				if (error)
1188 					return (error);
1189 				dp += elem_size;
1190 				buflen -= elem_size;
1191 				elem_count--;
1192 			}
1193 			needed += elem_size;
1194 		}
1195 	}
1196 	if (doingzomb == 0) {
1197 		p = LIST_FIRST(&zombproc);
1198 		doingzomb++;
1199 		goto again;
1200 	}
1201 	if (where != NULL) {
1202 		*sizep = dp - where;
1203 		if (needed > *sizep)
1204 			return (ENOMEM);
1205 	} else {
1206 		needed += KERN_PROCSLOP;
1207 		*sizep = needed;
1208 	}
1209 	return (0);
1210 }
1211 
1212 /*
1213  * Fill in an eproc structure for the specified process.
1214  */
1215 void
fill_eproc(struct proc * p,struct eproc * ep)1216 fill_eproc(struct proc *p, struct eproc *ep)
1217 {
1218 	struct tty *tp;
1219 
1220 	ep->e_paddr = p;
1221 	ep->e_sess = p->p_pgrp->pg_session;
1222 	ep->e_pcred = *p->p_cred;
1223 	ep->e_ucred = *p->p_ucred;
1224 	if (p->p_stat == SIDL || P_ZOMBIE(p)) {
1225 		ep->e_vm.vm_rssize = 0;
1226 		ep->e_vm.vm_tsize = 0;
1227 		ep->e_vm.vm_dsize = 0;
1228 		ep->e_vm.vm_ssize = 0;
1229 		bzero(&ep->e_pstats, sizeof(ep->e_pstats));
1230 		ep->e_pstats_valid = 0;
1231 	} else {
1232 		struct vmspace *vm = p->p_vmspace;
1233 
1234 		PHOLD(p);	/* need for pstats */
1235 		ep->e_vm.vm_rssize = vm_resident_count(vm);
1236 		ep->e_vm.vm_tsize = vm->vm_tsize;
1237 		ep->e_vm.vm_dsize = vm->vm_dsize;
1238 		ep->e_vm.vm_ssize = vm->vm_ssize;
1239 		ep->e_pstats = *p->p_stats;
1240 		ep->e_pstats_valid = 1;
1241 		PRELE(p);
1242 	}
1243 	if (p->p_pptr)
1244 		ep->e_ppid = p->p_pptr->p_pid;
1245 	else
1246 		ep->e_ppid = 0;
1247 	ep->e_pgid = p->p_pgrp->pg_id;
1248 	ep->e_jobc = p->p_pgrp->pg_jobc;
1249 	if ((p->p_flag & P_CONTROLT) &&
1250 	     (tp = ep->e_sess->s_ttyp)) {
1251 		ep->e_tdev = tp->t_dev;
1252 		ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
1253 		ep->e_tsess = tp->t_session;
1254 	} else
1255 		ep->e_tdev = NODEV;
1256 	ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
1257 	if (SESS_LEADER(p))
1258 		ep->e_flag |= EPROC_SLEADER;
1259 	strncpy(ep->e_wmesg, p->p_wmesg ? p->p_wmesg : "", WMESGLEN);
1260 	ep->e_wmesg[WMESGLEN] = '\0';
1261 	ep->e_xsize = ep->e_xrssize = 0;
1262 	ep->e_xccount = ep->e_xswrss = 0;
1263 	strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME-1);
1264 	ep->e_login[MAXLOGNAME-1] = '\0';
1265 	strncpy(ep->e_emul, p->p_emul->e_name, EMULNAMELEN);
1266 	ep->e_emul[EMULNAMELEN] = '\0';
1267 	ep->e_maxrss = p->p_rlimit ? p->p_rlimit[RLIMIT_RSS].rlim_cur : 0;
1268 }
1269 
1270 /*
1271  * Fill in a kproc2 structure for the specified process.
1272  */
1273 void
fill_kproc2(struct proc * p,struct kinfo_proc2 * ki)1274 fill_kproc2(struct proc *p, struct kinfo_proc2 *ki)
1275 {
1276 	struct tty *tp;
1277 	struct timeval ut, st;
1278 
1279 	bzero(ki, sizeof(*ki));
1280 
1281 	ki->p_paddr = PTRTOINT64(p);
1282 	ki->p_fd = PTRTOINT64(p->p_fd);
1283 	ki->p_stats = PTRTOINT64(p->p_stats);
1284 	ki->p_limit = PTRTOINT64(p->p_limit);
1285 	ki->p_vmspace = PTRTOINT64(p->p_vmspace);
1286 	ki->p_sigacts = PTRTOINT64(p->p_sigacts);
1287 	ki->p_sess = PTRTOINT64(p->p_session);
1288 	ki->p_tsess = 0;	/* may be changed if controlling tty below */
1289 	ki->p_ru = PTRTOINT64(p->p_ru);
1290 
1291 	ki->p_eflag = 0;
1292 	ki->p_exitsig = p->p_exitsig;
1293 	ki->p_flag = p->p_flag;
1294 
1295 	ki->p_pid = p->p_pid;
1296 	if (p->p_pptr)
1297 		ki->p_ppid = p->p_pptr->p_pid;
1298 	else
1299 		ki->p_ppid = 0;
1300 	if (p->p_session->s_leader)
1301 		ki->p_sid = p->p_session->s_leader->p_pid;
1302 	else
1303 		ki->p_sid = 0;
1304 	ki->p__pgid = p->p_pgrp->pg_id;
1305 
1306 	ki->p_tpgid = -1;	/* may be changed if controlling tty below */
1307 
1308 	ki->p_uid = p->p_ucred->cr_uid;
1309 	ki->p_ruid = p->p_cred->p_ruid;
1310 	ki->p_gid = p->p_ucred->cr_gid;
1311 	ki->p_rgid = p->p_cred->p_rgid;
1312 	ki->p_svuid = p->p_cred->p_svuid;
1313 	ki->p_svgid = p->p_cred->p_svgid;
1314 
1315 	memcpy(ki->p_groups, p->p_cred->pc_ucred->cr_groups,
1316 	    min(sizeof(ki->p_groups), sizeof(p->p_cred->pc_ucred->cr_groups)));
1317 	ki->p_ngroups = p->p_cred->pc_ucred->cr_ngroups;
1318 
1319 	ki->p_jobc = p->p_pgrp->pg_jobc;
1320 	if ((p->p_flag & P_CONTROLT) && (tp = p->p_session->s_ttyp)) {
1321 		ki->p_tdev = tp->t_dev;
1322 		ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : -1;
1323 		ki->p_tsess = PTRTOINT64(tp->t_session);
1324 	} else {
1325 		ki->p_tdev = NODEV;
1326 	}
1327 
1328 	ki->p_estcpu = p->p_estcpu;
1329 	ki->p_rtime_sec = p->p_rtime.tv_sec;
1330 	ki->p_rtime_usec = p->p_rtime.tv_usec;
1331 	ki->p_cpticks = p->p_cpticks;
1332 	ki->p_pctcpu = p->p_pctcpu;
1333 
1334 	ki->p_uticks = p->p_uticks;
1335 	ki->p_sticks = p->p_sticks;
1336 	ki->p_iticks = p->p_iticks;
1337 
1338 	ki->p_tracep = PTRTOINT64(p->p_tracep);
1339 	ki->p_traceflag = p->p_traceflag;
1340 
1341 	ki->p_siglist = p->p_siglist;
1342 	ki->p_sigmask = p->p_sigmask;
1343 	ki->p_sigignore = p->p_sigignore;
1344 	ki->p_sigcatch = p->p_sigcatch;
1345 
1346 	ki->p_stat = p->p_stat;
1347 	ki->p_nice = p->p_nice;
1348 
1349 	ki->p_xstat = p->p_xstat;
1350 	ki->p_acflag = p->p_acflag;
1351 
1352 	strlcpy(ki->p_emul, p->p_emul->e_name, sizeof(ki->p_emul));
1353 	strlcpy(ki->p_comm, p->p_comm, sizeof(ki->p_comm));
1354 	strncpy(ki->p_login, p->p_session->s_login,
1355 	    min(sizeof(ki->p_login) - 1, sizeof(p->p_session->s_login)));
1356 
1357 	if (p->p_stat == SIDL || P_ZOMBIE(p)) {
1358 		ki->p_vm_rssize = 0;
1359 		ki->p_vm_tsize = 0;
1360 		ki->p_vm_dsize = 0;
1361 		ki->p_vm_ssize = 0;
1362 	} else {
1363 		struct vmspace *vm = p->p_vmspace;
1364 
1365 		ki->p_vm_rssize = vm_resident_count(vm);
1366 		ki->p_vm_tsize = vm->vm_tsize;
1367 		ki->p_vm_dsize = vm->vm_dsize;
1368 		ki->p_vm_ssize = vm->vm_ssize;
1369 
1370 		ki->p_forw = PTRTOINT64(p->p_forw);
1371 		ki->p_back = PTRTOINT64(p->p_back);
1372 		ki->p_addr = PTRTOINT64(p->p_addr);
1373 		ki->p_stat = p->p_stat;
1374 		ki->p_swtime = p->p_swtime;
1375 		ki->p_slptime = p->p_slptime;
1376 #ifdef __HAVE_CPUINFO
1377 		ki->p_schedflags = 0;
1378 #else
1379 		ki->p_schedflags = p->p_schedflags;
1380 #endif
1381 		ki->p_holdcnt = p->p_holdcnt;
1382 		ki->p_priority = p->p_priority;
1383 		ki->p_usrpri = p->p_usrpri;
1384 		if (p->p_wmesg)
1385 			strlcpy(ki->p_wmesg, p->p_wmesg, sizeof(ki->p_wmesg));
1386 		ki->p_wchan = PTRTOINT64(p->p_wchan);
1387 
1388 	}
1389 
1390 	if (p->p_session->s_ttyvp)
1391 		ki->p_eflag |= EPROC_CTTY;
1392 	if (SESS_LEADER(p))
1393 		ki->p_eflag |= EPROC_SLEADER;
1394 	if (p->p_rlimit)
1395 		ki->p_rlim_rss_cur = p->p_rlimit[RLIMIT_RSS].rlim_cur;
1396 
1397 	/* XXX Is this double check necessary? */
1398 	if (P_ZOMBIE(p)) {
1399 		ki->p_uvalid = 0;
1400 	} else {
1401 		ki->p_uvalid = 1;
1402 
1403 		PHOLD(p);	/* need for pstats */
1404 		ki->p_ustart_sec = p->p_stats->p_start.tv_sec;
1405 		ki->p_ustart_usec = p->p_stats->p_start.tv_usec;
1406 
1407 		calcru(p, &ut, &st, 0);
1408 		ki->p_uutime_sec = ut.tv_sec;
1409 		ki->p_uutime_usec = ut.tv_usec;
1410 		ki->p_ustime_sec = st.tv_sec;
1411 		ki->p_ustime_usec = st.tv_usec;
1412 
1413 		ki->p_uru_maxrss = p->p_stats->p_ru.ru_maxrss;
1414 		ki->p_uru_ixrss = p->p_stats->p_ru.ru_ixrss;
1415 		ki->p_uru_idrss = p->p_stats->p_ru.ru_idrss;
1416 		ki->p_uru_isrss = p->p_stats->p_ru.ru_isrss;
1417 		ki->p_uru_minflt = p->p_stats->p_ru.ru_minflt;
1418 		ki->p_uru_majflt = p->p_stats->p_ru.ru_majflt;
1419 		ki->p_uru_nswap = p->p_stats->p_ru.ru_nswap;
1420 		ki->p_uru_inblock = p->p_stats->p_ru.ru_inblock;
1421 		ki->p_uru_oublock = p->p_stats->p_ru.ru_oublock;
1422 		ki->p_uru_msgsnd = p->p_stats->p_ru.ru_msgsnd;
1423 		ki->p_uru_msgrcv = p->p_stats->p_ru.ru_msgrcv;
1424 		ki->p_uru_nsignals = p->p_stats->p_ru.ru_nsignals;
1425 		ki->p_uru_nvcsw = p->p_stats->p_ru.ru_nvcsw;
1426 		ki->p_uru_nivcsw = p->p_stats->p_ru.ru_nivcsw;
1427 
1428 		timeradd(&p->p_stats->p_cru.ru_utime,
1429 			 &p->p_stats->p_cru.ru_stime, &ut);
1430 		ki->p_uctime_sec = ut.tv_sec;
1431 		ki->p_uctime_usec = ut.tv_usec;
1432 		PRELE(p);
1433 	}
1434 }
1435 
1436 int
sysctl_proc_args(int * name,u_int namelen,void * oldp,size_t * oldlenp,struct proc * cp)1437 sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1438     struct proc *cp)
1439 {
1440 	struct proc *vp, *cur = curproc;
1441 	pid_t pid;
1442 	int op;
1443 	struct ps_strings pss;
1444 	struct iovec iov;
1445 	struct uio uio;
1446 	int error;
1447 	size_t limit;
1448 	int cnt;
1449 	char **rargv, **vargv;		/* reader vs. victim */
1450 	char *rarg, *varg;
1451 	char *buf;
1452 
1453 	if (namelen > 2)
1454 		return (ENOTDIR);
1455 	if (namelen < 2)
1456 		return (EINVAL);
1457 
1458 	pid = name[0];
1459 	op = name[1];
1460 
1461 	switch (op) {
1462 	case KERN_PROC_ARGV:
1463 	case KERN_PROC_NARGV:
1464 	case KERN_PROC_ENV:
1465 	case KERN_PROC_NENV:
1466 		break;
1467 	default:
1468 		return (EOPNOTSUPP);
1469 	}
1470 
1471 	if ((vp = pfind(pid)) == NULL)
1472 		return (ESRCH);
1473 
1474 	if ((!allowpse) &&
1475 	    (cur->p_cred->p_ruid != vp->p_cred->p_ruid) &&
1476 	    (cur->p_cred->p_rgid))
1477 		return (EPERM);
1478 
1479 	if (oldp == NULL) {
1480 		if (op == KERN_PROC_NARGV || op == KERN_PROC_NENV)
1481 			*oldlenp = sizeof(int);
1482 		else
1483 			*oldlenp = ARG_MAX;	/* XXX XXX XXX */
1484 		return (0);
1485 	}
1486 
1487 	if (P_ZOMBIE(vp) || (vp->p_flag & P_SYSTEM))
1488 		return (EINVAL);
1489 
1490 	/* Exiting - don't bother, it will be gone soon anyway */
1491 	if ((vp->p_flag & P_WEXIT))
1492 		return (ESRCH);
1493 
1494 	/* Execing - danger. */
1495 	if ((vp->p_flag & P_INEXEC))
1496 		return (EBUSY);
1497 
1498 	vp->p_vmspace->vm_refcnt++;	/* XXX */
1499 	buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
1500 
1501 	iov.iov_base = &pss;
1502 	iov.iov_len = sizeof(pss);
1503 	uio.uio_iov = &iov;
1504 	uio.uio_iovcnt = 1;
1505 	uio.uio_offset = (off_t)PS_STRINGS;
1506 	uio.uio_resid = sizeof(pss);
1507 	uio.uio_segflg = UIO_SYSSPACE;
1508 	uio.uio_rw = UIO_READ;
1509 	uio.uio_procp = cp;
1510 
1511 	if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0)
1512 		goto out;
1513 
1514 	if (op == KERN_PROC_NARGV) {
1515 		error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr);
1516 		goto out;
1517 	}
1518 	if (op == KERN_PROC_NENV) {
1519 		error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr);
1520 		goto out;
1521 	}
1522 
1523 	if (op == KERN_PROC_ARGV) {
1524 		cnt = pss.ps_nargvstr;
1525 		vargv = pss.ps_argvstr;
1526 	} else {
1527 		cnt = pss.ps_nenvstr;
1528 		vargv = pss.ps_envstr;
1529 	}
1530 
1531 	/* -1 to have space for a terminating NUL */
1532 	limit = *oldlenp - 1;
1533 	*oldlenp = 0;
1534 
1535 	rargv = oldp;
1536 
1537 	/*
1538 	 * *oldlenp - number of bytes copied out into readers buffer.
1539 	 * limit - maximal number of bytes allowed into readers buffer.
1540 	 * rarg - pointer into readers buffer where next arg will be stored.
1541 	 * rargv - pointer into readers buffer where the next rarg pointer
1542 	 *  will be stored.
1543 	 * vargv - pointer into victim address space where the next argument
1544 	 *  will be read.
1545 	 */
1546 
1547 	/* space for cnt pointers and a NULL */
1548 	rarg = (char *)(rargv + cnt + 1);
1549 	*oldlenp += (cnt + 1) * sizeof(char **);
1550 
1551 	while (cnt > 0 && *oldlenp < limit) {
1552 		size_t len, vstrlen;
1553 
1554 		/* Write to readers argv */
1555 		if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0)
1556 			goto out;
1557 
1558 		/* read the victim argv */
1559 		iov.iov_base = &varg;
1560 		iov.iov_len = sizeof(varg);
1561 		uio.uio_iov = &iov;
1562 		uio.uio_iovcnt = 1;
1563 		uio.uio_offset = (off_t)(vaddr_t)vargv;
1564 		uio.uio_resid = sizeof(varg);
1565 		uio.uio_segflg = UIO_SYSSPACE;
1566 		uio.uio_rw = UIO_READ;
1567 		uio.uio_procp = cp;
1568 		if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0)
1569 			goto out;
1570 
1571 		if (varg == NULL)
1572 			break;
1573 
1574 		/*
1575 		 * read the victim arg. We must jump through hoops to avoid
1576 		 * crossing a page boundary too much and returning an error.
1577 		 */
1578 more:
1579 		len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK);
1580 		/* leave space for the terminating NUL */
1581 		iov.iov_base = buf;
1582 		iov.iov_len = len;
1583 		uio.uio_iov = &iov;
1584 		uio.uio_iovcnt = 1;
1585 		uio.uio_offset = (off_t)(vaddr_t)varg;
1586 		uio.uio_resid = len;
1587 		uio.uio_segflg = UIO_SYSSPACE;
1588 		uio.uio_rw = UIO_READ;
1589 		uio.uio_procp = cp;
1590 		if ((error = uvm_io(&vp->p_vmspace->vm_map, &uio)) != 0)
1591 			goto out;
1592 
1593 		for (vstrlen = 0; vstrlen < len; vstrlen++) {
1594 			if (buf[vstrlen] == '\0')
1595 				break;
1596 		}
1597 
1598 		/* Don't overflow readers buffer. */
1599 		if (*oldlenp + vstrlen + 1 >= limit) {
1600 			error = ENOMEM;
1601 			goto out;
1602 		}
1603 
1604 		if ((error = copyout(buf, rarg, vstrlen)) != 0)
1605 			goto out;
1606 
1607 		*oldlenp += vstrlen;
1608 		rarg += vstrlen;
1609 
1610 		/* The string didn't end in this page? */
1611 		if (vstrlen == len) {
1612 			varg += vstrlen;
1613 			goto more;
1614 		}
1615 
1616 		/* End of string. Terminate it with a NUL */
1617 		buf[0] = '\0';
1618 		if ((error = copyout(buf, rarg, 1)) != 0)
1619 			goto out;
1620 		*oldlenp += 1;
1621 		rarg += 1;
1622 
1623 		vargv++;
1624 		rargv++;
1625 		cnt--;
1626 	}
1627 
1628 	if (*oldlenp >= limit) {
1629 		error = ENOMEM;
1630 		goto out;
1631 	}
1632 
1633 	/* Write the terminating null */
1634 	rarg = NULL;
1635 	error = copyout(&rarg, rargv, sizeof(rarg));
1636 
1637 out:
1638 	uvmspace_free(vp->p_vmspace);
1639 	free(buf, M_TEMP);
1640 	return (error);
1641 }
1642 
1643 /*
1644  * Initialize disknames/diskstats for export by sysctl. If update is set,
1645  * then we simply update the disk statistics information.
1646  */
1647 int
sysctl_diskinit(update,p)1648 sysctl_diskinit(update, p)
1649 	int update;
1650 	struct proc *p;
1651 {
1652 	struct diskstats *sdk;
1653 	struct disk *dk;
1654 	int i, tlen, l;
1655 
1656 	if ((i = lockmgr(&sysctl_disklock, LK_EXCLUSIVE, NULL, p)) != 0)
1657 		return i;
1658 
1659 	if (disk_change) {
1660 		for (dk = TAILQ_FIRST(&disklist), tlen = 0; dk;
1661 		    dk = TAILQ_NEXT(dk, dk_link))
1662 			tlen += strlen(dk->dk_name) + 1;
1663 		tlen++;
1664 
1665 		if (disknames)
1666 			free(disknames, M_SYSCTL);
1667 		if (diskstats)
1668 			free(diskstats, M_SYSCTL);
1669 		diskstats = NULL;
1670 		disknames = NULL;
1671 		diskstats = malloc(disk_count * sizeof(struct diskstats),
1672 		    M_SYSCTL, M_WAITOK);
1673 		disknames = malloc(tlen, M_SYSCTL, M_WAITOK);
1674 		disknames[0] = '\0';
1675 
1676 		for (dk = TAILQ_FIRST(&disklist), i = 0, l = 0; dk;
1677 		    dk = TAILQ_NEXT(dk, dk_link), i++) {
1678 			snprintf(disknames + l, tlen - l, "%s,",
1679 			    dk->dk_name ? dk->dk_name : "");
1680 			l += strlen(disknames + l);
1681 			sdk = diskstats + i;
1682 			strlcpy(sdk->ds_name, dk->dk_name,
1683 			    sizeof(sdk->ds_name));
1684 			sdk->ds_busy = dk->dk_busy;
1685 			sdk->ds_rxfer = dk->dk_rxfer;
1686 			sdk->ds_wxfer = dk->dk_wxfer;
1687 			sdk->ds_seek = dk->dk_seek;
1688 			sdk->ds_rbytes = dk->dk_rbytes;
1689 			sdk->ds_wbytes = dk->dk_wbytes;
1690 			sdk->ds_attachtime = dk->dk_attachtime;
1691 			sdk->ds_timestamp = dk->dk_timestamp;
1692 			sdk->ds_time = dk->dk_time;
1693 		}
1694 
1695 		/* Eliminate trailing comma */
1696 		if (l != 0)
1697 			disknames[l - 1] = '\0';
1698 		disk_change = 0;
1699 	} else if (update) {
1700 		/* Just update, number of drives hasn't changed */
1701 		for (dk = TAILQ_FIRST(&disklist), i = 0; dk;
1702 		    dk = TAILQ_NEXT(dk, dk_link), i++) {
1703 			sdk = diskstats + i;
1704 			strlcpy(sdk->ds_name, dk->dk_name,
1705 			    sizeof(sdk->ds_name));
1706 			sdk->ds_busy = dk->dk_busy;
1707 			sdk->ds_rxfer = dk->dk_rxfer;
1708 			sdk->ds_wxfer = dk->dk_wxfer;
1709 			sdk->ds_seek = dk->dk_seek;
1710 			sdk->ds_rbytes = dk->dk_rbytes;
1711 			sdk->ds_wbytes = dk->dk_wbytes;
1712 			sdk->ds_attachtime = dk->dk_attachtime;
1713 			sdk->ds_timestamp = dk->dk_timestamp;
1714 			sdk->ds_time = dk->dk_time;
1715 		}
1716 	}
1717 	lockmgr(&sysctl_disklock, LK_RELEASE, NULL, p);
1718 	return 0;
1719 }
1720 
1721 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
1722 int
sysctl_sysvipc(name,namelen,where,sizep)1723 sysctl_sysvipc(name, namelen, where, sizep)
1724 	int *name;
1725 	u_int namelen;
1726 	void *where;
1727 	size_t *sizep;
1728 {
1729 #ifdef SYSVMSG
1730 	struct msg_sysctl_info *msgsi = NULL;
1731 #endif
1732 #ifdef SYSVSEM
1733 	struct sem_sysctl_info *semsi = NULL;
1734 #endif
1735 #ifdef SYSVSHM
1736 	struct shm_sysctl_info *shmsi = NULL;
1737 #endif
1738 	size_t infosize, dssize, tsize, buflen;
1739 	int i, nds, error, ret;
1740 	void *buf;
1741 
1742 	if (namelen != 1)
1743 		return (EINVAL);
1744 
1745 	buflen = *sizep;
1746 
1747 	switch (*name) {
1748 	case KERN_SYSVIPC_MSG_INFO:
1749 #ifdef SYSVMSG
1750 		infosize = sizeof(msgsi->msginfo);
1751 		nds = msginfo.msgmni;
1752 		dssize = sizeof(msgsi->msgids[0]);
1753 		break;
1754 #else
1755 		return (EOPNOTSUPP);
1756 #endif
1757 	case KERN_SYSVIPC_SEM_INFO:
1758 #ifdef SYSVSEM
1759 		infosize = sizeof(semsi->seminfo);
1760 		nds = seminfo.semmni;
1761 		dssize = sizeof(semsi->semids[0]);
1762 		break;
1763 #else
1764 		return (EOPNOTSUPP);
1765 #endif
1766 	case KERN_SYSVIPC_SHM_INFO:
1767 #ifdef SYSVSHM
1768 		infosize = sizeof(shmsi->shminfo);
1769 		nds = shminfo.shmmni;
1770 		dssize = sizeof(shmsi->shmids[0]);
1771 		break;
1772 #else
1773 		return (EOPNOTSUPP);
1774 #endif
1775 	default:
1776 		return (EINVAL);
1777 	}
1778 	tsize = infosize + (nds * dssize);
1779 
1780 	/* Return just the total size required. */
1781 	if (where == NULL) {
1782 		*sizep = tsize;
1783 		return (0);
1784 	}
1785 
1786 	/* Not enough room for even the info struct. */
1787 	if (buflen < infosize) {
1788 		*sizep = 0;
1789 		return (ENOMEM);
1790 	}
1791 	buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK);
1792 	bzero(buf, min(tsize, buflen));
1793 
1794 	switch (*name) {
1795 #ifdef SYSVMSG
1796 	case KERN_SYSVIPC_MSG_INFO:
1797 		msgsi = (struct msg_sysctl_info *)buf;
1798 		msgsi->msginfo = msginfo;
1799 		break;
1800 #endif
1801 #ifdef SYSVSEM
1802 	case KERN_SYSVIPC_SEM_INFO:
1803 		semsi = (struct sem_sysctl_info *)buf;
1804 		semsi->seminfo = seminfo;
1805 		break;
1806 #endif
1807 #ifdef SYSVSHM
1808 	case KERN_SYSVIPC_SHM_INFO:
1809 		shmsi = (struct shm_sysctl_info *)buf;
1810 		shmsi->shminfo = shminfo;
1811 		break;
1812 #endif
1813 	}
1814 	buflen -= infosize;
1815 
1816 	ret = 0;
1817 	if (buflen > 0) {
1818 		/* Fill in the IPC data structures.  */
1819 		for (i = 0; i < nds; i++) {
1820 			if (buflen < dssize) {
1821 				ret = ENOMEM;
1822 				break;
1823 			}
1824 			switch (*name) {
1825 #ifdef SYSVMSG
1826 			case KERN_SYSVIPC_MSG_INFO:
1827 				bcopy(&msqids[i], &msgsi->msgids[i], dssize);
1828 				break;
1829 #endif
1830 #ifdef SYSVSEM
1831 			case KERN_SYSVIPC_SEM_INFO:
1832 				if (sema[i] != NULL)
1833 					bcopy(sema[i], &semsi->semids[i],
1834 					    dssize);
1835 				else
1836 					bzero(&semsi->semids[i], dssize);
1837 				break;
1838 #endif
1839 #ifdef SYSVSHM
1840 			case KERN_SYSVIPC_SHM_INFO:
1841 				if (shmsegs[i] != NULL)
1842 					bcopy(shmsegs[i], &shmsi->shmids[i],
1843 					    dssize);
1844 				else
1845 					bzero(&shmsi->shmids[i], dssize);
1846 				break;
1847 #endif
1848 			}
1849 			buflen -= dssize;
1850 		}
1851 	}
1852 	*sizep -= buflen;
1853 	error = copyout(buf, where, *sizep);
1854 	free(buf, M_TEMP);
1855 	/* If copyout succeeded, use return code set earlier. */
1856 	return (error ? error : ret);
1857 }
1858 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */
1859 
1860 int
sysctl_intrcnt(int * name,u_int namelen,void * oldp,size_t * oldlenp)1861 sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp)
1862 {
1863 #ifdef __HAVE_EVCOUNT
1864 	return (evcount_sysctl(name, namelen, oldp, oldlenp, NULL, 0));
1865 #else
1866 	extern int intrcnt[], eintrcnt[];
1867 	extern char intrnames[], eintrnames[];
1868 	char *intrname;
1869 	int nintr, i;
1870 
1871 	nintr = (off_t)(eintrcnt - intrcnt);
1872 
1873 	if (name[0] != KERN_INTRCNT_NUM) {
1874 		if (namelen != 2)
1875 			return (ENOTDIR);
1876 		if (name[1] < 0 || name[1] >= nintr)
1877 			return (EINVAL);
1878 		i = name[1];
1879 	}
1880 
1881 	switch (name[0]) {
1882 	case KERN_INTRCNT_NUM:
1883 		return (sysctl_rdint(oldp, oldlenp, NULL, nintr));
1884 		break;
1885 	case KERN_INTRCNT_CNT:
1886 		return (sysctl_rdquad(oldp, oldlenp, NULL, intrcnt[i]));
1887 	case KERN_INTRCNT_NAME:
1888 		intrname = intrnames;
1889 		while (i > 0) {
1890 			intrname += strlen(intrname) + 1;
1891 			i--;
1892 			if (intrname > eintrnames)
1893 				return (EINVAL);
1894 		}
1895 		return (sysctl_rdstring(oldp, oldlenp, NULL, intrname));
1896 	default:
1897 		return (EOPNOTSUPP);
1898 	}
1899 #endif
1900 }
1901 
1902 int nsensors = 0;
1903 struct sensors_head sensors = SLIST_HEAD_INITIALIZER(&sensors);
1904 
1905 int
sysctl_sensors(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)1906 sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1907     void *newp, size_t newlen)
1908 {
1909 	struct sensor *s = NULL;
1910 	int num;
1911 
1912 	if (namelen != 1)
1913 		return (ENOTDIR);
1914 
1915 	num = name[0];
1916 	if (num < 0 || num >= nsensors)
1917 		return (ENXIO);
1918 
1919 	SLIST_FOREACH(s, &sensors, list)
1920 		if (s->num == num)
1921 			break;
1922 
1923 	return (sysctl_rdstruct(oldp, oldlenp, newp, s, sizeof(struct sensor)));
1924 }
1925 
1926 int
sysctl_emul(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)1927 sysctl_emul(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1928     void *newp, size_t newlen)
1929 {
1930 	int enabled, error;
1931 	struct emul *e;
1932 
1933 	if (name[0] == KERN_EMUL_NUM) {
1934 		if (namelen != 1)
1935 			return (ENOTDIR);
1936 		return (sysctl_rdint(oldp, oldlenp, newp, nexecs));
1937 	}
1938 
1939 	if (namelen != 2)
1940 		return (ENOTDIR);
1941 	if (name[0] > nexecs || name[0] < 0)
1942 		return (EINVAL);
1943 	e = execsw[name[0] - 1].es_emul;
1944 	if (e == NULL)
1945 		return (EINVAL);
1946 
1947 	switch (name[1]) {
1948 	case KERN_EMUL_NAME:
1949 		return (sysctl_rdstring(oldp, oldlenp, newp, e->e_name));
1950 	case KERN_EMUL_ENABLED:
1951 		enabled = (e->e_flags & EMUL_ENABLED);
1952 		error = sysctl_int(oldp, oldlenp, newp, newlen,
1953 		    &enabled);
1954 		e->e_flags = (enabled & EMUL_ENABLED);
1955 		return (error);
1956 	default:
1957 		return (EINVAL);
1958 	}
1959 }
1960 
1961 /* should be last because of declarations */
1962 void
sysctl_init_values(void)1963 sysctl_init_values(void)
1964 {
1965 	strlcpy(emul_uname, ostype, MAXEMULUNAMELEN);
1966 }
1967