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