1*ff3504bdSriastradh /* $NetBSD: misc.c,v 1.27 2023/07/29 08:46:47 riastradh Exp $ */
2380fafb7Schristos
3380fafb7Schristos /*-
4380fafb7Schristos * Copyright (c) 2008 The NetBSD Foundation, Inc.
5380fafb7Schristos * All rights reserved.
6380fafb7Schristos *
7380fafb7Schristos * This code is derived from software contributed to The NetBSD Foundation
8380fafb7Schristos * by Christos Zoulas
9380fafb7Schristos *
10380fafb7Schristos * Redistribution and use in source and binary forms, with or without
11380fafb7Schristos * modification, are permitted provided that the following conditions
12380fafb7Schristos * are met:
13380fafb7Schristos * 1. Redistributions of source code must retain the above copyright
14380fafb7Schristos * notice, this list of conditions and the following disclaimer.
15380fafb7Schristos * 2. Redistributions in binary form must reproduce the above copyright
16380fafb7Schristos * notice, this list of conditions and the following disclaimer in the
17380fafb7Schristos * documentation and/or other materials provided with the distribution.
18380fafb7Schristos *
19380fafb7Schristos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20380fafb7Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21380fafb7Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22380fafb7Schristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23380fafb7Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24380fafb7Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25380fafb7Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26380fafb7Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27380fafb7Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28380fafb7Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29380fafb7Schristos * POSSIBILITY OF SUCH DAMAGE.
30380fafb7Schristos */
31380fafb7Schristos
32380fafb7Schristos #include <sys/cdefs.h>
33*ff3504bdSriastradh __RCSID("$NetBSD: misc.c,v 1.27 2023/07/29 08:46:47 riastradh Exp $");
34380fafb7Schristos
358dd0b445Schristos #include <stdbool.h>
36380fafb7Schristos #include <sys/param.h>
37f73facbcSchristos #include <sys/types.h>
38380fafb7Schristos #include <sys/time.h>
39380fafb7Schristos #include <sys/stat.h>
408dd0b445Schristos #include <sys/condvar.h>
418dd0b445Schristos #include <sys/selinfo.h>
428dd0b445Schristos #include <sys/filedesc.h>
438dd0b445Schristos #define _KERNEL
448dd0b445Schristos #include <sys/mqueue.h>
458dd0b445Schristos #include <sys/eventvar.h>
468dd0b445Schristos #undef _KERNEL
47380fafb7Schristos #include <sys/proc.h>
48380fafb7Schristos #define _KERNEL
49380fafb7Schristos #include <sys/file.h>
5068e270a2Sthorpej #define copyin_t int
510548a80aSchristos #define copyout_t int
520548a80aSchristos #include <sys/ksem.h>
533d7bb1daSchristos #define _LIB_LIBKERN_LIBKERN_H_
543d7bb1daSchristos #define mutex_enter(a)
553d7bb1daSchristos #define mutex_exit(a)
56380fafb7Schristos #undef _KERNEL
57ea6af427Stls #include <sys/cprng.h>
58380fafb7Schristos #include <sys/vnode.h>
59*ff3504bdSriastradh #include <sys/memfd.h>
60380fafb7Schristos #include <sys/mount.h>
61380fafb7Schristos
62380fafb7Schristos #include <net/bpfdesc.h>
63380fafb7Schristos
64baa8677bSisaki #include <dev/audio/audiodef.h>
65baa8677bSisaki #include <dev/audio/audio_if.h>
66baa8677bSisaki
67380fafb7Schristos #include <err.h>
683d7bb1daSchristos #include <util.h>
690548a80aSchristos #include <string.h>
70380fafb7Schristos #include <kvm.h>
71380fafb7Schristos #include "fstat.h"
72380fafb7Schristos
73380fafb7Schristos static struct nlist nl[] = {
7448bd4d9cSchristos #define NL_BPF 0
75380fafb7Schristos { .n_name = "bpf_fileops", },
7648bd4d9cSchristos #define NL_CRYPTO 1
7748bd4d9cSchristos { .n_name = "cryptofops" },
7848bd4d9cSchristos #define NL_DMIO 2
7948bd4d9cSchristos { .n_name = "dmio_fileops", },
8048bd4d9cSchristos #define NL_DRVCTL 3
8148bd4d9cSchristos { .n_name = "drvctl_fileops", },
8248bd4d9cSchristos #define NL_DTV_DEMUX 4
8348bd4d9cSchristos { .n_name = "dtv_demux_fileops", },
8448bd4d9cSchristos #define NL_FILEMON 5
8548bd4d9cSchristos { .n_name = "filemon_fileops", },
8648bd4d9cSchristos #define NL_KQUEUE 6
8748bd4d9cSchristos { .n_name = "kqueueops" },
8848bd4d9cSchristos #define NL_MQUEUE 7
8948bd4d9cSchristos { .n_name = "mqops" },
9048bd4d9cSchristos #define NL_PIPE 8
9148bd4d9cSchristos { .n_name = "pipeops" },
9248bd4d9cSchristos #define NL_PUTTER 9
9348bd4d9cSchristos { .n_name = "putter_fileops", },
942732a80bSchristos #define NL_RND 10
952732a80bSchristos { .n_name = "rnd_fileops", },
962732a80bSchristos #define NL_SEM 11
9748bd4d9cSchristos { .n_name = "semops", },
982732a80bSchristos #define NL_SOCKET 12
9948bd4d9cSchristos { .n_name = "socketops" },
1002732a80bSchristos #define NL_SVR4_NET 13
10148bd4d9cSchristos { .n_name = "svr4_netops" },
1022732a80bSchristos #define NL_SVR4_32_NET 14
10348bd4d9cSchristos { .n_name = "svr4_32_netops" },
1042732a80bSchristos #define NL_TAP 15
105380fafb7Schristos { .n_name = "tap_fileops", },
1062732a80bSchristos #define NL_VNOPS 16
10748bd4d9cSchristos { .n_name = "vnops" },
1082732a80bSchristos #define NL_XENEVT 17
10948bd4d9cSchristos { .n_name = "xenevt_fileops" },
110911089b5Snat #define NL_AUDIO 18
111911089b5Snat { .n_name = "audio_fileops" },
112911089b5Snat #define NL_PAD 19
113911089b5Snat { .n_name = "pad_fileops" },
1147eace3daSchristos #define NL_MEMFD 20
1157eace3daSchristos { .n_name = "memfd_fileops" },
1167eace3daSchristos #define NL_MAX 21
117380fafb7Schristos { .n_name = NULL }
118380fafb7Schristos };
119380fafb7Schristos
12090baf4f2Schristos extern int vflg;
12190baf4f2Schristos
122380fafb7Schristos
123380fafb7Schristos static int
p_bpf(struct file * f)124380fafb7Schristos p_bpf(struct file *f)
125380fafb7Schristos {
126380fafb7Schristos struct bpf_d bpf;
127f51d1f25Schristos struct bpf_if bi;
128f51d1f25Schristos struct ifnet ifn;
129f51d1f25Schristos
130f51d1f25Schristos strlcpy(ifn.if_xname, "???", sizeof(ifn.if_xname));
131380fafb7Schristos
132380fafb7Schristos if (!KVM_READ(f->f_data, &bpf, sizeof(bpf))) {
133380fafb7Schristos dprintf("can't read bpf at %p for pid %d", f->f_data, Pid);
134380fafb7Schristos return 0;
135380fafb7Schristos }
136f51d1f25Schristos if (bpf.bd_bif != NULL) {
137f51d1f25Schristos if (!KVM_READ(bpf.bd_bif, &bi, sizeof(bi)))
138f51d1f25Schristos dprintf("can't read bpf interface at %p for pid %d",
139f51d1f25Schristos bpf.bd_bif, Pid);
140f51d1f25Schristos if (bi.bif_ifp != NULL)
141f51d1f25Schristos if (!KVM_READ(bi.bif_ifp, &ifn, sizeof(ifn)))
142f51d1f25Schristos dprintf("can't read net interfsace"
143f51d1f25Schristos " at %p for pid %d", bi.bif_ifp, Pid);
144f51d1f25Schristos }
145f51d1f25Schristos (void)printf("* bpf@%s rec=%lu, dr=%lu, cap=%lu, pid=%lu", ifn.if_xname,
146380fafb7Schristos bpf.bd_rcount, bpf.bd_dcount, bpf.bd_ccount,
147380fafb7Schristos (unsigned long)bpf.bd_pid);
148380fafb7Schristos if (bpf.bd_promisc)
149380fafb7Schristos (void)printf(", promisc");
150380fafb7Schristos if (bpf.bd_immediate)
151380fafb7Schristos (void)printf(", immed");
152204f26c6Smsaitoh if (bpf.bd_direction == BPF_D_IN)
153204f26c6Smsaitoh (void)printf(", in");
154204f26c6Smsaitoh else if (bpf.bd_direction == BPF_D_INOUT)
155204f26c6Smsaitoh (void)printf(", inout");
156204f26c6Smsaitoh else if (bpf.bd_direction == BPF_D_OUT)
157204f26c6Smsaitoh (void)printf(", out");
1584d1ae9a9Salnsn if (bpf.bd_jitcode != NULL)
1594d1ae9a9Salnsn (void)printf(", jit");
160380fafb7Schristos if (bpf.bd_async)
161380fafb7Schristos (void)printf(", asyncgrp=%lu", (unsigned long)bpf.bd_pgid);
162380fafb7Schristos if (bpf.bd_state == BPF_IDLE)
163380fafb7Schristos (void)printf(", idle");
164380fafb7Schristos else if (bpf.bd_state == BPF_WAITING)
165380fafb7Schristos (void)printf(", waiting");
166380fafb7Schristos else if (bpf.bd_state == BPF_TIMED_OUT)
167380fafb7Schristos (void)printf(", timeout");
168ebe962e4Schristos oprint(f, "\n");
169380fafb7Schristos return 0;
170380fafb7Schristos }
171380fafb7Schristos
172380fafb7Schristos static int
p_sem(struct file * f)1730548a80aSchristos p_sem(struct file *f)
1740548a80aSchristos {
1750548a80aSchristos ksem_t ks;
1760548a80aSchristos if (!KVM_READ(f->f_data, &ks, sizeof(ks))) {
1770548a80aSchristos dprintf("can't read sem at %p for pid %d", f->f_data, Pid);
1780548a80aSchristos return 0;
1790548a80aSchristos }
1800548a80aSchristos (void)printf("* ksem ref=%u, value=%u, waiters=%u, flags=0x%x, "
1810548a80aSchristos "mode=%o, uid=%u, gid=%u", ks.ks_ref, ks.ks_value, ks.ks_waiters,
1820548a80aSchristos ks.ks_flags, ks.ks_mode, ks.ks_uid, ks.ks_gid);
1830548a80aSchristos if (ks.ks_name && ks.ks_namelen) {
1840548a80aSchristos char buf[64];
1850548a80aSchristos if (ks.ks_namelen >= sizeof(buf))
1860548a80aSchristos ks.ks_namelen = sizeof(buf) - 1;
1870548a80aSchristos if (!KVM_READ(ks.ks_name, buf, ks.ks_namelen)) {
1880548a80aSchristos dprintf("can't read sem name at %p for pid %d",
1890548a80aSchristos ks.ks_name, Pid);
1900548a80aSchristos } else {
1910548a80aSchristos buf[ks.ks_namelen] = '\0';
192ebe962e4Schristos (void)printf(", name=%s", buf);
193ebe962e4Schristos oprint(f, "\n");
1940548a80aSchristos return 0;
1950548a80aSchristos }
1960548a80aSchristos }
197ebe962e4Schristos oprint(f, "\n");
1980548a80aSchristos return 0;
1990548a80aSchristos }
2000548a80aSchristos
2010548a80aSchristos static int
p_mqueue(struct file * f)202380fafb7Schristos p_mqueue(struct file *f)
203380fafb7Schristos {
204380fafb7Schristos struct mqueue mq;
205380fafb7Schristos
206380fafb7Schristos if (!KVM_READ(f->f_data, &mq, sizeof(mq))) {
207380fafb7Schristos dprintf("can't read mqueue at %p for pid %d", f->f_data, Pid);
208380fafb7Schristos return 0;
209380fafb7Schristos }
210ebe962e4Schristos (void)printf("* mqueue \"%s\"", mq.mq_name);
211ebe962e4Schristos oprint(f, "\n");
212380fafb7Schristos return 0;
213380fafb7Schristos }
2148dd0b445Schristos
2158dd0b445Schristos static int
p_kqueue(struct file * f)2168dd0b445Schristos p_kqueue(struct file *f)
2178dd0b445Schristos {
2188dd0b445Schristos struct kqueue kq;
2198dd0b445Schristos
2208dd0b445Schristos if (!KVM_READ(f->f_data, &kq, sizeof(kq))) {
2218dd0b445Schristos dprintf("can't read kqueue at %p for pid %d", f->f_data, Pid);
2228dd0b445Schristos return 0;
2238dd0b445Schristos }
224ebe962e4Schristos (void)printf("* kqueue pending %d", kq.kq_count);
225ebe962e4Schristos oprint(f, "\n");
2268dd0b445Schristos return 0;
2278dd0b445Schristos }
228380fafb7Schristos
229baa8677bSisaki static int
p_audio(struct file * f)230baa8677bSisaki p_audio(struct file *f)
231baa8677bSisaki {
232baa8677bSisaki struct audio_file af;
233baa8677bSisaki const char *devname;
234baa8677bSisaki const char *modename;
235baa8677bSisaki
236baa8677bSisaki if (!KVM_READ(f->f_data, &af, sizeof(af))) {
237baa8677bSisaki dprintf("can't read audio_file at %p for pid %d",
238baa8677bSisaki f->f_data, Pid);
239baa8677bSisaki return 0;
240baa8677bSisaki }
241baa8677bSisaki
242baa8677bSisaki if (ISDEVAUDIO(af.dev)) {
243baa8677bSisaki devname = "audio";
244baa8677bSisaki } else if (ISDEVSOUND(af.dev)) {
245baa8677bSisaki devname = "sound";
246baa8677bSisaki } else if (ISDEVAUDIOCTL(af.dev)) {
247baa8677bSisaki devname = "audioctl";
248baa8677bSisaki } else if (ISDEVMIXER(af.dev)) {
249baa8677bSisaki devname = "mixer";
250baa8677bSisaki } else {
251baa8677bSisaki devname = "???";
252baa8677bSisaki }
253baa8677bSisaki
254baa8677bSisaki if (af.ptrack && af.rtrack) {
255baa8677bSisaki modename = "playback, record";
256baa8677bSisaki } else if (af.ptrack) {
257baa8677bSisaki modename = "playback";
258baa8677bSisaki } else if (af.rtrack) {
259baa8677bSisaki modename = "record";
260baa8677bSisaki } else {
261baa8677bSisaki modename = "-";
262baa8677bSisaki }
263baa8677bSisaki
264baa8677bSisaki (void)printf("* audio@%s%d %s", devname, AUDIOUNIT(af.dev), modename);
265baa8677bSisaki oprint(f, "\n");
266baa8677bSisaki return 0;
267baa8677bSisaki }
268baa8677bSisaki
2697eace3daSchristos static int
p_memfd_seal(int seen,int all,int target,const char * name)2707eace3daSchristos p_memfd_seal(int seen, int all, int target, const char *name)
2717eace3daSchristos {
2727eace3daSchristos if (all & target)
2737eace3daSchristos (void)printf("%s%s", (seen ? "|" : ""), name);
2747eace3daSchristos
2757eace3daSchristos return seen || (all & target);
2767eace3daSchristos }
2777eace3daSchristos
2787eace3daSchristos static int
p_memfd(struct file * f)2797eace3daSchristos p_memfd(struct file *f)
2807eace3daSchristos {
2817eace3daSchristos int seal_yet = 0;
2827eace3daSchristos struct memfd mfd;
2837eace3daSchristos
2847eace3daSchristos if (!KVM_READ(f->f_data, &mfd, sizeof(mfd))) {
2857eace3daSchristos dprintf("can't read memfd at %p for pid %d", f->f_data, Pid);
2867eace3daSchristos return 0;
2877eace3daSchristos }
2887eace3daSchristos (void)printf("* %s, seals=", mfd.mfd_name);
2897eace3daSchristos if (mfd.mfd_seals == 0)
2907eace3daSchristos (void)printf("0");
2917eace3daSchristos else {
2927eace3daSchristos seal_yet = p_memfd_seal(seal_yet, mfd.mfd_seals, F_SEAL_SEAL, "F_SEAL_SEAL");
2937eace3daSchristos seal_yet = p_memfd_seal(seal_yet, mfd.mfd_seals, F_SEAL_SHRINK, "F_SEAL_SHRINK");
2947eace3daSchristos seal_yet = p_memfd_seal(seal_yet, mfd.mfd_seals, F_SEAL_GROW, "F_SEAL_GROW");
2957eace3daSchristos seal_yet = p_memfd_seal(seal_yet, mfd.mfd_seals, F_SEAL_WRITE, "F_SEAL_WRITE");
2967eace3daSchristos seal_yet = p_memfd_seal(seal_yet, mfd.mfd_seals, F_SEAL_FUTURE_WRITE, "F_SEAL_FUTURE_WRITE");
2977eace3daSchristos }
2987eace3daSchristos
2997eace3daSchristos oprint(f, "\n");
3007eace3daSchristos return 0;
3017eace3daSchristos }
3027eace3daSchristos
303380fafb7Schristos int
pmisc(struct file * f,const char * name)304380fafb7Schristos pmisc(struct file *f, const char *name)
305380fafb7Schristos {
306380fafb7Schristos size_t i;
307380fafb7Schristos if (nl[0].n_value == 0) {
308380fafb7Schristos int n;
309380fafb7Schristos if ((n = KVM_NLIST(nl)) == -1)
310380fafb7Schristos errx(1, "Cannot list kernel symbols (%s)",
311380fafb7Schristos KVM_GETERR());
3120548a80aSchristos else if (n != 0 && vflg) {
3130548a80aSchristos char buf[1024];
3140548a80aSchristos buf[0] = '\0';
3150548a80aSchristos for (struct nlist *l = nl; l->n_name != NULL; l++) {
3160548a80aSchristos if (l->n_value != 0)
3170548a80aSchristos continue;
3180548a80aSchristos strlcat(buf, ", ", sizeof(buf));
3190548a80aSchristos strlcat(buf, l->n_name, sizeof(buf));
3200548a80aSchristos }
3210548a80aSchristos warnx("Could not find %d symbols: %s", n, buf + 2);
3220548a80aSchristos }
323380fafb7Schristos }
324380fafb7Schristos for (i = 0; i < NL_MAX; i++)
325dadffc77Slukem if ((uintptr_t)f->f_ops == nl[i].n_value)
326380fafb7Schristos break;
327380fafb7Schristos switch (i) {
328380fafb7Schristos case NL_BPF:
329380fafb7Schristos return p_bpf(f);
330380fafb7Schristos case NL_MQUEUE:
331380fafb7Schristos return p_mqueue(f);
3328dd0b445Schristos case NL_KQUEUE:
3338dd0b445Schristos return p_kqueue(f);
3342732a80bSchristos case NL_RND:
335485ee481Schristos printf("* random %p", f->f_data);
336485ee481Schristos break;
3370548a80aSchristos case NL_SEM:
3380548a80aSchristos return p_sem(f);
339380fafb7Schristos case NL_TAP:
340ebe962e4Schristos printf("* tap %lu", (unsigned long)(intptr_t)f->f_data);
341ebe962e4Schristos break;
342380fafb7Schristos case NL_CRYPTO:
343ebe962e4Schristos printf("* crypto %p", f->f_data);
344ebe962e4Schristos break;
345911089b5Snat case NL_AUDIO:
346baa8677bSisaki return p_audio(f);
347911089b5Snat case NL_PAD:
348ebe962e4Schristos printf("* pad %p", f->f_data);
349ebe962e4Schristos break;
3507eace3daSchristos case NL_MEMFD:
3517eace3daSchristos return p_memfd(f);
35248bd4d9cSchristos case NL_MAX:
353ebe962e4Schristos printf("* %s ops=%p %p", name, f->f_ops, f->f_data);
354ebe962e4Schristos break;
35548bd4d9cSchristos default:
356ebe962e4Schristos printf("* %s %p", nl[i].n_name, f->f_data);
357ebe962e4Schristos break;
358380fafb7Schristos }
359ebe962e4Schristos oprint(f, "\n");
360ebe962e4Schristos return 0;
361380fafb7Schristos }
362