1 1.27 riastrad /* $NetBSD: misc.c,v 1.27 2023/07/29 08:46:47 riastradh Exp $ */ 2 1.1 christos 3 1.1 christos /*- 4 1.1 christos * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 1.1 christos * All rights reserved. 6 1.1 christos * 7 1.1 christos * This code is derived from software contributed to The NetBSD Foundation 8 1.1 christos * by Christos Zoulas 9 1.1 christos * 10 1.1 christos * Redistribution and use in source and binary forms, with or without 11 1.1 christos * modification, are permitted provided that the following conditions 12 1.1 christos * are met: 13 1.1 christos * 1. Redistributions of source code must retain the above copyright 14 1.1 christos * notice, this list of conditions and the following disclaimer. 15 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 christos * notice, this list of conditions and the following disclaimer in the 17 1.1 christos * documentation and/or other materials provided with the distribution. 18 1.1 christos * 19 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 christos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 christos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 christos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 christos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 christos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 christos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 christos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 christos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 christos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 christos * POSSIBILITY OF SUCH DAMAGE. 30 1.1 christos */ 31 1.1 christos 32 1.1 christos #include <sys/cdefs.h> 33 1.27 riastrad __RCSID("$NetBSD: misc.c,v 1.27 2023/07/29 08:46:47 riastradh Exp $"); 34 1.1 christos 35 1.2 christos #include <stdbool.h> 36 1.1 christos #include <sys/param.h> 37 1.5 christos #include <sys/types.h> 38 1.1 christos #include <sys/time.h> 39 1.1 christos #include <sys/stat.h> 40 1.2 christos #include <sys/condvar.h> 41 1.2 christos #include <sys/selinfo.h> 42 1.2 christos #include <sys/filedesc.h> 43 1.2 christos #define _KERNEL 44 1.2 christos #include <sys/mqueue.h> 45 1.2 christos #include <sys/eventvar.h> 46 1.2 christos #undef _KERNEL 47 1.1 christos #include <sys/proc.h> 48 1.1 christos #define _KERNEL 49 1.1 christos #include <sys/file.h> 50 1.21 thorpej #define copyin_t int 51 1.10 christos #define copyout_t int 52 1.10 christos #include <sys/ksem.h> 53 1.11 christos #define _LIB_LIBKERN_LIBKERN_H_ 54 1.11 christos #define mutex_enter(a) 55 1.11 christos #define mutex_exit(a) 56 1.14 tls #undef _KERNEL 57 1.11 christos #include <sys/cprng.h> 58 1.1 christos #include <sys/vnode.h> 59 1.27 riastrad #include <sys/memfd.h> 60 1.1 christos #include <sys/mount.h> 61 1.1 christos 62 1.1 christos #include <net/bpfdesc.h> 63 1.1 christos 64 1.24 isaki #include <dev/audio/audiodef.h> 65 1.24 isaki #include <dev/audio/audio_if.h> 66 1.24 isaki 67 1.1 christos #include <err.h> 68 1.11 christos #include <util.h> 69 1.10 christos #include <string.h> 70 1.1 christos #include <kvm.h> 71 1.1 christos #include "fstat.h" 72 1.1 christos 73 1.1 christos static struct nlist nl[] = { 74 1.8 christos #define NL_BPF 0 75 1.8 christos { .n_name = "bpf_fileops", }, 76 1.8 christos #define NL_CRYPTO 1 77 1.8 christos { .n_name = "cryptofops" }, 78 1.8 christos #define NL_DMIO 2 79 1.8 christos { .n_name = "dmio_fileops", }, 80 1.8 christos #define NL_DRVCTL 3 81 1.8 christos { .n_name = "drvctl_fileops", }, 82 1.8 christos #define NL_DTV_DEMUX 4 83 1.8 christos { .n_name = "dtv_demux_fileops", }, 84 1.8 christos #define NL_FILEMON 5 85 1.8 christos { .n_name = "filemon_fileops", }, 86 1.8 christos #define NL_KQUEUE 6 87 1.1 christos { .n_name = "kqueueops" }, 88 1.8 christos #define NL_MQUEUE 7 89 1.1 christos { .n_name = "mqops" }, 90 1.8 christos #define NL_PIPE 8 91 1.1 christos { .n_name = "pipeops" }, 92 1.8 christos #define NL_PUTTER 9 93 1.8 christos { .n_name = "putter_fileops", }, 94 1.15 christos #define NL_RND 10 95 1.15 christos { .n_name = "rnd_fileops", }, 96 1.15 christos #define NL_SEM 11 97 1.8 christos { .n_name = "semops", }, 98 1.15 christos #define NL_SOCKET 12 99 1.1 christos { .n_name = "socketops" }, 100 1.15 christos #define NL_SVR4_NET 13 101 1.8 christos { .n_name = "svr4_netops" }, 102 1.15 christos #define NL_SVR4_32_NET 14 103 1.8 christos { .n_name = "svr4_32_netops" }, 104 1.15 christos #define NL_TAP 15 105 1.8 christos { .n_name = "tap_fileops", }, 106 1.15 christos #define NL_VNOPS 16 107 1.1 christos { .n_name = "vnops" }, 108 1.15 christos #define NL_XENEVT 17 109 1.8 christos { .n_name = "xenevt_fileops" }, 110 1.18 nat #define NL_AUDIO 18 111 1.18 nat { .n_name = "audio_fileops" }, 112 1.18 nat #define NL_PAD 19 113 1.18 nat { .n_name = "pad_fileops" }, 114 1.25 christos #define NL_MEMFD 20 115 1.25 christos { .n_name = "memfd_fileops" }, 116 1.25 christos #define NL_MAX 21 117 1.1 christos { .n_name = NULL } 118 1.1 christos }; 119 1.1 christos 120 1.3 christos extern int vflg; 121 1.3 christos 122 1.1 christos 123 1.1 christos static int 124 1.1 christos p_bpf(struct file *f) 125 1.1 christos { 126 1.1 christos struct bpf_d bpf; 127 1.17 christos struct bpf_if bi; 128 1.17 christos struct ifnet ifn; 129 1.17 christos 130 1.17 christos strlcpy(ifn.if_xname, "???", sizeof(ifn.if_xname)); 131 1.1 christos 132 1.10 christos if (!KVM_READ(f->f_data, &bpf, sizeof(bpf))) { 133 1.1 christos dprintf("can't read bpf at %p for pid %d", f->f_data, Pid); 134 1.1 christos return 0; 135 1.1 christos } 136 1.17 christos if (bpf.bd_bif != NULL) { 137 1.17 christos if (!KVM_READ(bpf.bd_bif, &bi, sizeof(bi))) 138 1.17 christos dprintf("can't read bpf interface at %p for pid %d", 139 1.17 christos bpf.bd_bif, Pid); 140 1.17 christos if (bi.bif_ifp != NULL) 141 1.17 christos if (!KVM_READ(bi.bif_ifp, &ifn, sizeof(ifn))) 142 1.17 christos dprintf("can't read net interfsace" 143 1.17 christos " at %p for pid %d", bi.bif_ifp, Pid); 144 1.17 christos } 145 1.17 christos (void)printf("* bpf@%s rec=%lu, dr=%lu, cap=%lu, pid=%lu", ifn.if_xname, 146 1.1 christos bpf.bd_rcount, bpf.bd_dcount, bpf.bd_ccount, 147 1.1 christos (unsigned long)bpf.bd_pid); 148 1.1 christos if (bpf.bd_promisc) 149 1.1 christos (void)printf(", promisc"); 150 1.1 christos if (bpf.bd_immediate) 151 1.1 christos (void)printf(", immed"); 152 1.20 msaitoh if (bpf.bd_direction == BPF_D_IN) 153 1.20 msaitoh (void)printf(", in"); 154 1.20 msaitoh else if (bpf.bd_direction == BPF_D_INOUT) 155 1.20 msaitoh (void)printf(", inout"); 156 1.20 msaitoh else if (bpf.bd_direction == BPF_D_OUT) 157 1.20 msaitoh (void)printf(", out"); 158 1.9 alnsn if (bpf.bd_jitcode != NULL) 159 1.9 alnsn (void)printf(", jit"); 160 1.1 christos if (bpf.bd_async) 161 1.1 christos (void)printf(", asyncgrp=%lu", (unsigned long)bpf.bd_pgid); 162 1.1 christos if (bpf.bd_state == BPF_IDLE) 163 1.1 christos (void)printf(", idle"); 164 1.1 christos else if (bpf.bd_state == BPF_WAITING) 165 1.1 christos (void)printf(", waiting"); 166 1.1 christos else if (bpf.bd_state == BPF_TIMED_OUT) 167 1.1 christos (void)printf(", timeout"); 168 1.22 christos oprint(f, "\n"); 169 1.1 christos return 0; 170 1.1 christos } 171 1.1 christos 172 1.1 christos static int 173 1.10 christos p_sem(struct file *f) 174 1.10 christos { 175 1.10 christos ksem_t ks; 176 1.10 christos if (!KVM_READ(f->f_data, &ks, sizeof(ks))) { 177 1.10 christos dprintf("can't read sem at %p for pid %d", f->f_data, Pid); 178 1.10 christos return 0; 179 1.10 christos } 180 1.10 christos (void)printf("* ksem ref=%u, value=%u, waiters=%u, flags=0x%x, " 181 1.10 christos "mode=%o, uid=%u, gid=%u", ks.ks_ref, ks.ks_value, ks.ks_waiters, 182 1.10 christos ks.ks_flags, ks.ks_mode, ks.ks_uid, ks.ks_gid); 183 1.10 christos if (ks.ks_name && ks.ks_namelen) { 184 1.10 christos char buf[64]; 185 1.10 christos if (ks.ks_namelen >= sizeof(buf)) 186 1.10 christos ks.ks_namelen = sizeof(buf) - 1; 187 1.10 christos if (!KVM_READ(ks.ks_name, buf, ks.ks_namelen)) { 188 1.10 christos dprintf("can't read sem name at %p for pid %d", 189 1.10 christos ks.ks_name, Pid); 190 1.10 christos } else { 191 1.10 christos buf[ks.ks_namelen] = '\0'; 192 1.22 christos (void)printf(", name=%s", buf); 193 1.22 christos oprint(f, "\n"); 194 1.10 christos return 0; 195 1.10 christos } 196 1.10 christos } 197 1.22 christos oprint(f, "\n"); 198 1.10 christos return 0; 199 1.10 christos } 200 1.10 christos 201 1.10 christos static int 202 1.1 christos p_mqueue(struct file *f) 203 1.1 christos { 204 1.1 christos struct mqueue mq; 205 1.1 christos 206 1.10 christos if (!KVM_READ(f->f_data, &mq, sizeof(mq))) { 207 1.1 christos dprintf("can't read mqueue at %p for pid %d", f->f_data, Pid); 208 1.1 christos return 0; 209 1.1 christos } 210 1.22 christos (void)printf("* mqueue \"%s\"", mq.mq_name); 211 1.22 christos oprint(f, "\n"); 212 1.1 christos return 0; 213 1.1 christos } 214 1.2 christos 215 1.2 christos static int 216 1.2 christos p_kqueue(struct file *f) 217 1.2 christos { 218 1.2 christos struct kqueue kq; 219 1.2 christos 220 1.10 christos if (!KVM_READ(f->f_data, &kq, sizeof(kq))) { 221 1.2 christos dprintf("can't read kqueue at %p for pid %d", f->f_data, Pid); 222 1.2 christos return 0; 223 1.2 christos } 224 1.22 christos (void)printf("* kqueue pending %d", kq.kq_count); 225 1.22 christos oprint(f, "\n"); 226 1.2 christos return 0; 227 1.2 christos } 228 1.1 christos 229 1.24 isaki static int 230 1.24 isaki p_audio(struct file *f) 231 1.24 isaki { 232 1.24 isaki struct audio_file af; 233 1.24 isaki const char *devname; 234 1.24 isaki const char *modename; 235 1.24 isaki 236 1.24 isaki if (!KVM_READ(f->f_data, &af, sizeof(af))) { 237 1.24 isaki dprintf("can't read audio_file at %p for pid %d", 238 1.24 isaki f->f_data, Pid); 239 1.24 isaki return 0; 240 1.24 isaki } 241 1.24 isaki 242 1.24 isaki if (ISDEVAUDIO(af.dev)) { 243 1.24 isaki devname = "audio"; 244 1.24 isaki } else if (ISDEVSOUND(af.dev)) { 245 1.24 isaki devname = "sound"; 246 1.24 isaki } else if (ISDEVAUDIOCTL(af.dev)) { 247 1.24 isaki devname = "audioctl"; 248 1.24 isaki } else if (ISDEVMIXER(af.dev)) { 249 1.24 isaki devname = "mixer"; 250 1.24 isaki } else { 251 1.24 isaki devname = "???"; 252 1.24 isaki } 253 1.24 isaki 254 1.24 isaki if (af.ptrack && af.rtrack) { 255 1.24 isaki modename = "playback, record"; 256 1.24 isaki } else if (af.ptrack) { 257 1.24 isaki modename = "playback"; 258 1.24 isaki } else if (af.rtrack) { 259 1.24 isaki modename = "record"; 260 1.24 isaki } else { 261 1.24 isaki modename = "-"; 262 1.24 isaki } 263 1.24 isaki 264 1.24 isaki (void)printf("* audio@%s%d %s", devname, AUDIOUNIT(af.dev), modename); 265 1.24 isaki oprint(f, "\n"); 266 1.24 isaki return 0; 267 1.24 isaki } 268 1.24 isaki 269 1.25 christos static int 270 1.25 christos p_memfd_seal(int seen, int all, int target, const char *name) 271 1.25 christos { 272 1.25 christos if (all & target) 273 1.25 christos (void)printf("%s%s", (seen ? "|" : ""), name); 274 1.25 christos 275 1.25 christos return seen || (all & target); 276 1.25 christos } 277 1.25 christos 278 1.25 christos static int 279 1.25 christos p_memfd(struct file *f) 280 1.25 christos { 281 1.25 christos int seal_yet = 0; 282 1.25 christos struct memfd mfd; 283 1.25 christos 284 1.25 christos if (!KVM_READ(f->f_data, &mfd, sizeof(mfd))) { 285 1.25 christos dprintf("can't read memfd at %p for pid %d", f->f_data, Pid); 286 1.25 christos return 0; 287 1.25 christos } 288 1.25 christos (void)printf("* %s, seals=", mfd.mfd_name); 289 1.25 christos if (mfd.mfd_seals == 0) 290 1.25 christos (void)printf("0"); 291 1.25 christos else { 292 1.25 christos seal_yet = p_memfd_seal(seal_yet, mfd.mfd_seals, F_SEAL_SEAL, "F_SEAL_SEAL"); 293 1.25 christos seal_yet = p_memfd_seal(seal_yet, mfd.mfd_seals, F_SEAL_SHRINK, "F_SEAL_SHRINK"); 294 1.25 christos seal_yet = p_memfd_seal(seal_yet, mfd.mfd_seals, F_SEAL_GROW, "F_SEAL_GROW"); 295 1.25 christos seal_yet = p_memfd_seal(seal_yet, mfd.mfd_seals, F_SEAL_WRITE, "F_SEAL_WRITE"); 296 1.25 christos seal_yet = p_memfd_seal(seal_yet, mfd.mfd_seals, F_SEAL_FUTURE_WRITE, "F_SEAL_FUTURE_WRITE"); 297 1.25 christos } 298 1.25 christos 299 1.25 christos oprint(f, "\n"); 300 1.25 christos return 0; 301 1.25 christos } 302 1.25 christos 303 1.1 christos int 304 1.1 christos pmisc(struct file *f, const char *name) 305 1.1 christos { 306 1.1 christos size_t i; 307 1.1 christos if (nl[0].n_value == 0) { 308 1.1 christos int n; 309 1.1 christos if ((n = KVM_NLIST(nl)) == -1) 310 1.1 christos errx(1, "Cannot list kernel symbols (%s)", 311 1.1 christos KVM_GETERR()); 312 1.10 christos else if (n != 0 && vflg) { 313 1.10 christos char buf[1024]; 314 1.10 christos buf[0] = '\0'; 315 1.10 christos for (struct nlist *l = nl; l->n_name != NULL; l++) { 316 1.10 christos if (l->n_value != 0) 317 1.10 christos continue; 318 1.10 christos strlcat(buf, ", ", sizeof(buf)); 319 1.10 christos strlcat(buf, l->n_name, sizeof(buf)); 320 1.10 christos } 321 1.10 christos warnx("Could not find %d symbols: %s", n, buf + 2); 322 1.10 christos } 323 1.1 christos } 324 1.1 christos for (i = 0; i < NL_MAX; i++) 325 1.4 lukem if ((uintptr_t)f->f_ops == nl[i].n_value) 326 1.1 christos break; 327 1.1 christos switch (i) { 328 1.1 christos case NL_BPF: 329 1.1 christos return p_bpf(f); 330 1.1 christos case NL_MQUEUE: 331 1.1 christos return p_mqueue(f); 332 1.2 christos case NL_KQUEUE: 333 1.2 christos return p_kqueue(f); 334 1.15 christos case NL_RND: 335 1.23 christos printf("* random %p", f->f_data); 336 1.23 christos break; 337 1.10 christos case NL_SEM: 338 1.10 christos return p_sem(f); 339 1.1 christos case NL_TAP: 340 1.22 christos printf("* tap %lu", (unsigned long)(intptr_t)f->f_data); 341 1.22 christos break; 342 1.1 christos case NL_CRYPTO: 343 1.22 christos printf("* crypto %p", f->f_data); 344 1.22 christos break; 345 1.18 nat case NL_AUDIO: 346 1.24 isaki return p_audio(f); 347 1.18 nat case NL_PAD: 348 1.22 christos printf("* pad %p", f->f_data); 349 1.22 christos break; 350 1.25 christos case NL_MEMFD: 351 1.25 christos return p_memfd(f); 352 1.8 christos case NL_MAX: 353 1.22 christos printf("* %s ops=%p %p", name, f->f_ops, f->f_data); 354 1.22 christos break; 355 1.1 christos default: 356 1.22 christos printf("* %s %p", nl[i].n_name, f->f_data); 357 1.22 christos break; 358 1.1 christos } 359 1.22 christos oprint(f, "\n"); 360 1.22 christos return 0; 361 1.1 christos } 362