SYSCTL(7)

πŸ“¦ version 11.0, in nixpkgs unstable

πŸ‘‘ sysctl(7) β€” system information variables ✨

okay so welcome to sysctl(7), bestie!! this page lives in the Miscellaneous Information Manual, and it's literally the master list of every system variable the kernel keeps for u 🫢. it's a long one, so buckle up.


🌸 NAME 🌸

sysctl β€” system information variables πŸ’…


✨ DESCRIPTION ✨

so there's the sysctl(3) library function and the sysctl(8) utility, and like, both of them are how u get and set the values of system variables β€” which the kernel is out here maintaining for u 24/7, no cap.

the variables are organized in a tree, and each one is identified by a sequence of numbers. conventionally those numbers are separated by dots, with the topmost identifier chillin' on the left side. every number also has a corresponding text name, bestie. and if u ever need to convert the text representation into the numeric one, u have two options: the sysctlnametomib(3) function, or the -M argument to the sysctl(8) utility. iconic.

every individual sysctl variable is described below, both in textual and numeric form where applicable. quick breakdown of who uses which:

  • the textual names can be used as an argument to the sysctl(8) utility, and also in the file /etc/sysctl.conf πŸ’–
  • the numeric names are usually defined as preprocessor constants, and they're intended for use by programs.

every such constant expands to one integer, which identifies the sysctl variable relative to the upper level of the tree. if u want programming examples, go read the sysctl(3) manual page β€” that's where the lore is. πŸ“š

🌳 Top level names 🌳

the top level names are defined with a CTL_ prefix in <sys/sysctl.h>, and here's the full lineup. the next levels and subsequent levels down live in the include files listed here, and each one gets its own section below. so many vibes:

  • kern / CTL_KERN β€” next level names in <sys/sysctl.h> β€” High kernel limits
  • vm / CTL_VM β€” next level names in <uvm/uvm_param.h> β€” Virtual memory
  • vfs / CTL_VFS β€” next level names in <sys/mount.h> β€” Filesystem
  • net / CTL_NET β€” next level names in <sys/socket.h> β€” Networking
  • debug / CTL_DEBUG β€” next level names in <sys/sysctl.h> β€” Debugging
  • hw / CTL_HW β€” next level names in <sys/sysctl.h> β€” Generic CPU, I/O
  • machdep / CTL_MACHDEP β€” next level names in <sys/sysctl.h> β€” Machine dependent
  • user / CTL_USER β€” next level names in <sys/sysctl.h> β€” User-level
  • ddb / CTL_DDB β€” next level names in <sys/sysctl.h> β€” In-kernel debugger
  • proc / CTL_PROC β€” next level names in <sys/sysctl.h> β€” Per-process
  • vendor / CTL_VENDOR β€” next level names ? β€” Vendor specific
  • emul / CTL_EMUL β€” next level names in <sys/sysctl.h> β€” Emulation settings
  • security / CTL_SECURITY β€” next level names in <sys/sysctl.h> β€” Security settings

πŸ› The debug.* subtree πŸ›

the debugging variables vary from system to system, and that's literally the point. a debugging variable can be added or deleted without needing to recompile sysctl so it knows about it. every time it runs, sysctl gets the list of debugging variables straight from the kernel and displays their current values. main character energy, honestly.

the system defines twenty (struct ctldebug) variables, named debug0 through debug19. they're declared as separate variables so they can be individually initialized at the location of their associated variable. and the loader prevents multiple use of the same variable by issuing errors if a variable is initialized in more than one place. it's giving strict parents, but like, fair.

for example, to export the variable dospecialcheck as a debugging variable, the following declaration would be used:

int dospecialcheck = 1;
struct ctldebug debug5 = { "dospecialcheck", &dospecialcheck };
ngl, note that the dynamic implementation of sysctl currently in use largely makes this particular sysctl interface obsolete. see sysctl(8) for more information if u want the tea. πŸ’€

πŸ“ The vfs.* subtree πŸ“

a distinguished second level name, vfs.generic (VFS_GENERIC), is used to get general information about all file systems. it has the following third level identifiers:

  • vfs.generic.maxtypenum (VFS_MAXTYPENUM) β€” the highest valid file system type number.
  • vfs.generic.conf (VFS_CONF) β€” returns configuration information about the file system type given as a fourth level identifier.
  • vfs.generic.usermount (VFS_USERMOUNT) β€” controls whether users other than the super-user can mount file systems. defaults to 0, so only the super-user can mount file systems.
⚠️ file systems mounted by unprivileged users must be mounted with the nodev and nosuid mount(8) options. like, do not skip this, bestie.
  • vfs.generic.magiclinks (VFS_MAGICLINKS) β€” controls whether expansion of variables is going to be performed on pathnames or not. defaults to 0, no variable expansion. variables are of the form @name and the variables supported are described in symlink(7) under β€œMAGIC SYMLINKS”. ✨

there's also a second level name for controlling the wapbl(4) (Write Ahead Physical Block Logging file system journaling) capabilities, with these third level identifiers:

  • vfs.wapbl.flush_disk_cache β€” controls whether to attempt to flush the disk cache on each commit. it defaults to 1, and it should always be on to ensure integrity of file system metadata in the event of a power loss. for slow disks, turning it off can improve performance. 🐒
  • vfs.wapbl.verbose_commit β€” for each transaction log commit, print the number of bytes written and the time it took to commit as seconds.nanoseconds.

the remaining second level identifiers are the file system names themselves, identified by the type number returned by a statvfs(2) call or from vfs.generic.conf.

and the third level identifiers available for each file system? those are given in the header file that defines the mount argument structure for that file system. iykyk. πŸ¦‹

πŸ’» The hw.* subtree πŸ’»

the string and integer information available for the hw level is detailed below. the changeable column shows whether a process with appropriate privilege may change the value. πŸŽ€

  • hw.alignbytes β€” integer β€” changeable: no
  • hw.byteorder β€” integer β€” changeable: no
  • hw.cnmagic β€” string β€” changeable: yes
  • hw.disknames β€” string β€” changeable: no
  • hw.diskstats β€” struct β€” changeable: no
  • hw.machine β€” string β€” changeable: no
  • hw.machine_arch β€” string β€” changeable: no
  • hw.model β€” string β€” changeable: no
  • hw.ncpu β€” integer β€” changeable: no
  • hw.ncpuonline β€” integer β€” changeable: no
  • hw.pagesize β€” integer β€” changeable: no
  • hw.physmem β€” integer β€” changeable: no
  • hw.physmem64 β€” quad β€” changeable: no
  • hw.usermem β€” integer β€” changeable: no
  • hw.usermem64 β€” quad β€” changeable: no

and now the actual deets on each one, periodt:

  • hw.alignbytes (HW_ALIGNBYTES) β€” alignment constraint for all possible data types. this shows the value ALIGNBYTES in <machine/param.h>, at the kernel compilation time.
  • hw.byteorder (HW_BYTEORDER) β€” the byteorder (4321, or 1234).
  • hw.cnmagic (HW_CNMAGIC) β€” the console magic key sequence. πŸͺ„
  • hw.disknames (HW_DISKNAMES) β€” the list of (space separated) disk device names on the system.
  • hw.iostatnames (HW_IOSTATNAMES) β€” a space separated list of devices that will have I/O statistics collected on them.
  • hw.iostats (HW_IOSTATS) β€” return statistical information on the NFS mounts, disk and tape devices on the system. an array of struct io_sysctl structures is returned, whose size depends on the current number of such objects in the system. the third level name is the size of the struct io_sysctl. the type of object can be determined by examining the type element of struct io_sysctl. which can be IOSTAT_DISK (disk drive), IOSTAT_TAPE (tape drive), or IOSTAT_NFS (NFS mount). πŸ“Š
  • hw.machine (HW_MACHINE) β€” the machine class.
  • hw.machine_arch (HW_MACHINE_ARCH) β€” the machine CPU class.
  • hw.model (HW_MODEL) β€” the machine model.
  • hw.ncpu (HW_NCPU) β€” the number of CPUs configured.
  • hw.ncpuonline (HW_NCPUONLINE) β€” the number of CPUs online.
  • hw.pagesize (HW_PAGESIZE) β€” the software page size.
  • hw.physmem (HW_PHYSMEM) β€” the bytes of physical memory as a 32-bit integer.
  • hw.physmem64 (HW_PHYSMEM64) β€” the bytes of physical memory as a 64-bit integer.
  • hw.usermem (HW_USERMEM) β€” the bytes of non-kernel memory as a 32-bit integer.
  • hw.usermem64 (HW_USERMEM64) β€” the bytes of non-kernel memory as a 64-bit integer.

🧠 The kern.* subtree 🧠

this subtree includes data generally related to the kernel β€” like, the whole vibe of the kernel itself. the string and integer information available for the kern level is detailed below. the changeable column shows whether a process with appropriate privilege may change the value. πŸ‘€

okay so here's the whole menu of kern. second-level names β€” type on the left, whether you're allowed to change it on the right. I'm putting the changeability right there with the type so you don't have to squint at anything 🫢 (and yeah, node means "not applicable" in the changeable column, she's built different).

  • kern.aio_listio_max β€” integer, changeable: yes
  • kern.aio_max β€” integer, changeable: yes
  • kern.arandom β€” integer, changeable: no
  • kern.argmax β€” integer, changeable: no
  • kern.boothowto β€” integer, changeable: no
  • kern.boottime β€” struct timespec, changeable: no
  • kern.buildinfo β€” string, changeable: no
  • kern.ccpu β€” integer, changeable: no
  • kern.clockrate β€” struct clockinfo, changeable: no
  • kern.consdev β€” integer, changeable: no
  • kern.coredump β€” node, changeable: not applicable
  • kern.cp_id β€” struct, changeable: no
  • kern.cp_time β€” uint64_t[], changeable: no
  • kern.cryptodevallowsoft β€” integer, changeable: yes
  • kern.defcorename β€” string, changeable: yes
  • kern.detachall β€” integer, changeable: yes
  • kern.domainname β€” string, changeable: yes
  • kern.drivers β€” struct kinfo_drivers, changeable: no
  • kern.dump_on_panic β€” integer, changeable: yes
  • kern.expose_address β€” integer, changeable: yes
  • kern.file β€” struct file, changeable: no
  • kern.forkfsleep β€” integer, changeable: yes
  • kern.fscale β€” integer, changeable: no
  • kern.fsync β€” integer, changeable: no
  • kern.hardclock_ticks β€” integer, changeable: no
  • kern.heartbeat.max_period β€” integer, changeable: yes
  • kern.hostid β€” integer, changeable: yes
  • kern.hostname β€” string, changeable: yes
  • kern.iov_max β€” integer, changeable: no
  • kern.ipc β€” node, changeable: not applicable
  • kern.job_control β€” integer, changeable: no
  • kern.labeloffset β€” integer, changeable: no
  • kern.labelsector β€” integer, changeable: no
  • kern.login_name_max β€” integer, changeable: no
  • kern.logsigexit β€” integer, changeable: yes
  • kern.lwp β€” struct kinfo_lwp, changeable: yes
  • kern.mapped_files β€” integer, changeable: no
  • kern.maxfiles β€” integer, changeable: yes
  • kern.maxlwp β€” integer, changeable: yes
  • kern.maxpartitions β€” integer, changeable: no
  • kern.maxphys β€” integer, changeable: no
  • kern.maxproc β€” integer, changeable: yes
  • kern.maxptys β€” integer, changeable: yes
  • kern.maxvnodes β€” integer, changeable: yes
  • kern.messages β€” integer, changeable: yes
  • kern.mbuf β€” node, changeable: not applicable
  • kern.memlock β€” integer, changeable: no
  • kern.memlock_range β€” integer, changeable: no
  • kern.memory_protection β€” integer, changeable: no
  • kern.module β€” node, changeable: not applicable
  • kern.monotonic_clock β€” integer, changeable: no
  • kern.mqueue β€” node, changeable: not applicable
  • kern.msgbuf β€” integer, changeable: no
  • kern.msgbufsize β€” integer, changeable: no
  • kern.ngroups β€” integer, changeable: no
  • kern.ntptime β€” struct ntptimeval, changeable: no
  • kern.osrelease β€” string, changeable: no
  • kern.osrevision β€” integer, changeable: no
  • kern.ostype β€” string, changeable: no
  • kern.pipe β€” node, changeable: not applicable
  • kern.pool β€” struct pool_sysctl, changeable: no
  • kern.posix1version β€” integer, changeable: no
  • kern.posix_aio β€” integer, changeable: no
  • kern.posix_barriers β€” integer, changeable: no
  • kern.posix_reader_writer_locks β€” integer, changeable: no
  • kern.posix_semaphores β€” integer, changeable: no
  • kern.posix_spin_locks β€” integer, changeable: no
  • kern.posix_threads β€” integer, changeable: no
  • kern.posix_timers β€” integer, changeable: no
  • kern.proc β€” struct kinfo_proc, changeable: no
  • kern.proc2 β€” struct kinfo_proc2, changeable: no
  • kern.proc_args β€” string, changeable: no
  • kern.profiling β€” node, changeable: not applicable
  • kern.rawpartition β€” integer, changeable: no
  • kern.root_device β€” string, changeable: no
  • kern.root_partition β€” integer, changeable: no
  • kern.rtc_offset β€” integer, changeable: yes
  • kern.saved_ids β€” integer, changeable: no
  • kern.sbmax β€” integer, changeable: yes
  • kern.sched β€” node, changeable: not applicable
  • kern.securelevel β€” integer, changeable: raise only
  • kern.sofixedbuf β€” boolean, changeable: yes
  • kern.somaxkva β€” integer, changeable: yes
  • kern.sooptions β€” integer, changeable: yes
  • kern.synchronized_io β€” integer, changeable: no
  • kern.timecounter β€” node, changeable: not applicable
  • kern.timex β€” struct, changeable: no
  • kern.tkstat β€” node, changeable: not applicable
  • kern.tty β€” node, changeable: not applicable
  • kern.urandom β€” integer, changeable: no
  • kern.usercrypto β€” integer, changeable: yes
  • kern.userasymcrypto β€” integer, changeable: yes
  • kern.veriexec β€” node, changeable: not applicable
  • kern.version β€” string, changeable: no
  • kern.vnode β€” struct vnode, changeable: no

and now the ✨lore✨ for each one:

kern.aio_listio_max

the absolute cap on how many async I/O ops you can shove into one single list I/O call. and like literally every variable that has anything to do with aio(3), this one can get created and yeeted dynamically when the matching kernel module gets loaded or unloaded πŸŽ€

kern.aio_max

the max number of asynchronous I/O operations. that's it, that's the tweet.

kern.arandom (KERN_ARND)

returns independent, uniformly distributed random bytes every single time you ask β€” as many as you want, up to 256, all pulled from the system entropy pool; go peek at rnd(4) for the deets πŸ’œ

reading kern.arandom is equivalent to reading up to 256 bytes at a time from /dev/urandom. reading it never blocks, and once the system entropy pool has full entropy, everything you read from kern.arandom afterwards is fit for use as cryptographic key material πŸ‘‘ for example, the arc4random(3) library routine uses kern.arandom internally to seed a cryptographic pseudorandom number generator. icon behaviour, honestly.

kern.argmax (KERN_ARGMAX)

the maximum bytes of argument that get handed to execve(2).

kern.boothowto

the flags that came in from the boot loader. hop over to reboot(2) if you wanna know what each flag actually means 🌸

kern.boottime (KERN_BOOTTIME)

you get a struct timespec structure back. it holds the time the system was booted β€” and for this purpose that time is defined as the moment the kernel first started accumulating clock ticks ⭐

kern.bufq

this one's carrying info about the bufq(9) subsystem. rn the only third level name that's actually implemented is kern.bufq.strategies, which hands you a list of the buffer queue strategies currently available πŸ¦‹

kern.buildinfo

when the kernel gets built, the build environment can optionally drop arbitrary info into this variable. cute little build-time easter egg.

kern.ccpu (KERN_CCPU)

the scheduler exponential decay value. math girlie things πŸ’…

kern.clockrate (KERN_CLOCKRATE)

you get a struct clockinfo structure back. inside: the clock, statistics clock and profiling clock frequencies, the number of micro-seconds per hz tick, and the clock skew rate. hz(9) has additional details if you're feeling curious πŸ”₯

kern.consdev (KERN_CONSDEV)

console device. short and sweet.

kern.coredump

all the settings around set-id processes and coredumps πŸ’€ by default, set-id processes don't dump core in situations where other processes totally would. this node is how an admin changes that behaviour.

the third level name is kern.coredump.setid, and the fourth level variables are right here:

  • kern.coredump.setid.dump β€” integer, changeable: yes
  • kern.coredump.setid.group β€” integer, changeable: yes
  • kern.coredump.setid.mode β€” integer, changeable: yes
  • kern.coredump.setid.owner β€” integer, changeable: yes
  • kern.coredump.setid.path β€” string, changeable: yes

and what they do:

  • kern.coredump.setid.dump β€” if it's non-zero, set-id processes will dump core 🫢
  • kern.coredump.setid.group β€” the group-id for the set-id processes' coredump.
  • kern.coredump.setid.mode β€” the mode for the set-id processes' coredump. peep chmod(1) for how modes work.
  • kern.coredump.setid.owner β€” the user-id that gets used as the owner of the set-id processes' coredump.
  • kern.coredump.setid.path β€” the path where the set-id processes' coredumps get saved. same syntax as kern.defcorename.

kern.cp_id (KERN_CP_ID)

a mapping of CPU number to CPU id. matching game πŸ”₯

kern.cp_time (KERN_CP_TIME)

returns an array of CPUSTATES uint64_ts. that array holds the number of clock ticks spent in the different CPU states. on multi-processor systems, the sum across all CPUs comes back to you β€” unless you gave it appropriate space for one data set for each CPU. you can also grab data for one specific CPU by adding the number of that CPU at the end of the MIB, which enlarges it by one 🧚

kern.cryptodevallowsoft

this variable controls userland access to hardware versus software transforms in the crypto(4) system 😭 the available values are:

  • < 0 β€” always force userlevel requests to use software transforms.
  • = 0 β€” if present, use hardware and grant userlevel requests for non-accelerated transforms (handling the latter in software).
  • > 0 β€” allow user requests only for transforms which are hardware-accelerated. yes that's a greater than zero situation, not an option name, we're still finishing up the last entry 🫢
  • kern.defcorename (KERN_DEFCORENAME) β€” the default template for the name of core dump files. also peep proc.pid.corename in the per-process variables proc.*, and core(5) for the format of this template. the default value is %n.core and you can change it with the kernel config option options DEFCORENAME (see options(4)).
  • kern.detachall β€” detach all devices at shutdown. that's it, that's the whole vibe.
  • kern.domainname (KERN_DOMAINNAME) β€” get or set the YP domain name.
  • kern.drivers (KERN_DRIVERS) β€” returns an array of struct kinfo_drivers containing the name and major device numbers of all the device drivers in the current kernel. the d_name field is always a NUL terminated string. the d_bmajor field gets set to -1 if the driver doesn't have a block device. bestie said "no block device" and honestly valid πŸ’…
  • kern.expose_address β€” exposes kernel addresses in sysctl(3) calls used by fstat(1) and sockstat(1).
    • set it to 0 β†’ access is not allowed.
    • set it to 1 β†’ only processes that have opened /dev/kmem can have access.
    • set it to 2 β†’ every process is allowed.
    • defaults to 0 for KASLR kernels and 1 otherwise.
🚨 okay listen: allowing general access renders KASLR ineffective, and allowing only kmem accessing programs weakens KASLR if those programs can be subverted to leak the addresses. this is not the casual little toggle it looks like, fr.
  • kern.dump_on_panic (KERN_DUMP_ON_PANIC) β€” perform a crash dump on panic(9).
  • kern.file (KERN_FILE) β€” returns the entire file table. the returned data consists of a single struct filelist followed by an array of struct file, whose size depends on the current number of such objects in the system. so like, the size is doing its own thing based on how much is going on 😭
  • kern.forkfsleep (KERN_FORKFSLEEP) β€” if the fork(2) system call fails due to a limit on the number of processes (either the global maxproc limit or the user's one), wait this many milliseconds before returning EAGAIN error to the process. useful to keep heavily forking runaway processes in bay 🧚 default zero (no sleep). maximum is 20 seconds.
  • kern.fscale (KERN_FSCALE) β€” the kernel fixed-point scale factor.
  • kern.fsync (KERN_FSYNC) β€” returns 1 if the IEEE Std 1003.1b-1993 (β€œPOSIX.1”) File Synchronization Option is available on this system, otherwise 0.
  • kern.hardclock_ticks (KERN_HARDCLOCK_TICKS) β€” returns the number of hardclock(9) ticks.
  • kern.heartbeat.max_period β€” time in seconds since the last options HEARTBEAT progress check has passed before it will trigger a panic. see options(4).
  • kern.hist β€” this variable contains kernel history data if the kernel was configured for any of the options UVMHIST, USB_DEBUG, BIOHIST, or SCDEBUG. (see options(4) for more details.) the third-level names correspond to each available history table. the values of the history tables are in an internal format, and can be decoded by the vmstat(1) utility's -U and -u options; the -l option can be used to see which tables are available. lowkey a little archaeological dig πŸ”
  • kern.hostid (KERN_HOSTID) β€” get or set the host identifier. this is aimed to replace the legacy gethostid(3) and sethostid(3) system calls.
  • kern.hostname (KERN_HOSTNAME) β€” get or set the hostname(1). main character of your prompt, honestly.
  • kern.iov_max (KERN_IOV_MAX) β€” return the maximum number of iovec structures that a process has available for use with preadv(2), pwritev(2), readv(2), recvmsg(2), sendmsg(2) and writev(2). that's a whole friend group of syscalls 🫢
  • kern.ipc (KERN_SYSVIPC) β€” return information about the SysV IPC parameters. the third level names for the ipc variables are detailed below πŸ‘‡
Third level name         Type       Changeable
kern.ipc.sysvmsg         integer    no
kern.ipc.sysvsem         integer    no
kern.ipc.sysvshm         integer    no
kern.ipc.sysvipc_info    struct     no
kern.ipc.shmmax          integer    yes
kern.ipc.shmmni          integer    yes
kern.ipc.shmseg          integer    yes
kern.ipc.shmmaxpgs       integer    yes
kern.ipc.shm_use_phys    integer    yes
kern.ipc.msgmni          integer    yes
kern.ipc.msgseg          integer    yes
kern.ipc.semmni          integer    yes
kern.ipc.semmns          integer    yes
kern.ipc.semmnu          integer    yes
  • kern.ipc.sysvmsg (KERN_SYSVIPC_MSG) β€” returns 1 if System V style message queue functionality is available on this system, otherwise 0.
  • kern.ipc.sysvsem (KERN_SYSVIPC_SEM) β€” returns 1 if System V style semaphore functionality is available on this system, otherwise 0.
  • kern.ipc.sysvshm (KERN_SYSVIPC_SHM) β€” returns 1 if System V style share memory functionality is available on this system, otherwise 0.
  • kern.ipc.sysvipc_info (KERN_SYSVIPC_INFO) β€” return System V style IPC configuration and run-time information. the fourth level name selects the System V style IPC facility.
Fourth level name        Type
KERN_SYSVIPC_MSG_INFO    struct msg_sysctl_info
KERN_SYSVIPC_SEM_INFO    struct sem_sysctl_info
KERN_SYSVIPC_SHM_INFO    struct shm_sysctl_info
  • KERN_SYSVIPC_MSG_INFO β€” return information on the System V style message facility. the msg_sysctl_info structure is defined in <sys/msg.h>.
  • KERN_SYSVIPC_SEM_INFO β€” return information on the System V style semaphore facility. the sem_sysctl_info structure is defined in <sys/sem.h>.
  • KERN_SYSVIPC_SHM_INFO β€” return information on the System V style shared memory facility. the shm_sysctl_info structure is defined in <sys/shm.h>.
  • kern.ipc.shmmax (KERN_SYSVIPC_SHMMAX) β€” max shared memory segment size in bytes.
  • kern.ipc.shmmni (KERN_SYSVIPC_SHMMNI) β€” max number of shared memory identifiers.
  • kern.ipc.shmseg (KERN_SYSVIPC_SHMSEG) β€” max shared memory segments per process.
  • kern.ipc.shmmaxpgs (KERN_SYSVIPC_SHMMAXPGS) β€” max amount of shared memory in pages.
  • kern.ipc.shm_use_phys (KERN_SYSVIPC_SHMUSEPHYS) β€” locking of shared memory in physical memory. if 0, memory can be swapped out, otherwise it will be locked in physical memory.
  • kern.ipc.msgmni β€” max number of message queue identifiers.
  • kern.ipc.msgseg β€” max number of number of message segments. πŸ’€ yes it literally says "number of number of", the manpage said what it said and I'm not editing her.
  • kern.ipc.semmni β€” max number of number of semaphore identifiers. same energy, iconic.
  • kern.ipc.semmns β€” max number of number of semaphores in system.
  • kern.ipc.semmnu β€” max number of undo structures in system.
  • kern.job_control (KERN_JOB_CONTROL) β€” returns 1 if job control is available on this system, otherwise 0.
  • kern.labeloffset (KERN_LABELOFFSET) β€” the offset within the sector specified by KERN_LABELSECTOR of the disklabel(5).
  • kern.labelsector (KERN_LABELSECTOR) β€” the sector number containing the disklabel(5).
  • kern.login_name_max (KERN_LOGIN_NAME_MAX) β€” the size of the storage required for a login name, in bytes, including the terminating NUL. yes bestie, the NUL counts toward the byte budget 🌸
  • kern.logsigexit (KERN_LOGSIGEXIT) β€” if this flag is non-zero, the kernel will log(9) all process exits due to signals which create a core(5) file, and whether the coredump was created.
  • kern.lwp (KERN_LWP) β€” returns information about the current light-weight process. the kinfo_lwp structure is defined in <sys/sysctl.h>.
  • kern.mapped_files (KERN_MAPPED_FILES) β€” returns 1 if the IEEE Std 1003.1b-1993 (β€œPOSIX.1”) Memory Mapped Files Option is available on this system, otherwise 0.
  • kern.maxfiles (KERN_MAXFILES) β€” the maximum number of open files that may be open in the system. this also controls the maximum file locks per unprivileged user enforced by fcntl(2) and flock(2). two jobs, one variable, she's versatile ✨
  • kern.maxpartitions (KERN_MAXPARTITIONS) β€” the maximum number of partitions allowed per disk.
  • kern.maxlwp β€” the maximum number of Lightweight Processes (threads) the system allows per uid.
  • kern.maxphys (KERN_MAXPHYS) β€” maximum raw I/O transfer size.
  • kern.maxproc (KERN_MAXPROC) β€” the maximum number of simultaneous processes the system will allow.
  • kern.maxptys (KERN_MAXPTYS) β€” the maximum number of pseudo terminals. this value can be both raised and lowered, though it cannot be set lower than number of currently used ptys. see also pty(4).
  • kern.maxvnodes (KERN_MAXVNODES) β€” the maximum number of vnodes available on the system. this cannot be lowered below the number of currently active vnodes. so like, respect the ones already thriving πŸ‘‘
  • kern.mbuf (KERN_MBUF) β€” return information about the mbuf control variables. mbufs are data structures which store network packets and other data structures in the networking code, see mbuf(9). the third level names for the mbuf variables are detailed below. the Changeable column shows whether a process with appropriate privilege may change the value.
Third level name               Type       Changeable
kern.mbuf.mblowat              integer    yes
kern.mbuf.mclbytes             integer    yes
kern.mbuf.mcllowat             integer    yes
kern.mbuf.msize                integer    yes
kern.mbuf.nmbclusters          integer    yes
kern.mbuf.nmbclusters_limit    integer    no

the variables are as follows:

  • kern.mbuf.mblowat (MBUF_MBLOWAT) β€” the mbuf low water mark.
  • kern.mbuf.mclbytes (MBUF_MCLBYTES) β€” the mbuf cluster size.
  • kern.mbuf.mcllowat (MBUF_MCLLOWAT) β€” the mbuf cluster low water mark.

and that's where this part cuts off β€” more variables coming, don't go anywhere πŸ’–

πŸ’– kern.mbuf.msize (MBUF_MSIZE)

The mbuf base size. Short king. That's the whole entry, no notes.

πŸ¦‹ kern.mbuf.nmbclusters (MBUF_NMBCLUSTERS)

The limit on the number of mbuf clusters. Okay but hear me: this one can only be increased β€” and it can only be increased on machines with direct-mapped pool pages. So there's no take-backs, no lowering it later. It's giving one-way street, ngl. πŸ™ˆ

kern.mbuf.nmbclusters_limit (MBUF_NMBCLUSTERS_LIMIT)

The limit of nmbclusters. Yes bestie, the limit of the limit. πŸ’…


⭐ kern.memlock (KERN_MEMLOCK)

Returns 1 if the IEEE Std 1003.1b-1993 (β€œPOSIX.1”) Process Memory Locking Option is available on this system, otherwise 0. Binary queen β€” it's a yes or a no, no in-between. ✨

kern.memlock_range (KERN_MEMLOCK_RANGE)

Returns 1 if the IEEE Std 1003.1b-1993 (β€œPOSIX.1”) Range Memory Locking Option is available on this system, otherwise 0.

🫢 kern.memory_protection (KERN_MEMORY_PROTECTION)

Returns 1 if the IEEE Std 1003.1b-1993 (β€œPOSIX.1”) Memory Protection Option is available on this system, otherwise 0. Same energy, different option, we love a consistent trio. πŸ’œ


πŸŽ€ kern.messages

Kernel console message verbosity. See <sys/reboot.h>. The mapping goes like this:

  • 0 β€” Silent β€” AB_SILENT
  • 1 β€” Quiet β€” AB_QUIET
  • 2 β€” Normal β€” AB_NORMAL
  • 3 β€” Verbose β€” AB_VERBOSE
  • 4 β€” Debug β€” AB_DEBUG

So like, 0 is "don't perceive me" and 4 is "I will tell you EVERYTHING". 😭


🌈 kern.module

Settings related to kernel modules. The third level names for the settings are:

  • kern.module.autoload β€” integer β€” changeable: yes
  • kern.module.autounload_unsafe β€” integer β€” changeable: yes
  • kern.module.autotime β€” integer β€” changeable: yes
  • kern.module.verbose β€” boolean β€” changeable: yes

The variables are as follows:

kern.module.autoload

A boolean that controls whether kernel modules are loaded automatically. See module(7) for details. iykyk.

kern.module.autounload_unsafe

A boolean that controls whether the kernel will autounload modules that were automatically loaded and have not been audited for autounload.

By default, only modules that have been audited will be autounloaded, and only if they were autoloaded to begin with. So the safe behaviour is the default, and this flag is you choosing chaos. 🚨

kern.module.autotime

An integer that controls the delay before an attempt is made to automatically unload a module that was autoloaded. Setting this value to zero disables the autounload function. Zero = off, that's the whole trick. πŸ’…

kern.module.verbose

A boolean that enables or disables verbose debug messages related to kernel modules. Turn it on when you want the kernel to overshare.


🌸 kern.monotonic_clock (KERN_MONOTONIC_CLOCK)

Returns the standard version the implementation of the IEEE Std 1003.1b-1993 (β€œPOSIX.1”) Monotonic Clock Option conforms to, otherwise 0. Time only goes forward, bestie. ⏳


πŸ“ kern.mqueue

Settings related to POSIX message queues; see mqueue(3). Heads up: this node is created dynamically when the corresponding kernel module is loaded β€” so if you can't find it, that's why. 🫠

The third level names for the settings are:

  • kern.mqueue.mq_open_max β€” integer β€” changeable: yes
  • kern.mqueue.mq_prio_max β€” integer β€” changeable: yes
  • kern.mqueue.mq_max_msgsize β€” integer β€” changeable: yes
  • kern.mqueue.mq_def_maxmsg β€” integer β€” changeable: yes
  • kern.mqueue.mq_max_maxmsg β€” integer β€” changeable: yes

The variables are:

kern.mqueue.mq_open_max

The maximum number of message queue descriptors any single process can open.

kern.mqueue.mq_prio_max

The maximum priority of a message.

kern.mqueue.mq_max_msgsize

The maximum size of a message in a message queue.

kern.mqueue.mq_def_maxmsg

The default maximum message count.

kern.mqueue.mq_max_maxmsg

The maximum number of messages in a message queue. (Yes, max_maxmsg. They said what they said. πŸ’€)


🧚 kern.msgbuf (KERN_MSGBUF)

The kernel message buffer, rotated so that the head of the circular kernel message buffer is at the start of the returned data. Important lil caveat: the returned data may contain NUL bytes. So don't you dare treat it like a cute little C string, bestie. 😭

kern.msgbufsize (KERN_MSGBUFSIZE)

The maximum number of characters that the kernel message buffer can hold.


πŸ”₯ kern.ngroups (KERN_NGROUPS)

The maximum number of supplemental groups.

kern.ntptime (KERN_NTPTIME)

A struct ntptimeval structure is returned. This structure contains data used by the ntpd(8) program. Time girlies, rise. ⏰


πŸ’œ kern.osrelease (KERN_OSRELEASE)

The system release string.

kern.osrevision (KERN_OSREV)

The system revision, expressed as an integer.

kern.ostype (KERN_OSTYPE)

The system type string. Three lil identity sysctls, all iconic, all short. πŸ‘‘


πŸŽ€ kern.pipe (KERN_PIPE)

Pipe settings. The third level names for the integer pipe settings are detailed below, and the changeable column tells you whether a process with appropriate privilege may change the value:

  • kern.pipe.kvasiz β€” integer β€” changeable: yes
  • kern.pipe.maxbigpipes β€” integer β€” changeable: yes
  • kern.pipe.maxkvasz β€” integer β€” changeable: yes
  • kern.pipe.limitkva β€” integer β€” changeable: yes
  • kern.pipe.nbigpipes β€” integer β€” changeable: yes

The variables are as follows:

kern.pipe.kvasiz (KERN_PIPE_KVASIZ)

Amount of kernel memory consumed by pipe buffers.

kern.pipe.maxbigpipes (KERN_PIPE_MAXBIGPIPES)

Maximum number of β€œbig” pipes. Yes the quotes are doing heavy lifting there. πŸ’…

kern.pipe.maxkvasz (KERN_PIPE_MAXKVASZ)

Maximum amount of kernel memory to be used for pipes.

kern.pipe.limitkva (KERN_PIPE_LIMITKVA)

Limit for direct transfers via page loan.

kern.pipe.nbigpipes (KERN_PIPE_NBIGPIPES)

Number of β€œbig” pipes.


✨ kern.pool

Provides statistics about the pool(9) and pool_cache(9) subsystems. Stats, not vibes β€” well, stats about the vibes. πŸ“Š


🌸 kern.posix1version (KERN_POSIX1)

The version of ISO/IEC 9945 (IEEE Std 1003.1 (β€œPOSIX.1”)) with which the system attempts to comply. Attempts is doing a lot of work in that sentence, but okay. 😌

kern.posix_aio

The version of IEEE Std 1003.1 (β€œPOSIX.1”) and its Asynchronous I/O option to which the system attempts to conform.

πŸ¦‹ kern.posix_barriers (KERN_POSIX_BARRIERS)

The version of IEEE Std 1003.1 (β€œPOSIX.1”) and its Barriers option to which the system attempts to conform, otherwise 0.

kern.posix_reader_writer_locks (KERN_POSIX_READER_WRITER_LOCKS)

The version of IEEE Std 1003.1 (β€œPOSIX.1”) and its Read-Write Locks option to which the system attempts to conform, otherwise 0.

kern.posix_semaphores (KERN_POSIX_SEMAPHORES)

The version of IEEE Std 1003.1 (β€œPOSIX.1”) and its Semaphores option to which the system attempts to conform, otherwise 0.

kern.posix_spin_locks (KERN_POSIX_SPIN_LOCKS)

The version of IEEE Std 1003.1 (β€œPOSIX.1”) and its Spin Locks option to which the system attempts to conform, otherwise 0. (Spin locks: the extroverts of the locking world. πŸ”„)

kern.posix_threads (KERN_POSIX_THREADS)

The version of IEEE Std 1003.1 (β€œPOSIX.1”) and its Threads option to which the system attempts to conform, otherwise 0.

kern.posix_timers (KERN_POSIX_TIMERS)

The version of IEEE Std 1003.1 (β€œPOSIX.1”) and its Timers option to which the system attempts to conform, otherwise 0.


πŸ‘‘ kern.proc (KERN_PROC)

Return the entire process table, or a subset of it. An array of struct kinfo_proc structures is returned, whose size depends on the current number of such objects in the system. So like... the array size is doing whatever it wants based on how many procs exist, stay flexible. πŸ’…

The third and fourth level numeric names are as follows:

  • KERN_PROC_ALL β€” fourth level is: None
  • KERN_PROC_GID β€” fourth level is: A group ID
  • KERN_PROC_PID β€” fourth level is: A process ID
  • KERN_PROC_PGRP β€” fourth level is: A process group
  • KERN_PROC_RGID β€” fourth level is: A real group ID
  • KERN_PROC_RUID β€” fourth level is: A real user ID
  • KERN_PROC_SESSION β€” fourth level is: A session ID
  • KERN_PROC_TTY β€” fourth level is: A tty device
  • KERN_PROC_UID β€” fourth level is: A user ID

kern.proc2 (KERN_PROC2)

As for KERN_PROC, but an array of struct kinfo_proc2 structures are returned. The fifth level name is the size of the struct kinfo_proc2 and the sixth level name is the number of structures to return. Six levels deep, bestie β€” that's not a sysctl, that's a whole family tree. 🌳

πŸŽ€ kern.proc_args (KERN_PROC_ARGS)

Return the argv or environment strings (or the number thereof) of a process. Multiple strings are returned separated by NUL characters. The third level name is the process ID. The fourth level name is as follows:

  • KERN_PROC_ARGV β€” The argv strings
  • KERN_PROC_ENV β€” The environ strings
  • KERN_PROC_NARGV β€” The number of argv strings
  • KERN_PROC_NENV β€” The number of environ strings
  • KERN_PROC_PATHNAME β€” The full pathname of the executable
  • KERN_PROC_CWD β€” The current working directory

πŸ”₯ kern.profiling (KERN_PROF)

Return profiling information about the kernel. Warning bestie: if the kernel is not compiled for profiling, attempts to retrieve any of the KERN_PROF values will fail with EOPNOTSUPP. So don't come crying to me, check your kernel config first. 😭

The third level names for the string and integer profiling information are detailed below, and the changeable column shows whether a process with appropriate privilege may change the value:

  • kern.profiling.count β€” u_short[] β€” changeable: yes
  • kern.profiling.froms β€” u_short[] β€” changeable: yes
  • kern.profiling.gmonparam β€” struct gmonparam β€” changeable: no
  • kern.profiling.state β€” integer β€” changeable: yes
  • kern.profiling.tos β€” struct tostruct β€” changeable: yes

The variables are as follows:

kern.profiling.count (GPROF_COUNT)

Array of statistical program counter counts.

kern.profiling.froms (GPROF_FROMS)

Array indexed by program counter of call-from points.

🌸 kern.profiling.gmonparams (GPROF_GMONPARAM)

Structure giving the sizes of the above arrays. (And yes, it's spelled gmonparams here β€” that's literally what the page says, don't @ me. 🫢)

🩺 kern.profiling.state (GPROF_STATE)

Profiling state, bestie. Set it to GMON_PROF_ON and profiling starts. Set it to GMON_PROF_OFF and profiling stops. that's it, that's the whole switch 🌸

kern.profiling.tos (GPROF_TOS)

An array of struct tostruct that describes where calls actually land and how many times each one happened. like a lil receipts folder for your function calls 🧾

kern.rawpartition (KERN_RAWPARTITION)

The raw partition of a disk, and ngl it's zero-indexed so a == 0. yes queen, we start at zero πŸ’…

kern.root_device (KERN_ROOT_DEVICE)

The name of the root device, e.g. wd0. literally the origin story of your whole filesystem 🫢

kern.root_partition (KERN_ROOT_PARTITION)

The root partition on the root device (a == 0). πŸŽ€

kern.rtc_offset (KERN_RTC_OFFSET)

Returns the offset of your real time clock from UTC, measured in minutes. iykyk πŸ•°οΈ

kern.saved_ids (KERN_SAVED_IDS)

Returns 1 if the saved set-group and saved set-user ID are available, otherwise not. it's giving "do we have the thing" energy πŸ‘‘

kern.sbmax (KERN_SBMAX)

Maximum socket buffer size, in bytes. big buffer, big vibes πŸ“¦

kern.securelevel (KERN_SECURELVL)

Head on over to secmodel_securelevel(9) for this one ✨

kern.sched (dynamic)

This whole node is here to influence the scheduling of LWPs β€” their priorisation, how they're distributed on CPUs, and how they get moved between them. main character scheduler behavior fr fr πŸ”₯

Third level names:

  • kern.sched.cacheht_time β€” integer β€” changeable: yes
  • kern.sched.balance_period β€” integer β€” changeable: yes
  • kern.sched.average_weight β€” integer β€” changeable: yes
  • kern.sched.min_catch β€” integer β€” changeable: yes
  • kern.sched.timesoftints β€” integer β€” changeable: yes
  • kern.sched.kpreempt_pri β€” integer β€” changeable: yes
  • kern.sched.upreempt_pri β€” integer β€” changeable: yes
  • kern.sched.maxts β€” integer β€” changeable: yes
  • kern.sched.mints β€” integer β€” changeable: yes
  • kern.sched.name β€” string β€” changeable: no
  • kern.sched.rtts β€” integer β€” changeable: no
  • kern.sched.pri_min β€” integer β€” changeable: no
  • kern.sched.pri_max β€” integer β€” changeable: no

The variables are as follows, and yes we're going through all of them πŸ’–

  • kern.sched.cacheht_time (dynamic) β€” Cache hotness time, aka how long a LWP gets kept on one particular CPU instead of being shuffled off to another one. This is the whole point: it reduces the overhead of flushing and reloading caches. Defaults to 3ms. You gotta give it in hz units, see mstohz(9). 🧚
  • kern.sched.balance_period (dynamic) β€” The interval at which the CPU queues get checked for re-balancing. Defaults to 300ms. Also needs to be given in hz units, see mstohz(9). βš–οΈ
  • kern.sched.average_weight (dynamic) β€” This one influences how likely LWPs are to be migrated from one CPU's queue of LWPs that are ready to run over to a different, idle CPU. The value is the percentage used for weighting the average count of migratable threads from the past against the current number of migratable threads. Small value = more weight on the past, larger value = more weight on the current situation. Defaults to 50, and it must be between 0 and 100. respect the range bestie 🫢
  • kern.sched.min_catch (dynamic) β€” Minimum count of migratable (runnable) threads needed for catching (stealing) from another CPU. Defaults to 1, but you can bump it up to decrease the chance of thread migration between CPUs. light fingers, lowkey πŸ™ˆ
  • kern.sched.timesoftints (dynamic) β€” Enables tracking of CPU time for soft interrupts as part of a LWP's real execution time. Set it to a non-zero value to enable it, and see ps(1) for printing CPU times. πŸ“Š
  • kern.sched.kpreempt_pri (dynamic) β€” Minimum priority to trigger kernel preemption. πŸ’₯
  • kern.sched.upreempt_pri (dynamic) β€” Minimum priority to trigger user preemption. πŸ’₯
  • kern.sched.maxts (dynamic) β€” Scheduler-specific maximal time quantum, in milliseconds. Must be set to a value larger than mints and between 10 and hz as given by the kern.clockrate sysctl. Provided by the M2 scheduler. πŸ‘‘
  • kern.sched.mints (dynamic) β€” Scheduler-specific minimal time quantum, in milliseconds. Must be set to a value smaller than maxts and between 1 and hz as given by the kern.clockrate sysctl. Provided by the M2 scheduler. πŸŽ€
  • kern.sched.name (dynamic) β€” The scheduler name. Provided both by the M2 and the 4BSD scheduler. ✨
  • kern.sched.rtts (dynamic) β€” Fixed scheduler-specific round-robin time quantum, in milliseconds. Provided both by the M2 and the 4BSD scheduler. πŸ”„
  • kern.sched.pri_min (dynamic) β€” Minimal POSIX real-time priority. See sched(3). ⭐
  • kern.sched.pri_max (dynamic) β€” Maximal POSIX real-time priority. See sched(3). ⭐

kern.sofixedbuf (KERN_SOFIXEDBUF)

Prevents socket buffer autoscaling whenever a size is set with SO_SNDBUF or SO_RCVBUF. no surprise resizing, we said what we said πŸ’…

kern.somaxkva (KERN_SOMAXKVA)

Maximum amount of kernel memory to be used for socket buffers, in bytes. πŸ’Ύ

kern.sooptions

Sets the default socket option flags for socket(2) creation. Peep setsockopt(2) for the list of supported flags 🌈

kern.synchronized_io (KERN_SYNCHRONIZED_IO)

Returns 1 if the IEEE Std 1003.1b-1993 (β€œPOSIX.1”) Synchronized I/O Option is available on this system, otherwise 0. it's literally a yes/no girlie βœ…

kern.timecounter (dynamic)

Display and control the timecounter source of the system. very important, very demure πŸ•°οΈ

Third level names:

  • kern.timecounter.choice β€” string β€” changeable: no
  • kern.timecounter.hardware β€” string β€” changeable: yes
  • kern.timecounter.timestepwarnings β€” integer β€” changeable: yes

The variables are as follows:

  • kern.timecounter.choice (dynamic) β€” The list of available timecounters, with their quality and frequency. it's giving menu πŸ“
  • kern.timecounter.hardware (dynamic) β€” The currently selected timecounter source. the one that got picked πŸ’–
  • kern.timecounter.timestepwarnings (dynamic) β€” If non-zero, displays a message each time the time is stepped. 😭

kern.timex (KERN_TIMEX)

Not available. she's not coming to the function, bestie πŸ’€

kern.tkstat (KERN_TKSTAT)

Returns information about the number of characters sent and received on ttys. The third level names for the tty statistic variables are detailed below, and the changeable column shows whether a process with appropriate privilege may change the value.

Third level names:

  • kern.tkstat.cancc β€” quad β€” changeable: no
  • kern.tkstat.nin β€” quad β€” changeable: no
  • kern.tkstat.nout β€” quad β€” changeable: no
  • kern.tkstat.rawcc β€” quad β€” changeable: no

The variables are as follows:

  • kern.tkstat.cancc (KERN_TKSTAT_CANCC) β€” The number of canonical input characters. πŸŽ€
  • kern.tkstat.nin (KERN_TKSTAT_NIN) β€” The total number of input characters. ⬅️
  • kern.tkstat.nout (KERN_TKSTAT_NOUT) β€” The total number of output characters. ➑️
  • kern.tkstat.rawcc (KERN_TKSTAT_RAWCC) β€” The number of raw input characters. 🧚

kern.tty

The third level names for the tty setup variables are detailed below, and the changeable column shows whether a process with appropriate privilege may change the value.

Third level names:

  • kern.tty.qsize β€” int β€” changeable: yes

The variables are as follows:

  • kern.tty.qsize β€” Control/display the size of the default input and output queues selected during tty creation. It gets converted to a power of two, and its range is between 1024 and 65536. powers of two only, we don't do arbitrary here πŸ‘‘

kern.uidinfo

Resource usage for the current user. it's your personal receipts 🧾

Third level names:

  • kern.uidinfo.proccnt β€” integer β€” changeable: no
  • kern.uidinfo.lwpcnt β€” integer β€” changeable: no
  • kern.uidinfo.lockcnt β€” integer β€” changeable: no
  • kern.uidinfo.semcnt β€” integer β€” changeable: no
  • kern.uidinfo.sbsize β€” integer β€” changeable: no
  • kern.uidinfo.proccnt β€” Returns the number of active processes for the current user. 🫢
  • kern.uidinfo.lwpcnt β€” Returns the number of active threads for the current user, and heads up: the first thread of each process is not counted. πŸ™ˆ
  • kern.uidinfo.lockcnt β€” Number of locks held by the current user. πŸ”’
  • kern.uidinfo.semcnt β€” Number of semaphores held by the current user. 🚦
  • kern.uidinfo.sbsize β€” Number of bytes in socket buffers allocated to the current user. πŸ“¦

kern.urandom (KERN_URND)

Random integer value. chaos, but make it cryptographic 🎲

kern.usercrypto

When enabled, this allows userland to open(2) the /dev/crypto special device, which is the one used by the crypto(4) system. πŸ”

kern.userasymcrypto

Enables or disables the use of software asymmetric crypto support in the crypto(4) system. πŸ—οΈ

kern.veriexec

Runtime information for veriexec(8).

Third level names:

  • kern.veriexec.algorithms β€” string β€” changeable: no
  • kern.veriexec.count β€” node β€” changeable: not applicable
  • kern.veriexec.strict β€” integer β€” changeable: yes
  • kern.veriexec.verbose β€” integer β€” changeable: yes
  • kern.veriexec.algorithms β€” Returns a string with the supported algorithms in Veriexec. the whole roster ✨
  • kern.veriexec.count β€” Sub-nodes get added to this node as new mounts are monitored by Veriexec. Each mount lives under its own tableN node, and under each of those there will be three variables indicating the mount point, the file system type, and the number of entries. it grows, it's alive πŸ¦‹
  • kern.veriexec.strict β€” Controls the strict level of Veriexec. See security(7) for more information on each level's implications. and bestie, please actually read that, the implications are real 😭
  • kern.veriexec.verbose β€” the vibes dial for Veriexec 🎚️. Set it to 0 and you only get the bare-minimum tea: fingerprint mismatches, entries getting yeeted from the tables, and modification of a fingerprinted file. Set it to 1 and it gets chatty (ie., when a file with a valid fingerprint is accessed). Verbose level 2 is straight-up debug mode πŸ‘€.
  • kern.version (KERN_VERSION) β€” the system version string, aka the kernel's little name tag πŸ’–.
  • kern.vnode (KERN_VNODE) β€” returns the entire vnode table, bestie. Big dump energy. ⚠️ note: the vnode table is not necessarily a consistent snapshot of the system, so don't come for me if it's a little chaotic. The returned data is an array whose size depends on the current number of such objects in the system, and each element of the array contains the kernel address of a vnode struct vnode * followed by the vnode itself struct vnode.

The machdep.* subtree

The set of variables defined here is architecture dependent β€” so like, your mileage honestly varies by machine 🫢. Most architectures define at least the following variable:

  • machdep.booted_kernel β€” type: string, changeable: no (hands off, it's not that kind of variable βœ‹)

The net.* subtree

The string and integer information available for the net level is detailed below, and the changeable column tells you whether a process with appropriate privilege may change the value πŸ‘‘. The second and third levels are typically the protocol family and protocol number, though this is not always the case (iconic of them, honestly).

  • net.route β€” routing messages, changeable: no
  • net.inet β€” IPv4 values, changeable: yes ✨
  • net.inet6 β€” IPv6 values, changeable: yes ✨
  • net.key β€” IPsec key management values, changeable: yes ✨

net.route (PF_ROUTE)

Returns the entire routing table or a subset of it. The data comes back as a sequence of routing messages (see route(4) for the header file, format and meaning πŸ“–) β€” and the length of each message is contained in the message header.

So the levels work like this, bestie: the third level name is a protocol number, which is currently always 0. The fourth level name is an address family, which may be set to 0 to select all address families. The fifth and sixth level names are as follows:

  • NET_RT_FLAGS β€” sixth level is rtflags
  • NET_RT_DUMP β€” sixth level is: None
  • NET_RT_IFLIST β€” sixth level is: None

net.inet (PF_INET)

Get or set various global information about the IPv4 (Internet Protocol version 4). The third level name is the protocol, and the fourth level name is the variable name. The currently defined protocols and names are, and yes I'm listing every single one because you deserve the full menu πŸ“:

arp

  • arp / nd_delay β€” integer, changeable βœ…
  • arp / nd_bmaxtries β€” integer, changeable βœ…
  • arp / nd_umaxtries β€” integer, changeable βœ…
  • arp / nd_basereachable β€” integer, changeable βœ…
  • arp / nd_retrans β€” integer, changeable βœ…
  • arp / nd_nud β€” integer, changeable βœ…
  • arp / nd_maxnudhint β€” integer, changeable βœ…
  • arp / log_movements β€” integer, changeable βœ…
  • arp / log_permanent_modify β€” integer, changeable βœ…
  • arp / log_unknown_network β€” integer, changeable βœ…
  • arp / log_wrong_iface β€” integer, changeable βœ…

carp

  • carp / allow β€” integer, changeable βœ…
  • carp / preempt β€” integer, changeable βœ…
  • carp / log β€” integer, changeable βœ…
  • carp / arpbalance β€” integer, changeable βœ…

icmp

  • icmp / errppslimit β€” integer, changeable βœ…
  • icmp / maskrepl β€” integer, changeable βœ…
  • icmp / rediraccept β€” integer, changeable βœ…
  • icmp / redirtimeout β€” integer, changeable βœ…
  • icmp / bmcastecho β€” integer, changeable βœ…
  • icmp / dynamic_rt_msg β€” boolean, changeable βœ…

ip

  • ip / allowsrcrt β€” integer, changeable βœ…
  • ip / anonportalgo.selected β€” string, changeable βœ…
  • ip / anonportalgo.available β€” string, changeable βœ…
  • ip / anonportalgo.reserve β€” struct, changeable βœ…
  • ip / anonportmax β€” integer, changeable βœ…
  • ip / anonportmin β€” integer, changeable βœ…
  • ip / checkinterface β€” integer, changeable βœ…
  • ip / dad_count β€” integer, changeable βœ…
  • ip / directed-broadcast β€” integer, changeable βœ…
  • ip / do_loopback_cksum β€” integer, changeable βœ…
  • ip / forwarding β€” integer, changeable βœ…
  • ip / forwsrcrt β€” integer, changeable βœ…
  • ip / gifttl β€” integer, changeable βœ…
  • ip / grettl β€” integer, changeable βœ…
  • ip / hashsize β€” integer, changeable βœ…
  • ip / hostzerobroadcast β€” integer, changeable βœ…
  • ip / lowportmin β€” integer, changeable βœ…
  • ip / lowportmax β€” integer, changeable βœ…
  • ip / maxflows β€” integer, changeable βœ…
  • ip / maxfragpackets β€” integer, changeable βœ…
  • ip / mtudisc β€” integer, changeable βœ…
  • ip / mtudisctimeout β€” integer, changeable βœ…
  • ip / random_id β€” integer, changeable βœ…
  • ip / redirect β€” integer, changeable βœ…
  • ip / subnetsarelocal β€” integer, changeable βœ…
  • ip / ttl β€” integer, changeable βœ…

tcp

  • tcp / rfc1323 β€” integer, changeable βœ…
  • tcp / sendspace β€” integer, changeable βœ…
  • tcp / recvspace β€” integer, changeable βœ…
  • tcp / mssdflt β€” integer, changeable βœ…
  • tcp / syn_cache_limit β€” integer, changeable βœ…
  • tcp / syn_bucket_limit β€” integer, changeable βœ…
  • tcp / syn_cache_interval β€” integer, changeable βœ…
  • tcp / init_win β€” integer, changeable βœ…
  • tcp / init_win_local β€” integer, changeable βœ…
  • tcp / mss_ifmtu β€” integer, changeable βœ…
  • tcp / win_scale β€” integer, changeable βœ…
  • tcp / timestamps β€” integer, changeable βœ…
  • tcp / cwm β€” integer, changeable βœ…
  • tcp / cwm_burstsize β€” integer, changeable βœ…
  • tcp / ack_on_push β€” integer, changeable βœ…
  • tcp / keepidle β€” integer, changeable βœ…
  • tcp / keepintvl β€” integer, changeable βœ…
  • tcp / keepcnt β€” integer, changeable βœ…
  • tcp / slowhz β€” integer, changeable: no πŸ™…
  • tcp / keepinit β€” integer, changeable βœ…
  • tcp / log_refused β€” integer, changeable βœ…
  • tcp / rstppslimit β€” integer, changeable βœ…
  • tcp / ident β€” struct, changeable: no πŸ™…
  • tcp / drop β€” struct, changeable: no πŸ™…
  • tcp / sack.enable β€” integer, changeable βœ…
  • tcp / sack.globalholes β€” integer, changeable: no πŸ™…
  • tcp / sack.globalmaxholes β€” integer, changeable βœ…
  • tcp / sack.maxholes β€” integer, changeable βœ…
  • tcp / ecn.enable β€” integer, changeable βœ…
  • tcp / ecn.maxretries β€” integer, changeable βœ…
  • tcp / congctl.selected β€” string, changeable βœ…
  • tcp / congctl.available β€” string, changeable βœ…
  • tcp / abc.enable β€” integer, changeable βœ…
  • tcp / abc.aggressive β€” integer, changeable βœ…

udp

  • udp / checksum β€” integer, changeable βœ…
  • udp / do_loopback_cksum β€” integer, changeable βœ…
  • udp / recvspace β€” integer, changeable βœ…
  • udp / sendspace β€” integer, changeable βœ…

The variables are as follows πŸ’… (this is the part where it gets good):

  • arp.nd_delay β€” the delay in seconds before sending the first probe, after it has been decided that the entry is stale. ⏳
  • arp.nd_bmaxtries β€” the maximum number of broadcasts send to discover the hardware address claiming an IP address.
  • arp.nd_umaxtries β€” the maximum number of unicasts send to the hardware address to ensure it still claims an IP address.
  • arp.nd_basereachable β€” the number of milliseconds the ARP entry is considered reachable before probing reachability.
  • arp.nd_retrans β€” the number of milliseconds between ARP probes.
  • arp.nd_nud β€” if set to non-zero, perform Neighor Unreachability Detection. πŸ‘€ (yes, that's how it's spelled in the source, don't @ me)
  • arp.nd_maxnudhint β€” Neighbor discovery permits upper layer protocols to supply reachability hints, to avoid unnecessary neighbor discovery exchanges. This variable defines the number of consecutive hints the neighbor discovery layer will take. For example, by setting the variable to 3, neighbor discovery layer will take 3 consecutive hints in maximum. After receiving 3 hints, neighbor discovery layer will perform normal neighbor discovery process. 🧠✨
  • carp.allow β€” if set to 0, incoming carp(4) packets will not be processed. If set to any other value, processing will occur. Enabled by default πŸŽ€.

carp.arpbalance

Set this to literally anything that isn't 0 and the ARP balancing magic of carp(4) turns on ✨. Here's the vibe: when ARP requests come in for an IP address that belongs to any of your virtual hosts, carp hashes the source IP from that ARP request to pick one lucky virtual host out of the whole set of hosts that share that IP. Then the master of that chosen host answers with the correct virtual MAC address πŸŽ€. Off by default, bestie.

carp.log

If you set this to any value other than 0, carp(4) will log its errors πŸ“. Disabled by default.

carp.preempt

Okay so this one's the "do I fight for the throne" switch πŸ‘‘. If it's 0, carp(4) will not try to become master while it's still hearing advertisements from another active master. If it's set to any other value, carp will snatch the virtual host crown if it thinks it can send advertisements more frequently than whoever's currently master. Disabled by default.

ip.allowsrcrt

Set to 1 and the host accepts source routed packets πŸ›£οΈ.

ip.anonportalgo.available

The available RFC 6056 port randomization algorithms β€” like, the whole lineup of what's on the menu for port picking 🎲.

ip.anonportalgo.reserve

A bitmask of ports that will not be used during anonymous or privileged port selection πŸ™…. Reserved means reserved, periodt.

ip.anonportalgo.selected

The currently selected RFC 6056 port randomization algorithm; peep rfc6056(7) for the details πŸ‘€.

ip.anonportmax

The highest port number to use for TCP and UDP ephemeral port allocation πŸ”₯. This cannot be set to less than 1024 or greater than 65535, and it must be greater than ip.anonportmin.

ip.anonportmin

The lowest port number to use for TCP and UDP ephemeral port allocation 🌸. This cannot be set to less than 1024 or greater than 65535.

ip.checkinterface

If set to non-zero, the host will reject packets addressed to it that arrive on an interface not bound to that address 🚫. > Heads up fr fr: currently this has to be disabled if NAT is used to translate the destination address to another local interface, or if addresses are added to the loopback interface instead of the interface where the packets for those packets are received.

ip.dad_count

The number of arp(4) probes sent for Address Conflict Detection πŸ”. Set it to 0 to disable this entirely.

ip.directed-broadcast

If set to 1, enables directed broadcast behavior for the host πŸ“’.

ip.do_loopback_cksum

Perform IP checksum on loopback βœ….

ip.forwarding

If set to 1, enables IP forwarding for the host β€” meaning the host is acting as a router 🚦. Main character energy, honestly.

ip.forwsrcrt

If set to 1, enables forwarding of source-routed packets for the host πŸ›€οΈ. > Careful bestie: this value may only be changed if the kernel security level is less than 1.

ip.gifttl

The maximum time-to-live (hop count) value for an IPv4 packet generated by a gif(4) tunnel interface ⏳.

ip.grettl

The maximum time-to-live (hop count) value for an IPv4 packet generated by a gre(4) tunnel interface ⏳.

ip.hashsize

The size of the IPv4 Fast Forward hash table πŸ—‚οΈ. This value must be a power of 2 (64, 256...). A larger hash table size results in fewer collisions β€” fewer collisions is literally the dream πŸ’…. Also see ip.maxflows.

ip.hostzerobroadcast

All zeroes address is broadcast address. Simple as that 🎯.

ip.lowportmax

The highest port number to use for TCP and UDP reserved port allocation πŸ”’. This cannot be set to less than 0 or greater than 1024, and must be greater than ip.lowportmin.

ip.lowportmin

The lowest port number to use for TCP and UDP reserved port allocation πŸ”’. This cannot be set to less than 0 or greater than 1024, and must be smaller than ip.lowportmax.

ip.maxflows

IPv4 Fast Forwarding is enabled by default ⚑. If set to 0, IPv4 Fast Forwarding is disabled. ip.maxflows controls the maximum amount of flows which can be created. The default value is 256.

ip.maxfragpackets

The maximum number of fragmented packets the node will accept πŸ“¦. 0 means the node will not accept any fragmented packets. -1 means the node will accept as many fragmented packets as it receives. The flag is provided basically for avoiding possible DoS attacks πŸ›‘οΈ.

ip.mtudisc

If set to 1, enables Path MTU Discovery (RFC 1191) 🧭. When Path MTU Discovery is enabled, the transmitted TCP segment size will be determined by the advertised maximum segment size (MSS) from the remote end, as constrained by the path MTU. If MTU Discovery is disabled, the transmitted segment size will never be greater than tcp.mssdflt (the local maximum segment size).

ip.mtudisctimeout

The number of seconds in which a route added by the Path MTU Discovery engine will time out ⏱️. When the route times out, the Path MTU Discovery engine will attempt to probe a larger path MTU.

ip.random_id

Assign random ip_id values 🎲.

ip.redirect

If set to 1, ICMP redirects may be sent by the host ↩️. This option is ignored unless the host is routing IP packets, and should normally be enabled on all systems.

ip.subnetsarelocal

If set to 1, subnets are to be considered local addresses 🏑.

ip.ttl

The maximum time-to-live (hop count) value for an IP packet sourced by the system ⏳. This value applies to normal transport protocols, not to ICMP.

icmp.errppslimit

This variable specifies the maximum number of outgoing ICMP error messages, per second 🚨. ICMP error messages that exceeded the value are subject to rate limitation and will not go out from the node. A negative value disables rate limitation.

icmp.maskrepl

If set to 1, ICMP network mask requests are to be answered 🎭.

icmp.rediraccept

If set to non-zero, the host will accept ICMP redirect packets ↩️. > Note that routers will never accept ICMP redirect packets, and the variable is meaningful on IP hosts only.

icmp.redirtimeout

This variable specifies the lifetime of routing entries generated by incoming ICMP redirect ⏳. This defaults to 600 seconds.

icmp.returndatabytes

Number of bytes to return in an ICMP error message πŸ“.

icmp.bmcastecho

If set to 1, enables responding to ICMP echo or timestamp request to the broadcast address πŸ“‘.

icmp.dynamic_rt_msg

A boolean that says whether the kernel sends a routing message for RTM_DYNAMIC or not 🧾. If set to true, it sends such a routing message.

tcp.ack_on_push

If set to 1, TCP is to immediately transmit an ACK upon reception of a packet with PUSH set ⚑. This can avoid losing a round trip time in some rare situations, but has the caveat of potentially defeating TCP's delayed ACK algorithm. > Use of this option is generally not recommended, but the variable exists in case your configuration really needs it πŸ™ˆ.

tcp.cwm

If set to 1, enables use of the Hughes/Touch/Heidemann Congestion Window Monitoring algorithm πŸ“‰. This algorithm prevents line-rate bursts of packets that could otherwise occur when data begins flowing on an idle TCP connection. These line-rate bursts can contribute to network and router congestion. This can be particularly useful on World Wide Web servers which support HTTP/1.1, which has lingering connections β€” iykyk 🌐.

tcp.cwm_burstsize

The Congestion Window Monitoring allowed burst size, in terms of packet count πŸ“¦.

tcp.delack_ticks

Number of ticks to delay sending an ACK ⏲️.

tcp.do_loopback_cksum

Perform TCP checksum on loopback βœ….

tcp.init_win

A value indicating the TCP initial congestion window πŸͺŸ. The valid range is 0 to 10 (maximum specified by RFC6928), with a default of 4 (approximately 4K per RFC3390).

tcp.init_win_local

Like tcp.init_win, but used when communicating with hosts on a local network 🏘️.

tcp.keepcnt

Number of keepalive probes sent before declaring a connection dead πŸ’€. If set to zero, there is no limit; keepalives will be sent until some kind of response is received from the peer.

tcp.keepidle

Time a connection must be idle before keepalives are sent (if keepalives are enabled for the connection) 😴. See also tcp.slowhz.

tcp.keepintvl

Time after a keepalive probe is sent until, in the absence of any response, another probe is sent πŸ”. See also tcp.slowhz.

tcp.log_refused

If set to 1, refused TCP connections to the host will be logged πŸ“.

tcp.keepinit

Timeout in seconds during connection establishment ⏳.

  • tcp.mss_ifmtu β€” set this to 1 and TCP works out the outgoing maximum segment size from the MTU of the interface it's actually leaving through. Set it to 0 and it uses whichever is bigger: that interface's MTU, or the largest non-loopback interface MTU on the whole system.
  • tcp.mssdflt β€” the default maximum segment size, both the one we advertise to our peer and the one we use when the peer doesn't advertise an MSS to us during connection setup, or when Path MTU Discovery (ip.mtudisc) is disabled. 🫢 bestie please do not touch this value unless you literally know exactly what you're doing.
  • tcp.recvspace β€” the default TCP receive buffer size.
  • tcp.rfc1323 β€” set to 1 and the RFC 1323 extensions to TCP are enabled. slay.
  • tcp.rstppslimit β€” the max number of outgoing TCP RST packets per second. Any TCP RST packet that goes over that value gets rate limited and will not leave the node. A negative value disables rate limitation entirely.
  • tcp.ident β€” returns the user ID of a connected socket pair. (that's for RFC1413 Identification Protocol lookups, iykyk)
  • tcp.drop β€” drops a TCP socket pair connection. πŸ’€
  • tcp.sack.enable β€” set to 1 and RFC 2018 Selective ACKnowledgement is on.
  • tcp.sack.globalholes β€” global number of TCP SACK holes.
  • tcp.sack.globalmaxholes β€” global maximum number of TCP SACK holes.
  • tcp.sack.maxholes β€” maximum number of TCP SACK holes allowed per connection.
  • tcp.ecn.enable β€” set to 1 and RFC 3168 Explicit Congestion Notification is enabled.
  • tcp.ecn.maxretries β€” how many times to retry sending the ECN-setup packet.
  • tcp.sendspace β€” the default TCP send buffer size.
  • tcp.slowhz β€” the unit for tcp.keepidle and tcp.keepintvl; those variables are in ticks of a clock that ticks tcp.slowhz times per second. (so like, divide their values by tcp.slowhz to get seconds. math era ✨)
  • tcp.syn_bucket_limit β€” the maximum number of entries allowed per hash bucket in the TCP compressed state engine.
  • tcp.syn_cache_limit β€” the maximum number of entries allowed in the TCP compressed state engine.
  • tcp.timestamps β€” if rfc1323 is enabled, a value of 1 means RFC 1323 time stamp options β€” the ones used for measuring TCP round trip times β€” are enabled.
  • tcp.win_scale β€” if rfc1323 is enabled, a value of 1 means RFC 1323 window scale options, for increasing the TCP window size, are enabled.
  • tcp.congctl.available β€” the available TCP congestion control algorithms.
  • tcp.congctl.selected β€” the currently selected TCP congestion control algorithm.
  • tcp.abc.enable β€” set to 1 and we use RFC 3465 Appropriate Byte Counting (ABC). Set to 0 and it's traditional Packet Counting.
  • tcp.abc.aggressive β€” picks the L parameter from RFC 3465. L is the maximum cwnd increase for an ack during slow start. Set to 1 β†’ L=2*SMSS. Set to 0 β†’ L=1*SMSS. It has no effect unless tcp.abc.enable is set to 1. πŸ™ˆ
  • udp.checksum β€” set to 1 and UDP checksums are being computed. Received non-zero UDP checksums are always checked, no matter what. Disabling UDP checksums is strongly discouraged.
  • udp.recvspace β€” the default UDP receive buffer size.
  • udp.sendspace β€” the default UDP send buffer size.
for the net.*.ipsec variables, go peek at ipsec(4) bestie 🫢

🌈 net.inet6 (PF_INET6) 🌈

Get or set various global info about IPv6 (Internet Protocol version 6). The third level name is the protocol, and the fourth level name is the variable name. The currently defined protocols and names are:

  • icmp6
    • errppslimit β€” integer, changeable: yes
    • mtudisc_hiwat β€” integer, changeable: yes
    • mtudisc_lowat β€” integer, changeable: yes
    • nd6_debug β€” integer, changeable: yes
    • nd6_delay β€” integer, changeable: yes
    • nd6_maxnudhint β€” integer, changeable: yes
    • nd6_mmaxtries β€” integer, changeable: yes
    • nd6_prune β€” integer, changeable: yes
    • nd6_umaxtries β€” integer, changeable: yes
    • nd6_useloopback β€” integer, changeable: yes
    • nodeinfo β€” integer, changeable: yes
    • rediraccept β€” integer, changeable: yes
    • redirtimeout β€” integer, changeable: yes
    • reflect_pmtu β€” boolean, changeable: yes
    • dynamic_rt_msg β€” boolean, changeable: yes
  • ip6
    • accept_rtadv β€” integer, changeable: yes
    • addctlpolicy β€” struct in6_addrpolicy, changeable: no
    • anonportalgo.selected β€” string, changeable: yes
    • anonportalgo.available β€” string, changeable: yes
    • anonportalgo.reserve β€” struct, changeable: yes
    • anonportmax β€” integer, changeable: yes
    • anonportmin β€” integer, changeable: yes
    • auto_flowlabel β€” integer, changeable: yes
    • dad_count β€” integer, changeable: yes
    • defmcasthlim β€” integer, changeable: yes
    • forwarding β€” integer, changeable: yes
    • gifhlim β€” integer, changeable: yes
    • hashsize β€” integer, changeable: yes
    • hlim β€” integer, changeable: yes
    • hdrnestlimit β€” integer, changeable: yes
    • kame_version β€” string, changeable: no
    • keepfaith β€” integer, changeable: yes
    • log_interval β€” integer, changeable: yes
    • lowportmax β€” integer, changeable: yes
    • lowportmin β€” integer, changeable: yes
    • maxdynroutes β€” integer, changeable: yes
    • maxifprefixes β€” integer, changeable: yes
    • maxifdefrouters β€” integer, changeable: yes
    • maxflows β€” integer, changeable: yes
    • maxfragpackets β€” integer, changeable: yes
    • maxfrags β€” integer, changeable: yes
    • neighborgcthresh β€” integer, changeable: yes
    • param_rt_msg β€” integer, changeable: yes
    • redirect β€” integer, changeable: yes
    • rr_prune β€” integer, changeable: yes
    • use_deprecated β€” integer, changeable: yes
    • v6only β€” integer, changeable: yes
  • udp6
    • do_loopback_cksum β€” integer, changeable: yes
    • recvspace β€” integer, changeable: yes
    • sendspace β€” integer, changeable: yes

✨ The variables, explained ✨

  • ip6.accept_rtadv β€” set it to a non-zero value and the node will accept ICMPv6 router advertisement packets and autoconfigure address prefixes and default routers. Heads up: the node has to be a host (not a router) for this option to be meaningful.
  • ip6.anonportalgo.available β€” the available RFC 6056 port randomization algorithms.
  • ip6.anonportalgo.reserve β€” a bitmask of ports that will not be used during anonymous or privileged port selection.
  • ip6.anonportalgo.selected β€” the currently selected RFC 6056 port randomization algorithm; peep rfc6056(7) for the details. πŸŽ€
  • ip6.anonportmax β€” the highest port number to use for TCP and UDP ephemeral port allocation. Can't be set below 1024 or above 65535, and it must be greater than ip6.anonportmin.
  • ip6.anonportmin β€” the lowest port number to use for TCP and UDP ephemeral port allocation. Can't be set below 1024 or above 65535.
  • ip6.auto_flowlabel β€” on connected transport protocol packets, fills the IPv6 flowlabel field to help intermediate routers identify packet flows.
  • ip6.dad_count β€” configures the number of IPv6 DAD (duplicated address detection) probe packets. These packets get generated when IPv6 interface addresses are configured.
  • ip6.defmcasthlim β€” the default hop limit value for an IPv6 multicast packet sourced by the node. Applies to all the transport protocols sitting on top of IPv6. There are APIs to override this value, as documented in ip6(4).
  • ip6.forwarding β€” set to 1 and IPv6 forwarding is enabled for the node, meaning the node is acting as a router. Set to 0 and IPv6 forwarding is disabled, meaning the node is acting as a host. The IPv6 spec defines "router" case and "host" case node behavior quite differently, so changing this variable during operation may cause serious trouble. It is recommended to configure it at bootstrap time, and bootstrap time only. πŸ‘‘

  • ip6.gifhlim β€” the max hop limit value an IPv6 packet can have when it's generated by a gif(4) tunnel interface 🌈
  • ip6.hdrnestlimit β€” how many IPv6 extension headers are allowed on incoming IPv6 packets. Set it to 0 and the node will accept as many extension headers as possible (yes, as many as possible, bestie, be careful with that one πŸ™ˆ).
  • ip6.hashsize β€” the size of the IPv6 Fast Forward hash table. It must be a power of 2 (64, 256, ...). Bigger table = fewer collisions. Also peep ip6.maxflows πŸ‘€
  • ip6.hlim β€” the default hop limit value for an IPv6 unicast packet sourced by the node. This applies to all the transport protocols sitting on top of IPv6, and there are APIs to override it, as documented in ip6(4) ✨
  • ip6.kame_version β€” a string that identifies the version of the KAME IPv6 stack implemented in the kernel πŸ’–
  • ip6.keepfaith β€” set it to non-zero and it enables the β€œFAITH” TCP relay IPv6-to-IPv4 translator code in the kernel. Refer to faith(4) and faithd(8) for the details 🫢
  • ip6.log_interval β€” controls the amount of logs generated by the IPv6 packet forwarding engine, by setting the interval between log output (in seconds) πŸ“
  • ip6.lowportmax β€” the highest port number to use for TCP and UDP reserved port allocation. Can't be set to less than 0 or greater than 1024, and it must be greater than ip6.lowportmin. No cap on the drama, but there is a cap on this number πŸŽ€
  • ip6.lowportmin β€” the lowest port number to use for TCP and UDP reserved port allocation. Can't be set to less than 0 or greater than 1024, and it must be smaller than ip6.lowportmax. It's giving "these two are literally a matched set" πŸ’…
  • ip6.maxdynroutes β€” maximum number of routes created by redirect. Set it to a negative value to disable. The default value is 4096 πŸ”₯
  • ip6.maxifprefixes β€” maximum number of prefixes created by route advertisements per interface. Set it to a negative value to disable. The default value is 16 ⭐
  • ip6.maxifdefrouters 16 β€” maximum number of default routers created by route advertisements per interface. Set it to a negative value to disable. The default value is 16 πŸ¦‹
  • ip6.maxflows β€” IPv6 Fast Forwarding is enabled by default. If set to 0, IPv6 Fast Forwarding is disabled. ip6.maxflows controls the maximum amount of flows which can be created. The default value is 256 🌊
  • ip6.maxfragpackets β€” the maximum number of fragmented packets the node will accept. 0 means the node will not accept any fragmented packets. -1 means the node will accept as many fragmented packets as it receives. This flag is provided basically for avoiding possible DoS attacks πŸ›‘οΈ
  • ip6.maxfrags β€” the maximum number of fragments the node will accept. 0 means the node will not accept any fragments. -1 means the node will accept as many fragments as it receives. Same deal: the flag is provided basically for avoiding possible DoS attacks πŸ’€
  • ip6.neighborgcthresh β€” maximum number of entries in the neighbor cache per interface. Set to a negative value to disable. The default value is 2048 🧚
  • ip6.param_rt_msg β€” if set to 0, the parameter changing routing message is suppressed. If set to 1, the parameter changing routing message is sent by RTM_NEWADDR. Other values are undefined yet β€” so like, don't. πŸ™ˆ
  • ip6.redirect β€” if set to 1, ICMPv6 redirects may be sent by the node. This option is ignored unless the node is routing IP packets, and it should normally be enabled on all systems πŸ‘‘
  • ip6.rr_prune β€” specifies the interval between IPv6 router renumbering prefix babysitting, in seconds πŸ‘Ά
  • ip6.use_deprecated β€” controls use of deprecated address, as specified in RFC 2462 5.5.4 πŸ“œ
  • ip6.v6only β€” specifies the initial value for the IPV6_V6ONLY socket option for AF_INET6 sockets. Please refer to ip6(4) for detail πŸ’œ
  • icmp6.errppslimit β€” specifies the maximum number of outgoing ICMPv6 error messages, per second. ICMPv6 error messages that exceeded the value are subject to rate limitation and will not go out from the node. A negative value disables rate limitation 🚦
  • icmp6.mtudisc_hiwat, icmp6.mtudisc_lowat β€” these variables define the maximum number of routing table entries created due to path MTU discovery (which prevents denial-of-service attacks with ICMPv6 too big messages). When IPv6 path MTU discovery happens, we keep path MTU information in the routing table. If the number of routing table entries exceeds the value, the kernel will not attempt to keep the path MTU information. icmp6.mtudisc_hiwat is used when we have verified ICMPv6 too big messages. icmp6.mtudisc_lowat is used when we have unverified ICMPv6 too big messages. Verification is performed by using address/port pairs kept in connected pcbs. A negative value disables the upper limit πŸ”
  • icmp6.nd6_debug β€” if set to non-zero, the kernel IPv6 neighbor discovery code will generate debugging messages. Those debug outputs are useful to diagnose IPv6 interoperability issues. The flag must be set to 0 for normal operation β€” read that again, bestie ⚠️
  • icmp6.nd6_delay β€” specifies the DELAY_FIRST_PROBE_TIME timing constant in the IPv6 neighbor discovery specification (RFC 2461), in seconds ⏳
  • icmp6.nd6_maxnudhint β€” neighbor discovery permits upper layer protocols to supply reachability hints, to avoid unnecessary neighbor discovery exchanges. This variable defines the number of consecutive hints the neighbor discovery layer will take. For example, by setting the variable to 3, the neighbor discovery layer will take 3 consecutive hints in maximum. After receiving 3 hints, the neighbor discovery layer will perform the normal neighbor discovery process πŸ’‘
  • icmp6.nd6_mmaxtries β€” specifies the MAX_MULTICAST_SOLICIT constant in the IPv6 neighbor discovery specification (RFC 2461) πŸ“’
  • icmp6.nd6_prune β€” specifies the interval between IPv6 neighbor cache babysitting, in seconds 🧹
  • icmp6.nd6_umaxtries β€” specifies the MAX_UNICAST_SOLICIT constant in the IPv6 neighbor discovery specification (RFC 2461) πŸ“£
  • icmp6.nd6_useloopback β€” if set to non-zero, the kernel IPv6 stack will use the loopback interface for local traffic πŸ”
  • icmp6.nodeinfo β€” enables responses to ICMPv6 node information queries. If you set it to 0, responses will not be generated for ICMPv6 node information queries. Since node information queries can have a security impact, it's possible to fine tune which responses should be answered. Two separate bits can be set πŸŽ›οΈ
    • 1 β€” respond to ICMPv6 FQDN queries, e.g. ping6 -w.
    • 2 β€” respond to ICMPv6 node addresses queries, e.g. ping6 -a.
  • icmp6.rediraccept β€” if set to non-zero, the host will accept ICMPv6 redirect packets. Note that IPv6 routers will never accept ICMPv6 redirect packets, and the variable is meaningful on IPv6 hosts (non-router) only πŸ™…β€β™€οΈ
  • icmp6.redirtimeout β€” specifies the lifetime of routing entries generated by incoming ICMPv6 redirect βŒ›
  • icmp6.reflect_pmtu β€” a boolean for whether icmpv6 reflecting uses path MTU discovery or not. When not, icmpv6 reflecting uses IPV6_MINMTU πŸͺž
  • icmp6.dynamic_rt_msg β€” a boolean for whether the kernel sends a routing message for RTM_DYNAMIC or not. If set to true, it sends such a routing message πŸ“¨
  • udp6.do_loopback_cksum β€” perform UDP checksum on loopback βœ…
  • udp6.recvspace β€” default UDP receive buffer size πŸ“₯
  • udp6.sendspace β€” default UDP send buffer size πŸ“€

Variables net.inet6.tcp6.* and net.inet6.udp6.* have identical meanings to net.inet.tcp.* and net.inet.udp.*, respectively. Please refer to the PF_INET section above. For variables net.*.ipsec6, please refer to ipsec(4) 🫑

πŸ”‘ net.key (PF_KEY)

Get or set various global information about the IPsec key management. The third level name is the variable name. The currently defined variable and names are:

Variable             Type       Changeable
debug                integer    yes
enabled              integer    yes
used                 integer    no
spi_try              integer    yes
spi_min_value        integer    yes
spi_max_value        integer    yes
larval_lifetime      integer    yes
blockacq_count       integer    yes
blockacq_lifetime    integer    yes
esp_keymin           integer    yes
esp_auth             integer    yes
ah_keymin            integer    yes
allow_different_idtype          boolean       yes

The variables are as follows:

  • debug β€” turns on debugging messages from inside the kernel ✨ the value is a bitmap, exactly as defined in <netipsec/key_debug.h>.
  • enabled β€” controls how IPsec control messages get processed πŸ‘‘
    • 0 β€” never allow IPsec processing
    • 1 β€” allow IPsec processing when SPD policies are present
    • 2 β€” force IPsec processing even when SPD policies are not present
  • used β€” shows whether IPsec is actually being used, based on whether IPsec is enabled and whether SPD rules exist. > ⚠️ heads up bestie: currently, once IPsec is being used, it cannot be disabled. Like, ever. It's giving permanent commitment πŸ’€
  • spi_try β€” how many times the kernel will try to grab a unique SPI when it generates one from the random number generator 🎲
  • spi_min_value β€” the minimum SPI value when the kernel generates one.
  • spi_max_value β€” the maximum SPI value when the kernel generates one.
  • larval_lifetime β€” lifetime for LARVAL SAD entries, in seconds ⏳
  • blockacq_count β€” the number of ACQUIRE PF_KEY messages to be blocked after an ACQUIRE message. It stops a whole flood of ACQUIRE PF_KEY messages from being sent from the kernel to the key management daemon 🌊
  • blockacq_lifetime β€” lifetime of an ACQUIRE PF_KEY message.
  • esp_keymin β€” minimum ESP key length, in bits. This value is used when the kernel creates the proposal payload on an ACQUIRE PF_KEY message.
  • esp_auth β€” whether ESP authentication should be used or not. A non-zero value means yes, ESP authentication should be used πŸ’… The value is used when the kernel creates the proposal payload on an ACQUIRE PF_KEY message.
  • ah_keymin β€” minimum AH key length, in bits. The value is used when the kernel creates the proposal payload on an ACQUIRE PF_KEY message.
  • allow_different_idtype β€” a boolean that allows or disallows different identifier types on IDii and IDir. Allowing it can improve interconnectivity with some VPN appliances 🫢

🌸 net.local (PF_LOCAL)

Get or set various global info about AF_LOCAL type sockets. For some variables, the third level name is the variable name, iconic behavior honestly:

  • inflight β€” type integer, changeable: no
  • deferred β€” type integer, changeable: no

The variables are as follows:

  • inflight β€” the number of file descriptors currently passed between processes, i.e. "in flight" ✈️
  • deferred β€” the number of file descriptors passed between processes that have been deferred for cleanup by a kernel task 🧹

Other variables are specific to a socket type:

  • dgram / pcblist β€” type struct, changeable: no
  • dgram / recvspace β€” type integer, changeable: yes
  • dgram / sendspace β€” type integer, changeable: yes
  • seqpacket / pcblist β€” type struct, changeable: no
  • stream / pcblist β€” type struct, changeable: no
  • stream / recvspace β€” type integer, changeable: yes
  • stream / sendspace β€” type integer, changeable: yes

The variables are as follows:

  • dgram.pcblist β€” the Protocol Control Block list structure for datagram sockets. Parsed by netstat(1) or sockstat(1) πŸ”
  • dgram.recvspace β€” the default datagram receive buffer size.
  • dgram.sendspace β€” the default datagram send buffer size.
  • seqpacket.pcblist β€” the Protocol Control Block list structure for Sequential Packet sockets. Parsed by netstat(1) or sockstat(1).
  • stream.pcblist β€” the Protocol Control Block list structure for stream sockets. Parsed by netstat(1) or sockstat(1).
  • stream.recvspace β€” the default stream receive buffer size.
  • stream.sendspace β€” the default stream send buffer size.

🧚 The proc.* subtree

The string and integer info available for the proc level is detailed below. The changeable column tells you whether a process with appropriate privilege may change the value. These values are per-process, so they can literally change from one process to another β€” main character energy, each process gets its own ✨ When a process is created, the default values are inherited from its parent. When a set-user-ID or set-group-ID binary is executed, the value of PROC_PID_CORENAME is reset to the system default value. The second level name is either the magic value PROC_CURPROC, which points to the current process, or the PID of the target process 🎯

  • proc.pid.corename β€” type string, changeable: yes
  • proc.pid.rlimit β€” type node, changeable: not applicable
  • proc.pid.stopfork β€” type int, changeable: yes
  • proc.pid.stopexec β€” type int, changeable: yes
  • proc.pid.stopexit β€” type int, changeable: yes
  • proc.pid.paxflags β€” type int, changeable: no

πŸŽ€ proc.pid.corename (PROC_PID_CORENAME)

The template used for the core dump file name (see core(5) for the deets). The base name must either be core or end with the suffix .core β€” the super-user may set arbitrary names, because of course they can πŸ‘‘ By default it points to KERN_DEFCORENAME.

πŸ¦‹ proc.pid.rlimit (PROC_PID_LIMIT)

Returns resource limits, as defined for the getrlimit(2) and setrlimit(2) system calls. The fourth level name is one of:

  • proc.pid.rlimit.cputime (PROC_PID_LIMIT_CPU) β€” the maximum amount of CPU time (in seconds) to be used by each process ⏱️
  • proc.pid.rlimit.filesize (PROC_PID_LIMIT_FSIZE) β€” the largest size (in bytes) file that may be created.
  • proc.pid.rlimit.datasize (PROC_PID_LIMIT_DATA) β€” the maximum size (in bytes) of the data segment for a process; this defines how far a program may extend its break with the sbrk(2) system call.
  • proc.pid.rlimit.stacksize (PROC_PID_LIMIT_STACK) β€” the maximum size (in bytes) of the stack segment for a process; this defines how far a program's stack segment may be extended. Stack extension is performed automatically by the system πŸͺ„
  • proc.pid.rlimit.coredumpsize (PROC_PID_LIMIT_CORE) β€” the largest size (in bytes) core file that may be created.
  • proc.pid.rlimit.memoryuse (PROC_PID_LIMIT_RSS) β€” the maximum size (in bytes) to which a process's resident set size may grow. This puts a limit on the amount of physical memory handed to a process; if memory is tight, the system will prefer to take memory from processes that are exceeding their declared resident set size πŸ‘€
  • proc.pid.rlimit.memorylocked (PROC_PID_LIMIT_MEMLOCK) β€” the maximum size (in bytes) which a process may lock into memory using the mlock(2) function.
  • proc.pid.rlimit.maxproc (PROC_PID_LIMIT_NPROC) β€” the maximum number of simultaneous processes for this user id.
  • proc.pid.rlimit.descriptors (PROC_PID_LIMIT_NOFILE) β€” the maximum number of open files for this process.
  • proc.pid.rlimit.sbsize (PROC_PID_LIMIT_SBSIZE) β€” the maximum size (in bytes) of the socket buffers set by the setsockopt(2) SO_RCVBUF and SO_SNDBUF options.
  • proc.pid.rlimit.vmemoryuse (PROC_PID_LIMIT_AS) β€” the maximum size (in bytes) which a process can obtain.
  • proc.pid.rlimit.maxlwp (PROC_PID_LIMIT_NTHR) β€” the maximum number of threads that can be created and running at one time in the process. The first thread of each process is not counted against this 🧡

The fifth level name is one of soft (PROC_PID_LIMIT_TYPE_SOFT) or hard (PROC_PID_LIMIT_TYPE_HARD), to select the soft or hard limit respectively. Both are of type integer.

🌈 proc.pid.stopfork (PROC_PID_STOPFORK)

If non-zero, the process's children will be stopped after fork(2) calls. The children are created in the SSTOP state and are never scheduled for running before being stopped. This feature lets you attach to a process with a debugger such as gdb(1) before the process even gets the chance to actually do anything πŸ›‘

This value is inherited by the process's children, and it also applies to emulation specific system calls that fork a new process, such as sproc() or clone().

πŸ’œ proc.pid.stopexec (PROC_PID_STOPEXEC)

If non-zero, the process will be stopped on the next exec(3) call. The process created by exec(3) is created in the SSTOP state and is never scheduled for running before being stopped. This feature lets you attach to a process with a debugger such as gdb(1) before the process even gets the chance to actually do anything.

This value is inherited by the process's children.

πŸ“ proc.pid.stopexit (PROC_PID_STOPEXIT)

If non-zero, the process will be stopped when it has cause to exit, either by calling exit(3), _exit(2), or by receiving a specific signal. The process is stopped before any of its resources or vm space is released, which lets you examine the termination state of the process before it disappears πŸ” This feature can be used to examine the final conditions of the process's vmspace via pmap(1) or its resource settings with sysctl(8) before it vanishes.

This value is also inherited by the process's children.

⭐ proc.pid.paxflags (PROC_PID_PAXFLAGS)

This read-only variable returns the current value of the process's pax flags (see paxctl(8)).


🌈 The user.* subtree (CTL_USER)

The string and integer info available for the user level is detailed below. The changeable column shows whether a process with appropriate privilege may change the value.

  • user.atexit_max β€” integer, not changeable ✨
  • user.bc_base_max β€” integer, not changeable
  • user.bc_dim_max β€” integer, not changeable
  • user.bc_scale_max β€” integer, not changeable
  • user.bc_string_max β€” integer, not changeable
  • user.coll_weights_max β€” integer, not changeable
  • user.cs_path β€” string, not changeable
  • user.expr_nest_max β€” integer, not changeable
  • user.line_max β€” integer, not changeable
  • user.posix2_c_bind β€” integer, not changeable
  • user.posix2_c_dev β€” integer, not changeable
  • user.posix2_char_term β€” integer, not changeable
  • user.posix2_fort_dev β€” integer, not changeable
  • user.posix2_fort_run β€” integer, not changeable
  • user.posix2_localedef β€” integer, not changeable
  • user.posix2_sw_dev β€” integer, not changeable
  • user.posix2_upe β€” integer, not changeable
  • user.posix2_version β€” integer, not changeable
  • user.re_dup_max β€” integer, not changeable
  • user.stream_max β€” integer, not changeable
  • user.stream_max β€” integer, not changeable (yes bestie it's listed twice in the original, I'm not editing the sacred text πŸ’…)
  • user.tzname_max β€” integer, not changeable

🌸 user.atexit_max (USER_ATEXIT_MAX)

The max number of functions you can register with atexit(3). Stack 'em up, but know your limit. πŸŽ€

🌸 user.bc_base_max (USER_BC_BASE_MAX)

The biggest ibase/obase values you can use in the bc(1) utility.

🌸 user.bc_dim_max (USER_BC_DIM_MAX)

The biggest array size in bc(1). Big arrays, but not infinite arrays, bestie.

🌸 user.bc_scale_max (USER_BC_SCALE_MAX)

The biggest scale value in bc(1).

🌸 user.bc_string_max (USER_BC_STRING_MAX)

The longest string length in bc(1).

🌸 user.coll_weights_max (USER_COLL_WEIGHTS_MAX)

The max number of weights you can assign to any single entry of the LC_COLLATE order keyword in the locale definition file. Locale girlies stay winning πŸ’…

🌸 user.cs_path (USER_CS_PATH)

Returns a value for the PATH environment variable that finds all the standard utilities. It's giving "I know where everything is" energy.

🌸 user.expr_nest_max (USER_EXPR_NEST_MAX)

The max number of expressions the expr(1) utility can nest inside parentheses. Deep nesting: respected. Bottomless nesting: not a thing.

🌸 user.line_max (USER_LINE_MAX)

The maximum length in bytes of a text-processing utility's input line.

🌸 user.posix2_char_term (USER_POSIX2_CHAR_TERM)

Returns 1 if the system supports at least one terminal type capable of all operations described in IEEE Std 1003.2 (β€œPOSIX.2”), otherwise 0. Yes/no, no maybes πŸ¦‹

🌸 user.posix2_c_bind (USER_POSIX2_C_BIND)

Returns 1 if the system's C-language development facilities support the C-Language Bindings Option, otherwise 0.

🌸 user.posix2_c_dev (USER_POSIX2_C_DEV)

Returns 1 if the system supports the C-Language Development Utilities Option, otherwise 0.

🌸 user.posix2_fort_dev (USER_POSIX2_FORT_DEV)

Returns 1 if the system supports the FORTRAN Development Utilities Option, otherwise 0. FORTRAN girlies, this one's for you πŸ’œ

🌸 user.posix2_fort_run (USER_POSIX2_FORT_RUN)

Returns 1 if the system supports the FORTRAN Runtime Utilities Option, otherwise 0.

🌸 user.posix2_localedef (USER_POSIX2_LOCALEDEF)

Returns 1 if the system supports the creation of locales, otherwise 0.

🌸 user.posix2_sw_dev (USER_POSIX2_SW_DEV)

Returns 1 if the system supports the Software Development Utilities Option, otherwise 0.

🌸 user.posix2_upe (USER_POSIX2_UPE)

Returns 1 if the system supports the User Portability Utilities Option, otherwise 0.

🌸 user.posix2_version (USER_POSIX2_VERSION)

The version of IEEE Std 1003.2 (β€œPOSIX.2”) that the system is attempting to comply with. "Attempting" is doing a lot of heavy lifting there and I respect the honesty 😭

🌸 user.re_dup_max (USER_RE_DUP_MAX)

The max number of repeated occurrences of a regular expression that's permitted when you use interval notation. Regex girlies, this is your ceiling 🧚

🌸 user.stream_max (USER_STREAM_MAX)

The minimum maximum number of streams a process may have open at any one time. Yes, "minimum maximum" β€” sit with it.

🌸 user.tzname_max (USER_TZNAME_MAX)

The minimum maximum number of bytes supported for the name of a timezone (that is, a timezone abbreviation). Like UTC or EST β€” short kings only πŸ‘‘


πŸŒ€ The vm.* subtree (CTL_VM) πŸŒ€

Okay bestie, this is the virtual memory corner of the sysctl universe and it is lowkey the main character. Here's the string + integer info available at the vm level, and the changeable column tells you whether a process with appropriate privilege can change the value.

  • vm.anonmax β€” int, changeable: yes
  • vm.anonmin β€” int, changeable: yes
  • vm.bufcache β€” int, changeable: yes
  • vm.bufmem β€” int, changeable: no
  • vm.bufmem_hiwater β€” int, changeable: yes
  • vm.bufmem_lowater β€” int, changeable: yes
  • vm.execmax β€” int, changeable: yes
  • vm.execmin β€” int, changeable: yes
  • vm.filemax β€” int, changeable: yes
  • vm.filemin β€” int, changeable: yes
  • vm.loadavg β€” struct loadavg, changeable: no
  • vm.maxslp β€” int, changeable: no
  • vm.nkmempages β€” int, changeable: no
  • vm.uspace β€” int, changeable: no
  • vm.uvmexp β€” struct uvmexp, changeable: no
  • vm.uvmexp2 β€” struct uvmexp_sysctl, changeable: no
  • vm.vmmeter β€” struct vmtotal, changeable: no
  • vm.proc.map β€” struct kinfo_vmentry, changeable: no
  • vm.guard_size β€” unsigned int, changeable: no
  • vm.thread_guard_size β€” unsigned int, changeable: yes
  • vm.swap_encrypt β€” bool, changeable: yes

πŸ”₯ vm.anonmax (VM_ANONMAX)

The percentage of physical memory that will be reclaimed from other types of memory usage so it can store anonymous application data. Reclaiming: it's a whole vibe.

πŸ”₯ vm.anonmin (VM_ANONMIN)

The percentage of physical memory that will always be available for anonymous application data. (The original says "will be always be" β€” I am but a humble messenger 🫢)

πŸ”₯ vm.bufcache (VM_BUFCACHE)

The percentage of physical memory that will be available for the buffer cache.

πŸ”₯ vm.bufmem (VM_BUFMEM)

The amount of kernel memory currently being used by the buffer cache. Reading only, bestie β€” look, don't touch.

πŸ”₯ vm.bufmem_lowater (VM_BUFMEM_LOWATER)

The minimum amount of kernel memory to reserve for the buffer cache.

πŸ”₯ vm.bufmem_hiwater (VM_BUFMEM_HIWATER)

The maximum amount of kernel memory to be used for the buffer cache.

πŸ”₯ vm.execmax (VM_EXECMAX)

The percentage of physical memory that will be reclaimed from other types of memory usage to store cached executable data.

πŸ”₯ vm.execmin (VM_EXECMIN)

The percentage of physical memory that will always be available for cached executable data.

πŸ”₯ vm.filemax (VM_FILEMAX)

The percentage of physical memory that will be reclaimed from other types of memory usage to store cached file data.

πŸ”₯ vm.filemin (VM_FILEMIN)

The percentage of physical memory that will always be available for cached file data.

πŸ”₯ vm.loadavg (VM_LOADAVG)

Returns the load average history. The data that comes back is a struct loadavg. Uptime girlies know ✨

πŸ”₯ vm.maxslp (VM_MAXSLP)

The value of the maxslp kernel global variable.

πŸ”₯ vm.vmmeter (VM_METER)

Returns system wide virtual memory statistics. The returned data consists of a struct vmtotal.

πŸ”₯ vm.user_va0_disable

A flag that controls whether user processes can map virtual address 0. Literally address zero. The void. Respect it πŸ•³οΈ

πŸ”₯ vm.proc.map (VM_PROC)

So this one's a whole little ladder: the third level is VM_PROC_MAP, the fourth is the pid of the process you want the vm object entries for, and the fifth is the size of struct kinfo_vmentry. Returns an array of struct kinfo_vmentry objects. Nested like a set of matryoshka dolls, honestly πŸŽ€

πŸ”₯ vm.ubc_direct [EXPERIMENTAL, default off]

Uses direct map for UBC I/O, avoiding the need to map and unmap buffer memory. Speeds up operation for fast I/O devices like NVMe, especially on multi-CPU systems. Only available on some architectures.

⚠️ It's labelled EXPERIMENTAL and defaults to off β€” so like, proceed with the confidence of someone who read the label, not someone who didn't πŸ’€

πŸ”₯ vm.uspace (VM_USPACE)

The number of bytes allocated for each kernel stack.

πŸ”₯ vm.uvmexp (VM_UVMEXP)

Returns system wide virtual memory statistics. The returned data consists of a struct uvmexp.

πŸ”₯ vm.uvmexp2 (VM_UVMEXP2)

Returns system wide virtual memory statistics. The returned data consists of a struct uvmexp_sysctl. Yes, there's a 2 β€” they're cousins, not twins πŸ’…

πŸ”₯ vm.guard_size

Returns the system wide guard size for the main thread of a program.

πŸ”₯ vm.thread_guard_size

Returns the system wide default size for the guard area of all the other threads of a program. Main character gets vm.guard_size, the ensemble cast gets this one 🎭

πŸ”₯ vm.swap_encrypt

If true, encrypt data while it's swapped out to disk. Iconic, security-conscious behaviour.

Each swap device maintains an independent AES-256 key, generated when the first page is swapped to that device. Each page is swapped independently using AES-CBC, with an initialization vector chosen by the encryption under the AES-256 key of the little-endian swap slot number padded to 128 bits with zeros. (This is essentially the cgd(4) β€˜encblkno1’ method.)

⚠️ Changes to vm.swap_encrypt only affect pages of swap newly written out. To force encrypting or decrypting all existing swap, or to rekey previously encrypted swap, you can remove the swap devices and re-add them with swapctl(8) β€” with the caveat that whatever pages were already written to disk unencrypted, or encrypted with a compromised key, may still be written to disk afterward. So yeah. That's a real caveat, not a vibe. Read it twice 😭

πŸ› οΈ The ddb.* subtree (CTL_DDB) πŸ› οΈ

Kernel debugger territory. The info available at the ddb level is below, and the changeable column tells you whether a process with appropriate privilege can change the value.

  • ddb.commandonenter β€” string, changeable: yes
  • ddb.dumpstack β€” integer, changeable: yes
  • ddb.fromconsole β€” integer, changeable: yes
  • ddb.lines β€” integer, changeable: yes
  • ddb.maxoff β€” integer, changeable: yes
  • ddb.maxwidth β€” integer, changeable: yes
  • ddb.onpanic β€” integer, changeable: yes
  • ddb.panicstackframes β€” integer, changeable: yes
  • ddb.radix β€” integer, changeable: yes
  • ddb.tabstops β€” integer, changeable: yes
  • ddb.tee_msgbuf β€” integer, changeable: yes

🧚 ddb.commandonenter

If it's not empty, this string is used as the DDB command to be executed each time DDB is entered. Automatic on-entry behaviour? We love a self-starting queen πŸ‘‘

🧚 ddb.dumpstack

A value of 1 causes a stack trace to be printed on entering ddb from a panic. A value of 0 disables this behaviour. The default value is 1. So yes, by default you do get the receipts πŸ’€

🧚 ddb.fromconsole (DDBCTL_FROMCONSOLE)

If it's not zero, DDB may be entered by sending a break on a serial console, or by a special key sequence on a graphics console. Remote-entry energy πŸ”₯

🧚 ddb.lines (DDBCTL_LINES)

Number of display lines.

  • ddb.maxoff (DDBCTL_MAXOFF) β€” the biggest symbol offset allowed. the ceiling, basically.
  • ddb.maxwidth (DDBCTL_MAXWIDTH) β€” how wide an output line can get. no infinity scarves for your terminal.
  • ddb.onpanic (DDBCTL_ONPANIC) β€” what DDB does when the kernel panics. if it's greater than zero, DDB gets entered on panic. a value of 1 means the system enters DDB on panic, a value of 0 means the kernel tries to print a stack trace first and then reboots, and -1 means neither a stack trace gets printed nor DDB gets entered. pick your fighter πŸ’€
  • ddb.panicstackframes β€” how many stack frames get shown on a panic. lowkey a lifesaver, because it stops the interesting frames from scrolling off into the void on a glass tty. default is 65535 (like, all the frames), and a useful value is around 10.
  • ddb.radix (DDBCTL_RADIX) β€” the input and output radix. numbers, but make it base-whatever.
  • ddb.tabstops (DDBCTL_TABSTOPS) β€” tab width. spacing is a love language πŸŽ€
  • ddb.tee_msgbuf β€” if it's not zero, DDB outputs to the kernel message buffer too. double-dipping, respectfully.

some of these MIB nodes are also available as variables from inside the debugger itself. check ddb(4) for the whole lore 🫢


🌸 The security.* subtree (CTL_SECURITY) 🌸

the security level is where all the security-ish system settings live. here are the second level names, no cap:

  • security.curtain β€” type integer, changeable yes
  • security.models β€” type node, changeable not applicable
  • security.pax β€” type node, changeable not applicable

the settings themselves are all detailed below, bestie:

security.curtain if it's non-zero, it filters return objects based on the user ID asking about them, so users can't access objects they don't own. iconic gatekeeping, honestly.

right now it affects ps(1), netstat(1) (for PF_INET, PF_INET6, and PF_UNIX PCBs), and w(1).

security.models NetBSD supports pluggable security models. every security model in use β€” whether it's loaded as a module or built with the system β€” is required to add an entry to this node with at least one element, β€œname”, which indicates the name of the security model.

besides the name, any settings and other info private to the security model will be available under this node. see secmodel(9) for more πŸ’œ

security.pax the settings for PaX β€” the exploit mitigation features. for more on any of the PaX features, please see paxctl(8) and security(7). the available third and fourth level names are:

  • security.pax.aslr.enabled β€” integer, changeable yes
  • security.pax.aslr.global β€” integer, changeable yes
  • security.pax.mprotect.enabled β€” integer, changeable yes
  • security.pax.mprotect.global β€” integer, changeable yes
  • security.pax.mprotect.ptrace β€” integer, changeable yes
  • security.pax.segvguard.enabled β€” integer, changeable yes
  • security.pax.segvguard.expiry_timeout β€” integer, changeable yes
  • security.pax.segvguard.global β€” integer, changeable yes
  • security.pax.segvguard.max_crashes β€” integer, changeable yes
  • security.pax.segvguard.suspend_timeout β€” integer, changeable yes

security.pax.aslr.enabled enables PaX ASLR (Address Space Layout Randomization).

this knob must be non-zero for PaX ASLR to actually be enabled β€” even if a program is set to explicitly enable it. so like, the vibes have to match.

security.pax.aslr.global sets the default global policy for programs that don't have an explicit enable/disable flag.

when it's non-zero, all programs get PaX ASLR, except the ones exempted with paxctl(8). otherwise, no program gets PaX ASLR, except the ones specifically marked as such with paxctl(8). flipped logic, but we move.

security.pax.mprotect.enabled enables PaX MPROTECT restrictions.

these are mprotect(2) restrictions that enforce a W^X policy way better. this knob must be non-zero for PaX MPROTECT to be enabled, even if a program is set to explicitly enable it. same deal as above ✨

security.pax.mprotect.global sets the default global policy for programs without an explicit enable/disable flag.

when it's non-zero, all programs get the PaX MPROTECT restrictions, except those exempted with paxctl(8). otherwise, all programs don't get the PaX MPROTECT restrictions, except those specifically marked as such with paxctl(8).

security.pax.mprotect.ptrace this lets ptrace(2) override PaX MPROTECT permissions. it can be these values:

  • 0 β€” does not let override any permissions.
  • 1 β€” disables PaX MPROTECT from processes that start executing while traced (this is the default).
  • 2 β€” bypasses PaX MPROTECT for all processes being traced.

security.pax.segvguard.enabled enables PaX Segvguard.

PaX Segvguard can detect and prevent certain exploitation attempts β€” like when an attacker tries to brute-force function return addresses of respawning daemons. very much main character security energy πŸ‘‘

Note: the NetBSD interface and implementation of the Segvguard is still experimental, and may change in future releases. so don't get too attached, bestie 😭

security.pax.segvguard.expiry_timeout if the max number wasn't reached within this timeout (in seconds), the entry expires. time limit, babes.

security.pax.segvguard.global sets the default global policy for programs without an explicit enable/disable flag.

when it's non-zero, all programs get the PaX Segvguard, except those exempted with paxctl(8). otherwise, no program gets the PaX Segvguard restrictions, except those specifically marked as such with paxctl(8).

security.pax.segvguard.max_crashes the maximum number of segfaults a program can receive before suspension. like a strike system but for segfaults πŸ’€

security.pax.segvguard.suspend_timeout the number of seconds a user gets suspended from running a faulting program once the limit was exceeded. sit in the corner and think about what you did.


πŸŽ€ The vendor.* subtree (CTL_VENDOR) πŸŽ€

the vendor toplevel name is reserved for vendors who want their own private MIB tree. the intended use is storing values under β€œvendor.<yourname>.*”. your tree, your rules, your name on it 🌈


πŸ‘‘ SEE ALSO πŸ‘‘


πŸ•°οΈ HISTORY πŸ•°οΈ

the sysctl variables first appeared in 4.4BSD. an absolute legend, fr fr β€” we been knew πŸ’…


and that's a wrap on the whole page, bestie 🫢 this one's the Debian flavour, dated March 7, 2024 β€” go off, sysctl, you icon ✨

πŸ“¦ where this page comes from
  • nixpkgs unstable: netbsd-source 11.0
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms