Different seccomp behaviors on amd64 and pi2/armhf

Hi folks,

Previously, I verified my snap on a amd64 platform most of time. Yesterday I tested it on a pi2, the program was stopped and dmesg said:

[  279.803475] audit: type=1326 audit(1557910870.397:110): auid=1000 uid=1000 gid=1000 ses=1 pid=2722 comm="rtl_test" exe="/snap/adsb-box/69/usr/bin/rtl_test" sig=0 arch=40000028 syscall=281 compat=0 ip=0x76dceb48 code=0x50000

The snappy-debug.scanlog recommended:

= Seccomp =
Time: May 15 09:01:10
Log: auid=1000 uid=1000 gid=1000 ses=1 pid=2722 comm="rtl_test" exe="/snap/adsb-box/69/usr/bin/rtl_test" sig=0 arch=40000028 281(socket) compat=0 ip=0x76dceb48 code=0x50000
Syscall: socket
Suggestions:
* add account-control (if using NETLINK_AUDIT)
* add bluetooth-control (if using AF_{ALG,BLUETOOTH})
* add firewall-control (if using NETLINK_{FIREWALL,IP6_FW,NETFILTER,NF_LOG,ROUTE})
* add hardware-observe (if using NETLINK_{GENERIC,KOBJECT_UEVENT})
* add netlink-audit (if using NETLINK_AUDIT)
* add netlink-connector (if using NETLINK_CONNECTOR)
* add network (if using AF_INET{,6}, AF_CONN, NETLINK_ROUTE)
* add network-bind (if using AF_INET{,6}, NETLINK_ROUTE)
* add network-control (if using AF_{APPLETALK,BRIDGE,INET,INET6,IPX,PACKET,PPPOX,SNA}, NETLINK_{DNRTMSG,FIB_LOOKUP,GENERIC,INET_DIAG,ISCSI,KOBJECT_UEVENT,RDMA,ROUTE,XFRM})
* add network-observe (if using SOCK_RAW, AF_INET{,6}), NETLINK_{GENERIC,INET_DIAG,KOBJECT_UEVENT,ROUTE})
* add x11 (if using NETLINK_KOBJECT_UEVENT)

To find out the function call, I ran snap run --strace on both x64 and pi2. Then I found the case for me is hardware-observe.

[snipped]
stat("/sys/bus/usb/devices", {st_mode=S_IFDIR|0755, st_size=0, ...}) = 0
open("/etc/udev/udev.conf", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=153, ...}) = 0
read(3, "# see udev.conf(5) for details\n#"..., 1024) = 153
read(3, "", 1024)                       = 0
close(3)                                = 0
access("/run/udev/control", F_OK)       = 0
socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_KOBJECT_UEVENT) = 3
[snipped]

I added hardware-observe to the plut list and it works fine now.
I am wondering what’s reason that seccomp has different behaviors on amd64 and armhf.

I can confirm this as I was talking to @robertliu earlier about the issue. I tested the following setups:

  • pi3 with ubuntu core 16.04, snap in strict mode - leads to the the above seccomp message.
  • pi3 with ubuntu core 16.04, snap in devmode - works.
  • pi3 with ubuntu classic 18.04, snap in strict mode - works fine.
  • hardware-observe interfaces solves it for core 16.04.

This looks like socket vs socketcall that is common to 32bit architectures. CC @jdstrand

EDIT: What I mean by this is that some kernels had socket and some kernels had socketcall. Seccomp libshould make that transparent for us but perhaps it is buggy somewhere.

1 Like

There is a lot to making socketcall go away, including kernel support, libc and seccomp. socketcall isn’t a thing on arm though (it is on i386 for example):

$ scmp_sys_resolver -a arm socketcall
-10060

so that isn’t an issue. I also don’t think this is a bug in seccomp: the application is clearly using NETLINK_KOBJECT_UEVENT which doesn’t exist in the policy before adding hardware-observe, so libseccomp isn’t in a position to have the bug (it would be a bug if it was allowed when the policy didn’t allow it). :slight_smile:

What I suspect is happening is that the application/library has different syscall behavior on armhf vs amd64, which is not uncommon. Plugging hardware-observe is perhaps fine, or if a graphical application, x11 (it certainly is fine for you right now, but maybe we want to adjust our policy). What is your program trying to do at the time of the denial?

Thanks for the explanation.
I think using hardware-observe makes sense.

The program rtl_test is from this package rtl-sdr and is a benchmark tool for RTL2832 based DVB-T receivers.
At the time of the denial, the program is initializing libusb. By enabling the debug logging of libusb, it showed

libusb: debug [libusb_init] created default context
libusb: debug [libusb_init] libusb v1.0.20.11004
libusb: debug [find_usbfs_path] found usbfs at /dev/bus/usb
libusb: debug [op_init] bulk continuation flag supported
libusb: debug [op_init] zero length packet flag supported
libusb: debug [op_init] sysfs can relate devices
libusb: debug [op_init] sysfs has complete descriptors
libusb: error [linux_udev_start_event_monitor] could not initialize udev monitor
libusb: error [op_init] error starting hotplug event monitor

In libusb/os/linux_netlink.c: linux_netlink_start_event_monitor(), what libusb doing is:

linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);

Before, I was using the raw-usb interface. I suspected it should cover the my use-cases and it does on amd64. The behavior is not exactly the same with armhf though. But, again, hardware-observe makes sense to me as well.

1 Like