Hide Forgot
Add support for seccomp in libreswan. This is currently under development at upstream.
Paul, could you be more specific about this RFE? How are you planning to use seccomp? Do you have any pointers to upstream information?
We are using it to limit the number of syscalls that could be called by pluto or and the pluto helpers See: people.redhat.com/pwouters/libreswan-3.19-seccomp.patch
(note we still need to do some profiling so we can sort the filter and reduce the overhead)
Moving to 7.5 as it seems there is still some issues with not having all syscalls whitelisted. I'd prefer to postpone this while upstream gains a bit more experience with the list of syscalls. This feature is an option in the spec file for those who want to try it out, but disabled for the 7.4 build
Paul, seccomp support on RHEL-7 seems not to be working correctly. Enabling or even tolerating setting caused odd service state "reloading (reload)". Moreover I think I am not supposed to see SECCOMP audit records if there are no problems, right? See more details below. # cat /etc/ipsec.conf version 2.0 config setup plutodebug="all" plutostderrlog="/var/log/pluto.log" protostack=netkey nat_traversal=yes virtual_private= oe=off seccomp=enabled # rpm -q libreswan kernel libreswan-3.22-2.el7.x86_64 kernel-3.10.0-799.el7.x86_64 # service ipsec restart Redirecting to /bin/systemctl restart ipsec.service # service ipsec status Redirecting to /bin/systemctl status ipsec.service ● ipsec.service - Internet Key Exchange (IKE) Protocol Daemon for IPsec Loaded: loaded (/usr/lib/systemd/system/ipsec.service; disabled; vendor preset: disabled) Active: reloading (reload) since Fri 2017-12-08 09:49:20 EST; 1s ago Docs: man:ipsec(8) man:pluto(8) man:ipsec.conf(5) Process: 32234 ExecStopPost=/usr/sbin/ipsec --stopnflog (code=exited, status=0/SUCCESS) Process: 32233 ExecStopPost=/sbin/ip xfrm state flush (code=exited, status=0/SUCCESS) Process: 32231 ExecStopPost=/sbin/ip xfrm policy flush (code=exited, status=0/SUCCESS) Process: 32229 ExecStop=/usr/libexec/ipsec/whack --shutdown (code=exited, status=0/SUCCESS) Process: 32506 ExecStartPre=/usr/sbin/ipsec --checknflog (code=exited, status=0/SUCCESS) Process: 32504 ExecStartPre=/usr/sbin/ipsec --checknss (code=exited, status=0/SUCCESS) Process: 32242 ExecStartPre=/usr/libexec/ipsec/_stackmanager start (code=exited, status=0/SUCCESS) Process: 32241 ExecStartPre=/usr/libexec/ipsec/addconn --config /etc/ipsec.conf --checkconfig (code=exited, status=0/SUCCESS) Main PID: 32518 (pluto) Status: "Startup completed." CGroup: /system.slice/ipsec.service └─32547 addconn --ctlsocket /run/pluto//pluto.ctl --autoall ‣ 32518 [pluto] Dec 08 09:49:20 systemd[1]: Starting Internet Key Exchange (IKE) Protocol Daemon ...... Dec 08 09:49:20 addconn[32241]: Warning: ignored obsolete keyword 'nat_traversal' Dec 08 09:49:20 _stackmanager[32242]: Warning: ignored obsolete keyword 'nat_traversal' Dec 08 09:49:20 _stackmanager[32242]: Warning: ignored obsolete keyword 'nat_traversal' Dec 08 09:49:20 ipsec[32506]: Warning: ignored obsolete keyword 'nat_traversal' Dec 08 09:49:20 ipsec[32506]: nflog ipsec capture disabled Dec 08 09:49:20 systemd[1]: Started Internet Key Exchange (IKE) Protocol Daemon f...ec. Dec 08 09:49:21 ipsec_starter[32547]: Warning: ignored obsolete keyword 'nat_traversal' Hint: Some lines were ellipsized, use -l to show in full. # ausearch -ts 09:49:20 -i -m SECCOMP ---- type=SECCOMP msg=audit(12/08/2017 09:49:21.785:522) : auid=unset uid=root gid=root ses=unset subj=system_u:system_r:ipsec_t:s0 pid=32518 comm=pluto sig=SIGSYS arch=x86_64 syscall=openat compat=0 ip=0x7f78d2f258d0 code=kill Eventually systemd watchdog kill it: Dec 08 09:56:01 systemd[1]: ipsec.service: main process exited, code=killed, status=31/ Dec 08 09:56:01 systemd[1]: ipsec.service watchdog timeout (limit 3min 20s)! Dec 08 09:55:42 systemd[1]: ipsec.service reload operation timed out. Stopping.
It looks like we ended up using the syscall openat, that we did not have on our whitelist. So we need to add that syscall. I've launched a scratchbuild with that syscall added to the list. Can you re-run the test(s) and see if any other syscalls show up? scratchbuild going now at: Task info: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=14719049
Got two more to whitelist now with 3.22-5: 1. This one shows during start: type=SECCOMP msg=audit(12/08/2017 11:23:57.264:379) : auid=unset uid=root gid=root ses=unset subj=system_u:system_r:ipsec_t:s0 pid=11373 comm=pluto sig=SIGSYS arch=x86_64 syscall=getdents compat=0 ip=0x7fb93190dde5 code=kill 2. This one shows during stop: type=SECCOMP msg=audit(12/08/2017 11:30:48.782:409) : auid=unset uid=root gid=root ses=unset subj=system_u:system_r:ipsec_t:s0 pid=12079 comm=pluto sig=SIGSYS arch=x86_64 syscall=sendto compat=0 ip=0x7fea91e48c5b code=kill Service is still in "reloading" state (and then timeouts again). BTW: I checked it once more with tolerant setting and I got "reloading" again but no SECCOMP audit event at all.
I'll add getdents, but I'm confused about sendto, since that's been in the list from the start: paul@thinkpad:~/libreswan (master *)$ git blame programs/pluto/pluto_seccomp.c |grep sendto 4a66a13120 (Paul Wouters 2016-10-10 19:06:08 -0400 101) rc |= seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendto), 0); Maybe Paul Moore can shed some light on this?
(In reply to Paul Wouters from comment #12) > I'll add getdents, but I'm confused about sendto, since that's been in the > list from the start: > > paul@thinkpad:~/libreswan (master *)$ git blame > programs/pluto/pluto_seccomp.c |grep sendto > 4a66a13120 (Paul Wouters 2016-10-10 19:06:08 -0400 101) rc |= > seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sendto), 0); It looks like only the filter for "main" gets sendto() added to the filter, could this be the problem?
Switching back to ASSIGNED since we cannot use libreswan with seccomp support at the moment (see Comments 9 and 11).
Retested with libreswan-3.22-5.el7 and kernel-3.10.0-823.el7: a) seccomp=disabled - ipsec service can be started, is running and can be stopped - seccomp test (ipsec whack --seccomp-crash) PASSED: 003 Performing seccomp security test using getsid() syscall 003 pluto: seccomp test syscall was not blocked 003 OK: pluto seccomp was disabled and the rogue syscall was not blocked b) seccomp=tolerant - ipsec service can be started, is running and can be stopped - seccomp test FAILED 003 Performing seccomp security test using getsid() syscall 003 pluto: seccomp test syscall was not blocked 003 ERROR: pluto seccomp was tolerant but the rogue syscall was not blocked No SECCOMP event produced at all! c) seccomp=enabled - ipsec service can be start, is running and can be stopped - seccomp test HANGED 003 pluto is running with seccomp=enabled! pluto is expected to die! 003 Performing seccomp security test using getsid() syscall ...<hang for 3 minutes>... Then exits with exit code 3. A single SECCOMP event can be observed: type=SECCOMP msg=audit(01/09/2018 08:45:47.908:18574) : auid=unset uid=root gid=root ses=unset subj=system_u:system_r:ipsec_t:s0 pid=28479 comm=pluto sig=SIGSYS arch=x86_64 syscall=getsid compat=0 ip=0x7f83fe9db647 code=kill ipsec service restarted those 3 minutes: systemd[1]: ipsec.service watchdog timeout (limit 3min 20s)! systemd[1]: ipsec.service: main process exited, code=killed, status=31/SYS Therefore, it seems like it is working correctly. Paul, can you confirm that this is expected behaviour? All in all, both disabled and enabled seccomp setting is working at the moment, however - tolerant is not.
It works as upstream :) for the tolerant one: 003 ERROR: pluto seccomp was tolerant but the rogue syscall was not blocked I was going to ask Paul Moore about that. I would change your test to not hang for 3 minutes but run the whack in the background, sleep 1 second and check the SECCOMP in audit log. It is expected pluto will be shot. Why the kernel would take 3 minutes, I don't know. Also, systemd watchdog should kick in sooner. What might be happening is that your whack command died but you are still waiting for something on the socket and your test framework stops that after 3 minutes? I thought the watchdog timer was set to 1 minute for systemd? Ahh looks like default SD_WATCHDOGSEC is 200 seconds. One reason it is not shorter is that when people use XAUTH to type in their password, it blocks pluto and if they run "up" and then go find their hardware token, it would kill pluto. Once we make this password input not block pluto, we can put in a sane value like 30s Note the tolerant setting was more a testing kind of thing. Clearly without knowing what didnt execute, you are in danger territory and run the risk of hitting a passert() soon afterwards.
Thanks Paul. It is good to hear that. Based on the last two comments I am switching this bug back to ON_QA and I will proceed with automated verification.
It seems that addconn wants to use clone syscall (56 on intel) when ipsec service is started: ---- time->Fri Jan 19 13:51:38 2018 type=SECCOMP msg=audit(1516387898.863:106): auid=4294967295 uid=0 gid=0 ses=4294967295 subj=system_u:system_r:unconfined_service_t:s0 pid=31422 comm="addconn" exe="/usr/libexec/ipsec/addconn" sig=31 arch=c00000b7 syscall=56 compat=0 ip=0xffff8028caa8 code=0x0 According to pluto_seccomp.c in 3.23rc4 clone syscall is allowed only for "main". It is worth mentioning that I see this only when executing test in out testing infrastructure (ie. without interactive terminal, with slightly different selinux context, ...) but it is still valid use case. Shouldn't we whitelist clone event as well (not only for "main")?
I've added clone() to the whitelist of addconn in programs/pluto/addconn.c I've also double checked the addconn syscall white list. Since pluto forks an addconn, everything in addconn has to be in the pluto list for "main". That resulted in me adding prctl() and socketpair() The /usr/sbin/ip: permission denied is still present :/
While testing on non-intel architectures I realized we also need to whitelist socketcall syscall: type=SECCOMP msg=audit(01/28/2018 21:37:14.256:169) : auid=unset uid=root gid=root ses=unset subj=system_u:system_r:unconfined_service_t:s0 pid=8021 comm=addconn sig=SIGSYS arch=ppc64 syscall=socketcall compat=0 ip=0x3fffb0b15ea8 code=kill
added to upstream - we can backport
Perfect! Can you create a scratch build? I'll check all architectures and we can ask Mark or Libor for exception / blocker in the meantime.
Ad "Doc Text: Feature: A new option seccomp=yes enables syscall...". Shouldn't it be "...seccomp=enabled..."?
yes, fixed :)
Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. https://access.redhat.com/errata/RHBA-2018:0932