Kernel Hardening via Sysctl

Using sysctl

Settings that can be modified via /proc/ filesystem or sysctl(8).

Example sysctl config (/etc/sysctl.d/50-custom.conf):

kernel.dmesg_restrict = 1
fs.protected_symlinks = 1

Load config:

sysctl -p /etc/sysctl.d/50-custom.conf

Tip

On Debian, the package hardening-runtime can be installed which configures many of this parameters for you. Look at /usr/lib/sysctl.d/10-hardening.conf after installing it.

Sysctl Parameters

abi.vsyscall32

Disable VDSO for 32 bit syscalls:

abi.vsyscall32 = 0

This setting is only meaningful on 64 bit architectures and will likely break any 32 bit application. Luckily those no longer really exist.

See:

dev.tty.ldisc_autoload

Disable automatic loading TTY line disciplines that rarely anyone uses:

dev.tty.ldisc_autoload = 0

See commit 7c0cca7c847e6e0 introducing the sysctl.

fs.protected_fifos

Do not allow O_CREAT open on FIFOs in world-writable, sticky directories:

fs.protected_fifos = 2

See fs.protected_fifos (kernel docs)

fs.protected_regular

Do not allow O_CREAT open on regular files in world-writable, sticky directories:

fs.protected_regular = 2

See fs.protected_regular (kernel docs)

kernel.dmesg_restrict

Restrict access to kernel logs via dmesg to super users (CAP_SYSLOG):

kernel.dmesg_restrict = 1

See kernel.dmesg_restrict (kernel docs)

kernel.kexec_load_disabled

Do not allow a new kernel to be loaded via kexec(8) in order to skip hardware initialization during reboot:

kernel.kexec_load_disabled = 1

See kernel.kexec_load_disabled (kernel docs)

kernel.kptr_restrict

Do not expose any kernel pointer via /proc/:

kernel.kptr_restrict = 2

See kernel.kptr_restrict (kernel docs)

kernel.unprivileged_bpf_disabled

Do not allow unprivileged users to load eBPF programs (via bpf(2)):

kernel.unprivileged_bpf_disabled = 1

See kernel.unprivileged_bpf_disabled (kernel docs)

kernel.yama.ptrace_scope

Only allow admins to attach via ptrace:

kernel.yama.ptrace_scope = 2

Only allow admins and parent processes to attach via ptrace:

kernel.yama.ptrace_scope = 1

Disable ptrace attachment entirely (reboot required to undo):

kernel.yama.ptrace_scope = 3

See kernel.yama.ptrace_scope (kernel docs)

kernel.panic_on_oops

Trigger a kernel panic on BUG and oops:

kernel.panic_on_oops = 1

This will make certain attacks harder as it will be harder to corrupt the kernel. Drawback is that DoS attacks may be easier to carry out as the kernel is more likely to panic.

Set kernel.panic also to force a reboot on panic.

See kernel.panic_on_oops (kernel docs)

kernel.unprivileged_userns_clone

Do not allow unprivileged user to create user namespaces:

kernel.unprivileged_userns_clone = 0

Note

This sysctl option was not accepted upstream but is carried by many distrubitons including Debian.

Note

Some application use an unprivileged user namespace for sandboxing, including Firefox, and thus disabling this feature may weaken sandboxes. When unprivileged user namespaces aren’t used they can be safely disabled. If they are used, consider restricting access by critical services using RestrictNamespaces=user.

See unprivileged_userns_clone patch

net.core.bpf_jit_harden

Enable BPF JIT compiler hardening for all users:

net.core.bpf_jit_harden = 2

See net.core.bpf_jit_harden (kernel docs)

user.max_user_namespaces

Disable user namespaces entirely:

user.max_user_namespaces = 0

User namespaces don’t have the best security track record.

Note

Some processes may relay on this feature for sandboxing. See also note on kernel.unprivileged_userns_clone.

This will also render the (rarely used) PrivateUser systemd directive ineffective.

See:

kernel.perf_event_paranoid

Disallow any unprivileged use of perf events:

kernel.perf_event_paranoid = 3

Note

Patch for support of value 3 for this setting has been declined upstream bun many distribution, including Debian, carry it.

See:

vm.mmap_rnd_bits

Increase entropy used to map memory randomly:

vm.mmap_rnd_bits = 32

A higher value indicates higher entropy. Obtain the highest allowed value like this:

i=$(</proc/sys/vm/mmap_rnd_bits)
while echo $((i+1)) >/proc/sys/vm/mmap_rnd_bits 2>/dev/null; do ((i++)); done;
echo $i

See vm.mmap_rnd_bits (kernel docs)

vm.mmap_rnd_compat_bits

Increase entropy used to map memory randomly in compat mode:

vm.mmap_rnd_compat_bits = 16

A higher value indicates higher entropy. Obtain the highest allowed value like this:

i=$(</proc/sys/vm/mmap_rnd_compat_bits)
while echo $((i+1)) >/proc/sys/vm/mmap_rnd_compat_bits 2>/dev/null; do ((i++)); done;
echo $i

This is only useful on architectures with a compatibility mode. For instance, on x86_64 which has an x86 compatibility mode.

See vm.mmap_rnd_compat_bits (kernel docs)

vm.unprivileged_userfaultfd

Do not allow unprivileged users to handle page faults:

vm.unprivileged_userfaultfd = 0

See vm.unprivileged_userfaultfd (kernel docs)

Other Resources