You set fs.suid_dumpable = 0 in /etc/sysctl.d/. You reboot. It reads
2. You grep every sysctl path on the system for the key and find nothing
setting it to 2. Nothing is misconfigured, and the value is still wrong. On Ubuntu the answer is that this
is not a config problem at all.
Rule out the boring explanations first, because they are more common:
# what is it now
sysctl fs.suid_dumpable
# does anything at all set it, anywhere
grep -rn suid_dumpable /etc/sysctl.conf /etc/sysctl.d /usr/lib/sysctl.d /run/sysctl.d 2>/dev/null
# does applying by hand work
sudo sysctl --system | grep -i suid_dumpable
If your file is listed, applying by hand gives you 0, and nothing else in any of those directories mentions the key, then sysctl is doing its job correctly and something else is changing the value afterwards.
sysctl --system and wrong
later is being written by a running process, not by a file.
Ubuntu's crash-report handler, apport, sets fs.suid_dumpable at runtime as part of
installing its core-dump hook. It runs after systemd-sysctl has applied everything in
sysctl.d, so it wins by being later, and it leaves no trace in any configuration file because it
is not configuration.
Watch it happen:
grep -rn suid_dumpable /usr/share/apport/apport
systemctl status apport
cat /proc/sys/kernel/core_pattern # apport present means it owns core dumps
One layer is not enough here. The init script and the service both need turning off, or a package update or a reboot quietly restores it:
sudo sed -i 's/^enabled=1/enabled=0/' /etc/default/apport
sudo systemctl disable --now apport.service
sudo sysctl --system | grep suid_dumpable
sudo reboot
# then confirm it survived
sysctl fs.suid_dumpable
Verify after a real reboot, not just after applying sysctl. The entire nature of this bug is that it only shows up on the next boot, so a check that skips the reboot proves nothing.
This is a distribution default, not a local mistake, so it is wherever Ubuntu is. A sweep here found the
same thing on three more hosts immediately, all Ubuntu, all with suid_dumpable=2 and
apport enabled:
for h in host1 host2 host3; do
echo -n "$h: "
ssh "$h" 'sysctl -n fs.suid_dumpable; systemctl is-enabled apport 2>/dev/null || echo no-apport'
done
Debian hosts are unaffected. apport is not installed there, so the value stays where you put
it.
fs.suid_dumpable is not namespaced.
Containers share the host kernel's value and cannot set their own, so running this sweep against LXCs gives
you readings you cannot act on and changes that cannot apply. Fix it on the host and the containers inherit
it.
Worth one paragraph, so the fix is a decision rather than cargo cult. fs.suid_dumpable controls
whether a setuid program can produce a core dump when it crashes. A core dump is a copy of process memory,
and a setuid process's memory is exactly where privileged material lives. 2 permits dumps under
restricted ownership, 0 disables them for setuid binaries entirely. Hardening baselines want 0,
and a crash-reporting tool wants dumps, which is the whole conflict in one line.
If you actively use crash reports, keeping apport and accepting the value is a defensible
choice. Make it deliberately rather than discovering it in a scanner report.
When a setting reverts and no config file is responsible, stop searching the config layer. Ask what runs
after the thing that applies your setting. Crash handlers, container runtimes, VPN clients, tuning
daemons and cloud agents all write kernel parameters at runtime, none of them appear in a
sysctl.d grep, and all of them win simply by going last.
apport. If a sysctl still reverts,
apply the same reasoning to whatever equivalent daemon you do run.