[SOLVED] 'ipsec status' segfaults in LXD container

I have an Ubuntu Bionic container on LXD that runs strongSwan (the host is Bionic too). Symptoms:

  • I can start the ipsec service with systemctl
  • I can also use the ‘ipsec start|restart|stop’ commands
  • The VPN tunnel to a remote host is created.
  • However when I issue ‘ipsec status|statusall|listxxx|etc’ commands, I get a segfault:
    root@vpn1:~# ipsec statusall
    Segmentation fault

I tried the following:

  • I made sure that all kernel modules required by strongSwan are loaded and added to the container’s config (linux.kernel_modules = …)
  • Disabled AppArmor everywhere
  • Set the container to privileged
  • Launched a KVM VM using the same image (Ubuntu 18.04 LTS (Bionic Beaver) Daily Build [20180630]). It worked flawlessly.

Since it’s the same OS and strongSwan versions and the network config was similar, my only guess is it has something with LXD. I ran the ‘ipsec statusall’ with strace, here are the outputs:

Could you guys help solving this issue?

I found that ipsec is just a script calling ‘/usr/lib/ipsec/stroke’ for getting the status, and this process fails:

root@vpn1:~# strace /usr/lib/ipsec/stroke statusall
execve("/usr/lib/ipsec/stroke", ["/usr/lib/ipsec/stroke", "statusall"], 0x7fff5d0ae198 /* 14 vars */) = -1 EACCES (Permission denied)
--- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=NULL} ---
+++ killed by SIGSEGV +++
Segmentation fault

I can see a permission denied, however the file is readable/executable by everyone and doesn’t have any acl set on it:

root@vpn1:~# ll /usr/lib/ipsec/stroke
-rwxr-xr-x 1 root root 22616 Mar 20 06:37 /usr/lib/ipsec/stroke*

root@vpn1:~# getfacl /usr/lib/ipsec/stroke
getfacl: Removing leading '/' from absolute path names
# file: usr/lib/ipsec/stroke
# owner: root
# group: root
user::rwx
group::r-x
other::r-x

One step closer but I still can’t find the root cause.

It was AppArmor! Even though I stopped the daemon, the modules were still loaded and in enforce mode:

root@vpn1:~# aa-status 
apparmor module is loaded.
18 profiles are loaded.
18 profiles are in enforce mode.
[...]
   /usr/lib/ipsec/charon
   /usr/lib/ipsec/lookip
   /usr/lib/ipsec/stroke
[...]

It started working after switching to complain mode:
root@vpn1:~# aa-complain /etc/apparmor.d/usr.lib.ipsec.

This is the log entry I see if I switch back to enforce mode:
Jul 7 04:53:32 lxd1 kernel: [ 4526.583617] audit: type=1400 audit(1530939212.389:68): apparmor="DENIED" operation="file_mmap" namespace="root//lxd-vpn1_<var-lib-lxd>" profile="/usr/lib/ipsec/stroke" name="/usr/lib/ipsec/stroke" pid=3372 comm="stroke" requested_mask="m" denied_mask="m" fsuid=100000 ouid=100000

I’ll dig into that profile.

1 Like

I added /usr/lib/ipsec/stroke rm, to stroke’s AppArmor profile (line 26) and now it works well in enforced mode too. :smiley:

3 Likes

I’d like to add that packagers of strongswan now ship an updated AppArmor profile and this workaround is not required anymore.

1 Like

Excellent, looks like we will need the same update to quassel as it’s running into the exact same denial (there’s another forum thread about that).

Hi community,

I am planning to test IPSEC inside an LXD container image to improve over a setup that currently uses VMs.

Given the thread above, is this currently something that works in 20.04 container images or would it need workarounds?

Thank you,
Gustavo