Snapd can't access global Seccomp profile => can't even shell into snap

I’m building a snap for amd64, arm64, and armhf. The snap builds on all 3 architectures and runs on amd64 and arm64. However, I’m having trouble with armhf. I’ve tried using Raspberry Pi’s running Ubuntu 18 and 19.

This is a daemon app, so when I execute sudo snap start mysnap, I get the typical obscure daemon message:

error: cannot perform the following tasks:
- start of [mysnap.mydaemon] (# systemctl start snap.mysnap.mydaemon.service
Job for snap.mysnap.mydaemon.service failed because a fatal signal was delivered causing the control process to dump core.
See "systemctl status snap.mysnap.mydaemon.service" and "journalctl -xe" for details.
)

The odd part is that, when I try to run sudo snap run --shell mysnap.mydaemon to manually execute the
daemon wrapper, I get:

Illegal instruction

If I run without sudo, I get

Illegal instruction (core dumped)

The most informative error message comes from running sudo snap run --strace=--raw mysnap.mydaemon, which tracks early snap helpers. If I don’t use the --strace=--raw option, I get

error: signal: illegal instruction

When I run sudo snap run --strace=--raw mysnap.mydaemon, I get a long output ending in:

...
access("/var/lib/snapd/seccomp/bpf//snap.mysnap.mydaemon.bin", F_OK) = 0
stat64("/", {st_mode=S_IFDIR|0755, st_size=296, ...}) = 0
stat64("/var", {st_mode=S_IFDIR|0755, st_size=159, ...}) = 0
stat64("/var/lib", {st_mode=S_IFDIR|0755, st_size=220, ...}) = 0
stat64("/var/lib/snapd", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat64("/var/lib/snapd/seccomp", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat64("/var/lib/snapd/seccomp/bpf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat64("/var/lib/snapd/seccomp/bpf/snap.mysnap.mydaemon.bin", {st_mode=S_IFREG|0644, st_size=32, ...}) = 0
openat(AT_FDCWD, "/var/lib/snapd/seccomp/bpf//snap.mysnap.mydaemon.bin", O_RDONLY|O_LARGEFILE) = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=32, ...}) = 0
read(4, " \0\0\0\4\0\0\0\25\0\0\1(\0\0@\6\0\0\0\1\0\5\0\6\0\0\0\0\0\0\0", 32768) = 32
read(4, "", 28672)                      = 0
close(4)                                = 0
seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG, {len=4, filter=0x7e9a9ce8}) = 0
access("/var/lib/snapd/seccomp/bpf/global.bin", F_OK) = -1 EPERM (Operation not permitted)
umask(022)                              = 037777777777
readlink("/proc/self/fd/3", 0x7e9b0cf4, 4096) = -1 EPERM (Operation not permitted)
write(2, "cannot read symbolic link target"..., 48) = -1 EPERM (Operation not permitted)
write(2, ": Operation not permitted\n", 26) = -1 EPERM (Operation not permitted)
exit_group(1)                           = -1 EPERM (Operation not permitted)
exit(1)                                 = -1 EPERM (Operation not permitted)
--- SIGILL {si_signo=SIGILL, si_code=ILL_ILLOPC, si_addr=0x76e92b7e} ---
+++ killed by SIGILL (core dumped) +++
error: signal: illegal instruction

It seems to me like snapd is having trouble accessing the global.bin seccomp profile. Furthermore, this issue is limited to this snap, not even previous versions of this snap that are on the snapcraft store.

Is this a known issue? Are there any directions I should go in for debugging this?

I should mention that I’m having to build with snapcraft --use-lxd because these pi’s don’t support multipass’s use of kvm virtualization. I had to do the same with the arm64 version of the snap, although that was on a bare metal AWS ec2. This didn’t cause problems on arm64.

Updates

When I install the snap on devmode, I’m able to get the daemon running. I’ll investigate the possibility that this problem is a result of improper seccomp/apparmor profiles in the morning. I was going off the assumption that they’d be the same across architectures. This is odd because snappy-debug didn’t give any output.

do you have by chance your snapcraft.yaml public somewhere ?
that looks like your architectures: entry is not correct and uses the wrong binaries on armhf.

Here are the relevant parts of my snapcraft.yaml:

...
grade: devel # must be 'stable' to release into candidate/stable channels
confinement: strict # use 'strict' once you have the right plugs and slots

plugs:
  home:
    read: all

parts:
  main-part:
    plugin: dump
    source:
      - on amd64: <https link to tarball>
      # Arch Linux distribution for armv8 (alternative was OpenWrt)
      - on arm64: <https link to tarball>
      # Raspbian distribution for armv7l (alternative was OpenWrt)
      - on armhf: <https link to tarball>
    ...
    stage-packages:
      - python3.7
      - python2.7
      - openjdk-8-jre-headless
    override-build: |
      # Shouldn't be relevant, but I had to write some code described here:
      # https://forum.snapcraft.io/t/advanced-grammar-for-layouts-or-workaround/17177/4
  node12:
    plugin: dump
    # Links taken from https://nodejs.org/en/download/
    source:
      - on amd64: https://nodejs.org/dist/v12.16.3/node-v12.16.3-linux-x64.tar.xz
      - on arm64: https://nodejs.org/dist/v12.16.3/node-v12.16.3-linux-arm64.tar.xz
      - on armhf: https://nodejs.org/dist/v12.16.3/node-v12.16.3-linux-armv7l.tar.xz
    organize:
      # Put all contents inside a directory.
      '*': node-v12.16.3-linux/
    stage-packages:
      - libatomic1
    # Use a wrapper script to execute the daemon from the required cwd.
  exec-daemon:
    plugin: dump
    source: parts/exec-daemon/
  root-ca-certs:
    plugin: nil
    build-packages:
      - wget
    override-build: |
      # download a couple of certs using wget

hooks:
  configure:
    plugs:
      - home
      - log-observe

layout:
  # Bind the read-only config and certs directories with their
  # writeable counterparts.
  $SNAP/mysnap/config:
    bind: $SNAP_DATA/mysnap/config
  $SNAP/mysnap/certs:
    bind: $SNAP_DATA/mysnap/certs
  /usr/bin/python3.7:
    symlink: $SNAP/usr/bin/python3.7
  /usr/bin/python2.7:
    symlink: $SNAP/usr/bin/python2.7
  /usr/bin/nodejs12.x:
    symlink: $SNAP/node-v12.16.3-linux/bin/node
  /usr/bin/java8:
    symlink: $SNAP/usr/lib/jvm/java-8-openjdk-arch-symlink/jre/bin/java

apps:
  mydaemon:
    command: $SNAP/exec-daemon.sh start
    stop-command: $SNAP/exec-daemon.sh stop
    daemon: forking
    adapter: full
    plugs:
      - account-control
      - log-observe
      - mount-observe
      - network-bind
      - network-control
      - process-control
      - system-backup

I don’t think I’m getting the wrong binaries. I don’t have the architectures parameter, which I think means that the snap will be build for whatever architecture it’s built on (in this case, armhf).

I know that the eyebrow-raising line is the armhf https link, but a previous version of this snap uses the raspbian distribution as well. That would lead to an ordinary daemon error. It doesn’t explain why I’m not even able to shell into this snap.

I forgot to mention: I’m having to build with snapcraft --use-lxd because these pi’s don’t support multipass’s use of kvm virtualization. I had to do the same with the arm64 version of the snap, although that was on a bare metal AWS ec2.

well, snaps use the core/core18/core20 snaps as a base, so if it ever ran on raspbian is a moot point since raspbian is a re-build of debian (not of ubuntu) and might use completely different compiler defaults (plus a different glibc binary) … binaries between raspbian and ubuntu might not be easily interchangeable here …

I should rephrase: the Raspbian binaries previously ran on Ubuntu in a snap just fine. In fact, I just ran the new snap in devmode with the Raspbian binaries and it worked fine.

aha !

so whats the difference between these two snaps then ?
what did you add/remove/change ?

@zjoseal if you don’t mind, just a quick check, what are the permissions on these two files:

/var/lib/snapd/seccomp/bpf/global.bin
/var/lib/snapd/seccomp/bpf/snap.mysnap.mydaemon.bin

Can you also do file on the daemon binary and uname -a on the host.

This is just to rule out some potentially trivial but important issues.

1 Like

Sorry for the delay. It was pretty late at night in my time zone :sweat_smile:

Oh, a lot has changed since then (haha). The previous snapcraft.yaml is completely different. The main part was build using Docker to generate a special read-only filesystem. To be honest, comparing this snap with the previous snap brings in so many confounding variables that it’d be like comparing it with another snap.

-rw-r--r-- 1 root root   152 Feb 18 23:29 global.bin
-rw-r--r-- 1 root root    32 May  7 20:05 snap.mysnap.mydaemon.bin
$ file mydaemonexecutable
mydaemonexecutable: executable, regular file, no read permission
$ uname -a
Linux p3-usr-zjoseal 5.3.0-1023-raspi2 #25-Ubuntu SMP Tue Apr 14 11:38:43 UTC 2020 armv7l armv7l armv7l GNU/Linux

I should have also mentioned that I’ve been overwriting the seccomp and apparmor profiles as part of an effort to develop a custom interface. When I stop overwriting the profiles, I’m able to at least shell into the snap (although this breaks my snap). This somewhat makes sense. Earlier, I had a problem where I couldn’t shell into the snap because the profile wasn’t loaded.

These custom profiles didn’t cause problems on amd64 or arm64. Could it be that they’re not being accepted by the armhf snapd? How do I go about narrowing down why the profiles aren’t appropriate?

I also found that using > instead of | tee to write snappy-debug logs was not yielding logs. Apparently overwriting the profiles causes these objections from Seccomp:

= Seccomp =
Time: May  7 20:05:44
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12138 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 33(access) compat=0 ip=0xb6db7d56 code=0x50000
Syscall: access

= Seccomp =
Time: May  7 20:05:44
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12138 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 60(umask) compat=0 ip=0xb6e30dc8 code=0x50000
Syscall: umask

= Seccomp =
Time: May  7 20:05:44
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12138 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 85(readlink) compat=0 ip=0xb6e32b58 code=0x50000
Syscall: readlink

= Seccomp =
Time: May  7 20:05:44
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12138 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 4(write) compat=0 ip=0xb6db7d56 code=0x50000
Syscall: write

= Seccomp =
Time: May  7 20:05:44
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12138 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 248(exit_group) compat=0 ip=0xb6db7d56 code=0x50000
Syscall: exit_group

= Seccomp =
Time: May  7 20:05:44
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12138 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 1(exit) compat=0 ip=0xb6db7d56 code=0x50000
Syscall: exit

= Seccomp =
Time: May  7 20:05:49
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12205 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 33(access) compat=0 ip=0xb6dbcd56 code=0x50000
Syscall: access

= Seccomp =
Time: May  7 20:05:49
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12205 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 60(umask) compat=0 ip=0xb6e35dc8 code=0x50000
Syscall: umask

= Seccomp =
Time: May  7 20:05:49
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12205 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 85(readlink) compat=0 ip=0xb6e37b58 code=0x50000
Syscall: readlink

= Seccomp =
Time: May  7 20:05:49
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12205 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 4(write) compat=0 ip=0xb6dbcd56 code=0x50000
Syscall: write

= Seccomp =
Time: May  7 20:05:49
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12205 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 248(exit_group) compat=0 ip=0xb6dbcd56 code=0x50000
Syscall: exit_group

= Seccomp =
Time: May  7 20:05:49
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12205 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 1(exit) compat=0 ip=0xb6dbcd56 code=0x50000
Syscall: exit

= Seccomp =
Time: May  7 20:05:50
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12258 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 33(access) compat=0 ip=0xb6e7fd56 code=0x50000
Syscall: access

= Seccomp =
Time: May  7 20:05:50
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12258 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 60(umask) compat=0 ip=0xb6ef8dc8 code=0x50000
Syscall: umask

= Seccomp =
Time: May  7 20:05:50
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12258 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 85(readlink) compat=0 ip=0xb6efab58 code=0x50000
Syscall: readlink

= Seccomp =
Time: May  7 20:05:50
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12258 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 4(write) compat=0 ip=0xb6e7fd56 code=0x50000
Syscall: write

= Seccomp =
Time: May  7 20:05:50
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12258 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 248(exit_group) compat=0 ip=0xb6e7fd56 code=0x50000
Syscall: exit_group

= Seccomp =
Time: May  7 20:05:50
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12258 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 1(exit) compat=0 ip=0xb6e7fd56 code=0x50000
Syscall: exit

= Seccomp =
Time: May  7 20:05:51
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12310 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 33(access) compat=0 ip=0xb6e71d56 code=0x50000
Syscall: access

= Seccomp =
Time: May  7 20:05:51
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12310 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 60(umask) compat=0 ip=0xb6eeadc8 code=0x50000
Syscall: umask

= Seccomp =
Time: May  7 20:05:51
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12310 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 85(readlink) compat=0 ip=0xb6eecb58 code=0x50000
Syscall: readlink

= Seccomp =
Time: May  7 20:05:51
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12310 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 4(write) compat=0 ip=0xb6e71d56 code=0x50000
Syscall: write

= Seccomp =
Time: May  7 20:05:51
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12310 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 248(exit_group) compat=0 ip=0xb6e71d56 code=0x50000
Syscall: exit_group

= Seccomp =
Time: May  7 20:05:51
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12310 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 1(exit) compat=0 ip=0xb6e71d56 code=0x50000
Syscall: exit

= Seccomp =
Time: May  7 20:05:53
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12362 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 33(access) compat=0 ip=0xb6df5d56 code=0x50000
Syscall: access

= Seccomp =
Time: May  7 20:05:53
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12362 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 60(umask) compat=0 ip=0xb6e6edc8 code=0x50000
Syscall: umask

= Seccomp =
Time: May  7 20:05:53
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12362 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 85(readlink) compat=0 ip=0xb6e70b58 code=0x50000
Syscall: readlink

= Seccomp =
Time: May  7 20:05:53
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12362 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 4(write) compat=0 ip=0xb6df5d56 code=0x50000
Syscall: write

= Seccomp =
Time: May  7 20:05:53
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12362 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 248(exit_group) compat=0 ip=0xb6df5d56 code=0x50000
Syscall: exit_group

= Seccomp =
Time: May  7 20:05:53
Log: auid=4294967295 uid=0 gid=0 ses=4294967295 pid=12362 comm="snap-confine" exe="/snap/snapd/7266/usr/lib/snapd/snap-confine" sig=0 arch=40000028 1(exit) compat=0 ip=0xb6df5d56 code=0x50000
Syscall: exit


Omg the new profiles were somehow erased. I was replacing the profiles with blank profiles :upside_down_face:

Sorry, thanks for the help anyways!

1 Like