Bug Summary

File:kern/kern_sysctl.c
Warning:line 1133, column 16
Access to field 'v_type' results in a dereference of a null pointer (loaded from variable 'vp')

Annotated Source Code

Press '?' to see keyboard shortcuts

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