I just noticed I broke gzip(1) by blocking fchown(2).
Attached is what I'm using now (see especially SystemCallFilter=).
# FIXME: convince upstream to use logrotate instead of an equivalent sh script!
[Service]
PrivateNetwork=yes
User=ntpsec
PrivateUsers=yes
PrivateNetwork=yes
CapabilityBoundingSet=
RestrictAddressFamilies=AF_UNIX
PrivateDevices=yes
PrivateTmp=yes
ProtectHome=yes
ProtectControlGroups=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectSystem=strict
ReadWritePaths=-/var/log/ntpsec/
WorkingDirectory=/var/log/ntpsec
IPAddressDeny=any
SystemCallArchitectures=native
RestrictNamespaces=yes
NoNewPrivileges=yes

# This is the conservative baseline suggested by "systemd-analyze security".
# It breaks because gzip tries to call fchown(2).
#SystemCallFilter=@system-service
#SystemCallFilter=~@privileged @resources
# This doesn't work because the aliases "overlap"
#SystemCallFilter=@system-service @chown
#SystemCallFilter=~@privileged @resources
# Doing it as "add lots, then remove some, then re-add a little" works.
# If that made no sense, try wdiffing before/after of "systemctl show",
# to see the exact list of syscalls that end up in the allow list.
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources
SystemCallFilter=@chown

RestrictRealtime=yes
LockPersonality=yes
RemoveIPC=yes
MemoryDenyWriteExecute=yes
# FIXME: ntpsec logs are world-readable.  Should we restrict them to e.g. adm 
group?
UMask=022

# Resource exhaustion (i.e. DOS) isn't covered by "systemd-analyze security", 
but
# WE care about it.  This is the lowest priority available.
# See also logrotate.service.
# MemoryHigh= mitigates read-once jobs flushing fscache (see 
https://github.com/Feh/nocache)
# TasksMax= mitigates accidental forkbombs.
# CPUQuota=100% limits the slice to equivalent of 100% of a single CPU core
# CPUWeight=
[Service]
Nice=19
CPUSchedulingPolicy=batch
IOSchedulingClass=idle
MemoryHigh=128M
TasksMax=16
CPUQuota=50%
Jun 04 06:25:01 not-omega systemd[1]: cron-sysstat-root-0.service: Succeeded.
Jun 04 06:25:01 not-omega systemd[1]: Started [Cron] "5-55/10 * * * * root 
command -v debian-sa1 > /dev/null && debian-sa1 1 1".
Jun 04 06:25:01 not-omega systemd[1]: cron-sysstat-root-0.service: Consumed 2ms 
CPU time, no IP traffic.
Jun 04 06:25:01 not-omega systemd[1]: cron-ntpsec-root-0.service: Succeeded.
Jun 04 06:25:01 not-omega systemd[1]: Started [Cron] "25 6 * * * root if [ ! -d 
/run/systemd/system ] && [ -x /usr/lib/ntp/rotate-stats ]; then 
/usr/lib/ntp/rotate-stats; fi".
Jun 04 06:25:01 not-omega systemd[1]: cron-ntpsec-root-0.service: Consumed 1ms 
CPU time, no IP traffic.
Jun 04 06:25:01 not-omega systemd[1]: cron-daily.service: Succeeded.
Jun 04 06:25:01 not-omega systemd[1]: Started systemd-cron daily script service.
Jun 04 06:25:01 not-omega systemd[1]: cron-daily.service: Consumed 213ms CPU 
time, received 3.9K IP traffic, sent 1.0K IP traffic.
Jun 04 06:25:01 not-omega systemd[1]: Reached target systemd-cron daily target.
Jun 04 06:25:01 not-omega systemd[1]: Stopped target systemd-cron daily target.
Jun 04 06:25:01 not-omega rotate-stats[30067]: gzip: loopstats.20190530.gz 
already exists;        not overwritten
Jun 04 06:25:01 not-omega rotate-stats[30067]: gzip: loopstats.20190531.gz 
already exists;        not overwritten
Jun 04 06:25:01 not-omega rotate-stats[30067]: gzip: loopstats.20190601.gz 
already exists;        not overwritten
Jun 04 06:25:01 not-omega audit[30167]: SECCOMP auid=4294967295 uid=107 gid=114 
ses=4294967295 subj==unconfined pid=30167 comm="gzip" exe="/usr/bin/gzip" 
sig=31 arch=c000003e syscall=93 compat
Jun 04 06:25:01 not-omega kernel: audit: type=1326 audit(1559593501.751:53): 
auid=4294967295 uid=107 gid=114 ses=4294967295 subj==unconfined pid=30167 
comm="gzip" exe="/usr/bin/gzip" sig=31 ar
Jun 04 06:25:01 not-omega systemd[1]: Started Process Core Dump (PID 30168/UID 
0).
Jun 04 06:25:02 not-omega rotate-stats[30067]: Bad system call (core dumped)
Jun 04 06:25:02 not-omega systemd[1]: ntpsec-rotate-stats.service: Main process 
exited, code=exited, status=159/n/a
Jun 04 06:25:02 not-omega systemd[1]: ntpsec-rotate-stats.service: Failed with 
result 'exit-code'.
Jun 04 06:25:02 not-omega systemd[1]: ntpsec-rotate-stats.service: Consumed 
61ms CPU time, no IP traffic.
Jun 04 06:25:03 not-omega systemd-coredump[30169]: Process 30167 (gzip) of user 
107 dumped core.

                                                   Stack trace of thread 30167:
                                                   #0  0x00007f61abfab667 
fchown (libc.so.6)
                                                   #1  0x000055ce0462865e n/a 
(gzip)
                                                   #2  0x000055ce04624b27 n/a 
(gzip)
                                                   #3  0x00007f61abee409b 
__libc_start_main (libc.so.6)
                                                   #4  0x000055ce04624cfa n/a 
(gzip)
Jun 04 06:25:03 not-omega systemd[1]: systemd-coredump@4-30168-0.service: 
Succeeded.
Jun 04 06:25:03 not-omega systemd[1]: systemd-coredump@4-30168-0.service: 
Consumed 129ms CPU time, no IP traffic.
Jun 04 06:35:01 not-omega systemd[1]: Starting [Cron] "5-55/10 * * * * root 
command -v debian-sa1 > /dev/null && debian-sa1 1 1"...
Jun 04 06:35:01 not-omega systemd[1]: cron-sysstat-root-0.service: Succeeded.
Jun 04 06:35:01 not-omega systemd[1]: Started [Cron] "5-55/10 * * * * root 
command -v debian-sa1 > /dev/null && debian-sa1 1 1".
Jun 04 06:35:01 not-omega systemd[1]: cron-sysstat-root-0.service: Consumed 2ms 
CPU time, no IP traffic.
Jun 04 06:45:01 not-omega systemd[1]: Starting [Cron] "5-55/10 * * * * root 
command -v debian-sa1 > /dev/null && debian-sa1 1 1"...
Jun 04 06:45:01 not-omega systemd[1]: cron-sysstat-root-0.service: Succeeded.
Jun 04 06:45:01 not-omega systemd[1]: Started [Cron] "5-55/10 * * * * root 
command -v debian-sa1 > /dev/null && debian-sa1 1 1".
Jun 04 06:45:01 not-omega systemd[1]: cron-sysstat-root-0.service: Consumed 2ms 
CPU time, no IP traffic.
Jun 04 06:55:01 not-omega systemd[1]: Starting [Cron] "5-55/10 * * * * root 
command -v debian-sa1 > /dev/null && debian-sa1 1 1"...
Jun 04 06:55:01 not-omega systemd[1]: cron-sysstat-root-0.service: Succeeded.
Jun 04 06:55:01 not-omega systemd[1]: Started [Cron] "5-55/10 * * * * root 
command -v debian-sa1 > /dev/null && debian-sa1 1 1".
Jun 04 06:55:01 not-omega systemd[1]: cron-sysstat-root-0.service: Consumed 2ms 
CPU time, no IP traffic.
Jun 04 07:05:01 not-omega systemd[1]: Starting [Cron] "5-55/10 * * * * root 
command -v debian-sa1 > /dev/null && debian-sa1 1 1"...
Jun 04 07:05:01 not-omega systemd[1]: cron-sysstat-root-0.service: Succeeded.
Jun 04 07:05:01 not-omega systemd[1]: Started [Cron] "5-55/10 * * * * root 
command -v debian-sa1 > /dev/null && debian-sa1 1 1".
Jun 04 07:05:01 not-omega systemd[1]: cron-sysstat-root-0.service: Consumed 2ms 
CPU time, no IP traffic.
Jun 04 07:15:01 not-omega systemd[1]: Starting [Cron] "5-55/10 * * * * root 
command -v debian-sa1 > /dev/null && debian-sa1 1 1"...
Jun 04 07:15:01 not-omega systemd[1]: cron-sysstat-root-0.service: Succeeded.
Jun 04 07:15:01 not-omega systemd[1]: Started [Cron] "5-55/10 * * * * root 
command -v debian-sa1 > /dev/null && debian-sa1 1 1".
Jun 04 07:15:01 not-omega systemd[1]: cron-sysstat-root-0.service: Consumed 2ms 
CPU time, no IP traffic.
Jun 04 07:17:01 not-omega systemd[1]: Condition check resulted in systemd-cron 
hourly script service being skipped.
lines 208-259

Reply via email to