Skip to main content

max / alloy

5.0 KB · 117 lines History Blame Raw
1 # Alloy kernel hardening.
2 #
3 # The number is load-bearing. systemd-sysctl applies these files in
4 # lexicographic order and the last value wins, so a `50-` file would lose to
5 # Fedora's own `50-coredump.conf` on any key they share. `90-` wins on merit
6 # and on order.
7 #
8 # Derived from secureblue's hardening.conf, itself derived from Kicksecure's,
9 # and trimmed to what a development machine can pay. Rationale and the full
10 # adopt/reject list: wiki `alloy-hardening-posture`.
11 #
12 # Every entry states what it costs. An entry with no cost worth naming says so
13 # rather than staying silent, because silence here reads as "nobody measured".
14
15 # ---------------------------------------------------------------------
16 # Kernel information leaks
17 # ---------------------------------------------------------------------
18
19 # Kernel pointers read as zero for everyone, including root. Costs: a
20 # profiler or a crash dump that wants symbol addresses gets zeros. perf
21 # still works; kernel symbol resolution in third-party tools may not.
22 kernel.kptr_restrict=2
23
24 # The kernel ring buffer needs CAP_SYSLOG to read. `dmesg` as a user stops
25 # working; `sudo dmesg` and `journalctl -k` are unaffected.
26 kernel.dmesg_restrict=1
27
28 # ---------------------------------------------------------------------
29 # Kernel integrity
30 # ---------------------------------------------------------------------
31
32 # No kexec, ever, until reboot. Costs kexec-based fast reboot and
33 # kdump-on-panic. Neither is in this image.
34 kernel.kexec_load_disabled=1
35
36 # eBPF needs CAP_BPF. Costs: an unprivileged `bpftrace` or `bcc` script.
37 # Both need root here anyway.
38 kernel.unprivileged_bpf_disabled=1
39
40 # Constant blinding in the BPF JIT for privileged users too. Costs a small
41 # amount of JIT throughput on a machine that runs almost no BPF.
42 net.core.bpf_jit_harden=2
43
44 # ---------------------------------------------------------------------
45 # NOT SET, and this is the entry that explains the shape of the file
46 # ---------------------------------------------------------------------
47 #
48 # kernel.yama.ptrace_scope=2 is what secureblue ships and it is not here.
49 # Fedora already sets scope 1 (/usr/lib/sysctl.d/10-default-yama-scope.conf),
50 # which stops a process attaching to a non-descendant. Scope 2 requires
51 # CAP_SYS_PTRACE for any attach at all, which breaks `gdb -p`, `perf record
52 # -p`, and rust-gdb against an already-running process.
53 #
54 # Alloy is the machine its author develops on. A mitigation that makes the
55 # debugger ask for root every time is one that gets turned off, and a
56 # hardening file nobody leaves enabled hardens nothing.
57
58 # ---------------------------------------------------------------------
59 # Filesystem
60 # ---------------------------------------------------------------------
61
62 # Symlink and hardlink following restricted in world-writable sticky
63 # directories: the classic /tmp race. Fedora sets both already; stated here
64 # so the policy is legible in one file rather than inherited.
65 fs.protected_symlinks=1
66 fs.protected_hardlinks=1
67
68 # Same idea for FIFOs and regular files: no writing to something you do not
69 # own in a directory you do not own. 2 covers group-writable directories too.
70 fs.protected_fifos=2
71 fs.protected_regular=2
72
73 # ---------------------------------------------------------------------
74 # Network stack
75 # ---------------------------------------------------------------------
76 #
77 # These matter more once the machine is on a network it does not control,
78 # which for a laptop is most of them.
79
80 # SYN flood mitigation.
81 net.ipv4.tcp_syncookies=1
82
83 # Reverse-path filtering, LOOSE (2) rather than strict (1). Drops packets
84 # whose source address has no route back at all, which is the spoofing case,
85 # while permitting a reply to leave by a different interface than the request
86 # arrived on.
87 #
88 # Strict is the stronger setting and it is not taken, because strict RPF is a
89 # known way to break a Tailscale subnet router or exit node: the tailnet path
90 # is legitimately asymmetric. Nothing here is an exit node today, and a
91 # hardening default that quietly breaks the way every machine in this tree is
92 # addressed the first time someone enables one is not worth the increment.
93 net.ipv4.conf.all.rp_filter=2
94 net.ipv4.conf.default.rp_filter=2
95
96 # ICMP redirects, in both directions. A redirect is a router telling the
97 # machine to change its route, and on an untrusted network that is an
98 # attacker telling the machine to change its route.
99 net.ipv4.conf.all.accept_redirects=0
100 net.ipv4.conf.default.accept_redirects=0
101 net.ipv4.conf.all.secure_redirects=0
102 net.ipv4.conf.default.secure_redirects=0
103 net.ipv4.conf.all.send_redirects=0
104 net.ipv4.conf.default.send_redirects=0
105 net.ipv6.conf.all.accept_redirects=0
106 net.ipv6.conf.default.accept_redirects=0
107
108 # Source routing: the sender choosing the path. No legitimate use here.
109 net.ipv4.conf.all.accept_source_route=0
110 net.ipv4.conf.default.accept_source_route=0
111 net.ipv6.conf.all.accept_source_route=0
112 net.ipv6.conf.default.accept_source_route=0
113
114 # Log packets with impossible source addresses.
115 net.ipv4.conf.all.log_martians=1
116 net.ipv4.conf.default.log_martians=1
117