Bug Summary

File:kern/kern_sysctl.c
Warning:line 1396, column 38
Access to field 'f_data' results in a dereference of a null pointer (loaded from variable 'fp')

Annotated Source Code

Press '?' to see keyboard shortcuts

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