1 /*- 2 * SPDX-License-Identifier: BSD-4-Clause 3 * 4 * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav 5 * Copyright (c) 1999 Pierre Beyssac 6 * Copyright (c) 1993 Jan-Simon Pendry 7 * Copyright (c) 1993 8 * The Regents of the University of California. All rights reserved. 9 * 10 * This code is derived from software contributed to Berkeley by 11 * Jan-Simon Pendry. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94 42 */ 43 44 #include <sys/cdefs.h> 45 __FBSDID("$FreeBSD$"); 46 47 #include <sys/param.h> 48 #include <sys/queue.h> 49 #include <sys/blist.h> 50 #include <sys/conf.h> 51 #include <sys/exec.h> 52 #include <sys/fcntl.h> 53 #include <sys/filedesc.h> 54 #include <sys/jail.h> 55 #include <sys/kernel.h> 56 #include <sys/limits.h> 57 #include <sys/linker.h> 58 #include <sys/lock.h> 59 #include <sys/malloc.h> 60 #include <sys/msg.h> 61 #include <sys/mutex.h> 62 #include <sys/namei.h> 63 #include <sys/proc.h> 64 #include <sys/ptrace.h> 65 #include <sys/resourcevar.h> 66 #include <sys/resource.h> 67 #include <sys/sbuf.h> 68 #include <sys/sem.h> 69 #include <sys/shm.h> 70 #include <sys/smp.h> 71 #include <sys/socket.h> 72 #include <sys/syscallsubr.h> 73 #include <sys/sysctl.h> 74 #include <sys/sysent.h> 75 #include <sys/systm.h> 76 #include <sys/time.h> 77 #include <sys/tty.h> 78 #include <sys/user.h> 79 #include <sys/uuid.h> 80 #include <sys/vmmeter.h> 81 #include <sys/vnode.h> 82 #include <sys/bus.h> 83 #include <sys/uio.h> 84 85 #include <net/if.h> 86 #include <net/if_var.h> 87 #include <net/if_types.h> 88 89 #include <vm/vm.h> 90 #include <vm/vm_extern.h> 91 #include <vm/pmap.h> 92 #include <vm/vm_map.h> 93 #include <vm/vm_param.h> 94 #include <vm/vm_object.h> 95 #include <vm/swap_pager.h> 96 97 #include <machine/clock.h> 98 99 #include <geom/geom.h> 100 #include <geom/geom_int.h> 101 102 #if defined(__i386__) || defined(__amd64__) 103 #include <machine/cputypes.h> 104 #include <machine/md_var.h> 105 #endif /* __i386__ || __amd64__ */ 106 107 #include <compat/linux/linux.h> 108 #include <compat/linux/linux_emul.h> 109 #include <compat/linux/linux_mib.h> 110 #include <compat/linux/linux_misc.h> 111 #include <compat/linux/linux_util.h> 112 #include <fs/pseudofs/pseudofs.h> 113 #include <fs/procfs/procfs.h> 114 115 /* 116 * Various conversion macros 117 */ 118 #define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to jiffies */ 119 #define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to centiseconds */ 120 #define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ 121 #define B2K(x) ((x) >> 10) /* bytes to kbytes */ 122 #define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ 123 #define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ 124 #define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ 125 #define TV2J(x) ((x)->tv_sec * 100UL + (x)->tv_usec / 10000) 126 127 /** 128 * @brief Mapping of ki_stat in struct kinfo_proc to the linux state 129 * 130 * The linux procfs state field displays one of the characters RSDZTW to 131 * denote running, sleeping in an interruptible wait, waiting in an 132 * uninterruptible disk sleep, a zombie process, process is being traced 133 * or stopped, or process is paging respectively. 134 * 135 * Our struct kinfo_proc contains the variable ki_stat which contains a 136 * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK. 137 * 138 * This character array is used with ki_stati-1 as an index and tries to 139 * map our states to suitable linux states. 140 */ 141 static char linux_state[] = "RRSTZDD"; 142 143 /* 144 * Filler function for proc/meminfo 145 */ 146 static int 147 linprocfs_domeminfo(PFS_FILL_ARGS) 148 { 149 unsigned long memtotal; /* total memory in bytes */ 150 unsigned long memfree; /* free memory in bytes */ 151 unsigned long cached; /* page cache */ 152 unsigned long buffers; /* buffer cache */ 153 unsigned long long swaptotal; /* total swap space in bytes */ 154 unsigned long long swapused; /* used swap space in bytes */ 155 unsigned long long swapfree; /* free swap space in bytes */ 156 size_t sz; 157 int error, i, j; 158 159 memtotal = physmem * PAGE_SIZE; 160 memfree = (unsigned long)vm_free_count() * PAGE_SIZE; 161 swap_pager_status(&i, &j); 162 swaptotal = (unsigned long long)i * PAGE_SIZE; 163 swapused = (unsigned long long)j * PAGE_SIZE; 164 swapfree = swaptotal - swapused; 165 166 /* 167 * This value may exclude wired pages, but we have no good way of 168 * accounting for that. 169 */ 170 cached = 171 (vm_active_count() + vm_inactive_count() + vm_laundry_count()) * 172 PAGE_SIZE; 173 174 sz = sizeof(buffers); 175 error = kernel_sysctlbyname(curthread, "vfs.bufspace", &buffers, &sz, 176 NULL, 0, 0, 0); 177 if (error != 0) 178 buffers = 0; 179 180 sbuf_printf(sb, 181 "MemTotal: %9lu kB\n" 182 "MemFree: %9lu kB\n" 183 "Buffers: %9lu kB\n" 184 "Cached: %9lu kB\n" 185 "SwapTotal:%9llu kB\n" 186 "SwapFree: %9llu kB\n", 187 B2K(memtotal), B2K(memfree), B2K(buffers), 188 B2K(cached), B2K(swaptotal), B2K(swapfree)); 189 190 return (0); 191 } 192 193 #if defined(__i386__) || defined(__amd64__) 194 /* 195 * Filler function for proc/cpuinfo (i386 & amd64 version) 196 */ 197 static int 198 linprocfs_docpuinfo(PFS_FILL_ARGS) 199 { 200 int hw_model[2]; 201 char model[128]; 202 uint64_t freq; 203 size_t size; 204 u_int cache_size[4]; 205 u_int regs[4] = { 0 }; 206 int fqmhz, fqkhz; 207 int i, j; 208 209 /* 210 * We default the flags to include all non-conflicting flags, 211 * and the Intel versions of conflicting flags. 212 */ 213 static char *cpu_feature_names[] = { 214 /* 0 */ "fpu", "vme", "de", "pse", 215 /* 4 */ "tsc", "msr", "pae", "mce", 216 /* 8 */ "cx8", "apic", "", "sep", 217 /* 12 */ "mtrr", "pge", "mca", "cmov", 218 /* 16 */ "pat", "pse36", "pn", "clflush", 219 /* 20 */ "", "dts", "acpi", "mmx", 220 /* 24 */ "fxsr", "sse", "sse2", "ss", 221 /* 28 */ "ht", "tm", "ia64", "pbe" 222 }; 223 224 static char *amd_feature_names[] = { 225 /* 0 */ "", "", "", "", 226 /* 4 */ "", "", "", "", 227 /* 8 */ "", "", "", "syscall", 228 /* 12 */ "", "", "", "", 229 /* 16 */ "", "", "", "mp", 230 /* 20 */ "nx", "", "mmxext", "", 231 /* 24 */ "", "fxsr_opt", "pdpe1gb", "rdtscp", 232 /* 28 */ "", "lm", "3dnowext", "3dnow" 233 }; 234 235 static char *cpu_feature2_names[] = { 236 /* 0 */ "pni", "pclmulqdq", "dtes64", "monitor", 237 /* 4 */ "ds_cpl", "vmx", "smx", "est", 238 /* 8 */ "tm2", "ssse3", "cid", "sdbg", 239 /* 12 */ "fma", "cx16", "xtpr", "pdcm", 240 /* 16 */ "", "pcid", "dca", "sse4_1", 241 /* 20 */ "sse4_2", "x2apic", "movbe", "popcnt", 242 /* 24 */ "tsc_deadline_timer", "aes", "xsave", "", 243 /* 28 */ "avx", "f16c", "rdrand", "hypervisor" 244 }; 245 246 static char *amd_feature2_names[] = { 247 /* 0 */ "lahf_lm", "cmp_legacy", "svm", "extapic", 248 /* 4 */ "cr8_legacy", "abm", "sse4a", "misalignsse", 249 /* 8 */ "3dnowprefetch", "osvw", "ibs", "xop", 250 /* 12 */ "skinit", "wdt", "", "lwp", 251 /* 16 */ "fma4", "tce", "", "nodeid_msr", 252 /* 20 */ "", "tbm", "topoext", "perfctr_core", 253 /* 24 */ "perfctr_nb", "", "bpext", "ptsc", 254 /* 28 */ "perfctr_llc", "mwaitx", "", "" 255 }; 256 257 static char *cpu_stdext_feature_names[] = { 258 /* 0 */ "fsgsbase", "tsc_adjust", "sgx", "bmi1", 259 /* 4 */ "hle", "avx2", "", "smep", 260 /* 8 */ "bmi2", "erms", "invpcid", "rtm", 261 /* 12 */ "cqm", "", "mpx", "rdt_a", 262 /* 16 */ "avx512f", "avx512dq", "rdseed", "adx", 263 /* 20 */ "smap", "avx512ifma", "", "clflushopt", 264 /* 24 */ "clwb", "intel_pt", "avx512pf", "avx512er", 265 /* 28 */ "avx512cd", "sha_ni", "avx512bw", "avx512vl" 266 }; 267 268 static char *cpu_stdext_feature2_names[] = { 269 /* 0 */ "prefetchwt1", "avx512vbmi", "umip", "pku", 270 /* 4 */ "ospke", "waitpkg", "avx512_vbmi2", "", 271 /* 8 */ "gfni", "vaes", "vpclmulqdq", "avx512_vnni", 272 /* 12 */ "avx512_bitalg", "", "avx512_vpopcntdq", "", 273 /* 16 */ "", "", "", "", 274 /* 20 */ "", "", "rdpid", "", 275 /* 24 */ "", "cldemote", "", "movdiri", 276 /* 28 */ "movdir64b", "enqcmd", "sgx_lc", "" 277 }; 278 279 static char *cpu_stdext_feature3_names[] = { 280 /* 0 */ "", "", "avx512_4vnniw", "avx512_4fmaps", 281 /* 4 */ "fsrm", "", "", "", 282 /* 8 */ "avx512_vp2intersect", "", "md_clear", "", 283 /* 12 */ "", "", "", "", 284 /* 16 */ "", "", "pconfig", "", 285 /* 20 */ "", "", "", "", 286 /* 24 */ "", "", "ibrs", "stibp", 287 /* 28 */ "flush_l1d", "arch_capabilities", "core_capabilities", "ssbd" 288 }; 289 290 static char *cpu_stdext_feature_l1_names[] = { 291 /* 0 */ "xsaveopt", "xsavec", "xgetbv1", "xsaves", 292 /* 4 */ "xfd" 293 }; 294 295 static char *power_flags[] = { 296 "ts", "fid", "vid", 297 "ttp", "tm", "stc", 298 "100mhzsteps", "hwpstate", "", 299 "cpb", "eff_freq_ro", "proc_feedback", 300 "acc_power", 301 }; 302 303 hw_model[0] = CTL_HW; 304 hw_model[1] = HW_MODEL; 305 model[0] = '\0'; 306 size = sizeof(model); 307 if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0) 308 strcpy(model, "unknown"); 309 #ifdef __i386__ 310 switch (cpu_vendor_id) { 311 case CPU_VENDOR_AMD: 312 if (cpu_class < CPUCLASS_686) 313 cpu_feature_names[16] = "fcmov"; 314 break; 315 case CPU_VENDOR_CYRIX: 316 cpu_feature_names[24] = "cxmmx"; 317 break; 318 } 319 #endif 320 if (cpu_exthigh >= 0x80000006) 321 do_cpuid(0x80000006, cache_size); 322 else 323 memset(cache_size, 0, sizeof(cache_size)); 324 for (i = 0; i < mp_ncpus; ++i) { 325 fqmhz = 0; 326 fqkhz = 0; 327 freq = atomic_load_acq_64(&tsc_freq); 328 if (freq != 0) { 329 fqmhz = (freq + 4999) / 1000000; 330 fqkhz = ((freq + 4999) / 10000) % 100; 331 } 332 sbuf_printf(sb, 333 "processor\t: %d\n" 334 "vendor_id\t: %.20s\n" 335 "cpu family\t: %u\n" 336 "model\t\t: %u\n" 337 "model name\t: %s\n" 338 "stepping\t: %u\n" 339 "cpu MHz\t\t: %d.%02d\n" 340 "cache size\t: %d KB\n" 341 "physical id\t: %d\n" 342 "siblings\t: %d\n" 343 "core id\t\t: %d\n" 344 "cpu cores\t: %d\n" 345 "apicid\t\t: %d\n" 346 "initial apicid\t: %d\n" 347 "fpu\t\t: %s\n" 348 "fpu_exception\t: %s\n" 349 "cpuid level\t: %d\n" 350 "wp\t\t: %s\n", 351 i, cpu_vendor, CPUID_TO_FAMILY(cpu_id), 352 CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING, 353 fqmhz, fqkhz, 354 (cache_size[2] >> 16), 0, mp_ncpus, i, mp_ncpus, 355 i, i, /*cpu_id & CPUID_LOCAL_APIC_ID ??*/ 356 (cpu_feature & CPUID_FPU) ? "yes" : "no", "yes", 357 CPUID_TO_FAMILY(cpu_id), "yes"); 358 sbuf_cat(sb, "flags\t\t:"); 359 for (j = 0; j < nitems(cpu_feature_names); j++) 360 if (cpu_feature & (1 << j) && 361 cpu_feature_names[j][0] != '\0') 362 sbuf_printf(sb, " %s", cpu_feature_names[j]); 363 for (j = 0; j < nitems(amd_feature_names); j++) 364 if (amd_feature & (1 << j) && 365 amd_feature_names[j][0] != '\0') 366 sbuf_printf(sb, " %s", amd_feature_names[j]); 367 for (j = 0; j < nitems(cpu_feature2_names); j++) 368 if (cpu_feature2 & (1 << j) && 369 cpu_feature2_names[j][0] != '\0') 370 sbuf_printf(sb, " %s", cpu_feature2_names[j]); 371 for (j = 0; j < nitems(amd_feature2_names); j++) 372 if (amd_feature2 & (1 << j) && 373 amd_feature2_names[j][0] != '\0') 374 sbuf_printf(sb, " %s", amd_feature2_names[j]); 375 for (j = 0; j < nitems(cpu_stdext_feature_names); j++) 376 if (cpu_stdext_feature & (1 << j) && 377 cpu_stdext_feature_names[j][0] != '\0') 378 sbuf_printf(sb, " %s", 379 cpu_stdext_feature_names[j]); 380 if (tsc_is_invariant) 381 sbuf_cat(sb, " constant_tsc"); 382 for (j = 0; j < nitems(cpu_stdext_feature2_names); j++) 383 if (cpu_stdext_feature2 & (1 << j) && 384 cpu_stdext_feature2_names[j][0] != '\0') 385 sbuf_printf(sb, " %s", 386 cpu_stdext_feature2_names[j]); 387 for (j = 0; j < nitems(cpu_stdext_feature3_names); j++) 388 if (cpu_stdext_feature3 & (1 << j) && 389 cpu_stdext_feature3_names[j][0] != '\0') 390 sbuf_printf(sb, " %s", 391 cpu_stdext_feature3_names[j]); 392 if ((cpu_feature2 & CPUID2_XSAVE) != 0) { 393 cpuid_count(0xd, 0x1, regs); 394 for (j = 0; j < nitems(cpu_stdext_feature_l1_names); j++) 395 if (regs[0] & (1 << j) && 396 cpu_stdext_feature_l1_names[j][0] != '\0') 397 sbuf_printf(sb, " %s", 398 cpu_stdext_feature_l1_names[j]); 399 } 400 sbuf_cat(sb, "\n"); 401 sbuf_printf(sb, 402 "bugs\t\t: %s\n" 403 "bogomips\t: %d.%02d\n" 404 "clflush size\t: %d\n" 405 "cache_alignment\t: %d\n" 406 "address sizes\t: %d bits physical, %d bits virtual\n", 407 #if defined(I586_CPU) && !defined(NO_F00F_HACK) 408 (has_f00f_bug) ? "Intel F00F" : "", 409 #else 410 "", 411 #endif 412 fqmhz * 2, fqkhz, 413 cpu_clflush_line_size, cpu_clflush_line_size, 414 cpu_maxphyaddr, 415 (cpu_maxphyaddr > 32) ? 48 : 0); 416 sbuf_cat(sb, "power management: "); 417 for (j = 0; j < nitems(power_flags); j++) 418 if (amd_pminfo & (1 << j)) 419 sbuf_printf(sb, " %s", power_flags[j]); 420 sbuf_cat(sb, "\n\n"); 421 422 /* XXX per-cpu vendor / class / model / id? */ 423 } 424 sbuf_cat(sb, "\n"); 425 426 return (0); 427 } 428 #else 429 /* ARM64TODO: implement non-stubbed linprocfs_docpuinfo */ 430 static int 431 linprocfs_docpuinfo(PFS_FILL_ARGS) 432 { 433 int i; 434 435 for (i = 0; i < mp_ncpus; ++i) { 436 sbuf_printf(sb, 437 "processor\t: %d\n" 438 "BogoMIPS\t: %d.%02d\n", 439 i, 0, 0); 440 sbuf_cat(sb, "Features\t: "); 441 sbuf_cat(sb, "\n"); 442 sbuf_printf(sb, 443 "CPU implementer\t: \n" 444 "CPU architecture: \n" 445 "CPU variant\t: 0x%x\n" 446 "CPU part\t: 0x%x\n" 447 "CPU revision\t: %d\n", 448 0, 0, 0); 449 sbuf_cat(sb, "\n"); 450 } 451 452 return (0); 453 } 454 #endif /* __i386__ || __amd64__ */ 455 456 static const char *path_slash_sys = "/sys"; 457 static const char *fstype_sysfs = "sysfs"; 458 459 static int 460 _mtab_helper(const struct pfs_node *pn, const struct statfs *sp, 461 const char **mntfrom, const char **mntto, const char **fstype) 462 { 463 /* determine device name */ 464 *mntfrom = sp->f_mntfromname; 465 466 /* determine mount point */ 467 *mntto = sp->f_mntonname; 468 469 /* determine fs type */ 470 *fstype = sp->f_fstypename; 471 if (strcmp(*fstype, pn->pn_info->pi_name) == 0) 472 *mntfrom = *fstype = "proc"; 473 else if (strcmp(*fstype, "procfs") == 0) 474 return (ECANCELED); 475 476 if (strcmp(*fstype, "autofs") == 0) { 477 /* 478 * FreeBSD uses eg "map -hosts", whereas Linux 479 * expects just "-hosts". 480 */ 481 if (strncmp(*mntfrom, "map ", 4) == 0) 482 *mntfrom += 4; 483 } 484 485 if (strcmp(*fstype, "linsysfs") == 0) { 486 *mntfrom = path_slash_sys; 487 *fstype = fstype_sysfs; 488 } else { 489 /* For Linux msdosfs is called vfat */ 490 if (strcmp(*fstype, "msdosfs") == 0) 491 *fstype = "vfat"; 492 } 493 return (0); 494 } 495 496 static void 497 _sbuf_mntoptions_helper(struct sbuf *sb, uint64_t f_flags) 498 { 499 sbuf_cat(sb, (f_flags & MNT_RDONLY) ? "ro" : "rw"); 500 #define ADD_OPTION(opt, name) \ 501 if (f_flags & (opt)) sbuf_cat(sb, "," name); 502 ADD_OPTION(MNT_SYNCHRONOUS, "sync"); 503 ADD_OPTION(MNT_NOEXEC, "noexec"); 504 ADD_OPTION(MNT_NOSUID, "nosuid"); 505 ADD_OPTION(MNT_UNION, "union"); 506 ADD_OPTION(MNT_ASYNC, "async"); 507 ADD_OPTION(MNT_SUIDDIR, "suiddir"); 508 ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow"); 509 ADD_OPTION(MNT_NOATIME, "noatime"); 510 #undef ADD_OPTION 511 } 512 513 /* 514 * Filler function for proc/mtab and proc/<pid>/mounts. 515 * 516 * /proc/mtab doesn't exist in Linux' procfs, but is included here so 517 * users can symlink /compat/linux/etc/mtab to /proc/mtab 518 */ 519 static int 520 linprocfs_domtab(PFS_FILL_ARGS) 521 { 522 struct nameidata nd; 523 const char *lep, *mntto, *mntfrom, *fstype; 524 char *dlep, *flep; 525 size_t lep_len; 526 int error; 527 struct statfs *buf, *sp; 528 size_t count; 529 530 /* resolve symlinks etc. in the emulation tree prefix */ 531 /* 532 * Ideally, this would use the current chroot rather than some 533 * hardcoded path. 534 */ 535 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path); 536 flep = NULL; 537 error = namei(&nd); 538 lep = linux_emul_path; 539 if (error == 0) { 540 if (vn_fullpath(nd.ni_vp, &dlep, &flep) == 0) 541 lep = dlep; 542 vrele(nd.ni_vp); 543 } 544 lep_len = strlen(lep); 545 546 buf = NULL; 547 error = kern_getfsstat(td, &buf, SIZE_T_MAX, &count, 548 UIO_SYSSPACE, MNT_WAIT); 549 if (error != 0) { 550 free(buf, M_TEMP); 551 free(flep, M_TEMP); 552 return (error); 553 } 554 555 for (sp = buf; count > 0; sp++, count--) { 556 error = _mtab_helper(pn, sp, &mntfrom, &mntto, &fstype); 557 if (error != 0) { 558 MPASS(error == ECANCELED); 559 continue; 560 } 561 562 /* determine mount point */ 563 if (strncmp(mntto, lep, lep_len) == 0 && mntto[lep_len] == '/') 564 mntto += lep_len; 565 566 sbuf_printf(sb, "%s %s %s ", mntfrom, mntto, fstype); 567 _sbuf_mntoptions_helper(sb, sp->f_flags); 568 /* a real Linux mtab will also show NFS options */ 569 sbuf_printf(sb, " 0 0\n"); 570 } 571 572 free(buf, M_TEMP); 573 free(flep, M_TEMP); 574 return (error); 575 } 576 577 static int 578 linprocfs_doprocmountinfo(PFS_FILL_ARGS) 579 { 580 struct nameidata nd; 581 const char *mntfrom, *mntto, *fstype; 582 const char *lep; 583 char *dlep, *flep; 584 struct statfs *buf, *sp; 585 size_t count, lep_len; 586 int error; 587 588 /* 589 * Ideally, this would use the current chroot rather than some 590 * hardcoded path. 591 */ 592 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path); 593 flep = NULL; 594 error = namei(&nd); 595 lep = linux_emul_path; 596 if (error == 0) { 597 if (vn_fullpath(nd.ni_vp, &dlep, &flep) == 0) 598 lep = dlep; 599 vrele(nd.ni_vp); 600 } 601 lep_len = strlen(lep); 602 603 buf = NULL; 604 error = kern_getfsstat(td, &buf, SIZE_T_MAX, &count, 605 UIO_SYSSPACE, MNT_WAIT); 606 if (error != 0) 607 goto out; 608 609 for (sp = buf; count > 0; sp++, count--) { 610 error = _mtab_helper(pn, sp, &mntfrom, &mntto, &fstype); 611 if (error != 0) { 612 MPASS(error == ECANCELED); 613 continue; 614 } 615 616 if (strncmp(mntto, lep, lep_len) == 0 && mntto[lep_len] == '/') 617 mntto += lep_len; 618 #if 0 619 /* 620 * If the prefix is a chroot, and this mountpoint is not under 621 * the prefix, we should skip it. Leave it for now for 622 * consistency with procmtab above. 623 */ 624 else 625 continue; 626 #endif 627 628 /* 629 * (1) mount id 630 * 631 * (2) parent mount id -- we don't have this cheaply, so 632 * provide a dummy value 633 * 634 * (3) major:minor -- ditto 635 * 636 * (4) root filesystem mount -- probably a namespaces thing 637 * 638 * (5) mountto path 639 */ 640 sbuf_printf(sb, "%u 0 0:0 / %s ", 641 sp->f_fsid.val[0] ^ sp->f_fsid.val[1], mntto); 642 /* (6) mount options */ 643 _sbuf_mntoptions_helper(sb, sp->f_flags); 644 /* 645 * (7) zero or more optional fields -- again, namespace related 646 * 647 * (8) End of variable length fields separator ("-") 648 * 649 * (9) fstype 650 * 651 * (10) mount from 652 * 653 * (11) "superblock" options -- like (6), but different 654 * semantics in Linux 655 */ 656 sbuf_printf(sb, " - %s %s %s\n", fstype, mntfrom, 657 (sp->f_flags & MNT_RDONLY) ? "ro" : "rw"); 658 } 659 660 error = 0; 661 out: 662 free(buf, M_TEMP); 663 free(flep, M_TEMP); 664 return (error); 665 } 666 667 /* 668 * Filler function for proc/partitions 669 */ 670 static int 671 linprocfs_dopartitions(PFS_FILL_ARGS) 672 { 673 struct g_class *cp; 674 struct g_geom *gp; 675 struct g_provider *pp; 676 int major, minor; 677 678 g_topology_lock(); 679 sbuf_printf(sb, "major minor #blocks name rio rmerge rsect " 680 "ruse wio wmerge wsect wuse running use aveq\n"); 681 682 LIST_FOREACH(cp, &g_classes, class) { 683 if (strcmp(cp->name, "DISK") == 0 || 684 strcmp(cp->name, "PART") == 0) 685 LIST_FOREACH(gp, &cp->geom, geom) { 686 LIST_FOREACH(pp, &gp->provider, provider) { 687 if (linux_driver_get_major_minor( 688 pp->name, &major, &minor) != 0) { 689 major = 0; 690 minor = 0; 691 } 692 sbuf_printf(sb, "%d %d %lld %s " 693 "%d %d %d %d %d " 694 "%d %d %d %d %d %d\n", 695 major, minor, 696 (long long)pp->mediasize, pp->name, 697 0, 0, 0, 0, 0, 698 0, 0, 0, 0, 0, 0); 699 } 700 } 701 } 702 g_topology_unlock(); 703 704 return (0); 705 } 706 707 /* 708 * Filler function for proc/stat 709 * 710 * Output depends on kernel version: 711 * 712 * v2.5.40 <= 713 * user nice system idle 714 * v2.5.41 715 * user nice system idle iowait 716 * v2.6.11 717 * user nice system idle iowait irq softirq steal 718 * v2.6.24 719 * user nice system idle iowait irq softirq steal guest 720 * v2.6.33 >= 721 * user nice system idle iowait irq softirq steal guest guest_nice 722 */ 723 static int 724 linprocfs_dostat(PFS_FILL_ARGS) 725 { 726 struct pcpu *pcpu; 727 long cp_time[CPUSTATES]; 728 long *cp; 729 struct timeval boottime; 730 int i; 731 char *zero_pad; 732 bool has_intr = true; 733 734 if (linux_kernver(td) >= LINUX_KERNVER(2,6,33)) { 735 zero_pad = " 0 0 0 0\n"; 736 } else if (linux_kernver(td) >= LINUX_KERNVER(2,6,24)) { 737 zero_pad = " 0 0 0\n"; 738 } else if (linux_kernver(td) >= LINUX_KERNVER(2,6,11)) { 739 zero_pad = " 0 0\n"; 740 } else if (linux_kernver(td) >= LINUX_KERNVER(2,5,41)) { 741 has_intr = false; 742 zero_pad = " 0\n"; 743 } else { 744 has_intr = false; 745 zero_pad = "\n"; 746 } 747 748 read_cpu_time(cp_time); 749 getboottime(&boottime); 750 /* Parameters common to all versions */ 751 sbuf_printf(sb, "cpu %lu %lu %lu %lu", 752 T2J(cp_time[CP_USER]), 753 T2J(cp_time[CP_NICE]), 754 T2J(cp_time[CP_SYS]), 755 T2J(cp_time[CP_IDLE])); 756 757 /* Print interrupt stats if available */ 758 if (has_intr) { 759 sbuf_printf(sb, " 0 %lu", T2J(cp_time[CP_INTR])); 760 } 761 762 /* Pad out remaining fields depending on version */ 763 sbuf_printf(sb, "%s", zero_pad); 764 765 CPU_FOREACH(i) { 766 pcpu = pcpu_find(i); 767 cp = pcpu->pc_cp_time; 768 sbuf_printf(sb, "cpu%d %lu %lu %lu %lu", i, 769 T2J(cp[CP_USER]), 770 T2J(cp[CP_NICE]), 771 T2J(cp[CP_SYS]), 772 T2J(cp[CP_IDLE])); 773 774 if (has_intr) { 775 sbuf_printf(sb, " 0 %lu", T2J(cp[CP_INTR])); 776 } 777 778 sbuf_printf(sb, "%s", zero_pad); 779 } 780 sbuf_printf(sb, 781 "disk 0 0 0 0\n" 782 "page %ju %ju\n" 783 "swap %ju %ju\n" 784 "intr %ju\n" 785 "ctxt %ju\n" 786 "btime %lld\n", 787 (uintmax_t)VM_CNT_FETCH(v_vnodepgsin), 788 (uintmax_t)VM_CNT_FETCH(v_vnodepgsout), 789 (uintmax_t)VM_CNT_FETCH(v_swappgsin), 790 (uintmax_t)VM_CNT_FETCH(v_swappgsout), 791 (uintmax_t)VM_CNT_FETCH(v_intr), 792 (uintmax_t)VM_CNT_FETCH(v_swtch), 793 (long long)boottime.tv_sec); 794 return (0); 795 } 796 797 static int 798 linprocfs_doswaps(PFS_FILL_ARGS) 799 { 800 struct xswdev xsw; 801 uintmax_t total, used; 802 int n; 803 char devname[SPECNAMELEN + 1]; 804 805 sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"); 806 for (n = 0; ; n++) { 807 if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0) 808 break; 809 total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024; 810 used = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024; 811 812 /* 813 * The space and not tab after the device name is on 814 * purpose. Linux does so. 815 */ 816 sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n", 817 devname, total, used); 818 } 819 return (0); 820 } 821 822 /* 823 * Filler function for proc/uptime 824 */ 825 static int 826 linprocfs_douptime(PFS_FILL_ARGS) 827 { 828 long cp_time[CPUSTATES]; 829 struct timeval tv; 830 831 getmicrouptime(&tv); 832 read_cpu_time(cp_time); 833 sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n", 834 (long long)tv.tv_sec, tv.tv_usec / 10000, 835 T2S(cp_time[CP_IDLE] / mp_ncpus), 836 T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100); 837 return (0); 838 } 839 840 /* 841 * Get OS build date 842 */ 843 static void 844 linprocfs_osbuild(struct thread *td, struct sbuf *sb) 845 { 846 #if 0 847 char osbuild[256]; 848 char *cp1, *cp2; 849 850 strncpy(osbuild, version, 256); 851 osbuild[255] = '\0'; 852 cp1 = strstr(osbuild, "\n"); 853 cp2 = strstr(osbuild, ":"); 854 if (cp1 && cp2) { 855 *cp1 = *cp2 = '\0'; 856 cp1 = strstr(osbuild, "#"); 857 } else 858 cp1 = NULL; 859 if (cp1) 860 sbuf_printf(sb, "%s%s", cp1, cp2 + 1); 861 else 862 #endif 863 sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977"); 864 } 865 866 /* 867 * Get OS builder 868 */ 869 static void 870 linprocfs_osbuilder(struct thread *td, struct sbuf *sb) 871 { 872 #if 0 873 char builder[256]; 874 char *cp; 875 876 cp = strstr(version, "\n "); 877 if (cp) { 878 strncpy(builder, cp + 5, 256); 879 builder[255] = '\0'; 880 cp = strstr(builder, ":"); 881 if (cp) 882 *cp = '\0'; 883 } 884 if (cp) 885 sbuf_cat(sb, builder); 886 else 887 #endif 888 sbuf_cat(sb, "des@freebsd.org"); 889 } 890 891 /* 892 * Filler function for proc/version 893 */ 894 static int 895 linprocfs_doversion(PFS_FILL_ARGS) 896 { 897 char osname[LINUX_MAX_UTSNAME]; 898 char osrelease[LINUX_MAX_UTSNAME]; 899 900 linux_get_osname(td, osname); 901 linux_get_osrelease(td, osrelease); 902 sbuf_printf(sb, "%s version %s (", osname, osrelease); 903 linprocfs_osbuilder(td, sb); 904 sbuf_cat(sb, ") (gcc version " __VERSION__ ") "); 905 linprocfs_osbuild(td, sb); 906 sbuf_cat(sb, "\n"); 907 908 return (0); 909 } 910 911 /* 912 * Filler function for proc/loadavg 913 */ 914 static int 915 linprocfs_doloadavg(PFS_FILL_ARGS) 916 { 917 918 sbuf_printf(sb, 919 "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 920 (int)(averunnable.ldavg[0] / averunnable.fscale), 921 (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 922 (int)(averunnable.ldavg[1] / averunnable.fscale), 923 (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 924 (int)(averunnable.ldavg[2] / averunnable.fscale), 925 (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 926 1, /* number of running tasks */ 927 nprocs, /* number of tasks */ 928 lastpid /* the last pid */ 929 ); 930 return (0); 931 } 932 933 static int 934 linprocfs_get_tty_nr(struct proc *p) 935 { 936 struct session *sp; 937 const char *ttyname; 938 int error, major, minor, nr; 939 940 PROC_LOCK_ASSERT(p, MA_OWNED); 941 sx_assert(&proctree_lock, SX_LOCKED); 942 943 if ((p->p_flag & P_CONTROLT) == 0) 944 return (-1); 945 946 sp = p->p_pgrp->pg_session; 947 if (sp == NULL) 948 return (-1); 949 950 ttyname = devtoname(sp->s_ttyp->t_dev); 951 error = linux_driver_get_major_minor(ttyname, &major, &minor); 952 if (error != 0) 953 return (-1); 954 955 nr = makedev(major, minor); 956 return (nr); 957 } 958 959 /* 960 * Filler function for proc/pid/stat 961 */ 962 static int 963 linprocfs_doprocstat(PFS_FILL_ARGS) 964 { 965 struct kinfo_proc kp; 966 struct timeval boottime; 967 char state; 968 static int ratelimit = 0; 969 int tty_nr; 970 vm_offset_t startcode, startdata; 971 972 getboottime(&boottime); 973 sx_slock(&proctree_lock); 974 PROC_LOCK(p); 975 fill_kinfo_proc(p, &kp); 976 tty_nr = linprocfs_get_tty_nr(p); 977 sx_sunlock(&proctree_lock); 978 if (p->p_vmspace) { 979 startcode = (vm_offset_t)p->p_vmspace->vm_taddr; 980 startdata = (vm_offset_t)p->p_vmspace->vm_daddr; 981 } else { 982 startcode = 0; 983 startdata = 0; 984 } 985 sbuf_printf(sb, "%d", p->p_pid); 986 #define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg) 987 PS_ADD("comm", "(%s)", p->p_comm); 988 if (kp.ki_stat > sizeof(linux_state)) { 989 state = 'R'; 990 991 if (ratelimit == 0) { 992 printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n", 993 kp.ki_stat, sizeof(linux_state)); 994 ++ratelimit; 995 } 996 } else 997 state = linux_state[kp.ki_stat - 1]; 998 PS_ADD("state", "%c", state); 999 PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); 1000 PS_ADD("pgrp", "%d", p->p_pgid); 1001 PS_ADD("session", "%d", p->p_session->s_sid); 1002 PROC_UNLOCK(p); 1003 PS_ADD("tty", "%d", tty_nr); 1004 PS_ADD("tpgid", "%d", kp.ki_tpgid); 1005 PS_ADD("flags", "%u", 0); /* XXX */ 1006 PS_ADD("minflt", "%lu", kp.ki_rusage.ru_minflt); 1007 PS_ADD("cminflt", "%lu", kp.ki_rusage_ch.ru_minflt); 1008 PS_ADD("majflt", "%lu", kp.ki_rusage.ru_majflt); 1009 PS_ADD("cmajflt", "%lu", kp.ki_rusage_ch.ru_majflt); 1010 PS_ADD("utime", "%ld", TV2J(&kp.ki_rusage.ru_utime)); 1011 PS_ADD("stime", "%ld", TV2J(&kp.ki_rusage.ru_stime)); 1012 PS_ADD("cutime", "%ld", TV2J(&kp.ki_rusage_ch.ru_utime)); 1013 PS_ADD("cstime", "%ld", TV2J(&kp.ki_rusage_ch.ru_stime)); 1014 PS_ADD("priority", "%d", kp.ki_pri.pri_user); 1015 PS_ADD("nice", "%d", kp.ki_nice); /* 19 (nicest) to -19 */ 1016 PS_ADD("0", "%d", 0); /* removed field */ 1017 PS_ADD("itrealvalue", "%d", 0); /* XXX */ 1018 PS_ADD("starttime", "%lu", TV2J(&kp.ki_start) - TV2J(&boottime)); 1019 PS_ADD("vsize", "%ju", P2K((uintmax_t)kp.ki_size)); 1020 PS_ADD("rss", "%ju", (uintmax_t)kp.ki_rssize); 1021 PS_ADD("rlim", "%lu", kp.ki_rusage.ru_maxrss); 1022 PS_ADD("startcode", "%ju", (uintmax_t)startcode); 1023 PS_ADD("endcode", "%ju", (uintmax_t)startdata); 1024 PS_ADD("startstack", "%u", 0); /* XXX */ 1025 PS_ADD("kstkesp", "%u", 0); /* XXX */ 1026 PS_ADD("kstkeip", "%u", 0); /* XXX */ 1027 PS_ADD("signal", "%u", 0); /* XXX */ 1028 PS_ADD("blocked", "%u", 0); /* XXX */ 1029 PS_ADD("sigignore", "%u", 0); /* XXX */ 1030 PS_ADD("sigcatch", "%u", 0); /* XXX */ 1031 PS_ADD("wchan", "%u", 0); /* XXX */ 1032 PS_ADD("nswap", "%lu", kp.ki_rusage.ru_nswap); 1033 PS_ADD("cnswap", "%lu", kp.ki_rusage_ch.ru_nswap); 1034 PS_ADD("exitsignal", "%d", 0); /* XXX */ 1035 PS_ADD("processor", "%u", kp.ki_lastcpu); 1036 PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */ 1037 PS_ADD("policy", "%u", kp.ki_pri.pri_class); /* >= 2.5.19 */ 1038 #undef PS_ADD 1039 sbuf_putc(sb, '\n'); 1040 1041 return (0); 1042 } 1043 1044 /* 1045 * Filler function for proc/pid/statm 1046 */ 1047 static int 1048 linprocfs_doprocstatm(PFS_FILL_ARGS) 1049 { 1050 struct kinfo_proc kp; 1051 segsz_t lsize; 1052 1053 sx_slock(&proctree_lock); 1054 PROC_LOCK(p); 1055 fill_kinfo_proc(p, &kp); 1056 PROC_UNLOCK(p); 1057 sx_sunlock(&proctree_lock); 1058 1059 /* 1060 * See comments in linprocfs_doprocstatus() regarding the 1061 * computation of lsize. 1062 */ 1063 /* size resident share trs drs lrs dt */ 1064 sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size)); 1065 sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize); 1066 sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */ 1067 sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize); 1068 sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize)); 1069 lsize = B2P(kp.ki_size) - kp.ki_dsize - 1070 kp.ki_ssize - kp.ki_tsize - 1; 1071 sbuf_printf(sb, "%ju ", (uintmax_t)lsize); 1072 sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */ 1073 1074 return (0); 1075 } 1076 1077 /* 1078 * Filler function for proc/pid/status 1079 */ 1080 static int 1081 linprocfs_doprocstatus(PFS_FILL_ARGS) 1082 { 1083 struct kinfo_proc kp; 1084 char *state; 1085 segsz_t lsize; 1086 struct thread *td2; 1087 struct sigacts *ps; 1088 l_sigset_t siglist, sigignore, sigcatch; 1089 int i; 1090 1091 sx_slock(&proctree_lock); 1092 PROC_LOCK(p); 1093 td2 = FIRST_THREAD_IN_PROC(p); 1094 1095 if (P_SHOULDSTOP(p)) { 1096 state = "T (stopped)"; 1097 } else { 1098 switch(p->p_state) { 1099 case PRS_NEW: 1100 state = "I (idle)"; 1101 break; 1102 case PRS_NORMAL: 1103 if (p->p_flag & P_WEXIT) { 1104 state = "X (exiting)"; 1105 break; 1106 } 1107 switch(TD_GET_STATE(td2)) { 1108 case TDS_INHIBITED: 1109 state = "S (sleeping)"; 1110 break; 1111 case TDS_RUNQ: 1112 case TDS_RUNNING: 1113 state = "R (running)"; 1114 break; 1115 default: 1116 state = "? (unknown)"; 1117 break; 1118 } 1119 break; 1120 case PRS_ZOMBIE: 1121 state = "Z (zombie)"; 1122 break; 1123 default: 1124 state = "? (unknown)"; 1125 break; 1126 } 1127 } 1128 1129 fill_kinfo_proc(p, &kp); 1130 sx_sunlock(&proctree_lock); 1131 1132 sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ 1133 sbuf_printf(sb, "State:\t%s\n", state); 1134 1135 /* 1136 * Credentials 1137 */ 1138 sbuf_printf(sb, "Tgid:\t%d\n", p->p_pid); 1139 sbuf_printf(sb, "Pid:\t%d\n", p->p_pid); 1140 sbuf_printf(sb, "PPid:\t%d\n", kp.ki_ppid ); 1141 sbuf_printf(sb, "TracerPid:\t%d\n", kp.ki_tracer ); 1142 sbuf_printf(sb, "Uid:\t%d\t%d\t%d\t%d\n", p->p_ucred->cr_ruid, 1143 p->p_ucred->cr_uid, 1144 p->p_ucred->cr_svuid, 1145 /* FreeBSD doesn't have fsuid */ 1146 p->p_ucred->cr_uid); 1147 sbuf_printf(sb, "Gid:\t%d\t%d\t%d\t%d\n", p->p_ucred->cr_rgid, 1148 p->p_ucred->cr_gid, 1149 p->p_ucred->cr_svgid, 1150 /* FreeBSD doesn't have fsgid */ 1151 p->p_ucred->cr_gid); 1152 sbuf_cat(sb, "Groups:\t"); 1153 for (i = 0; i < p->p_ucred->cr_ngroups; i++) 1154 sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]); 1155 PROC_UNLOCK(p); 1156 sbuf_putc(sb, '\n'); 1157 1158 /* 1159 * Memory 1160 * 1161 * While our approximation of VmLib may not be accurate (I 1162 * don't know of a simple way to verify it, and I'm not sure 1163 * it has much meaning anyway), I believe it's good enough. 1164 * 1165 * The same code that could (I think) accurately compute VmLib 1166 * could also compute VmLck, but I don't really care enough to 1167 * implement it. Submissions are welcome. 1168 */ 1169 sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size)); 1170 sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ 1171 sbuf_printf(sb, "VmRSS:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize)); 1172 sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize)); 1173 sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize)); 1174 sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize)); 1175 lsize = B2P(kp.ki_size) - kp.ki_dsize - 1176 kp.ki_ssize - kp.ki_tsize - 1; 1177 sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize)); 1178 1179 /* 1180 * Signal masks 1181 */ 1182 PROC_LOCK(p); 1183 bsd_to_linux_sigset(&p->p_siglist, &siglist); 1184 ps = p->p_sigacts; 1185 mtx_lock(&ps->ps_mtx); 1186 bsd_to_linux_sigset(&ps->ps_sigignore, &sigignore); 1187 bsd_to_linux_sigset(&ps->ps_sigcatch, &sigcatch); 1188 mtx_unlock(&ps->ps_mtx); 1189 PROC_UNLOCK(p); 1190 1191 sbuf_printf(sb, "SigPnd:\t%016jx\n", siglist.__mask); 1192 /* 1193 * XXX. SigBlk - target thread's signal mask, td_sigmask. 1194 * To implement SigBlk pseudofs should support proc/tid dir entries. 1195 */ 1196 sbuf_printf(sb, "SigBlk:\t%016x\n", 0); 1197 sbuf_printf(sb, "SigIgn:\t%016jx\n", sigignore.__mask); 1198 sbuf_printf(sb, "SigCgt:\t%016jx\n", sigcatch.__mask); 1199 1200 /* 1201 * Linux also prints the capability masks, but we don't have 1202 * capabilities yet, and when we do get them they're likely to 1203 * be meaningless to Linux programs, so we lie. XXX 1204 */ 1205 sbuf_printf(sb, "CapInh:\t%016x\n", 0); 1206 sbuf_printf(sb, "CapPrm:\t%016x\n", 0); 1207 sbuf_printf(sb, "CapEff:\t%016x\n", 0); 1208 1209 return (0); 1210 } 1211 1212 /* 1213 * Filler function for proc/pid/cwd 1214 */ 1215 static int 1216 linprocfs_doproccwd(PFS_FILL_ARGS) 1217 { 1218 struct pwd *pwd; 1219 char *fullpath = "unknown"; 1220 char *freepath = NULL; 1221 1222 pwd = pwd_hold_proc(p); 1223 vn_fullpath(pwd->pwd_cdir, &fullpath, &freepath); 1224 sbuf_printf(sb, "%s", fullpath); 1225 if (freepath) 1226 free(freepath, M_TEMP); 1227 pwd_drop(pwd); 1228 return (0); 1229 } 1230 1231 /* 1232 * Filler function for proc/pid/root 1233 */ 1234 static int 1235 linprocfs_doprocroot(PFS_FILL_ARGS) 1236 { 1237 struct pwd *pwd; 1238 struct vnode *vp; 1239 char *fullpath = "unknown"; 1240 char *freepath = NULL; 1241 1242 pwd = pwd_hold_proc(p); 1243 vp = jailed(p->p_ucred) ? pwd->pwd_jdir : pwd->pwd_rdir; 1244 vn_fullpath(vp, &fullpath, &freepath); 1245 sbuf_printf(sb, "%s", fullpath); 1246 if (freepath) 1247 free(freepath, M_TEMP); 1248 pwd_drop(pwd); 1249 return (0); 1250 } 1251 1252 /* 1253 * Filler function for proc/pid/cmdline 1254 */ 1255 static int 1256 linprocfs_doproccmdline(PFS_FILL_ARGS) 1257 { 1258 int ret; 1259 1260 PROC_LOCK(p); 1261 if ((ret = p_cansee(td, p)) != 0) { 1262 PROC_UNLOCK(p); 1263 return (ret); 1264 } 1265 1266 /* 1267 * Mimic linux behavior and pass only processes with usermode 1268 * address space as valid. Return zero silently otherwize. 1269 */ 1270 if (p->p_vmspace == &vmspace0) { 1271 PROC_UNLOCK(p); 1272 return (0); 1273 } 1274 if (p->p_args != NULL) { 1275 sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length); 1276 PROC_UNLOCK(p); 1277 return (0); 1278 } 1279 1280 if ((p->p_flag & P_SYSTEM) != 0) { 1281 PROC_UNLOCK(p); 1282 return (0); 1283 } 1284 1285 PROC_UNLOCK(p); 1286 1287 ret = proc_getargv(td, p, sb); 1288 return (ret); 1289 } 1290 1291 /* 1292 * Filler function for proc/pid/environ 1293 */ 1294 static int 1295 linprocfs_doprocenviron(PFS_FILL_ARGS) 1296 { 1297 1298 /* 1299 * Mimic linux behavior and pass only processes with usermode 1300 * address space as valid. Return zero silently otherwize. 1301 */ 1302 if (p->p_vmspace == &vmspace0) 1303 return (0); 1304 1305 return (proc_getenvv(td, p, sb)); 1306 } 1307 1308 static char l32_map_str[] = "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n"; 1309 static char l64_map_str[] = "%016lx-%016lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n"; 1310 static char vdso_str[] = " [vdso]"; 1311 static char stack_str[] = " [stack]"; 1312 1313 /* 1314 * Filler function for proc/pid/maps 1315 */ 1316 static int 1317 linprocfs_doprocmaps(PFS_FILL_ARGS) 1318 { 1319 struct vmspace *vm; 1320 vm_map_t map; 1321 vm_map_entry_t entry, tmp_entry; 1322 vm_object_t obj, tobj, lobj; 1323 vm_offset_t e_start, e_end; 1324 vm_ooffset_t off; 1325 vm_prot_t e_prot; 1326 unsigned int last_timestamp; 1327 char *name = "", *freename = NULL; 1328 const char *l_map_str; 1329 ino_t ino; 1330 int error; 1331 struct vnode *vp; 1332 struct vattr vat; 1333 bool private; 1334 1335 PROC_LOCK(p); 1336 error = p_candebug(td, p); 1337 PROC_UNLOCK(p); 1338 if (error) 1339 return (error); 1340 1341 if (uio->uio_rw != UIO_READ) 1342 return (EOPNOTSUPP); 1343 1344 error = 0; 1345 vm = vmspace_acquire_ref(p); 1346 if (vm == NULL) 1347 return (ESRCH); 1348 1349 if (SV_CURPROC_FLAG(SV_LP64)) 1350 l_map_str = l64_map_str; 1351 else 1352 l_map_str = l32_map_str; 1353 map = &vm->vm_map; 1354 vm_map_lock_read(map); 1355 VM_MAP_ENTRY_FOREACH(entry, map) { 1356 name = ""; 1357 freename = NULL; 1358 /* 1359 * Skip printing of the guard page of the stack region, as 1360 * it confuses glibc pthread_getattr_np() method, where both 1361 * the base address and size of the stack of the initial thread 1362 * are calculated. 1363 */ 1364 if ((entry->eflags & (MAP_ENTRY_IS_SUB_MAP | MAP_ENTRY_GUARD)) != 0) 1365 continue; 1366 e_prot = entry->protection; 1367 e_start = entry->start; 1368 e_end = entry->end; 1369 obj = entry->object.vm_object; 1370 off = entry->offset; 1371 for (lobj = tobj = obj; tobj != NULL; 1372 lobj = tobj, tobj = tobj->backing_object) { 1373 VM_OBJECT_RLOCK(tobj); 1374 off += lobj->backing_object_offset; 1375 if (lobj != obj) 1376 VM_OBJECT_RUNLOCK(lobj); 1377 } 1378 private = (entry->eflags & MAP_ENTRY_COW) != 0 || obj == NULL || 1379 (obj->flags & OBJ_ANON) != 0; 1380 last_timestamp = map->timestamp; 1381 vm_map_unlock_read(map); 1382 ino = 0; 1383 if (lobj) { 1384 vp = vm_object_vnode(lobj); 1385 if (vp != NULL) 1386 vref(vp); 1387 if (lobj != obj) 1388 VM_OBJECT_RUNLOCK(lobj); 1389 VM_OBJECT_RUNLOCK(obj); 1390 if (vp != NULL) { 1391 vn_fullpath(vp, &name, &freename); 1392 vn_lock(vp, LK_SHARED | LK_RETRY); 1393 VOP_GETATTR(vp, &vat, td->td_ucred); 1394 ino = vat.va_fileid; 1395 vput(vp); 1396 } else if (SV_PROC_ABI(p) == SV_ABI_LINUX) { 1397 /* 1398 * sv_shared_page_base pointed out to the 1399 * FreeBSD sharedpage, PAGE_SIZE is a size 1400 * of it. The vDSO page is above. 1401 */ 1402 if (e_start == p->p_sysent->sv_shared_page_base + 1403 PAGE_SIZE) 1404 name = vdso_str; 1405 if (e_end == p->p_sysent->sv_usrstack) 1406 name = stack_str; 1407 } 1408 } 1409 1410 /* 1411 * format: 1412 * start, end, access, offset, major, minor, inode, name. 1413 */ 1414 error = sbuf_printf(sb, l_map_str, 1415 (u_long)e_start, (u_long)e_end, 1416 (e_prot & VM_PROT_READ)?"r":"-", 1417 (e_prot & VM_PROT_WRITE)?"w":"-", 1418 (e_prot & VM_PROT_EXECUTE)?"x":"-", 1419 private ? "p" : "s", 1420 (u_long)off, 1421 0, 1422 0, 1423 (u_long)ino, 1424 *name ? " " : " ", 1425 name 1426 ); 1427 if (freename) 1428 free(freename, M_TEMP); 1429 vm_map_lock_read(map); 1430 if (error == -1) { 1431 error = 0; 1432 break; 1433 } 1434 if (last_timestamp != map->timestamp) { 1435 /* 1436 * Look again for the entry because the map was 1437 * modified while it was unlocked. Specifically, 1438 * the entry may have been clipped, merged, or deleted. 1439 */ 1440 vm_map_lookup_entry(map, e_end - 1, &tmp_entry); 1441 entry = tmp_entry; 1442 } 1443 } 1444 vm_map_unlock_read(map); 1445 vmspace_free(vm); 1446 1447 return (error); 1448 } 1449 1450 /* 1451 * Filler function for proc/pid/mem 1452 */ 1453 static int 1454 linprocfs_doprocmem(PFS_FILL_ARGS) 1455 { 1456 ssize_t resid; 1457 int error; 1458 1459 resid = uio->uio_resid; 1460 error = procfs_doprocmem(PFS_FILL_ARGNAMES); 1461 1462 if (uio->uio_rw == UIO_READ && resid != uio->uio_resid) 1463 return (0); 1464 1465 if (error == EFAULT) 1466 error = EIO; 1467 1468 return (error); 1469 } 1470 1471 static int 1472 linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen) 1473 { 1474 struct ifnet *ifscan; 1475 int ethno; 1476 1477 IFNET_RLOCK_ASSERT(); 1478 1479 /* Short-circuit non ethernet interfaces */ 1480 if (linux_use_real_ifname(ifp)) 1481 return (strlcpy(buffer, ifp->if_xname, buflen)); 1482 1483 /* Determine the (relative) unit number for ethernet interfaces */ 1484 ethno = 0; 1485 CK_STAILQ_FOREACH(ifscan, &V_ifnet, if_link) { 1486 if (ifscan == ifp) 1487 return (snprintf(buffer, buflen, "eth%d", ethno)); 1488 if (!linux_use_real_ifname(ifscan)) 1489 ethno++; 1490 } 1491 1492 return (0); 1493 } 1494 1495 /* 1496 * Filler function for proc/net/dev 1497 */ 1498 static int 1499 linprocfs_donetdev(PFS_FILL_ARGS) 1500 { 1501 char ifname[16]; /* XXX LINUX_IFNAMSIZ */ 1502 struct ifnet *ifp; 1503 1504 sbuf_printf(sb, "%6s|%58s|%s\n" 1505 "%6s|%58s|%58s\n", 1506 "Inter-", " Receive", " Transmit", 1507 " face", 1508 "bytes packets errs drop fifo frame compressed multicast", 1509 "bytes packets errs drop fifo colls carrier compressed"); 1510 1511 CURVNET_SET(TD_TO_VNET(curthread)); 1512 IFNET_RLOCK(); 1513 CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) { 1514 linux_ifname(ifp, ifname, sizeof ifname); 1515 sbuf_printf(sb, "%6.6s: ", ifname); 1516 sbuf_printf(sb, "%7ju %7ju %4ju %4ju %4lu %5lu %10lu %9ju ", 1517 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IBYTES), 1518 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IPACKETS), 1519 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IERRORS), 1520 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IQDROPS), 1521 /* rx_missed_errors */ 1522 0UL, /* rx_fifo_errors */ 1523 0UL, /* rx_length_errors + 1524 * rx_over_errors + 1525 * rx_crc_errors + 1526 * rx_frame_errors */ 1527 0UL, /* rx_compressed */ 1528 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IMCASTS)); 1529 /* XXX-BZ rx only? */ 1530 sbuf_printf(sb, "%8ju %7ju %4ju %4ju %4lu %5ju %7lu %10lu\n", 1531 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OBYTES), 1532 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS), 1533 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OERRORS), 1534 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OQDROPS), 1535 0UL, /* tx_fifo_errors */ 1536 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_COLLISIONS), 1537 0UL, /* tx_carrier_errors + 1538 * tx_aborted_errors + 1539 * tx_window_errors + 1540 * tx_heartbeat_errors*/ 1541 0UL); /* tx_compressed */ 1542 } 1543 IFNET_RUNLOCK(); 1544 CURVNET_RESTORE(); 1545 1546 return (0); 1547 } 1548 1549 /* 1550 * Filler function for proc/sys/kernel/osrelease 1551 */ 1552 static int 1553 linprocfs_doosrelease(PFS_FILL_ARGS) 1554 { 1555 char osrelease[LINUX_MAX_UTSNAME]; 1556 1557 linux_get_osrelease(td, osrelease); 1558 sbuf_printf(sb, "%s\n", osrelease); 1559 1560 return (0); 1561 } 1562 1563 /* 1564 * Filler function for proc/sys/kernel/ostype 1565 */ 1566 static int 1567 linprocfs_doostype(PFS_FILL_ARGS) 1568 { 1569 char osname[LINUX_MAX_UTSNAME]; 1570 1571 linux_get_osname(td, osname); 1572 sbuf_printf(sb, "%s\n", osname); 1573 1574 return (0); 1575 } 1576 1577 /* 1578 * Filler function for proc/sys/kernel/version 1579 */ 1580 static int 1581 linprocfs_doosbuild(PFS_FILL_ARGS) 1582 { 1583 1584 linprocfs_osbuild(td, sb); 1585 sbuf_cat(sb, "\n"); 1586 return (0); 1587 } 1588 1589 /* 1590 * Filler function for proc/sys/kernel/msgmax 1591 */ 1592 static int 1593 linprocfs_domsgmax(PFS_FILL_ARGS) 1594 { 1595 1596 sbuf_printf(sb, "%d\n", msginfo.msgmax); 1597 return (0); 1598 } 1599 1600 /* 1601 * Filler function for proc/sys/kernel/msgmni 1602 */ 1603 static int 1604 linprocfs_domsgmni(PFS_FILL_ARGS) 1605 { 1606 1607 sbuf_printf(sb, "%d\n", msginfo.msgmni); 1608 return (0); 1609 } 1610 1611 /* 1612 * Filler function for proc/sys/kernel/msgmnb 1613 */ 1614 static int 1615 linprocfs_domsgmnb(PFS_FILL_ARGS) 1616 { 1617 1618 sbuf_printf(sb, "%d\n", msginfo.msgmnb); 1619 return (0); 1620 } 1621 1622 /* 1623 * Filler function for proc/sys/kernel/ngroups_max 1624 * 1625 * Note that in Linux it defaults to 65536, not 1023. 1626 */ 1627 static int 1628 linprocfs_dongroups_max(PFS_FILL_ARGS) 1629 { 1630 1631 sbuf_printf(sb, "%d\n", ngroups_max); 1632 return (0); 1633 } 1634 1635 /* 1636 * Filler function for proc/sys/kernel/pid_max 1637 */ 1638 static int 1639 linprocfs_dopid_max(PFS_FILL_ARGS) 1640 { 1641 1642 sbuf_printf(sb, "%i\n", PID_MAX); 1643 return (0); 1644 } 1645 1646 /* 1647 * Filler function for proc/sys/kernel/sem 1648 */ 1649 static int 1650 linprocfs_dosem(PFS_FILL_ARGS) 1651 { 1652 1653 sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns, 1654 seminfo.semopm, seminfo.semmni); 1655 return (0); 1656 } 1657 1658 /* 1659 * Filler function for proc/sys/kernel/shmall 1660 */ 1661 static int 1662 linprocfs_doshmall(PFS_FILL_ARGS) 1663 { 1664 1665 sbuf_printf(sb, "%lu\n", shminfo.shmall); 1666 return (0); 1667 } 1668 1669 /* 1670 * Filler function for proc/sys/kernel/shmmax 1671 */ 1672 static int 1673 linprocfs_doshmmax(PFS_FILL_ARGS) 1674 { 1675 1676 sbuf_printf(sb, "%lu\n", shminfo.shmmax); 1677 return (0); 1678 } 1679 1680 /* 1681 * Filler function for proc/sys/kernel/shmmni 1682 */ 1683 static int 1684 linprocfs_doshmmni(PFS_FILL_ARGS) 1685 { 1686 1687 sbuf_printf(sb, "%lu\n", shminfo.shmmni); 1688 return (0); 1689 } 1690 1691 /* 1692 * Filler function for proc/sys/kernel/tainted 1693 */ 1694 static int 1695 linprocfs_dotainted(PFS_FILL_ARGS) 1696 { 1697 1698 sbuf_printf(sb, "0\n"); 1699 return (0); 1700 } 1701 1702 /* 1703 * Filler function for proc/sys/vm/min_free_kbytes 1704 * 1705 * This mirrors the approach in illumos to return zero for reads. Effectively, 1706 * it says, no memory is kept in reserve for "atomic allocations". This class 1707 * of allocation can be used at times when a thread cannot be suspended. 1708 */ 1709 static int 1710 linprocfs_dominfree(PFS_FILL_ARGS) 1711 { 1712 1713 sbuf_printf(sb, "%d\n", 0); 1714 return (0); 1715 } 1716 1717 /* 1718 * Filler function for proc/scsi/device_info 1719 */ 1720 static int 1721 linprocfs_doscsidevinfo(PFS_FILL_ARGS) 1722 { 1723 1724 return (0); 1725 } 1726 1727 /* 1728 * Filler function for proc/scsi/scsi 1729 */ 1730 static int 1731 linprocfs_doscsiscsi(PFS_FILL_ARGS) 1732 { 1733 1734 return (0); 1735 } 1736 1737 /* 1738 * Filler function for proc/devices 1739 */ 1740 static int 1741 linprocfs_dodevices(PFS_FILL_ARGS) 1742 { 1743 char *char_devices; 1744 sbuf_printf(sb, "Character devices:\n"); 1745 1746 char_devices = linux_get_char_devices(); 1747 sbuf_printf(sb, "%s", char_devices); 1748 linux_free_get_char_devices(char_devices); 1749 1750 sbuf_printf(sb, "\nBlock devices:\n"); 1751 1752 return (0); 1753 } 1754 1755 /* 1756 * Filler function for proc/cmdline 1757 */ 1758 static int 1759 linprocfs_docmdline(PFS_FILL_ARGS) 1760 { 1761 1762 sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname); 1763 sbuf_printf(sb, " ro root=302\n"); 1764 return (0); 1765 } 1766 1767 /* 1768 * Filler function for proc/filesystems 1769 */ 1770 static int 1771 linprocfs_dofilesystems(PFS_FILL_ARGS) 1772 { 1773 struct vfsconf *vfsp; 1774 1775 vfsconf_slock(); 1776 TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) { 1777 if (vfsp->vfc_flags & VFCF_SYNTHETIC) 1778 sbuf_printf(sb, "nodev"); 1779 sbuf_printf(sb, "\t%s\n", vfsp->vfc_name); 1780 } 1781 vfsconf_sunlock(); 1782 return(0); 1783 } 1784 1785 /* 1786 * Filler function for proc/modules 1787 */ 1788 static int 1789 linprocfs_domodules(PFS_FILL_ARGS) 1790 { 1791 #if 0 1792 struct linker_file *lf; 1793 1794 TAILQ_FOREACH(lf, &linker_files, link) { 1795 sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename, 1796 (unsigned long)lf->size, lf->refs); 1797 } 1798 #endif 1799 return (0); 1800 } 1801 1802 /* 1803 * Filler function for proc/pid/fd 1804 */ 1805 static int 1806 linprocfs_dofdescfs(PFS_FILL_ARGS) 1807 { 1808 1809 if (p == curproc) 1810 sbuf_printf(sb, "/dev/fd"); 1811 else 1812 sbuf_printf(sb, "unknown"); 1813 return (0); 1814 } 1815 1816 /* 1817 * Filler function for proc/pid/limits 1818 */ 1819 static const struct linux_rlimit_ident { 1820 const char *desc; 1821 const char *unit; 1822 unsigned int rlim_id; 1823 } linux_rlimits_ident[] = { 1824 { "Max cpu time", "seconds", RLIMIT_CPU }, 1825 { "Max file size", "bytes", RLIMIT_FSIZE }, 1826 { "Max data size", "bytes", RLIMIT_DATA }, 1827 { "Max stack size", "bytes", RLIMIT_STACK }, 1828 { "Max core file size", "bytes", RLIMIT_CORE }, 1829 { "Max resident set", "bytes", RLIMIT_RSS }, 1830 { "Max processes", "processes", RLIMIT_NPROC }, 1831 { "Max open files", "files", RLIMIT_NOFILE }, 1832 { "Max locked memory", "bytes", RLIMIT_MEMLOCK }, 1833 { "Max address space", "bytes", RLIMIT_AS }, 1834 { "Max file locks", "locks", LINUX_RLIMIT_LOCKS }, 1835 { "Max pending signals", "signals", LINUX_RLIMIT_SIGPENDING }, 1836 { "Max msgqueue size", "bytes", LINUX_RLIMIT_MSGQUEUE }, 1837 { "Max nice priority", "", LINUX_RLIMIT_NICE }, 1838 { "Max realtime priority", "", LINUX_RLIMIT_RTPRIO }, 1839 { "Max realtime timeout", "us", LINUX_RLIMIT_RTTIME }, 1840 { 0, 0, 0 } 1841 }; 1842 1843 static int 1844 linprocfs_doproclimits(PFS_FILL_ARGS) 1845 { 1846 const struct linux_rlimit_ident *li; 1847 struct plimit *limp; 1848 struct rlimit rl; 1849 ssize_t size; 1850 int res, error; 1851 1852 error = 0; 1853 1854 PROC_LOCK(p); 1855 limp = lim_hold(p->p_limit); 1856 PROC_UNLOCK(p); 1857 size = sizeof(res); 1858 sbuf_printf(sb, "%-26s%-21s%-21s%-21s\n", "Limit", "Soft Limit", 1859 "Hard Limit", "Units"); 1860 for (li = linux_rlimits_ident; li->desc != NULL; ++li) { 1861 switch (li->rlim_id) 1862 { 1863 case LINUX_RLIMIT_LOCKS: 1864 /* FALLTHROUGH */ 1865 case LINUX_RLIMIT_RTTIME: 1866 rl.rlim_cur = RLIM_INFINITY; 1867 break; 1868 case LINUX_RLIMIT_SIGPENDING: 1869 error = kernel_sysctlbyname(td, 1870 "kern.sigqueue.max_pending_per_proc", 1871 &res, &size, 0, 0, 0, 0); 1872 if (error != 0) 1873 goto out; 1874 rl.rlim_cur = res; 1875 rl.rlim_max = res; 1876 break; 1877 case LINUX_RLIMIT_MSGQUEUE: 1878 error = kernel_sysctlbyname(td, 1879 "kern.ipc.msgmnb", &res, &size, 0, 0, 0, 0); 1880 if (error != 0) 1881 goto out; 1882 rl.rlim_cur = res; 1883 rl.rlim_max = res; 1884 break; 1885 case LINUX_RLIMIT_NICE: 1886 /* FALLTHROUGH */ 1887 case LINUX_RLIMIT_RTPRIO: 1888 rl.rlim_cur = 0; 1889 rl.rlim_max = 0; 1890 break; 1891 default: 1892 rl = limp->pl_rlimit[li->rlim_id]; 1893 break; 1894 } 1895 if (rl.rlim_cur == RLIM_INFINITY) 1896 sbuf_printf(sb, "%-26s%-21s%-21s%-10s\n", 1897 li->desc, "unlimited", "unlimited", li->unit); 1898 else 1899 sbuf_printf(sb, "%-26s%-21llu%-21llu%-10s\n", 1900 li->desc, (unsigned long long)rl.rlim_cur, 1901 (unsigned long long)rl.rlim_max, li->unit); 1902 } 1903 out: 1904 lim_free(limp); 1905 return (error); 1906 } 1907 1908 /* 1909 * The point of the following two functions is to work around 1910 * an assertion in Chromium; see kern/240991 for details. 1911 */ 1912 static int 1913 linprocfs_dotaskattr(PFS_ATTR_ARGS) 1914 { 1915 1916 vap->va_nlink = 3; 1917 return (0); 1918 } 1919 1920 /* 1921 * Filler function for proc/<pid>/task/.dummy 1922 */ 1923 static int 1924 linprocfs_dotaskdummy(PFS_FILL_ARGS) 1925 { 1926 1927 return (0); 1928 } 1929 1930 /* 1931 * Filler function for proc/sys/kernel/random/uuid 1932 */ 1933 static int 1934 linprocfs_douuid(PFS_FILL_ARGS) 1935 { 1936 struct uuid uuid; 1937 1938 kern_uuidgen(&uuid, 1); 1939 sbuf_printf_uuid(sb, &uuid); 1940 sbuf_printf(sb, "\n"); 1941 return(0); 1942 } 1943 1944 /* 1945 * Filler function for proc/sys/kernel/random/boot_id 1946 */ 1947 static int 1948 linprocfs_doboot_id(PFS_FILL_ARGS) 1949 { 1950 static bool firstboot = 1; 1951 static struct uuid uuid; 1952 1953 if (firstboot) { 1954 kern_uuidgen(&uuid, 1); 1955 firstboot = 0; 1956 } 1957 sbuf_printf_uuid(sb, &uuid); 1958 sbuf_printf(sb, "\n"); 1959 return(0); 1960 } 1961 1962 /* 1963 * Filler function for proc/pid/auxv 1964 */ 1965 static int 1966 linprocfs_doauxv(PFS_FILL_ARGS) 1967 { 1968 struct sbuf *asb; 1969 off_t buflen, resid; 1970 int error; 1971 1972 /* 1973 * Mimic linux behavior and pass only processes with usermode 1974 * address space as valid. Return zero silently otherwise. 1975 */ 1976 if (p->p_vmspace == &vmspace0) 1977 return (0); 1978 1979 if (uio->uio_resid == 0) 1980 return (0); 1981 if (uio->uio_offset < 0 || uio->uio_resid < 0) 1982 return (EINVAL); 1983 1984 asb = sbuf_new_auto(); 1985 if (asb == NULL) 1986 return (ENOMEM); 1987 error = proc_getauxv(td, p, asb); 1988 if (error == 0) 1989 error = sbuf_finish(asb); 1990 1991 resid = sbuf_len(asb) - uio->uio_offset; 1992 if (resid > uio->uio_resid) 1993 buflen = uio->uio_resid; 1994 else 1995 buflen = resid; 1996 if (buflen > IOSIZE_MAX) 1997 return (EINVAL); 1998 if (buflen > maxphys) 1999 buflen = maxphys; 2000 if (resid <= 0) 2001 return (0); 2002 2003 if (error == 0) 2004 error = uiomove(sbuf_data(asb) + uio->uio_offset, buflen, uio); 2005 sbuf_delete(asb); 2006 return (error); 2007 } 2008 2009 /* 2010 * Filler function for proc/self/oom_score_adj 2011 */ 2012 static int 2013 linprocfs_do_oom_score_adj(PFS_FILL_ARGS) 2014 { 2015 struct linux_pemuldata *pem; 2016 long oom; 2017 2018 pem = pem_find(p); 2019 if (pem == NULL || uio == NULL) 2020 return (EOPNOTSUPP); 2021 if (uio->uio_rw == UIO_READ) { 2022 sbuf_printf(sb, "%d\n", pem->oom_score_adj); 2023 } else { 2024 sbuf_trim(sb); 2025 sbuf_finish(sb); 2026 oom = strtol(sbuf_data(sb), NULL, 10); 2027 if (oom < LINUX_OOM_SCORE_ADJ_MIN || 2028 oom > LINUX_OOM_SCORE_ADJ_MAX) 2029 return (EINVAL); 2030 pem->oom_score_adj = oom; 2031 } 2032 return (0); 2033 } 2034 2035 /* 2036 * Filler function for proc/sys/vm/max_map_count 2037 * 2038 * Maximum number of active map areas, on Linux this limits the number 2039 * of vmaps per mm struct. We don't limit mappings, return a suitable 2040 * large value. 2041 */ 2042 static int 2043 linprocfs_domax_map_cnt(PFS_FILL_ARGS) 2044 { 2045 2046 sbuf_printf(sb, "%d\n", INT32_MAX); 2047 return (0); 2048 } 2049 2050 /* 2051 * Constructor 2052 */ 2053 static int 2054 linprocfs_init(PFS_INIT_ARGS) 2055 { 2056 struct pfs_node *root; 2057 struct pfs_node *dir; 2058 struct pfs_node *sys; 2059 2060 root = pi->pi_root; 2061 2062 /* /proc/... */ 2063 pfs_create_file(root, "cmdline", &linprocfs_docmdline, 2064 NULL, NULL, NULL, PFS_RD); 2065 pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo, 2066 NULL, NULL, NULL, PFS_RD); 2067 pfs_create_file(root, "devices", &linprocfs_dodevices, 2068 NULL, NULL, NULL, PFS_RD); 2069 pfs_create_file(root, "filesystems", &linprocfs_dofilesystems, 2070 NULL, NULL, NULL, PFS_RD); 2071 pfs_create_file(root, "loadavg", &linprocfs_doloadavg, 2072 NULL, NULL, NULL, PFS_RD); 2073 pfs_create_file(root, "meminfo", &linprocfs_domeminfo, 2074 NULL, NULL, NULL, PFS_RD); 2075 pfs_create_file(root, "modules", &linprocfs_domodules, 2076 NULL, NULL, NULL, PFS_RD); 2077 pfs_create_file(root, "mounts", &linprocfs_domtab, 2078 NULL, NULL, NULL, PFS_RD); 2079 pfs_create_file(root, "mtab", &linprocfs_domtab, 2080 NULL, NULL, NULL, PFS_RD); 2081 pfs_create_file(root, "partitions", &linprocfs_dopartitions, 2082 NULL, NULL, NULL, PFS_RD); 2083 pfs_create_link(root, "self", &procfs_docurproc, 2084 NULL, NULL, NULL, 0); 2085 pfs_create_file(root, "stat", &linprocfs_dostat, 2086 NULL, NULL, NULL, PFS_RD); 2087 pfs_create_file(root, "swaps", &linprocfs_doswaps, 2088 NULL, NULL, NULL, PFS_RD); 2089 pfs_create_file(root, "uptime", &linprocfs_douptime, 2090 NULL, NULL, NULL, PFS_RD); 2091 pfs_create_file(root, "version", &linprocfs_doversion, 2092 NULL, NULL, NULL, PFS_RD); 2093 2094 /* /proc/bus/... */ 2095 dir = pfs_create_dir(root, "bus", NULL, NULL, NULL, 0); 2096 dir = pfs_create_dir(dir, "pci", NULL, NULL, NULL, 0); 2097 dir = pfs_create_dir(dir, "devices", NULL, NULL, NULL, 0); 2098 2099 /* /proc/net/... */ 2100 dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0); 2101 pfs_create_file(dir, "dev", &linprocfs_donetdev, 2102 NULL, NULL, NULL, PFS_RD); 2103 2104 /* /proc/<pid>/... */ 2105 dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP); 2106 pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline, 2107 NULL, NULL, NULL, PFS_RD); 2108 pfs_create_link(dir, "cwd", &linprocfs_doproccwd, 2109 NULL, NULL, NULL, 0); 2110 pfs_create_file(dir, "environ", &linprocfs_doprocenviron, 2111 NULL, &procfs_candebug, NULL, PFS_RD); 2112 pfs_create_link(dir, "exe", &procfs_doprocfile, 2113 NULL, &procfs_notsystem, NULL, 0); 2114 pfs_create_file(dir, "maps", &linprocfs_doprocmaps, 2115 NULL, NULL, NULL, PFS_RD | PFS_AUTODRAIN); 2116 pfs_create_file(dir, "mem", &linprocfs_doprocmem, 2117 procfs_attr_rw, &procfs_candebug, NULL, PFS_RDWR | PFS_RAW); 2118 pfs_create_file(dir, "mountinfo", &linprocfs_doprocmountinfo, 2119 NULL, NULL, NULL, PFS_RD); 2120 pfs_create_file(dir, "mounts", &linprocfs_domtab, 2121 NULL, NULL, NULL, PFS_RD); 2122 pfs_create_link(dir, "root", &linprocfs_doprocroot, 2123 NULL, NULL, NULL, 0); 2124 pfs_create_file(dir, "stat", &linprocfs_doprocstat, 2125 NULL, NULL, NULL, PFS_RD); 2126 pfs_create_file(dir, "statm", &linprocfs_doprocstatm, 2127 NULL, NULL, NULL, PFS_RD); 2128 pfs_create_file(dir, "status", &linprocfs_doprocstatus, 2129 NULL, NULL, NULL, PFS_RD); 2130 pfs_create_link(dir, "fd", &linprocfs_dofdescfs, 2131 NULL, NULL, NULL, 0); 2132 pfs_create_file(dir, "auxv", &linprocfs_doauxv, 2133 NULL, &procfs_candebug, NULL, PFS_RD|PFS_RAWRD); 2134 pfs_create_file(dir, "limits", &linprocfs_doproclimits, 2135 NULL, NULL, NULL, PFS_RD); 2136 pfs_create_file(dir, "oom_score_adj", &linprocfs_do_oom_score_adj, 2137 procfs_attr_rw, &procfs_candebug, NULL, PFS_RDWR); 2138 2139 /* /proc/<pid>/task/... */ 2140 dir = pfs_create_dir(dir, "task", linprocfs_dotaskattr, NULL, NULL, 0); 2141 pfs_create_file(dir, ".dummy", &linprocfs_dotaskdummy, 2142 NULL, NULL, NULL, PFS_RD); 2143 2144 /* /proc/scsi/... */ 2145 dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0); 2146 pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo, 2147 NULL, NULL, NULL, PFS_RD); 2148 pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi, 2149 NULL, NULL, NULL, PFS_RD); 2150 2151 /* /proc/sys/... */ 2152 sys = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0); 2153 2154 /* /proc/sys/kernel/... */ 2155 dir = pfs_create_dir(sys, "kernel", NULL, NULL, NULL, 0); 2156 pfs_create_file(dir, "osrelease", &linprocfs_doosrelease, 2157 NULL, NULL, NULL, PFS_RD); 2158 pfs_create_file(dir, "ostype", &linprocfs_doostype, 2159 NULL, NULL, NULL, PFS_RD); 2160 pfs_create_file(dir, "version", &linprocfs_doosbuild, 2161 NULL, NULL, NULL, PFS_RD); 2162 pfs_create_file(dir, "msgmax", &linprocfs_domsgmax, 2163 NULL, NULL, NULL, PFS_RD); 2164 pfs_create_file(dir, "msgmni", &linprocfs_domsgmni, 2165 NULL, NULL, NULL, PFS_RD); 2166 pfs_create_file(dir, "msgmnb", &linprocfs_domsgmnb, 2167 NULL, NULL, NULL, PFS_RD); 2168 pfs_create_file(dir, "ngroups_max", &linprocfs_dongroups_max, 2169 NULL, NULL, NULL, PFS_RD); 2170 pfs_create_file(dir, "pid_max", &linprocfs_dopid_max, 2171 NULL, NULL, NULL, PFS_RD); 2172 pfs_create_file(dir, "sem", &linprocfs_dosem, 2173 NULL, NULL, NULL, PFS_RD); 2174 pfs_create_file(dir, "shmall", &linprocfs_doshmall, 2175 NULL, NULL, NULL, PFS_RD); 2176 pfs_create_file(dir, "shmmax", &linprocfs_doshmmax, 2177 NULL, NULL, NULL, PFS_RD); 2178 pfs_create_file(dir, "shmmni", &linprocfs_doshmmni, 2179 NULL, NULL, NULL, PFS_RD); 2180 pfs_create_file(dir, "tainted", &linprocfs_dotainted, 2181 NULL, NULL, NULL, PFS_RD); 2182 2183 /* /proc/sys/kernel/random/... */ 2184 dir = pfs_create_dir(dir, "random", NULL, NULL, NULL, 0); 2185 pfs_create_file(dir, "uuid", &linprocfs_douuid, 2186 NULL, NULL, NULL, PFS_RD); 2187 pfs_create_file(dir, "boot_id", &linprocfs_doboot_id, 2188 NULL, NULL, NULL, PFS_RD); 2189 2190 /* /proc/sys/vm/.... */ 2191 dir = pfs_create_dir(sys, "vm", NULL, NULL, NULL, 0); 2192 pfs_create_file(dir, "min_free_kbytes", &linprocfs_dominfree, 2193 NULL, NULL, NULL, PFS_RD); 2194 pfs_create_file(dir, "max_map_count", &linprocfs_domax_map_cnt, 2195 NULL, NULL, NULL, PFS_RD); 2196 2197 return (0); 2198 } 2199 2200 /* 2201 * Destructor 2202 */ 2203 static int 2204 linprocfs_uninit(PFS_INIT_ARGS) 2205 { 2206 2207 /* nothing to do, pseudofs will GC */ 2208 return (0); 2209 } 2210 2211 PSEUDOFS(linprocfs, 1, VFCF_JAIL); 2212 #if defined(__aarch64__) || defined(__amd64__) 2213 MODULE_DEPEND(linprocfs, linux_common, 1, 1, 1); 2214 #else 2215 MODULE_DEPEND(linprocfs, linux, 1, 1, 1); 2216 #endif 2217 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1); 2218 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1); 2219 MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1); 2220 MODULE_DEPEND(linprocfs, sysvshm, 1, 1, 1); 2221