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