recipe_sysctl.ts

Recipes for kernel parameters a hardened host keeps set: a sysctl.d file that holds them across boots, and a script that puts them in force now.

  • LINK_PROTECTION_SYSCTLS — the link and file protections the kernel applies in world-writable directories: a hard link to a file the linker doesn't own, a symlink followed out of a sticky directory, and a FIFO or regular file opened with O_CREAT in one, each refused. They close the class of attack in which one account plants a link or file at a path a more privileged process (root's apply, a service) then opens. systemd sets all four on Debian and Ubuntu; Alpine sets only the first two, so an Alpine host declares them.
  • sysctl_conf — the sysctl.d file text for a set of parameters.
  • sysctl_apply — the script that loads that file when a parameter's live value differs from it.

Distro-neutral: both families read /etc/sysctl.d/*.conf at boot (systemd's systemd-sysctl, OpenRC's sysctl service in the boot runlevel), and both sysctl commands (procps and BusyBox) load a file with -p.

Pure functions evaluated in zap's sandboxed config eval (fgro eval: no I/O, clock, or randomness); the output is deterministic.

The caller writes the file and orders the script after it, e.g. zap.file({id: 'sysctl-links', path: LINK_PROTECTION_SYSCTL_PATH, content: {type: 'inline', content: sysctl_conf(LINK_PROTECTION_SYSCTLS)}}) and zap.script({id: 'sysctl-links-applied', ...sysctl_apply(LINK_PROTECTION_SYSCTL_PATH, LINK_PROTECTION_SYSCTLS), depends_on: ['sysctl-links']}).

view source

Declarations
#

6 declarations

LINK_PROTECTION_SYSCTL_PATH
#

LINK_PROTECTION_SYSCTLS
#

sysctl_apply
#

recipe_sysctl.ts view source

(path: string, values: Readonly<Record<string, string>>): SysctlApplyScript import {sysctl_apply} from '@fuzdev/zap/recipe_sysctl.js';

Build the script that puts values in force from the file at path.

check reads each parameter's live value from /proc/sys, readable by any account, with its tabs and runs of blanks read as one space (a multi-value parameter such as net.ipv4.ip_local_port_range reads 32768<tab>60999 there), and passes when every one is the declared value; run loads the file with sysctl -p and fails when a value still differs. Pass the same values the file was written from.

path

the absolute path of the sysctl.d file

type string

values

the parameters the file holds

type Readonly<Record<string, string>>

returns

SysctlApplyScript

the script check/run pair.

sysctl_conf
#

recipe_sysctl.ts view source

(values: Readonly<Record<string, string>>): string import {sysctl_conf} from '@fuzdev/zap/recipe_sysctl.js';

Build the sysctl.d file text for values, one name = value line each, in the order given.

values

type Readonly<Record<string, string>>

returns

string

the file text, terminated by a trailing newline.

SysctlApplyScript
#

recipe_sysctl.ts view source

SysctlApplyScript import type {SysctlApplyScript} from '@fuzdev/zap/recipe_sysctl.js';

The check/run sysctl_apply returns (caller supplies id/name/depends_on).

check

Check command — exit 0 means the script is already applied (skip).

type string

run

The command the planner emits when the check fails.

type string

SysctlValues
#

recipe_sysctl.ts view source

Readonly<Record<string, string>>

type Readonly<Record<string, string>>

import type {SysctlValues} from '@fuzdev/zap/recipe_sysctl.js';

Kernel parameters by sysctl name, each with the value it is set to.

[key: string]

type string

readonly

Depends on
#