Python UNIX socket.bind fails in strict confinement

Hi everyone,

I am trying to create a new snap for the calibre application. I have correctly created the snapcraft.yaml file and works fine for me in classic mode when using it in my development environment.

The problem comes when we try to restrict it to strict confinement. The calibre package internally tries to create a unix socket, and this is forbidden in my snap environemnt.

Here is the Python traceback (strict confinement):

Traceback (most recent call last):
  File "runpy.py", line 194, in _run_module_as_main
  File "runpy.py", line 87, in _run_code
  File "site.py", line 45, in <module>
  File "site.py", line 41, in main
  File "calibre/gui_launch.py", line 73, in calibre
  File "calibre/gui2/main.py", line 501, in main
  File "calibre/utils/lock.py", line 195, in __enter__
  File "calibre/utils/lock.py", line 149, in create_single_instance_mutex
  File "calibre/utils/ipc/__init__.py", line 23, in eintr_retry_call
PermissionError: [Errno 13] Permission denied

Here is the method of calibre where the socket is created.

Here are the permissions for the app command:

apps:
  calibre:
    command: calibre/calibre
    plugs: 
      - desktop 
      - home
      - x11 
      - network
      - network-bind
      - network-control
      - process-control

Thank you for all.

more interesting than the traceback would be to get the output of dmesg | grep DENIED (or a journal excerpt for calibre) to see any apparmor denials.

Here is the dmesg output:

[19605.284167] audit: type=1400 audit(1604157007.517:13828): apparmor="DENIED" operation="open" profile="snap.calibre-unofficial.calibre" name="/snap/core18/1932/lib/x86_64-linux-gnu/librt-2.27.so" pid=64203 comm="calibre" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
[19605.284178] audit: type=1400 audit(1604157007.517:13829): apparmor="DENIED" operation="open" profile="snap.calibre-unofficial.calibre" name="/snap/core18/1932/lib/x86_64-linux-gnu/librt-2.27.so" pid=64203 comm="calibre" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
[19605.284220] audit: type=1400 audit(1604157007.517:13830): apparmor="DENIED" operation="open" profile="snap.calibre-unofficial.calibre" name="/snap/core18/1932/lib/x86_64-linux-gnu/librt-2.27.so" pid=64203 comm="calibre" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
[19605.284227] audit: type=1400 audit(1604157007.517:13831): apparmor="DENIED" operation="open" profile="snap.calibre-unofficial.calibre" name="/snap/core18/1932/lib/x86_64-linux-gnu/librt-2.27.so" pid=64203 comm="calibre" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
[19605.284235] audit: type=1400 audit(1604157007.517:13832): apparmor="DENIED" operation="open" profile="snap.calibre-unofficial.calibre" name="/snap/core18/1932/lib/x86_64-linux-gnu/librt-2.27.so" pid=64203 comm="calibre" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
[19605.284241] audit: type=1400 audit(1604157007.517:13833): apparmor="DENIED" operation="open" profile="snap.calibre-unofficial.calibre" name="/snap/core18/1932/lib/x86_64-linux-gnu/librt-2.27.so" pid=64203 comm="calibre" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
[19605.347972] audit: type=1400 audit(1604157007.581:13834): apparmor="DENIED" operation="open" profile="snap.calibre-unofficial.calibre" name="/snap/core18/1932/lib/x86_64-linux-gnu/libuuid.so.1.3.0" pid=64203 comm="calibre" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
[19605.360939] audit: type=1400 audit(1604157007.593:13835): apparmor="DENIED" operation="open" profile="snap.calibre-unofficial.calibre" name="/sys/devices/pci0000:00/0000:00:02.0/vendor" pid=64203 comm="calibre" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
[19605.360967] audit: type=1400 audit(1604157007.593:13836): apparmor="DENIED" operation="open" profile="snap.calibre-unofficial.calibre" name="/sys/devices/pci0000:00/0000:00:02.0/vendor" pid=64203 comm="calibre" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
[19605.361108] audit: type=1400 audit(1604157007.593:13837): apparmor="DENIED" operation="open" profile="snap.calibre-unofficial.calibre" name="/sys/devices/pci0000:00/0000:00:02.0/vendor" pid=64203 comm="calibre" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0

Here is also the snappy-debug output

david@hp:~/devel/snap/calibre$ snappy-debug.security scanlog
INFO: Following '/var/log/syslog'. If have dropped messages, use:
INFO: $ sudo journalctl --output=short --follow --all | sudo snappy-debug
= AppArmor =
Time: Oct 31 16:26:14
Log: apparmor="DENIED" operation="open" profile="snap.calibre-unofficial.calibre" name="/sys/devices/pci0000:00/0000:00:02.0/vendor"
pid=69607 comm="calibre" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
File: /sys/devices/pci0000:00/0000:00:02.0/vendor (read)
Suggestions:
* adjust program to not access '/sys/devices/pci0000:00/0000:00:02.0/vendor'
* adjust program to not access '/sys/devices/pci[0-9]*:[0-9]*/[0-9]*:[0-9]*:[0-9]*.[0-9]*/vendor'

= AppArmor =
Time: Oct 31 16:26:14
Log: apparmor="DENIED" operation="bind" profile="snap.calibre-unofficial.calibre" pid=69607 comm="calibre" family="unix" sock_type="s
tream" protocol=0 requested_mask="bind" denied_mask="bind" addr="@calibre-singleinstance-1000-GUI"
Suggestions:
* adjust '@calibre-singleinstance-1000-GUI' to start with 'snap.calibre-unofficial.' (eg, '@snap.calibre-unofficial.calibre-singleins
tance-1000-GUI')
* use 'listen-stream: @snap.calibre-unofficial.calibre-singleinstance-1000-GUI' for a socket-activated daemon
2 Likes

This seems to be the proper way to deal with this problem, however the source code needs to be patched means that the prebuilt distribution can’t be used.

calibre is python, if lock.py is the only place where the socket name is defined, then a simple sed command in an override-pull scriptlet should be enough …

i.e. something like:

    override-pull: |
      snapcraftctl pull
      sed "s/\%s-singleinstance/snap.$SNAPCRAFT_PROJECT_NAME-%s-singleinstance/" path/to/lock.py

should work …
(path/to/lock.py is relative to parts/<yourpart>/src)

1 Like

I have taken a look and the official download script seems to download a binary executable, not source code. So I may have to build it or try to use in source.

In the git home page there are instructions for linux installation, I will try it this weekend :slightly_smiling_face: