1 /* $OpenBSD: kern_sysctl.c,v 1.427 2024/04/12 16:07:09 bluhm Exp $ */
2 /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
3
4 /*-
5 * Copyright (c) 1982, 1986, 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Mike Karels at Berkeley Software Design, Inc.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94
36 */
37
38 /*
39 * sysctl system call.
40 */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/malloc.h>
46 #include <sys/pool.h>
47 #include <sys/proc.h>
48 #include <sys/resourcevar.h>
49 #include <sys/signalvar.h>
50 #include <sys/fcntl.h>
51 #include <sys/file.h>
52 #include <sys/filedesc.h>
53 #include <sys/vnode.h>
54 #include <sys/unistd.h>
55 #include <sys/buf.h>
56 #include <sys/clockintr.h>
57 #include <sys/tty.h>
58 #include <sys/disklabel.h>
59 #include <sys/disk.h>
60 #include <sys/sysctl.h>
61 #include <sys/msgbuf.h>
62 #include <sys/vmmeter.h>
63 #include <sys/namei.h>
64 #include <sys/exec.h>
65 #include <sys/mbuf.h>
66 #include <sys/percpu.h>
67 #include <sys/sensors.h>
68 #include <sys/pipe.h>
69 #include <sys/eventvar.h>
70 #include <sys/socketvar.h>
71 #include <sys/socket.h>
72 #include <sys/domain.h>
73 #include <sys/protosw.h>
74 #include <sys/pledge.h>
75 #include <sys/timetc.h>
76 #include <sys/evcount.h>
77 #include <sys/un.h>
78 #include <sys/unpcb.h>
79 #include <sys/sched.h>
80 #include <sys/mount.h>
81 #include <sys/syscallargs.h>
82 #include <sys/wait.h>
83 #include <sys/witness.h>
84
85 #include <uvm/uvm_extern.h>
86
87 #include <dev/cons.h>
88
89 #include <dev/usb/ucomvar.h>
90
91 #include <net/route.h>
92 #include <netinet/in.h>
93 #include <netinet/ip.h>
94 #include <netinet/ip_var.h>
95 #include <netinet/in_pcb.h>
96 #include <netinet/ip6.h>
97 #include <netinet/tcp.h>
98 #include <netinet/tcp_timer.h>
99 #include <netinet/tcp_var.h>
100 #include <netinet/udp.h>
101 #include <netinet/udp_var.h>
102 #include <netinet6/ip6_var.h>
103
104 #ifdef DDB
105 #include <ddb/db_var.h>
106 #endif
107
108 #ifdef SYSVMSG
109 #include <sys/msg.h>
110 #endif
111 #ifdef SYSVSEM
112 #include <sys/sem.h>
113 #endif
114 #ifdef SYSVSHM
115 #include <sys/shm.h>
116 #endif
117
118 #include "audio.h"
119 #include "dt.h"
120 #include "pf.h"
121 #include "ucom.h"
122 #include "video.h"
123
124 extern struct forkstat forkstat;
125 extern struct nchstats nchstats;
126 extern int fscale;
127 extern fixpt_t ccpu;
128 extern long numvnodes;
129 extern int allowdt;
130 extern int audio_record_enable;
131 extern int video_record_enable;
132 extern int autoconf_serial;
133
134 int allowkmem;
135
136 int sysctl_diskinit(int, struct proc *);
137 int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *);
138 int sysctl_proc_cwd(int *, u_int, void *, size_t *, struct proc *);
139 int sysctl_proc_nobroadcastkill(int *, u_int, void *, size_t, void *, size_t *,
140 struct proc *);
141 int sysctl_proc_vmmap(int *, u_int, void *, size_t *, struct proc *);
142 int sysctl_intrcnt(int *, u_int, void *, size_t *);
143 int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t);
144 int sysctl_cptime2(int *, u_int, void *, size_t *, void *, size_t);
145 int sysctl_audio(int *, u_int, void *, size_t *, void *, size_t);
146 int sysctl_video(int *, u_int, void *, size_t *, void *, size_t);
147 int sysctl_cpustats(int *, u_int, void *, size_t *, void *, size_t);
148 int sysctl_utc_offset(void *, size_t *, void *, size_t);
149 int sysctl_hwbattery(int *, u_int, void *, size_t *, void *, size_t);
150
151 void fill_file(struct kinfo_file *, struct file *, struct filedesc *, int,
152 struct vnode *, struct process *, struct proc *, struct socket *, int);
153 void fill_kproc(struct process *, struct kinfo_proc *, struct proc *, int);
154
155 int (*cpu_cpuspeed)(int *);
156
157 /*
158 * Lock to avoid too many processes vslocking a large amount of memory
159 * at the same time.
160 */
161 struct rwlock sysctl_lock = RWLOCK_INITIALIZER("sysctllk");
162 struct rwlock sysctl_disklock = RWLOCK_INITIALIZER("sysctldlk");
163
164 int
sys_sysctl(struct proc * p,void * v,register_t * retval)165 sys_sysctl(struct proc *p, void *v, register_t *retval)
166 {
167 struct sys_sysctl_args /* {
168 syscallarg(const int *) name;
169 syscallarg(u_int) namelen;
170 syscallarg(void *) old;
171 syscallarg(size_t *) oldlenp;
172 syscallarg(void *) new;
173 syscallarg(size_t) newlen;
174 } */ *uap = v;
175 int error, dolock = 1;
176 size_t savelen = 0, oldlen = 0;
177 sysctlfn *fn;
178 int name[CTL_MAXNAME];
179
180 if (SCARG(uap, new) != NULL &&
181 (error = suser(p)))
182 return (error);
183 /*
184 * all top-level sysctl names are non-terminal
185 */
186 if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2)
187 return (EINVAL);
188 error = copyin(SCARG(uap, name), name,
189 SCARG(uap, namelen) * sizeof(int));
190 if (error)
191 return (error);
192
193 error = pledge_sysctl(p, SCARG(uap, namelen),
194 name, SCARG(uap, new));
195 if (error)
196 return (error);
197
198 switch (name[0]) {
199 case CTL_KERN:
200 fn = kern_sysctl;
201 break;
202 case CTL_HW:
203 fn = hw_sysctl;
204 break;
205 case CTL_VM:
206 fn = uvm_sysctl;
207 break;
208 case CTL_NET:
209 fn = net_sysctl;
210 break;
211 case CTL_FS:
212 fn = fs_sysctl;
213 break;
214 case CTL_VFS:
215 fn = vfs_sysctl;
216 break;
217 case CTL_MACHDEP:
218 fn = cpu_sysctl;
219 break;
220 #ifdef DEBUG_SYSCTL
221 case CTL_DEBUG:
222 fn = debug_sysctl;
223 break;
224 #endif
225 #ifdef DDB
226 case CTL_DDB:
227 fn = ddb_sysctl;
228 break;
229 #endif
230 default:
231 return (EOPNOTSUPP);
232 }
233
234 if (SCARG(uap, oldlenp) &&
235 (error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
236 return (error);
237 if (SCARG(uap, old) != NULL) {
238 if ((error = rw_enter(&sysctl_lock, RW_WRITE|RW_INTR)) != 0)
239 return (error);
240 if (dolock) {
241 if (atop(oldlen) > uvmexp.wiredmax - uvmexp.wired) {
242 rw_exit_write(&sysctl_lock);
243 return (ENOMEM);
244 }
245 error = uvm_vslock(p, SCARG(uap, old), oldlen,
246 PROT_READ | PROT_WRITE);
247 if (error) {
248 rw_exit_write(&sysctl_lock);
249 return (error);
250 }
251 }
252 savelen = oldlen;
253 }
254 error = (*fn)(&name[1], SCARG(uap, namelen) - 1, SCARG(uap, old),
255 &oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
256 if (SCARG(uap, old) != NULL) {
257 if (dolock)
258 uvm_vsunlock(p, SCARG(uap, old), savelen);
259 rw_exit_write(&sysctl_lock);
260 }
261 if (error)
262 return (error);
263 if (SCARG(uap, oldlenp))
264 error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen));
265 return (error);
266 }
267
268 /*
269 * Attributes stored in the kernel.
270 */
271 char hostname[MAXHOSTNAMELEN];
272 int hostnamelen;
273 char domainname[MAXHOSTNAMELEN];
274 int domainnamelen;
275 long hostid;
276 char *disknames = NULL;
277 size_t disknameslen;
278 struct diskstats *diskstats = NULL;
279 size_t diskstatslen;
280 int securelevel;
281
282 /* morally const values reported by sysctl_bounded_arr */
283 static int arg_max = ARG_MAX;
284 static int openbsd = OpenBSD;
285 static int posix_version = _POSIX_VERSION;
286 static int ngroups_max = NGROUPS_MAX;
287 static int int_zero = 0;
288 static int int_one = 1;
289 static int maxpartitions = MAXPARTITIONS;
290 static int raw_part = RAW_PART;
291
292 extern int somaxconn, sominconn;
293 extern int nosuidcoredump;
294 extern int maxlocksperuid;
295 extern int uvm_wxabort;
296 extern int global_ptrace;
297
298 const struct sysctl_bounded_args kern_vars[] = {
299 {KERN_OSREV, &openbsd, SYSCTL_INT_READONLY},
300 {KERN_MAXVNODES, &maxvnodes, 0, INT_MAX},
301 {KERN_MAXPROC, &maxprocess, 0, INT_MAX},
302 {KERN_MAXFILES, &maxfiles, 0, INT_MAX},
303 {KERN_NFILES, &numfiles, SYSCTL_INT_READONLY},
304 {KERN_TTYCOUNT, &tty_count, SYSCTL_INT_READONLY},
305 {KERN_ARGMAX, &arg_max, SYSCTL_INT_READONLY},
306 {KERN_POSIX1, &posix_version, SYSCTL_INT_READONLY},
307 {KERN_NGROUPS, &ngroups_max, SYSCTL_INT_READONLY},
308 {KERN_JOB_CONTROL, &int_one, SYSCTL_INT_READONLY},
309 {KERN_SAVED_IDS, &int_one, SYSCTL_INT_READONLY},
310 {KERN_MAXPARTITIONS, &maxpartitions, SYSCTL_INT_READONLY},
311 {KERN_RAWPARTITION, &raw_part, SYSCTL_INT_READONLY},
312 {KERN_MAXTHREAD, &maxthread, 0, INT_MAX},
313 {KERN_NTHREADS, &nthreads, SYSCTL_INT_READONLY},
314 {KERN_SOMAXCONN, &somaxconn, 0, SHRT_MAX},
315 {KERN_SOMINCONN, &sominconn, 0, SHRT_MAX},
316 {KERN_NOSUIDCOREDUMP, &nosuidcoredump, 0, 3},
317 {KERN_FSYNC, &int_one, SYSCTL_INT_READONLY},
318 {KERN_SYSVMSG,
319 #ifdef SYSVMSG
320 &int_one,
321 #else
322 &int_zero,
323 #endif
324 SYSCTL_INT_READONLY},
325 {KERN_SYSVSEM,
326 #ifdef SYSVSEM
327 &int_one,
328 #else
329 &int_zero,
330 #endif
331 SYSCTL_INT_READONLY},
332 {KERN_SYSVSHM,
333 #ifdef SYSVSHM
334 &int_one,
335 #else
336 &int_zero,
337 #endif
338 SYSCTL_INT_READONLY},
339 {KERN_FSCALE, &fscale, SYSCTL_INT_READONLY},
340 {KERN_CCPU, &ccpu, SYSCTL_INT_READONLY},
341 {KERN_NPROCS, &nprocesses, SYSCTL_INT_READONLY},
342 {KERN_SPLASSERT, &splassert_ctl, 0, 3},
343 {KERN_MAXLOCKSPERUID, &maxlocksperuid, 0, INT_MAX},
344 {KERN_WXABORT, &uvm_wxabort, 0, 1},
345 {KERN_NETLIVELOCKS, &int_zero, SYSCTL_INT_READONLY},
346 #ifdef PTRACE
347 {KERN_GLOBAL_PTRACE, &global_ptrace, 0, 1},
348 #endif
349 {KERN_AUTOCONF_SERIAL, &autoconf_serial, SYSCTL_INT_READONLY},
350 };
351
352 int
kern_sysctl_dirs(int top_name,int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen,struct proc * p)353 kern_sysctl_dirs(int top_name, int *name, u_int namelen,
354 void *oldp, size_t *oldlenp, void *newp, size_t newlen, struct proc *p)
355 {
356 switch (top_name) {
357 #ifndef SMALL_KERNEL
358 case KERN_PROC:
359 return (sysctl_doproc(name, namelen, oldp, oldlenp));
360 case KERN_PROC_ARGS:
361 return (sysctl_proc_args(name, namelen, oldp, oldlenp, p));
362 case KERN_PROC_CWD:
363 return (sysctl_proc_cwd(name, namelen, oldp, oldlenp, p));
364 case KERN_PROC_NOBROADCASTKILL:
365 return (sysctl_proc_nobroadcastkill(name, namelen,
366 newp, newlen, oldp, oldlenp, p));
367 case KERN_PROC_VMMAP:
368 return (sysctl_proc_vmmap(name, namelen, oldp, oldlenp, p));
369 case KERN_FILE:
370 return (sysctl_file(name, namelen, oldp, oldlenp, p));
371 #endif
372 #if defined(GPROF) || defined(DDBPROF)
373 case KERN_PROF:
374 return (sysctl_doprof(name, namelen, oldp, oldlenp,
375 newp, newlen));
376 #endif
377 case KERN_MALLOCSTATS:
378 return (sysctl_malloc(name, namelen, oldp, oldlenp,
379 newp, newlen, p));
380 case KERN_TTY:
381 return (sysctl_tty(name, namelen, oldp, oldlenp,
382 newp, newlen));
383 case KERN_POOL:
384 return (sysctl_dopool(name, namelen, oldp, oldlenp));
385 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
386 case KERN_SYSVIPC_INFO:
387 return (sysctl_sysvipc(name, namelen, oldp, oldlenp));
388 #endif
389 #ifdef SYSVSEM
390 case KERN_SEMINFO:
391 return (sysctl_sysvsem(name, namelen, oldp, oldlenp,
392 newp, newlen));
393 #endif
394 #ifdef SYSVSHM
395 case KERN_SHMINFO:
396 return (sysctl_sysvshm(name, namelen, oldp, oldlenp,
397 newp, newlen));
398 #endif
399 #ifndef SMALL_KERNEL
400 case KERN_INTRCNT:
401 return (sysctl_intrcnt(name, namelen, oldp, oldlenp));
402 case KERN_WATCHDOG:
403 return (sysctl_wdog(name, namelen, oldp, oldlenp,
404 newp, newlen));
405 #endif
406 #ifndef SMALL_KERNEL
407 case KERN_EVCOUNT:
408 return (evcount_sysctl(name, namelen, oldp, oldlenp,
409 newp, newlen));
410 #endif
411 case KERN_TIMECOUNTER:
412 return (sysctl_tc(name, namelen, oldp, oldlenp, newp, newlen));
413 case KERN_CPTIME2:
414 return (sysctl_cptime2(name, namelen, oldp, oldlenp,
415 newp, newlen));
416 #ifdef WITNESS
417 case KERN_WITNESSWATCH:
418 return witness_sysctl_watch(oldp, oldlenp, newp, newlen);
419 case KERN_WITNESS:
420 return witness_sysctl(name, namelen, oldp, oldlenp,
421 newp, newlen);
422 #endif
423 #if NAUDIO > 0
424 case KERN_AUDIO:
425 return (sysctl_audio(name, namelen, oldp, oldlenp,
426 newp, newlen));
427 #endif
428 #if NVIDEO > 0
429 case KERN_VIDEO:
430 return (sysctl_video(name, namelen, oldp, oldlenp,
431 newp, newlen));
432 #endif
433 case KERN_CPUSTATS:
434 return (sysctl_cpustats(name, namelen, oldp, oldlenp,
435 newp, newlen));
436 case KERN_CLOCKINTR:
437 return sysctl_clockintr(name, namelen, oldp, oldlenp, newp,
438 newlen);
439 default:
440 return (ENOTDIR); /* overloaded */
441 }
442 }
443
444 /*
445 * kernel related system variables.
446 */
447 int
kern_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen,struct proc * p)448 kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
449 size_t newlen, struct proc *p)
450 {
451 int error, level, inthostid, stackgap;
452 dev_t dev;
453 extern int pool_debug;
454
455 /* dispatch the non-terminal nodes first */
456 if (namelen != 1) {
457 return kern_sysctl_dirs(name[0], name + 1, namelen - 1,
458 oldp, oldlenp, newp, newlen, p);
459 }
460
461 switch (name[0]) {
462 case KERN_OSTYPE:
463 return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
464 case KERN_OSRELEASE:
465 return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
466 case KERN_OSVERSION:
467 return (sysctl_rdstring(oldp, oldlenp, newp, osversion));
468 case KERN_VERSION:
469 return (sysctl_rdstring(oldp, oldlenp, newp, version));
470 case KERN_NUMVNODES: /* XXX numvnodes is a long */
471 return (sysctl_rdint(oldp, oldlenp, newp, numvnodes));
472 case KERN_SECURELVL:
473 level = securelevel;
474 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
475 newp == NULL)
476 return (error);
477 if ((securelevel > 0 || level < -1) &&
478 level < securelevel && p->p_p->ps_pid != 1)
479 return (EPERM);
480 securelevel = level;
481 return (0);
482 #if NDT > 0
483 case KERN_ALLOWDT:
484 return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen,
485 &allowdt));
486 #endif
487 case KERN_ALLOWKMEM:
488 return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen,
489 &allowkmem));
490 case KERN_HOSTNAME:
491 error = sysctl_tstring(oldp, oldlenp, newp, newlen,
492 hostname, sizeof(hostname));
493 if (newp && !error)
494 hostnamelen = newlen;
495 return (error);
496 case KERN_DOMAINNAME:
497 if (securelevel >= 1 && domainnamelen && newp)
498 error = EPERM;
499 else
500 error = sysctl_tstring(oldp, oldlenp, newp, newlen,
501 domainname, sizeof(domainname));
502 if (newp && !error)
503 domainnamelen = newlen;
504 return (error);
505 case KERN_HOSTID:
506 inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */
507 error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
508 hostid = inthostid;
509 return (error);
510 case KERN_CLOCKRATE:
511 return (sysctl_clockrate(oldp, oldlenp, newp));
512 case KERN_BOOTTIME: {
513 struct timeval bt;
514 memset(&bt, 0, sizeof bt);
515 microboottime(&bt);
516 return (sysctl_rdstruct(oldp, oldlenp, newp, &bt, sizeof bt));
517 }
518 case KERN_MBSTAT: {
519 extern struct cpumem *mbstat;
520 uint64_t counters[MBSTAT_COUNT];
521 struct mbstat mbs;
522 unsigned int i;
523
524 memset(&mbs, 0, sizeof(mbs));
525 counters_read(mbstat, counters, MBSTAT_COUNT, NULL);
526 for (i = 0; i < MBSTAT_TYPES; i++)
527 mbs.m_mtypes[i] = counters[i];
528
529 mbs.m_drops = counters[MBSTAT_DROPS];
530 mbs.m_wait = counters[MBSTAT_WAIT];
531 mbs.m_drain = counters[MBSTAT_DRAIN];
532
533 return (sysctl_rdstruct(oldp, oldlenp, newp,
534 &mbs, sizeof(mbs)));
535 }
536 case KERN_MSGBUFSIZE:
537 case KERN_CONSBUFSIZE: {
538 struct msgbuf *mp;
539 mp = (name[0] == KERN_MSGBUFSIZE) ? msgbufp : consbufp;
540 /*
541 * deal with cases where the message buffer has
542 * become corrupted.
543 */
544 if (!mp || mp->msg_magic != MSG_MAGIC)
545 return (ENXIO);
546 return (sysctl_rdint(oldp, oldlenp, newp, mp->msg_bufs));
547 }
548 case KERN_CONSBUF:
549 if ((error = suser(p)))
550 return (error);
551 /* FALLTHROUGH */
552 case KERN_MSGBUF: {
553 struct msgbuf *mp;
554 mp = (name[0] == KERN_MSGBUF) ? msgbufp : consbufp;
555 /* see note above */
556 if (!mp || mp->msg_magic != MSG_MAGIC)
557 return (ENXIO);
558 return (sysctl_rdstruct(oldp, oldlenp, newp, mp,
559 mp->msg_bufs + offsetof(struct msgbuf, msg_bufc)));
560 }
561 case KERN_CPTIME:
562 {
563 CPU_INFO_ITERATOR cii;
564 struct cpu_info *ci;
565 long cp_time[CPUSTATES];
566 int i, n = 0;
567
568 memset(cp_time, 0, sizeof(cp_time));
569
570 CPU_INFO_FOREACH(cii, ci) {
571 if (!cpu_is_online(ci))
572 continue;
573 n++;
574 for (i = 0; i < CPUSTATES; i++)
575 cp_time[i] += ci->ci_schedstate.spc_cp_time[i];
576 }
577
578 for (i = 0; i < CPUSTATES; i++)
579 cp_time[i] /= n;
580
581 return (sysctl_rdstruct(oldp, oldlenp, newp, &cp_time,
582 sizeof(cp_time)));
583 }
584 case KERN_NCHSTATS:
585 return (sysctl_rdstruct(oldp, oldlenp, newp, &nchstats,
586 sizeof(struct nchstats)));
587 case KERN_FORKSTAT:
588 return (sysctl_rdstruct(oldp, oldlenp, newp, &forkstat,
589 sizeof(struct forkstat)));
590 case KERN_STACKGAPRANDOM:
591 stackgap = stackgap_random;
592 error = sysctl_int(oldp, oldlenp, newp, newlen, &stackgap);
593 if (error)
594 return (error);
595 /*
596 * Safety harness.
597 */
598 if ((stackgap < ALIGNBYTES && stackgap != 0) ||
599 !powerof2(stackgap) || stackgap >= MAXSSIZ)
600 return (EINVAL);
601 stackgap_random = stackgap;
602 return (0);
603 case KERN_MAXCLUSTERS: {
604 int val = nmbclust;
605 error = sysctl_int(oldp, oldlenp, newp, newlen, &val);
606 if (error == 0 && val != nmbclust)
607 error = nmbclust_update(val);
608 return (error);
609 }
610 case KERN_CACHEPCT: {
611 u_int64_t dmapages;
612 int opct, pgs;
613 opct = bufcachepercent;
614 error = sysctl_int(oldp, oldlenp, newp, newlen,
615 &bufcachepercent);
616 if (error)
617 return(error);
618 if (bufcachepercent > 90 || bufcachepercent < 5) {
619 bufcachepercent = opct;
620 return (EINVAL);
621 }
622 dmapages = uvm_pagecount(&dma_constraint);
623 if (bufcachepercent != opct) {
624 pgs = bufcachepercent * dmapages / 100;
625 bufadjust(pgs); /* adjust bufpages */
626 bufhighpages = bufpages; /* set high water mark */
627 }
628 return(0);
629 }
630 case KERN_CONSDEV:
631 if (cn_tab != NULL)
632 dev = cn_tab->cn_dev;
633 else
634 dev = NODEV;
635 return sysctl_rdstruct(oldp, oldlenp, newp, &dev, sizeof(dev));
636 case KERN_POOL_DEBUG: {
637 int old_pool_debug = pool_debug;
638
639 error = sysctl_int(oldp, oldlenp, newp, newlen,
640 &pool_debug);
641 if (error == 0 && pool_debug != old_pool_debug)
642 pool_reclaim_all();
643 return (error);
644 }
645 #if NPF > 0
646 case KERN_PFSTATUS:
647 return (pf_sysctl(oldp, oldlenp, newp, newlen));
648 #endif
649 case KERN_TIMEOUT_STATS:
650 return (timeout_sysctl(oldp, oldlenp, newp, newlen));
651 case KERN_UTC_OFFSET:
652 return (sysctl_utc_offset(oldp, oldlenp, newp, newlen));
653 default:
654 return (sysctl_bounded_arr(kern_vars, nitems(kern_vars), name,
655 namelen, oldp, oldlenp, newp, newlen));
656 }
657 /* NOTREACHED */
658 }
659
660 /*
661 * hardware related system variables.
662 */
663 char *hw_vendor, *hw_prod, *hw_uuid, *hw_serial, *hw_ver;
664 int allowpowerdown = 1;
665 int hw_power = 1;
666
667 /* morally const values reported by sysctl_bounded_arr */
668 static int byte_order = BYTE_ORDER;
669
670 const struct sysctl_bounded_args hw_vars[] = {
671 {HW_NCPU, &ncpus, SYSCTL_INT_READONLY},
672 {HW_NCPUFOUND, &ncpusfound, SYSCTL_INT_READONLY},
673 {HW_BYTEORDER, &byte_order, SYSCTL_INT_READONLY},
674 {HW_PAGESIZE, &uvmexp.pagesize, SYSCTL_INT_READONLY},
675 {HW_DISKCOUNT, &disk_count, SYSCTL_INT_READONLY},
676 {HW_POWER, &hw_power, SYSCTL_INT_READONLY},
677 };
678
679 int
hw_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen,struct proc * p)680 hw_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
681 size_t newlen, struct proc *p)
682 {
683 extern char machine[], cpu_model[];
684 int err, cpuspeed;
685
686 /*
687 * all sysctl names at this level except sensors and battery
688 * are terminal
689 */
690 if (name[0] != HW_SENSORS && name[0] != HW_BATTERY && namelen != 1)
691 return (ENOTDIR); /* overloaded */
692
693 switch (name[0]) {
694 case HW_MACHINE:
695 return (sysctl_rdstring(oldp, oldlenp, newp, machine));
696 case HW_MODEL:
697 return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
698 case HW_NCPUONLINE:
699 return (sysctl_rdint(oldp, oldlenp, newp,
700 sysctl_hwncpuonline()));
701 case HW_PHYSMEM:
702 return (sysctl_rdint(oldp, oldlenp, newp, ptoa(physmem)));
703 case HW_USERMEM:
704 return (sysctl_rdint(oldp, oldlenp, newp,
705 ptoa(physmem - uvmexp.wired)));
706 case HW_DISKNAMES:
707 err = sysctl_diskinit(0, p);
708 if (err)
709 return err;
710 if (disknames)
711 return (sysctl_rdstring(oldp, oldlenp, newp,
712 disknames));
713 else
714 return (sysctl_rdstring(oldp, oldlenp, newp, ""));
715 case HW_DISKSTATS:
716 err = sysctl_diskinit(1, p);
717 if (err)
718 return err;
719 return (sysctl_rdstruct(oldp, oldlenp, newp, diskstats,
720 disk_count * sizeof(struct diskstats)));
721 case HW_CPUSPEED:
722 if (!cpu_cpuspeed)
723 return (EOPNOTSUPP);
724 err = cpu_cpuspeed(&cpuspeed);
725 if (err)
726 return err;
727 return (sysctl_rdint(oldp, oldlenp, newp, cpuspeed));
728 #ifndef SMALL_KERNEL
729 case HW_SENSORS:
730 return (sysctl_sensors(name + 1, namelen - 1, oldp, oldlenp,
731 newp, newlen));
732 case HW_SETPERF:
733 return (sysctl_hwsetperf(oldp, oldlenp, newp, newlen));
734 case HW_PERFPOLICY:
735 return (sysctl_hwperfpolicy(oldp, oldlenp, newp, newlen));
736 #endif /* !SMALL_KERNEL */
737 case HW_VENDOR:
738 if (hw_vendor)
739 return (sysctl_rdstring(oldp, oldlenp, newp,
740 hw_vendor));
741 else
742 return (EOPNOTSUPP);
743 case HW_PRODUCT:
744 if (hw_prod)
745 return (sysctl_rdstring(oldp, oldlenp, newp, hw_prod));
746 else
747 return (EOPNOTSUPP);
748 case HW_VERSION:
749 if (hw_ver)
750 return (sysctl_rdstring(oldp, oldlenp, newp, hw_ver));
751 else
752 return (EOPNOTSUPP);
753 case HW_SERIALNO:
754 if (hw_serial)
755 return (sysctl_rdstring(oldp, oldlenp, newp,
756 hw_serial));
757 else
758 return (EOPNOTSUPP);
759 case HW_UUID:
760 if (hw_uuid)
761 return (sysctl_rdstring(oldp, oldlenp, newp, hw_uuid));
762 else
763 return (EOPNOTSUPP);
764 case HW_PHYSMEM64:
765 return (sysctl_rdquad(oldp, oldlenp, newp,
766 ptoa((psize_t)physmem)));
767 case HW_USERMEM64:
768 return (sysctl_rdquad(oldp, oldlenp, newp,
769 ptoa((psize_t)physmem - uvmexp.wired)));
770 case HW_ALLOWPOWERDOWN:
771 return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen,
772 &allowpowerdown));
773 case HW_UCOMNAMES: {
774 const char *str = "";
775 #if NUCOM > 0
776 str = sysctl_ucominit();
777 #endif /* NUCOM > 0 */
778 return (sysctl_rdstring(oldp, oldlenp, newp, str));
779 }
780 #ifdef __HAVE_CPU_TOPOLOGY
781 case HW_SMT:
782 return (sysctl_hwsmt(oldp, oldlenp, newp, newlen));
783 #endif
784 #ifndef SMALL_KERNEL
785 case HW_BATTERY:
786 return (sysctl_hwbattery(name + 1, namelen - 1, oldp, oldlenp,
787 newp, newlen));
788 #endif
789 default:
790 return sysctl_bounded_arr(hw_vars, nitems(hw_vars), name,
791 namelen, oldp, oldlenp, newp, newlen);
792 }
793 /* NOTREACHED */
794 }
795
796 #ifndef SMALL_KERNEL
797
798 int hw_battery_chargemode;
799 int hw_battery_chargestart;
800 int hw_battery_chargestop;
801 int (*hw_battery_setchargemode)(int);
802 int (*hw_battery_setchargestart)(int);
803 int (*hw_battery_setchargestop)(int);
804
805 int
sysctl_hwchargemode(void * oldp,size_t * oldlenp,void * newp,size_t newlen)806 sysctl_hwchargemode(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
807 {
808 int mode = hw_battery_chargemode;
809 int error;
810
811 if (!hw_battery_setchargemode)
812 return EOPNOTSUPP;
813
814 error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
815 &mode, -1, 1);
816 if (error)
817 return error;
818
819 if (newp != NULL)
820 error = hw_battery_setchargemode(mode);
821
822 return error;
823 }
824
825 int
sysctl_hwchargestart(void * oldp,size_t * oldlenp,void * newp,size_t newlen)826 sysctl_hwchargestart(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
827 {
828 int start = hw_battery_chargestart;
829 int error;
830
831 if (!hw_battery_setchargestart)
832 return EOPNOTSUPP;
833
834 error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
835 &start, 0, 100);
836 if (error)
837 return error;
838
839 if (newp != NULL)
840 error = hw_battery_setchargestart(start);
841
842 return error;
843 }
844
845 int
sysctl_hwchargestop(void * oldp,size_t * oldlenp,void * newp,size_t newlen)846 sysctl_hwchargestop(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
847 {
848 int stop = hw_battery_chargestop;
849 int error;
850
851 if (!hw_battery_setchargestop)
852 return EOPNOTSUPP;
853
854 error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
855 &stop, 0, 100);
856 if (error)
857 return error;
858
859 if (newp != NULL)
860 error = hw_battery_setchargestop(stop);
861
862 return error;
863 }
864
865 int
sysctl_hwbattery(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)866 sysctl_hwbattery(int *name, u_int namelen, void *oldp, size_t *oldlenp,
867 void *newp, size_t newlen)
868 {
869 if (namelen != 1)
870 return (ENOTDIR);
871
872 switch (name[0]) {
873 case HW_BATTERY_CHARGEMODE:
874 return (sysctl_hwchargemode(oldp, oldlenp, newp, newlen));
875 case HW_BATTERY_CHARGESTART:
876 return (sysctl_hwchargestart(oldp, oldlenp, newp, newlen));
877 case HW_BATTERY_CHARGESTOP:
878 return (sysctl_hwchargestop(oldp, oldlenp, newp, newlen));
879 default:
880 return (EOPNOTSUPP);
881 }
882 /* NOTREACHED */
883 }
884
885 #endif
886
887 #ifdef DEBUG_SYSCTL
888 /*
889 * Debugging related system variables.
890 */
891 extern struct ctldebug debug_vfs_busyprt;
892 struct ctldebug debug1, debug2, debug3, debug4;
893 struct ctldebug debug5, debug6, debug7, debug8, debug9;
894 struct ctldebug debug10, debug11, debug12, debug13, debug14;
895 struct ctldebug debug15, debug16, debug17, debug18, debug19;
896 static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
897 &debug_vfs_busyprt,
898 &debug1, &debug2, &debug3, &debug4,
899 &debug5, &debug6, &debug7, &debug8, &debug9,
900 &debug10, &debug11, &debug12, &debug13, &debug14,
901 &debug15, &debug16, &debug17, &debug18, &debug19,
902 };
903 int
debug_sysctl(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen,struct proc * p)904 debug_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
905 size_t newlen, struct proc *p)
906 {
907 struct ctldebug *cdp;
908
909 /* all sysctl names at this level are name and field */
910 if (namelen != 2)
911 return (ENOTDIR); /* overloaded */
912 if (name[0] < 0 || name[0] >= nitems(debugvars))
913 return (EOPNOTSUPP);
914 cdp = debugvars[name[0]];
915 if (cdp->debugname == 0)
916 return (EOPNOTSUPP);
917 switch (name[1]) {
918 case CTL_DEBUG_NAME:
919 return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
920 case CTL_DEBUG_VALUE:
921 return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
922 default:
923 return (EOPNOTSUPP);
924 }
925 /* NOTREACHED */
926 }
927 #endif /* DEBUG_SYSCTL */
928
929 /*
930 * Reads, or writes that lower the value
931 */
932 int
sysctl_int_lower(void * oldp,size_t * oldlenp,void * newp,size_t newlen,int * valp)933 sysctl_int_lower(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
934 int *valp)
935 {
936 unsigned int oval = *valp, val = *valp;
937 int error;
938
939 if (newp == NULL)
940 return (sysctl_rdint(oldp, oldlenp, newp, val));
941
942 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val)))
943 return (error);
944 if (val > oval)
945 return (EPERM); /* do not allow raising */
946 *(unsigned int *)valp = val;
947 return (0);
948 }
949
950 /*
951 * Validate parameters and get old / set new parameters
952 * for an integer-valued sysctl function.
953 */
954 int
sysctl_int(void * oldp,size_t * oldlenp,void * newp,size_t newlen,int * valp)955 sysctl_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp)
956 {
957 int error = 0;
958
959 if (oldp && *oldlenp < sizeof(int))
960 return (ENOMEM);
961 if (newp && newlen != sizeof(int))
962 return (EINVAL);
963 *oldlenp = sizeof(int);
964 if (oldp)
965 error = copyout(valp, oldp, sizeof(int));
966 if (error == 0 && newp)
967 error = copyin(newp, valp, sizeof(int));
968 return (error);
969 }
970
971 /*
972 * As above, but read-only.
973 */
974 int
sysctl_rdint(void * oldp,size_t * oldlenp,void * newp,int val)975 sysctl_rdint(void *oldp, size_t *oldlenp, void *newp, int val)
976 {
977 int error = 0;
978
979 if (oldp && *oldlenp < sizeof(int))
980 return (ENOMEM);
981 if (newp)
982 return (EPERM);
983 *oldlenp = sizeof(int);
984 if (oldp)
985 error = copyout((caddr_t)&val, oldp, sizeof(int));
986 return (error);
987 }
988
989 /*
990 * Selects between sysctl_rdint and sysctl_int according to securelevel.
991 */
992 int
sysctl_securelevel_int(void * oldp,size_t * oldlenp,void * newp,size_t newlen,int * valp)993 sysctl_securelevel_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
994 int *valp)
995 {
996 if (securelevel > 0)
997 return (sysctl_rdint(oldp, oldlenp, newp, *valp));
998 return (sysctl_int(oldp, oldlenp, newp, newlen, valp));
999 }
1000
1001 /*
1002 * Read-only or bounded integer values.
1003 */
1004 int
sysctl_int_bounded(void * oldp,size_t * oldlenp,void * newp,size_t newlen,int * valp,int minimum,int maximum)1005 sysctl_int_bounded(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
1006 int *valp, int minimum, int maximum)
1007 {
1008 int val = *valp;
1009 int error;
1010
1011 /* read only */
1012 if (newp == NULL || minimum > maximum)
1013 return (sysctl_rdint(oldp, oldlenp, newp, val));
1014
1015 if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val)))
1016 return (error);
1017 /* outside limits */
1018 if (val < minimum || maximum < val)
1019 return (EINVAL);
1020 *valp = val;
1021 return (0);
1022 }
1023
1024 /*
1025 * Array of read-only or bounded integer values.
1026 */
1027 int
sysctl_bounded_arr(const struct sysctl_bounded_args * valpp,u_int valplen,int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)1028 sysctl_bounded_arr(const struct sysctl_bounded_args *valpp, u_int valplen,
1029 int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
1030 size_t newlen)
1031 {
1032 u_int i;
1033 if (namelen != 1)
1034 return (ENOTDIR);
1035 for (i = 0; i < valplen; ++i) {
1036 if (valpp[i].mib == name[0]) {
1037 return (sysctl_int_bounded(oldp, oldlenp, newp, newlen,
1038 valpp[i].var, valpp[i].minimum, valpp[i].maximum));
1039 }
1040 }
1041 return (EOPNOTSUPP);
1042 }
1043
1044 /*
1045 * Validate parameters and get old / set new parameters
1046 * for an integer-valued sysctl function.
1047 */
1048 int
sysctl_quad(void * oldp,size_t * oldlenp,void * newp,size_t newlen,int64_t * valp)1049 sysctl_quad(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
1050 int64_t *valp)
1051 {
1052 int error = 0;
1053
1054 if (oldp && *oldlenp < sizeof(int64_t))
1055 return (ENOMEM);
1056 if (newp && newlen != sizeof(int64_t))
1057 return (EINVAL);
1058 *oldlenp = sizeof(int64_t);
1059 if (oldp)
1060 error = copyout(valp, oldp, sizeof(int64_t));
1061 if (error == 0 && newp)
1062 error = copyin(newp, valp, sizeof(int64_t));
1063 return (error);
1064 }
1065
1066 /*
1067 * As above, but read-only.
1068 */
1069 int
sysctl_rdquad(void * oldp,size_t * oldlenp,void * newp,int64_t val)1070 sysctl_rdquad(void *oldp, size_t *oldlenp, void *newp, int64_t val)
1071 {
1072 int error = 0;
1073
1074 if (oldp && *oldlenp < sizeof(int64_t))
1075 return (ENOMEM);
1076 if (newp)
1077 return (EPERM);
1078 *oldlenp = sizeof(int64_t);
1079 if (oldp)
1080 error = copyout((caddr_t)&val, oldp, sizeof(int64_t));
1081 return (error);
1082 }
1083
1084 /*
1085 * Validate parameters and get old / set new parameters
1086 * for a string-valued sysctl function.
1087 */
1088 int
sysctl_string(void * oldp,size_t * oldlenp,void * newp,size_t newlen,char * str,size_t maxlen)1089 sysctl_string(void *oldp, size_t *oldlenp, void *newp, size_t newlen, char *str,
1090 size_t maxlen)
1091 {
1092 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 0);
1093 }
1094
1095 int
sysctl_tstring(void * oldp,size_t * oldlenp,void * newp,size_t newlen,char * str,size_t maxlen)1096 sysctl_tstring(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
1097 char *str, size_t maxlen)
1098 {
1099 return sysctl__string(oldp, oldlenp, newp, newlen, str, maxlen, 1);
1100 }
1101
1102 int
sysctl__string(void * oldp,size_t * oldlenp,void * newp,size_t newlen,char * str,size_t maxlen,int trunc)1103 sysctl__string(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
1104 char *str, size_t maxlen, int trunc)
1105 {
1106 size_t len;
1107 int error = 0;
1108
1109 len = strlen(str) + 1;
1110 if (oldp && *oldlenp < len) {
1111 if (trunc == 0 || *oldlenp == 0)
1112 return (ENOMEM);
1113 }
1114 if (newp && newlen >= maxlen)
1115 return (EINVAL);
1116 if (oldp) {
1117 if (trunc && *oldlenp < len) {
1118 len = *oldlenp;
1119 error = copyout(str, oldp, len - 1);
1120 if (error == 0)
1121 error = copyout("", (char *)oldp + len - 1, 1);
1122 } else {
1123 error = copyout(str, oldp, len);
1124 }
1125 }
1126 *oldlenp = len;
1127 if (error == 0 && newp) {
1128 error = copyin(newp, str, newlen);
1129 str[newlen] = 0;
1130 }
1131 return (error);
1132 }
1133
1134 /*
1135 * As above, but read-only.
1136 */
1137 int
sysctl_rdstring(void * oldp,size_t * oldlenp,void * newp,const char * str)1138 sysctl_rdstring(void *oldp, size_t *oldlenp, void *newp, const char *str)
1139 {
1140 size_t len;
1141 int error = 0;
1142
1143 len = strlen(str) + 1;
1144 if (oldp && *oldlenp < len)
1145 return (ENOMEM);
1146 if (newp)
1147 return (EPERM);
1148 *oldlenp = len;
1149 if (oldp)
1150 error = copyout(str, oldp, len);
1151 return (error);
1152 }
1153
1154 /*
1155 * Validate parameters and get old / set new parameters
1156 * for a structure oriented sysctl function.
1157 */
1158 int
sysctl_struct(void * oldp,size_t * oldlenp,void * newp,size_t newlen,void * sp,size_t len)1159 sysctl_struct(void *oldp, size_t *oldlenp, void *newp, size_t newlen, void *sp,
1160 size_t len)
1161 {
1162 int error = 0;
1163
1164 if (oldp && *oldlenp < len)
1165 return (ENOMEM);
1166 if (newp && newlen > len)
1167 return (EINVAL);
1168 if (oldp) {
1169 *oldlenp = len;
1170 error = copyout(sp, oldp, len);
1171 }
1172 if (error == 0 && newp)
1173 error = copyin(newp, sp, len);
1174 return (error);
1175 }
1176
1177 /*
1178 * Validate parameters and get old parameters
1179 * for a structure oriented sysctl function.
1180 */
1181 int
sysctl_rdstruct(void * oldp,size_t * oldlenp,void * newp,const void * sp,size_t len)1182 sysctl_rdstruct(void *oldp, size_t *oldlenp, void *newp, const void *sp,
1183 size_t len)
1184 {
1185 int error = 0;
1186
1187 if (oldp && *oldlenp < len)
1188 return (ENOMEM);
1189 if (newp)
1190 return (EPERM);
1191 *oldlenp = len;
1192 if (oldp)
1193 error = copyout(sp, oldp, len);
1194 return (error);
1195 }
1196
1197 #ifndef SMALL_KERNEL
1198 void
fill_file(struct kinfo_file * kf,struct file * fp,struct filedesc * fdp,int fd,struct vnode * vp,struct process * pr,struct proc * p,struct socket * so,int show_pointers)1199 fill_file(struct kinfo_file *kf, struct file *fp, struct filedesc *fdp,
1200 int fd, struct vnode *vp, struct process *pr, struct proc *p,
1201 struct socket *so, int show_pointers)
1202 {
1203 struct vattr va;
1204
1205 memset(kf, 0, sizeof(*kf));
1206
1207 kf->fd_fd = fd; /* might not really be an fd */
1208
1209 if (fp != NULL) {
1210 if (show_pointers)
1211 kf->f_fileaddr = PTRTOINT64(fp);
1212 kf->f_flag = fp->f_flag;
1213 kf->f_iflags = fp->f_iflags;
1214 kf->f_type = fp->f_type;
1215 kf->f_count = fp->f_count;
1216 if (show_pointers)
1217 kf->f_ucred = PTRTOINT64(fp->f_cred);
1218 kf->f_uid = fp->f_cred->cr_uid;
1219 kf->f_gid = fp->f_cred->cr_gid;
1220 if (show_pointers)
1221 kf->f_ops = PTRTOINT64(fp->f_ops);
1222 if (show_pointers)
1223 kf->f_data = PTRTOINT64(fp->f_data);
1224 kf->f_usecount = 0;
1225
1226 if (suser(p) == 0 || p->p_ucred->cr_uid == fp->f_cred->cr_uid) {
1227 mtx_enter(&fp->f_mtx);
1228 kf->f_offset = fp->f_offset;
1229 kf->f_rxfer = fp->f_rxfer;
1230 kf->f_rwfer = fp->f_wxfer;
1231 kf->f_seek = fp->f_seek;
1232 kf->f_rbytes = fp->f_rbytes;
1233 kf->f_wbytes = fp->f_wbytes;
1234 mtx_leave(&fp->f_mtx);
1235 } else
1236 kf->f_offset = -1;
1237 } else if (vp != NULL) {
1238 /* fake it */
1239 kf->f_type = DTYPE_VNODE;
1240 kf->f_flag = FREAD;
1241 if (fd == KERN_FILE_TRACE)
1242 kf->f_flag |= FWRITE;
1243 } else if (so != NULL) {
1244 /* fake it */
1245 kf->f_type = DTYPE_SOCKET;
1246 }
1247
1248 /* information about the object associated with this file */
1249 switch (kf->f_type) {
1250 case DTYPE_VNODE:
1251 if (fp != NULL)
1252 vp = (struct vnode *)fp->f_data;
1253
1254 if (show_pointers)
1255 kf->v_un = PTRTOINT64(vp->v_un.vu_socket);
1256 kf->v_type = vp->v_type;
1257 kf->v_tag = vp->v_tag;
1258 kf->v_flag = vp->v_flag;
1259 if (show_pointers)
1260 kf->v_data = PTRTOINT64(vp->v_data);
1261 if (show_pointers)
1262 kf->v_mount = PTRTOINT64(vp->v_mount);
1263 if (vp->v_mount)
1264 strlcpy(kf->f_mntonname,
1265 vp->v_mount->mnt_stat.f_mntonname,
1266 sizeof(kf->f_mntonname));
1267
1268 if (VOP_GETATTR(vp, &va, p->p_ucred, p) == 0) {
1269 kf->va_fileid = va.va_fileid;
1270 kf->va_mode = MAKEIMODE(va.va_type, va.va_mode);
1271 kf->va_size = va.va_size;
1272 kf->va_rdev = va.va_rdev;
1273 kf->va_fsid = va.va_fsid & 0xffffffff;
1274 kf->va_nlink = va.va_nlink;
1275 }
1276 break;
1277
1278 case DTYPE_SOCKET: {
1279 int locked = 0;
1280
1281 if (so == NULL) {
1282 so = (struct socket *)fp->f_data;
1283 /* if so is passed as parameter it is already locked */
1284 solock(so);
1285 locked = 1;
1286 }
1287
1288 kf->so_type = so->so_type;
1289 kf->so_state = so->so_state | so->so_snd.sb_state |
1290 so->so_rcv.sb_state;
1291 if (show_pointers)
1292 kf->so_pcb = PTRTOINT64(so->so_pcb);
1293 else
1294 kf->so_pcb = -1;
1295 kf->so_protocol = so->so_proto->pr_protocol;
1296 kf->so_family = so->so_proto->pr_domain->dom_family;
1297 kf->so_rcv_cc = so->so_rcv.sb_cc;
1298 kf->so_snd_cc = so->so_snd.sb_cc;
1299 if (isspliced(so)) {
1300 if (show_pointers)
1301 kf->so_splice =
1302 PTRTOINT64(so->so_sp->ssp_socket);
1303 kf->so_splicelen = so->so_sp->ssp_len;
1304 } else if (issplicedback(so))
1305 kf->so_splicelen = -1;
1306 if (so->so_pcb == NULL) {
1307 if (locked)
1308 sounlock(so);
1309 break;
1310 }
1311 switch (kf->so_family) {
1312 case AF_INET: {
1313 struct inpcb *inpcb = so->so_pcb;
1314
1315 soassertlocked(so);
1316 if (show_pointers)
1317 kf->inp_ppcb = PTRTOINT64(inpcb->inp_ppcb);
1318 kf->inp_lport = inpcb->inp_lport;
1319 kf->inp_laddru[0] = inpcb->inp_laddr.s_addr;
1320 kf->inp_fport = inpcb->inp_fport;
1321 kf->inp_faddru[0] = inpcb->inp_faddr.s_addr;
1322 kf->inp_rtableid = inpcb->inp_rtableid;
1323 if (so->so_type == SOCK_RAW)
1324 kf->inp_proto = inpcb->inp_ip.ip_p;
1325 if (so->so_proto->pr_protocol == IPPROTO_TCP) {
1326 struct tcpcb *tcpcb = (void *)inpcb->inp_ppcb;
1327 kf->t_rcv_wnd = tcpcb->rcv_wnd;
1328 kf->t_snd_wnd = tcpcb->snd_wnd;
1329 kf->t_snd_cwnd = tcpcb->snd_cwnd;
1330 kf->t_state = tcpcb->t_state;
1331 }
1332 break;
1333 }
1334 case AF_INET6: {
1335 struct inpcb *inpcb = so->so_pcb;
1336
1337 soassertlocked(so);
1338 if (show_pointers)
1339 kf->inp_ppcb = PTRTOINT64(inpcb->inp_ppcb);
1340 kf->inp_lport = inpcb->inp_lport;
1341 kf->inp_laddru[0] = inpcb->inp_laddr6.s6_addr32[0];
1342 kf->inp_laddru[1] = inpcb->inp_laddr6.s6_addr32[1];
1343 kf->inp_laddru[2] = inpcb->inp_laddr6.s6_addr32[2];
1344 kf->inp_laddru[3] = inpcb->inp_laddr6.s6_addr32[3];
1345 kf->inp_fport = inpcb->inp_fport;
1346 kf->inp_faddru[0] = inpcb->inp_faddr6.s6_addr32[0];
1347 kf->inp_faddru[1] = inpcb->inp_faddr6.s6_addr32[1];
1348 kf->inp_faddru[2] = inpcb->inp_faddr6.s6_addr32[2];
1349 kf->inp_faddru[3] = inpcb->inp_faddr6.s6_addr32[3];
1350 kf->inp_rtableid = inpcb->inp_rtableid;
1351 if (so->so_type == SOCK_RAW)
1352 kf->inp_proto = inpcb->inp_ipv6.ip6_nxt;
1353 if (so->so_proto->pr_protocol == IPPROTO_TCP) {
1354 struct tcpcb *tcpcb = (void *)inpcb->inp_ppcb;
1355 kf->t_rcv_wnd = tcpcb->rcv_wnd;
1356 kf->t_snd_wnd = tcpcb->snd_wnd;
1357 kf->t_state = tcpcb->t_state;
1358 }
1359 break;
1360 }
1361 case AF_UNIX: {
1362 struct unpcb *unpcb = so->so_pcb;
1363
1364 kf->f_msgcount = unpcb->unp_msgcount;
1365 if (show_pointers) {
1366 kf->unp_conn = PTRTOINT64(unpcb->unp_conn);
1367 kf->unp_refs = PTRTOINT64(
1368 SLIST_FIRST(&unpcb->unp_refs));
1369 kf->unp_nextref = PTRTOINT64(
1370 SLIST_NEXT(unpcb, unp_nextref));
1371 kf->v_un = PTRTOINT64(unpcb->unp_vnode);
1372 kf->unp_addr = PTRTOINT64(unpcb->unp_addr);
1373 }
1374 if (unpcb->unp_addr != NULL) {
1375 struct sockaddr_un *un = mtod(unpcb->unp_addr,
1376 struct sockaddr_un *);
1377 memcpy(kf->unp_path, un->sun_path, un->sun_len
1378 - offsetof(struct sockaddr_un,sun_path));
1379 }
1380 break;
1381 }
1382 }
1383 if (locked)
1384 sounlock(so);
1385 break;
1386 }
1387
1388 case DTYPE_PIPE: {
1389 struct pipe *pipe = (struct pipe *)fp->f_data;
1390
1391 if (show_pointers)
1392 kf->pipe_peer = PTRTOINT64(pipe->pipe_peer);
1393 kf->pipe_state = pipe->pipe_state;
1394 break;
1395 }
1396
1397 case DTYPE_KQUEUE: {
1398 struct kqueue *kqi = (struct kqueue *)fp->f_data;
1399
1400 kf->kq_count = kqi->kq_count;
1401 kf->kq_state = kqi->kq_state;
1402 break;
1403 }
1404 }
1405
1406 /* per-process information for KERN_FILE_BY[PU]ID */
1407 if (pr != NULL) {
1408 kf->p_pid = pr->ps_pid;
1409 kf->p_uid = pr->ps_ucred->cr_uid;
1410 kf->p_gid = pr->ps_ucred->cr_gid;
1411 kf->p_tid = -1;
1412 strlcpy(kf->p_comm, pr->ps_comm, sizeof(kf->p_comm));
1413 }
1414 if (fdp != NULL) {
1415 fdplock(fdp);
1416 kf->fd_ofileflags = fdp->fd_ofileflags[fd];
1417 fdpunlock(fdp);
1418 }
1419 }
1420
1421 /*
1422 * Get file structures.
1423 */
1424 int
sysctl_file(int * name,u_int namelen,char * where,size_t * sizep,struct proc * p)1425 sysctl_file(int *name, u_int namelen, char *where, size_t *sizep,
1426 struct proc *p)
1427 {
1428 struct kinfo_file *kf;
1429 struct filedesc *fdp;
1430 struct file *fp;
1431 struct process *pr;
1432 size_t buflen, elem_size, elem_count, outsize;
1433 char *dp = where;
1434 int arg, i, error = 0, needed = 0, matched;
1435 u_int op;
1436 int show_pointers;
1437
1438 if (namelen > 4)
1439 return (ENOTDIR);
1440 if (namelen < 4 || name[2] > sizeof(*kf))
1441 return (EINVAL);
1442
1443 buflen = where != NULL ? *sizep : 0;
1444 op = name[0];
1445 arg = name[1];
1446 elem_size = name[2];
1447 elem_count = name[3];
1448 outsize = MIN(sizeof(*kf), elem_size);
1449
1450 if (elem_size < 1)
1451 return (EINVAL);
1452
1453 show_pointers = suser(curproc) == 0;
1454
1455 kf = malloc(sizeof(*kf), M_TEMP, M_WAITOK);
1456
1457 #define FILLIT2(fp, fdp, i, vp, pr, so) do { \
1458 if (buflen >= elem_size && elem_count > 0) { \
1459 fill_file(kf, fp, fdp, i, vp, pr, p, so, show_pointers);\
1460 error = copyout(kf, dp, outsize); \
1461 if (error) \
1462 break; \
1463 dp += elem_size; \
1464 buflen -= elem_size; \
1465 elem_count--; \
1466 } \
1467 needed += elem_size; \
1468 } while (0)
1469 #define FILLIT(fp, fdp, i, vp, pr) \
1470 FILLIT2(fp, fdp, i, vp, pr, NULL)
1471 #define FILLSO(so) \
1472 FILLIT2(NULL, NULL, 0, NULL, NULL, so)
1473
1474 switch (op) {
1475 case KERN_FILE_BYFILE:
1476 /* use the inp-tables to pick up closed connections, too */
1477 if (arg == DTYPE_SOCKET) {
1478 struct inpcb *inp;
1479
1480 NET_LOCK();
1481 mtx_enter(&tcbtable.inpt_mtx);
1482 TAILQ_FOREACH(inp, &tcbtable.inpt_queue, inp_queue)
1483 FILLSO(inp->inp_socket);
1484 mtx_leave(&tcbtable.inpt_mtx);
1485 #ifdef INET6
1486 mtx_enter(&tcb6table.inpt_mtx);
1487 TAILQ_FOREACH(inp, &tcb6table.inpt_queue, inp_queue)
1488 FILLSO(inp->inp_socket);
1489 mtx_leave(&tcb6table.inpt_mtx);
1490 #endif
1491 mtx_enter(&udbtable.inpt_mtx);
1492 TAILQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue)
1493 FILLSO(inp->inp_socket);
1494 mtx_leave(&udbtable.inpt_mtx);
1495 #ifdef INET6
1496 mtx_enter(&udb6table.inpt_mtx);
1497 TAILQ_FOREACH(inp, &udb6table.inpt_queue, inp_queue)
1498 FILLSO(inp->inp_socket);
1499 mtx_leave(&udb6table.inpt_mtx);
1500 #endif
1501 mtx_enter(&rawcbtable.inpt_mtx);
1502 TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue)
1503 FILLSO(inp->inp_socket);
1504 mtx_leave(&rawcbtable.inpt_mtx);
1505 #ifdef INET6
1506 mtx_enter(&rawin6pcbtable.inpt_mtx);
1507 TAILQ_FOREACH(inp, &rawin6pcbtable.inpt_queue,
1508 inp_queue)
1509 FILLSO(inp->inp_socket);
1510 mtx_leave(&rawin6pcbtable.inpt_mtx);
1511 #endif
1512 NET_UNLOCK();
1513 }
1514 fp = NULL;
1515 while ((fp = fd_iterfile(fp, p)) != NULL) {
1516 if ((arg == 0 || fp->f_type == arg)) {
1517 int af, skip = 0;
1518 if (arg == DTYPE_SOCKET && fp->f_type == arg) {
1519 af = ((struct socket *)fp->f_data)->
1520 so_proto->pr_domain->dom_family;
1521 if (af == AF_INET || af == AF_INET6)
1522 skip = 1;
1523 }
1524 if (!skip)
1525 FILLIT(fp, NULL, 0, NULL, NULL);
1526 }
1527 }
1528 break;
1529 case KERN_FILE_BYPID:
1530 /* A arg of -1 indicates all processes */
1531 if (arg < -1) {
1532 error = EINVAL;
1533 break;
1534 }
1535 matched = 0;
1536 LIST_FOREACH(pr, &allprocess, ps_list) {
1537 /*
1538 * skip system, exiting, embryonic and undead
1539 * processes
1540 */
1541 if (pr->ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING))
1542 continue;
1543 if (arg > 0 && pr->ps_pid != (pid_t)arg) {
1544 /* not the pid we are looking for */
1545 continue;
1546 }
1547 matched = 1;
1548 fdp = pr->ps_fd;
1549 if (pr->ps_textvp)
1550 FILLIT(NULL, NULL, KERN_FILE_TEXT, pr->ps_textvp, pr);
1551 if (fdp->fd_cdir)
1552 FILLIT(NULL, NULL, KERN_FILE_CDIR, fdp->fd_cdir, pr);
1553 if (fdp->fd_rdir)
1554 FILLIT(NULL, NULL, KERN_FILE_RDIR, fdp->fd_rdir, pr);
1555 if (pr->ps_tracevp)
1556 FILLIT(NULL, NULL, KERN_FILE_TRACE, pr->ps_tracevp, pr);
1557 for (i = 0; i < fdp->fd_nfiles; i++) {
1558 if ((fp = fd_getfile(fdp, i)) == NULL)
1559 continue;
1560 FILLIT(fp, fdp, i, NULL, pr);
1561 FRELE(fp, p);
1562 }
1563 }
1564 if (!matched)
1565 error = ESRCH;
1566 break;
1567 case KERN_FILE_BYUID:
1568 LIST_FOREACH(pr, &allprocess, ps_list) {
1569 /*
1570 * skip system, exiting, embryonic and undead
1571 * processes
1572 */
1573 if (pr->ps_flags & (PS_SYSTEM | PS_EMBRYO | PS_EXITING))
1574 continue;
1575 if (arg >= 0 && pr->ps_ucred->cr_uid != (uid_t)arg) {
1576 /* not the uid we are looking for */
1577 continue;
1578 }
1579 fdp = pr->ps_fd;
1580 if (fdp->fd_cdir)
1581 FILLIT(NULL, NULL, KERN_FILE_CDIR, fdp->fd_cdir, pr);
1582 if (fdp->fd_rdir)
1583 FILLIT(NULL, NULL, KERN_FILE_RDIR, fdp->fd_rdir, pr);
1584 if (pr->ps_tracevp)
1585 FILLIT(NULL, NULL, KERN_FILE_TRACE, pr->ps_tracevp, pr);
1586 for (i = 0; i < fdp->fd_nfiles; i++) {
1587 if ((fp = fd_getfile(fdp, i)) == NULL)
1588 continue;
1589 FILLIT(fp, fdp, i, NULL, pr);
1590 FRELE(fp, p);
1591 }
1592 }
1593 break;
1594 default:
1595 error = EINVAL;
1596 break;
1597 }
1598 free(kf, M_TEMP, sizeof(*kf));
1599
1600 if (!error) {
1601 if (where == NULL)
1602 needed += KERN_FILESLOP * elem_size;
1603 else if (*sizep < needed)
1604 error = ENOMEM;
1605 *sizep = needed;
1606 }
1607
1608 return (error);
1609 }
1610
1611 /*
1612 * try over estimating by 5 procs
1613 */
1614 #define KERN_PROCSLOP 5
1615
1616 int
sysctl_doproc(int * name,u_int namelen,char * where,size_t * sizep)1617 sysctl_doproc(int *name, u_int namelen, char *where, size_t *sizep)
1618 {
1619 struct kinfo_proc *kproc = NULL;
1620 struct proc *p;
1621 struct process *pr;
1622 char *dp;
1623 int arg, buflen, doingzomb, elem_size, elem_count;
1624 int error, needed, op;
1625 int dothreads = 0;
1626 int show_pointers;
1627
1628 dp = where;
1629 buflen = where != NULL ? *sizep : 0;
1630 needed = error = 0;
1631
1632 if (namelen != 4 || name[2] <= 0 || name[3] < 0 ||
1633 name[2] > sizeof(*kproc))
1634 return (EINVAL);
1635 op = name[0];
1636 arg = name[1];
1637 elem_size = name[2];
1638 elem_count = name[3];
1639
1640 dothreads = op & KERN_PROC_SHOW_THREADS;
1641 op &= ~KERN_PROC_SHOW_THREADS;
1642
1643 show_pointers = suser(curproc) == 0;
1644
1645 if (where != NULL)
1646 kproc = malloc(sizeof(*kproc), M_TEMP, M_WAITOK);
1647
1648 pr = LIST_FIRST(&allprocess);
1649 doingzomb = 0;
1650 again:
1651 for (; pr != NULL; pr = LIST_NEXT(pr, ps_list)) {
1652 /* XXX skip processes in the middle of being zapped */
1653 if (pr->ps_pgrp == NULL)
1654 continue;
1655
1656 /*
1657 * Skip embryonic processes.
1658 */
1659 if (pr->ps_flags & PS_EMBRYO)
1660 continue;
1661
1662 /*
1663 * TODO - make more efficient (see notes below).
1664 */
1665 switch (op) {
1666
1667 case KERN_PROC_PID:
1668 /* could do this with just a lookup */
1669 if (pr->ps_pid != (pid_t)arg)
1670 continue;
1671 break;
1672
1673 case KERN_PROC_PGRP:
1674 /* could do this by traversing pgrp */
1675 if (pr->ps_pgrp->pg_id != (pid_t)arg)
1676 continue;
1677 break;
1678
1679 case KERN_PROC_SESSION:
1680 if (pr->ps_session->s_leader == NULL ||
1681 pr->ps_session->s_leader->ps_pid != (pid_t)arg)
1682 continue;
1683 break;
1684
1685 case KERN_PROC_TTY:
1686 if ((pr->ps_flags & PS_CONTROLT) == 0 ||
1687 pr->ps_session->s_ttyp == NULL ||
1688 pr->ps_session->s_ttyp->t_dev != (dev_t)arg)
1689 continue;
1690 break;
1691
1692 case KERN_PROC_UID:
1693 if (pr->ps_ucred->cr_uid != (uid_t)arg)
1694 continue;
1695 break;
1696
1697 case KERN_PROC_RUID:
1698 if (pr->ps_ucred->cr_ruid != (uid_t)arg)
1699 continue;
1700 break;
1701
1702 case KERN_PROC_ALL:
1703 if (pr->ps_flags & PS_SYSTEM)
1704 continue;
1705 break;
1706
1707 case KERN_PROC_KTHREAD:
1708 /* no filtering */
1709 break;
1710
1711 default:
1712 error = EINVAL;
1713 goto err;
1714 }
1715
1716 if (buflen >= elem_size && elem_count > 0) {
1717 fill_kproc(pr, kproc, NULL, show_pointers);
1718 error = copyout(kproc, dp, elem_size);
1719 if (error)
1720 goto err;
1721 dp += elem_size;
1722 buflen -= elem_size;
1723 elem_count--;
1724 }
1725 needed += elem_size;
1726
1727 /* Skip per-thread entries if not required by op */
1728 if (!dothreads)
1729 continue;
1730
1731 TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) {
1732 if (buflen >= elem_size && elem_count > 0) {
1733 fill_kproc(pr, kproc, p, show_pointers);
1734 error = copyout(kproc, dp, elem_size);
1735 if (error)
1736 goto err;
1737 dp += elem_size;
1738 buflen -= elem_size;
1739 elem_count--;
1740 }
1741 needed += elem_size;
1742 }
1743 }
1744 if (doingzomb == 0) {
1745 pr = LIST_FIRST(&zombprocess);
1746 doingzomb++;
1747 goto again;
1748 }
1749 if (where != NULL) {
1750 *sizep = dp - where;
1751 if (needed > *sizep) {
1752 error = ENOMEM;
1753 goto err;
1754 }
1755 } else {
1756 needed += KERN_PROCSLOP * elem_size;
1757 *sizep = needed;
1758 }
1759 err:
1760 if (kproc)
1761 free(kproc, M_TEMP, sizeof(*kproc));
1762 return (error);
1763 }
1764
1765 /*
1766 * Fill in a kproc structure for the specified process.
1767 */
1768 void
fill_kproc(struct process * pr,struct kinfo_proc * ki,struct proc * p,int show_pointers)1769 fill_kproc(struct process *pr, struct kinfo_proc *ki, struct proc *p,
1770 int show_pointers)
1771 {
1772 struct session *s = pr->ps_session;
1773 struct tty *tp;
1774 struct vmspace *vm = pr->ps_vmspace;
1775 struct timespec booted, st, ut, utc;
1776 int isthread;
1777
1778 isthread = p != NULL;
1779 if (!isthread)
1780 p = pr->ps_mainproc; /* XXX */
1781
1782 FILL_KPROC(ki, strlcpy, p, pr, pr->ps_ucred, pr->ps_pgrp,
1783 p, pr, s, vm, pr->ps_limit, pr->ps_sigacts, isthread,
1784 show_pointers);
1785
1786 /* stuff that's too painful to generalize into the macros */
1787 if (pr->ps_pptr)
1788 ki->p_ppid = pr->ps_ppid;
1789 if (s->s_leader)
1790 ki->p_sid = s->s_leader->ps_pid;
1791
1792 if ((pr->ps_flags & PS_CONTROLT) && (tp = s->s_ttyp)) {
1793 ki->p_tdev = tp->t_dev;
1794 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : -1;
1795 if (show_pointers)
1796 ki->p_tsess = PTRTOINT64(tp->t_session);
1797 } else {
1798 ki->p_tdev = NODEV;
1799 ki->p_tpgid = -1;
1800 }
1801
1802 /* fixups that can only be done in the kernel */
1803 if ((pr->ps_flags & PS_ZOMBIE) == 0) {
1804 if ((pr->ps_flags & PS_EMBRYO) == 0 && vm != NULL)
1805 ki->p_vm_rssize = vm_resident_count(vm);
1806 calctsru(isthread ? &p->p_tu : &pr->ps_tu, &ut, &st, NULL);
1807 ki->p_uutime_sec = ut.tv_sec;
1808 ki->p_uutime_usec = ut.tv_nsec/1000;
1809 ki->p_ustime_sec = st.tv_sec;
1810 ki->p_ustime_usec = st.tv_nsec/1000;
1811
1812 /* Convert starting uptime to a starting UTC time. */
1813 nanoboottime(&booted);
1814 timespecadd(&booted, &pr->ps_start, &utc);
1815 ki->p_ustart_sec = utc.tv_sec;
1816 ki->p_ustart_usec = utc.tv_nsec / 1000;
1817
1818 #ifdef MULTIPROCESSOR
1819 if (p->p_cpu != NULL)
1820 ki->p_cpuid = CPU_INFO_UNIT(p->p_cpu);
1821 #endif
1822 }
1823
1824 /* get %cpu and schedule state: just one thread or sum of all? */
1825 if (isthread) {
1826 ki->p_pctcpu = p->p_pctcpu;
1827 ki->p_stat = p->p_stat;
1828 } else {
1829 ki->p_pctcpu = 0;
1830 ki->p_stat = (pr->ps_flags & PS_ZOMBIE) ? SDEAD : SIDL;
1831 TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) {
1832 ki->p_pctcpu += p->p_pctcpu;
1833 /* find best state: ONPROC > RUN > STOP > SLEEP > .. */
1834 if (p->p_stat == SONPROC || ki->p_stat == SONPROC)
1835 ki->p_stat = SONPROC;
1836 else if (p->p_stat == SRUN || ki->p_stat == SRUN)
1837 ki->p_stat = SRUN;
1838 else if (p->p_stat == SSTOP || ki->p_stat == SSTOP)
1839 ki->p_stat = SSTOP;
1840 else if (p->p_stat == SSLEEP)
1841 ki->p_stat = SSLEEP;
1842 }
1843 }
1844 }
1845
1846 int
sysctl_proc_args(int * name,u_int namelen,void * oldp,size_t * oldlenp,struct proc * cp)1847 sysctl_proc_args(int *name, u_int namelen, void *oldp, size_t *oldlenp,
1848 struct proc *cp)
1849 {
1850 struct process *vpr;
1851 pid_t pid;
1852 struct ps_strings pss;
1853 struct iovec iov;
1854 struct uio uio;
1855 int error, cnt, op;
1856 size_t limit;
1857 char **rargv, **vargv; /* reader vs. victim */
1858 char *rarg, *varg, *buf;
1859 struct vmspace *vm;
1860 vaddr_t ps_strings;
1861
1862 if (namelen > 2)
1863 return (ENOTDIR);
1864 if (namelen < 2)
1865 return (EINVAL);
1866
1867 pid = name[0];
1868 op = name[1];
1869
1870 switch (op) {
1871 case KERN_PROC_ARGV:
1872 case KERN_PROC_NARGV:
1873 case KERN_PROC_ENV:
1874 case KERN_PROC_NENV:
1875 break;
1876 default:
1877 return (EOPNOTSUPP);
1878 }
1879
1880 if ((vpr = prfind(pid)) == NULL)
1881 return (ESRCH);
1882
1883 if (oldp == NULL) {
1884 if (op == KERN_PROC_NARGV || op == KERN_PROC_NENV)
1885 *oldlenp = sizeof(int);
1886 else
1887 *oldlenp = ARG_MAX; /* XXX XXX XXX */
1888 return (0);
1889 }
1890
1891 /* Either system process or exiting/zombie */
1892 if (vpr->ps_flags & (PS_SYSTEM | PS_EXITING))
1893 return (EINVAL);
1894
1895 /* Execing - danger. */
1896 if ((vpr->ps_flags & PS_INEXEC))
1897 return (EBUSY);
1898
1899 /* Only owner or root can get env */
1900 if ((op == KERN_PROC_NENV || op == KERN_PROC_ENV) &&
1901 (vpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid &&
1902 (error = suser(cp)) != 0))
1903 return (error);
1904
1905 ps_strings = vpr->ps_strings;
1906 vm = vpr->ps_vmspace;
1907 uvmspace_addref(vm);
1908 vpr = NULL;
1909
1910 buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
1911
1912 iov.iov_base = &pss;
1913 iov.iov_len = sizeof(pss);
1914 uio.uio_iov = &iov;
1915 uio.uio_iovcnt = 1;
1916 uio.uio_offset = (off_t)ps_strings;
1917 uio.uio_resid = sizeof(pss);
1918 uio.uio_segflg = UIO_SYSSPACE;
1919 uio.uio_rw = UIO_READ;
1920 uio.uio_procp = cp;
1921
1922 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0)
1923 goto out;
1924
1925 if (op == KERN_PROC_NARGV) {
1926 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nargvstr);
1927 goto out;
1928 }
1929 if (op == KERN_PROC_NENV) {
1930 error = sysctl_rdint(oldp, oldlenp, NULL, pss.ps_nenvstr);
1931 goto out;
1932 }
1933
1934 if (op == KERN_PROC_ARGV) {
1935 cnt = pss.ps_nargvstr;
1936 vargv = pss.ps_argvstr;
1937 } else {
1938 cnt = pss.ps_nenvstr;
1939 vargv = pss.ps_envstr;
1940 }
1941
1942 /* -1 to have space for a terminating NUL */
1943 limit = *oldlenp - 1;
1944 *oldlenp = 0;
1945
1946 rargv = oldp;
1947
1948 /*
1949 * *oldlenp - number of bytes copied out into readers buffer.
1950 * limit - maximal number of bytes allowed into readers buffer.
1951 * rarg - pointer into readers buffer where next arg will be stored.
1952 * rargv - pointer into readers buffer where the next rarg pointer
1953 * will be stored.
1954 * vargv - pointer into victim address space where the next argument
1955 * will be read.
1956 */
1957
1958 /* space for cnt pointers and a NULL */
1959 rarg = (char *)(rargv + cnt + 1);
1960 *oldlenp += (cnt + 1) * sizeof(char **);
1961
1962 while (cnt > 0 && *oldlenp < limit) {
1963 size_t len, vstrlen;
1964
1965 /* Write to readers argv */
1966 if ((error = copyout(&rarg, rargv, sizeof(rarg))) != 0)
1967 goto out;
1968
1969 /* read the victim argv */
1970 iov.iov_base = &varg;
1971 iov.iov_len = sizeof(varg);
1972 uio.uio_iov = &iov;
1973 uio.uio_iovcnt = 1;
1974 uio.uio_offset = (off_t)(vaddr_t)vargv;
1975 uio.uio_resid = sizeof(varg);
1976 uio.uio_segflg = UIO_SYSSPACE;
1977 uio.uio_rw = UIO_READ;
1978 uio.uio_procp = cp;
1979 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0)
1980 goto out;
1981
1982 if (varg == NULL)
1983 break;
1984
1985 /*
1986 * read the victim arg. We must jump through hoops to avoid
1987 * crossing a page boundary too much and returning an error.
1988 */
1989 more:
1990 len = PAGE_SIZE - (((vaddr_t)varg) & PAGE_MASK);
1991 /* leave space for the terminating NUL */
1992 iov.iov_base = buf;
1993 iov.iov_len = len;
1994 uio.uio_iov = &iov;
1995 uio.uio_iovcnt = 1;
1996 uio.uio_offset = (off_t)(vaddr_t)varg;
1997 uio.uio_resid = len;
1998 uio.uio_segflg = UIO_SYSSPACE;
1999 uio.uio_rw = UIO_READ;
2000 uio.uio_procp = cp;
2001 if ((error = uvm_io(&vm->vm_map, &uio, 0)) != 0)
2002 goto out;
2003
2004 for (vstrlen = 0; vstrlen < len; vstrlen++) {
2005 if (buf[vstrlen] == '\0')
2006 break;
2007 }
2008
2009 /* Don't overflow readers buffer. */
2010 if (*oldlenp + vstrlen + 1 >= limit) {
2011 error = ENOMEM;
2012 goto out;
2013 }
2014
2015 if ((error = copyout(buf, rarg, vstrlen)) != 0)
2016 goto out;
2017
2018 *oldlenp += vstrlen;
2019 rarg += vstrlen;
2020
2021 /* The string didn't end in this page? */
2022 if (vstrlen == len) {
2023 varg += vstrlen;
2024 goto more;
2025 }
2026
2027 /* End of string. Terminate it with a NUL */
2028 buf[0] = '\0';
2029 if ((error = copyout(buf, rarg, 1)) != 0)
2030 goto out;
2031 *oldlenp += 1;
2032 rarg += 1;
2033
2034 vargv++;
2035 rargv++;
2036 cnt--;
2037 }
2038
2039 if (*oldlenp >= limit) {
2040 error = ENOMEM;
2041 goto out;
2042 }
2043
2044 /* Write the terminating null */
2045 rarg = NULL;
2046 error = copyout(&rarg, rargv, sizeof(rarg));
2047
2048 out:
2049 uvmspace_free(vm);
2050 free(buf, M_TEMP, PAGE_SIZE);
2051 return (error);
2052 }
2053
2054 int
sysctl_proc_cwd(int * name,u_int namelen,void * oldp,size_t * oldlenp,struct proc * cp)2055 sysctl_proc_cwd(int *name, u_int namelen, void *oldp, size_t *oldlenp,
2056 struct proc *cp)
2057 {
2058 struct process *findpr;
2059 struct vnode *vp;
2060 pid_t pid;
2061 int error;
2062 size_t lenused, len;
2063 char *path, *bp, *bend;
2064
2065 if (namelen > 1)
2066 return (ENOTDIR);
2067 if (namelen < 1)
2068 return (EINVAL);
2069
2070 pid = name[0];
2071 if ((findpr = prfind(pid)) == NULL)
2072 return (ESRCH);
2073
2074 if (oldp == NULL) {
2075 *oldlenp = MAXPATHLEN * 4;
2076 return (0);
2077 }
2078
2079 /* Either system process or exiting/zombie */
2080 if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING))
2081 return (EINVAL);
2082
2083 /* Only owner or root can get cwd */
2084 if (findpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid &&
2085 (error = suser(cp)) != 0)
2086 return (error);
2087
2088 len = *oldlenp;
2089 if (len > MAXPATHLEN * 4)
2090 len = MAXPATHLEN * 4;
2091 else if (len < 2)
2092 return (ERANGE);
2093 *oldlenp = 0;
2094
2095 /* snag a reference to the vnode before we can sleep */
2096 vp = findpr->ps_fd->fd_cdir;
2097 vref(vp);
2098
2099 path = malloc(len, M_TEMP, M_WAITOK);
2100
2101 bp = &path[len];
2102 bend = bp;
2103 *(--bp) = '\0';
2104
2105 /* Same as sys__getcwd */
2106 error = vfs_getcwd_common(vp, NULL,
2107 &bp, path, len / 2, GETCWD_CHECK_ACCESS, cp);
2108 if (error == 0) {
2109 *oldlenp = lenused = bend - bp;
2110 error = copyout(bp, oldp, lenused);
2111 }
2112
2113 vrele(vp);
2114 free(path, M_TEMP, len);
2115
2116 return (error);
2117 }
2118
2119 int
sysctl_proc_nobroadcastkill(int * name,u_int namelen,void * newp,size_t newlen,void * oldp,size_t * oldlenp,struct proc * cp)2120 sysctl_proc_nobroadcastkill(int *name, u_int namelen, void *newp, size_t newlen,
2121 void *oldp, size_t *oldlenp, struct proc *cp)
2122 {
2123 struct process *findpr;
2124 pid_t pid;
2125 int error, flag;
2126
2127 if (namelen > 1)
2128 return (ENOTDIR);
2129 if (namelen < 1)
2130 return (EINVAL);
2131
2132 pid = name[0];
2133 if ((findpr = prfind(pid)) == NULL)
2134 return (ESRCH);
2135
2136 /* Either system process or exiting/zombie */
2137 if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING))
2138 return (EINVAL);
2139
2140 /* Only root can change PS_NOBROADCASTKILL */
2141 if (newp != NULL && (error = suser(cp)) != 0)
2142 return (error);
2143
2144 /* get the PS_NOBROADCASTKILL flag */
2145 flag = findpr->ps_flags & PS_NOBROADCASTKILL ? 1 : 0;
2146
2147 error = sysctl_int(oldp, oldlenp, newp, newlen, &flag);
2148 if (error == 0 && newp) {
2149 if (flag)
2150 atomic_setbits_int(&findpr->ps_flags,
2151 PS_NOBROADCASTKILL);
2152 else
2153 atomic_clearbits_int(&findpr->ps_flags,
2154 PS_NOBROADCASTKILL);
2155 }
2156
2157 return (error);
2158 }
2159
2160 /* Arbitrary but reasonable limit for one iteration. */
2161 #define VMMAP_MAXLEN MAXPHYS
2162
2163 int
sysctl_proc_vmmap(int * name,u_int namelen,void * oldp,size_t * oldlenp,struct proc * cp)2164 sysctl_proc_vmmap(int *name, u_int namelen, void *oldp, size_t *oldlenp,
2165 struct proc *cp)
2166 {
2167 struct process *findpr;
2168 pid_t pid;
2169 int error;
2170 size_t oldlen, len;
2171 struct kinfo_vmentry *kve, *ukve;
2172 u_long *ustart, start;
2173
2174 if (namelen > 1)
2175 return (ENOTDIR);
2176 if (namelen < 1)
2177 return (EINVAL);
2178
2179 /* Provide max buffer length as hint. */
2180 if (oldp == NULL) {
2181 if (oldlenp == NULL)
2182 return (EINVAL);
2183 else {
2184 *oldlenp = VMMAP_MAXLEN;
2185 return (0);
2186 }
2187 }
2188
2189 pid = name[0];
2190 if (pid == cp->p_p->ps_pid) {
2191 /* Self process mapping. */
2192 findpr = cp->p_p;
2193 } else if (pid > 0) {
2194 if ((findpr = prfind(pid)) == NULL)
2195 return (ESRCH);
2196
2197 /* Either system process or exiting/zombie */
2198 if (findpr->ps_flags & (PS_SYSTEM | PS_EXITING))
2199 return (EINVAL);
2200
2201 #if 1
2202 /* XXX Allow only root for now */
2203 if ((error = suser(cp)) != 0)
2204 return (error);
2205 #else
2206 /* Only owner or root can get vmmap */
2207 if (findpr->ps_ucred->cr_uid != cp->p_ucred->cr_uid &&
2208 (error = suser(cp)) != 0)
2209 return (error);
2210 #endif
2211 } else {
2212 /* Only root can get kernel_map */
2213 if ((error = suser(cp)) != 0)
2214 return (error);
2215 findpr = NULL;
2216 }
2217
2218 /* Check the given size. */
2219 oldlen = *oldlenp;
2220 if (oldlen == 0 || oldlen % sizeof(*kve) != 0)
2221 return (EINVAL);
2222
2223 /* Deny huge allocation. */
2224 if (oldlen > VMMAP_MAXLEN)
2225 return (EINVAL);
2226
2227 /*
2228 * Iterate from the given address passed as the first element's
2229 * kve_start via oldp.
2230 */
2231 ukve = (struct kinfo_vmentry *)oldp;
2232 ustart = &ukve->kve_start;
2233 error = copyin(ustart, &start, sizeof(start));
2234 if (error != 0)
2235 return (error);
2236
2237 /* Allocate wired memory to not block. */
2238 kve = malloc(oldlen, M_TEMP, M_WAITOK);
2239
2240 /* Set the base address and read entries. */
2241 kve[0].kve_start = start;
2242 len = oldlen;
2243 error = fill_vmmap(findpr, kve, &len);
2244 if (error != 0 && error != ENOMEM)
2245 goto done;
2246 if (len == 0)
2247 goto done;
2248
2249 KASSERT(len <= oldlen);
2250 KASSERT((len % sizeof(struct kinfo_vmentry)) == 0);
2251
2252 error = copyout(kve, oldp, len);
2253
2254 done:
2255 *oldlenp = len;
2256
2257 free(kve, M_TEMP, oldlen);
2258
2259 return (error);
2260 }
2261 #endif
2262
2263 /*
2264 * Initialize disknames/diskstats for export by sysctl. If update is set,
2265 * then we simply update the disk statistics information.
2266 */
2267 int
sysctl_diskinit(int update,struct proc * p)2268 sysctl_diskinit(int update, struct proc *p)
2269 {
2270 struct diskstats *sdk;
2271 struct disk *dk;
2272 const char *duid;
2273 int error, changed = 0;
2274
2275 KERNEL_ASSERT_LOCKED();
2276
2277 if ((error = rw_enter(&sysctl_disklock, RW_WRITE|RW_INTR)) != 0)
2278 return error;
2279
2280 /* Run in a loop, disks may change while malloc sleeps. */
2281 while (disk_change) {
2282 int tlen;
2283
2284 disk_change = 0;
2285
2286 tlen = 0;
2287 TAILQ_FOREACH(dk, &disklist, dk_link) {
2288 if (dk->dk_name)
2289 tlen += strlen(dk->dk_name);
2290 tlen += 18; /* label uid + separators */
2291 }
2292 tlen++;
2293
2294 /*
2295 * The sysctl_disklock ensures that no other process can
2296 * allocate disknames and diskstats while our malloc sleeps.
2297 */
2298 free(disknames, M_SYSCTL, disknameslen);
2299 free(diskstats, M_SYSCTL, diskstatslen);
2300 diskstats = NULL;
2301 disknames = NULL;
2302 diskstats = mallocarray(disk_count, sizeof(struct diskstats),
2303 M_SYSCTL, M_WAITOK|M_ZERO);
2304 diskstatslen = disk_count * sizeof(struct diskstats);
2305 disknames = malloc(tlen, M_SYSCTL, M_WAITOK|M_ZERO);
2306 disknameslen = tlen;
2307 disknames[0] = '\0';
2308 changed = 1;
2309 }
2310
2311 if (changed) {
2312 int l;
2313
2314 l = 0;
2315 sdk = diskstats;
2316 TAILQ_FOREACH(dk, &disklist, dk_link) {
2317 duid = NULL;
2318 if (dk->dk_label && !duid_iszero(dk->dk_label->d_uid))
2319 duid = duid_format(dk->dk_label->d_uid);
2320 snprintf(disknames + l, disknameslen - l, "%s:%s,",
2321 dk->dk_name ? dk->dk_name : "",
2322 duid ? duid : "");
2323 l += strlen(disknames + l);
2324 strlcpy(sdk->ds_name, dk->dk_name,
2325 sizeof(sdk->ds_name));
2326 mtx_enter(&dk->dk_mtx);
2327 sdk->ds_busy = dk->dk_busy;
2328 sdk->ds_rxfer = dk->dk_rxfer;
2329 sdk->ds_wxfer = dk->dk_wxfer;
2330 sdk->ds_seek = dk->dk_seek;
2331 sdk->ds_rbytes = dk->dk_rbytes;
2332 sdk->ds_wbytes = dk->dk_wbytes;
2333 sdk->ds_attachtime = dk->dk_attachtime;
2334 sdk->ds_timestamp = dk->dk_timestamp;
2335 sdk->ds_time = dk->dk_time;
2336 mtx_leave(&dk->dk_mtx);
2337 sdk++;
2338 }
2339
2340 /* Eliminate trailing comma */
2341 if (l != 0)
2342 disknames[l - 1] = '\0';
2343 } else if (update) {
2344 /* Just update, number of drives hasn't changed */
2345 sdk = diskstats;
2346 TAILQ_FOREACH(dk, &disklist, dk_link) {
2347 strlcpy(sdk->ds_name, dk->dk_name,
2348 sizeof(sdk->ds_name));
2349 mtx_enter(&dk->dk_mtx);
2350 sdk->ds_busy = dk->dk_busy;
2351 sdk->ds_rxfer = dk->dk_rxfer;
2352 sdk->ds_wxfer = dk->dk_wxfer;
2353 sdk->ds_seek = dk->dk_seek;
2354 sdk->ds_rbytes = dk->dk_rbytes;
2355 sdk->ds_wbytes = dk->dk_wbytes;
2356 sdk->ds_attachtime = dk->dk_attachtime;
2357 sdk->ds_timestamp = dk->dk_timestamp;
2358 sdk->ds_time = dk->dk_time;
2359 mtx_leave(&dk->dk_mtx);
2360 sdk++;
2361 }
2362 }
2363 rw_exit_write(&sysctl_disklock);
2364 return 0;
2365 }
2366
2367 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
2368 int
sysctl_sysvipc(int * name,u_int namelen,void * where,size_t * sizep)2369 sysctl_sysvipc(int *name, u_int namelen, void *where, size_t *sizep)
2370 {
2371 #ifdef SYSVSEM
2372 struct sem_sysctl_info *semsi;
2373 #endif
2374 #ifdef SYSVSHM
2375 struct shm_sysctl_info *shmsi;
2376 #endif
2377 size_t infosize, dssize, tsize, buflen, bufsiz;
2378 int i, nds, error, ret;
2379 void *buf;
2380
2381 if (namelen != 1)
2382 return (EINVAL);
2383
2384 buflen = *sizep;
2385
2386 switch (*name) {
2387 case KERN_SYSVIPC_MSG_INFO:
2388 #ifdef SYSVMSG
2389 return (sysctl_sysvmsg(name, namelen, where, sizep));
2390 #else
2391 return (EOPNOTSUPP);
2392 #endif
2393 case KERN_SYSVIPC_SEM_INFO:
2394 #ifdef SYSVSEM
2395 infosize = sizeof(semsi->seminfo);
2396 nds = seminfo.semmni;
2397 dssize = sizeof(semsi->semids[0]);
2398 break;
2399 #else
2400 return (EOPNOTSUPP);
2401 #endif
2402 case KERN_SYSVIPC_SHM_INFO:
2403 #ifdef SYSVSHM
2404 infosize = sizeof(shmsi->shminfo);
2405 nds = shminfo.shmmni;
2406 dssize = sizeof(shmsi->shmids[0]);
2407 break;
2408 #else
2409 return (EOPNOTSUPP);
2410 #endif
2411 default:
2412 return (EINVAL);
2413 }
2414 tsize = infosize + (nds * dssize);
2415
2416 /* Return just the total size required. */
2417 if (where == NULL) {
2418 *sizep = tsize;
2419 return (0);
2420 }
2421
2422 /* Not enough room for even the info struct. */
2423 if (buflen < infosize) {
2424 *sizep = 0;
2425 return (ENOMEM);
2426 }
2427 bufsiz = min(tsize, buflen);
2428 buf = malloc(bufsiz, M_TEMP, M_WAITOK|M_ZERO);
2429
2430 switch (*name) {
2431 #ifdef SYSVSEM
2432 case KERN_SYSVIPC_SEM_INFO:
2433 semsi = (struct sem_sysctl_info *)buf;
2434 semsi->seminfo = seminfo;
2435 break;
2436 #endif
2437 #ifdef SYSVSHM
2438 case KERN_SYSVIPC_SHM_INFO:
2439 shmsi = (struct shm_sysctl_info *)buf;
2440 shmsi->shminfo = shminfo;
2441 break;
2442 #endif
2443 }
2444 buflen -= infosize;
2445
2446 ret = 0;
2447 if (buflen > 0) {
2448 /* Fill in the IPC data structures. */
2449 for (i = 0; i < nds; i++) {
2450 if (buflen < dssize) {
2451 ret = ENOMEM;
2452 break;
2453 }
2454 switch (*name) {
2455 #ifdef SYSVSEM
2456 case KERN_SYSVIPC_SEM_INFO:
2457 if (sema[i] != NULL)
2458 memcpy(&semsi->semids[i], sema[i],
2459 dssize);
2460 else
2461 memset(&semsi->semids[i], 0, dssize);
2462 break;
2463 #endif
2464 #ifdef SYSVSHM
2465 case KERN_SYSVIPC_SHM_INFO:
2466 if (shmsegs[i] != NULL)
2467 memcpy(&shmsi->shmids[i], shmsegs[i],
2468 dssize);
2469 else
2470 memset(&shmsi->shmids[i], 0, dssize);
2471 break;
2472 #endif
2473 }
2474 buflen -= dssize;
2475 }
2476 }
2477 *sizep -= buflen;
2478 error = copyout(buf, where, *sizep);
2479 free(buf, M_TEMP, bufsiz);
2480 /* If copyout succeeded, use return code set earlier. */
2481 return (error ? error : ret);
2482 }
2483 #endif /* SYSVMSG || SYSVSEM || SYSVSHM */
2484
2485 #ifndef SMALL_KERNEL
2486
2487 int
sysctl_intrcnt(int * name,u_int namelen,void * oldp,size_t * oldlenp)2488 sysctl_intrcnt(int *name, u_int namelen, void *oldp, size_t *oldlenp)
2489 {
2490 return (evcount_sysctl(name, namelen, oldp, oldlenp, NULL, 0));
2491 }
2492
2493
2494 int
sysctl_sensors(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2495 sysctl_sensors(int *name, u_int namelen, void *oldp, size_t *oldlenp,
2496 void *newp, size_t newlen)
2497 {
2498 struct ksensor *ks;
2499 struct sensor *us;
2500 struct ksensordev *ksd;
2501 struct sensordev *usd;
2502 int dev, numt, ret;
2503 enum sensor_type type;
2504
2505 if (namelen != 1 && namelen != 3)
2506 return (ENOTDIR);
2507
2508 dev = name[0];
2509 if (namelen == 1) {
2510 ret = sensordev_get(dev, &ksd);
2511 if (ret)
2512 return (ret);
2513
2514 /* Grab a copy, to clear the kernel pointers */
2515 usd = malloc(sizeof(*usd), M_TEMP, M_WAITOK|M_ZERO);
2516 usd->num = ksd->num;
2517 strlcpy(usd->xname, ksd->xname, sizeof(usd->xname));
2518 memcpy(usd->maxnumt, ksd->maxnumt, sizeof(usd->maxnumt));
2519 usd->sensors_count = ksd->sensors_count;
2520
2521 ret = sysctl_rdstruct(oldp, oldlenp, newp, usd,
2522 sizeof(struct sensordev));
2523
2524 free(usd, M_TEMP, sizeof(*usd));
2525 return (ret);
2526 }
2527
2528 type = name[1];
2529 numt = name[2];
2530
2531 ret = sensor_find(dev, type, numt, &ks);
2532 if (ret)
2533 return (ret);
2534
2535 /* Grab a copy, to clear the kernel pointers */
2536 us = malloc(sizeof(*us), M_TEMP, M_WAITOK|M_ZERO);
2537 memcpy(us->desc, ks->desc, sizeof(us->desc));
2538 us->tv = ks->tv;
2539 us->value = ks->value;
2540 us->type = ks->type;
2541 us->status = ks->status;
2542 us->numt = ks->numt;
2543 us->flags = ks->flags;
2544
2545 ret = sysctl_rdstruct(oldp, oldlenp, newp, us,
2546 sizeof(struct sensor));
2547 free(us, M_TEMP, sizeof(*us));
2548 return (ret);
2549 }
2550 #endif /* SMALL_KERNEL */
2551
2552 int
sysctl_cptime2(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2553 sysctl_cptime2(int *name, u_int namelen, void *oldp, size_t *oldlenp,
2554 void *newp, size_t newlen)
2555 {
2556 CPU_INFO_ITERATOR cii;
2557 struct cpu_info *ci;
2558 int found = 0;
2559
2560 if (namelen != 1)
2561 return (ENOTDIR);
2562
2563 CPU_INFO_FOREACH(cii, ci) {
2564 if (name[0] == CPU_INFO_UNIT(ci)) {
2565 found = 1;
2566 break;
2567 }
2568 }
2569 if (!found)
2570 return (ENOENT);
2571
2572 return (sysctl_rdstruct(oldp, oldlenp, newp,
2573 &ci->ci_schedstate.spc_cp_time,
2574 sizeof(ci->ci_schedstate.spc_cp_time)));
2575 }
2576
2577 #if NAUDIO > 0
2578 int
sysctl_audio(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2579 sysctl_audio(int *name, u_int namelen, void *oldp, size_t *oldlenp,
2580 void *newp, size_t newlen)
2581 {
2582 if (namelen != 1)
2583 return (ENOTDIR);
2584
2585 if (name[0] != KERN_AUDIO_RECORD)
2586 return (ENOENT);
2587
2588 return (sysctl_int(oldp, oldlenp, newp, newlen, &audio_record_enable));
2589 }
2590 #endif
2591
2592 #if NVIDEO > 0
2593 int
sysctl_video(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2594 sysctl_video(int *name, u_int namelen, void *oldp, size_t *oldlenp,
2595 void *newp, size_t newlen)
2596 {
2597 if (namelen != 1)
2598 return (ENOTDIR);
2599
2600 if (name[0] != KERN_VIDEO_RECORD)
2601 return (ENOENT);
2602
2603 return (sysctl_int(oldp, oldlenp, newp, newlen, &video_record_enable));
2604 }
2605 #endif
2606
2607 int
sysctl_cpustats(int * name,u_int namelen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2608 sysctl_cpustats(int *name, u_int namelen, void *oldp, size_t *oldlenp,
2609 void *newp, size_t newlen)
2610 {
2611 CPU_INFO_ITERATOR cii;
2612 struct cpustats cs;
2613 struct cpu_info *ci;
2614 int found = 0;
2615
2616 if (namelen != 1)
2617 return (ENOTDIR);
2618
2619 CPU_INFO_FOREACH(cii, ci) {
2620 if (name[0] == CPU_INFO_UNIT(ci)) {
2621 found = 1;
2622 break;
2623 }
2624 }
2625 if (!found)
2626 return (ENOENT);
2627
2628 memset(&cs, 0, sizeof cs);
2629 memcpy(&cs.cs_time, &ci->ci_schedstate.spc_cp_time, sizeof(cs.cs_time));
2630 cs.cs_flags = 0;
2631 if (cpu_is_online(ci))
2632 cs.cs_flags |= CPUSTATS_ONLINE;
2633
2634 return (sysctl_rdstruct(oldp, oldlenp, newp, &cs, sizeof(cs)));
2635 }
2636
2637 int
sysctl_utc_offset(void * oldp,size_t * oldlenp,void * newp,size_t newlen)2638 sysctl_utc_offset(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
2639 {
2640 struct timespec adjusted, now;
2641 int adjustment_seconds, error, new_offset_minutes, old_offset_minutes;
2642
2643 old_offset_minutes = utc_offset / 60; /* seconds -> minutes */
2644 new_offset_minutes = old_offset_minutes;
2645 error = sysctl_securelevel_int(oldp, oldlenp, newp, newlen,
2646 &new_offset_minutes);
2647 if (error)
2648 return error;
2649 if (new_offset_minutes < -24 * 60 || new_offset_minutes > 24 * 60)
2650 return EINVAL;
2651 if (new_offset_minutes == old_offset_minutes)
2652 return 0;
2653
2654 utc_offset = new_offset_minutes * 60; /* minutes -> seconds */
2655 adjustment_seconds = (new_offset_minutes - old_offset_minutes) * 60;
2656
2657 nanotime(&now);
2658 adjusted = now;
2659 adjusted.tv_sec -= adjustment_seconds;
2660 tc_setrealtimeclock(&adjusted);
2661 resettodr();
2662
2663 return 0;
2664 }
2665