I am snapping CUPS and everything is working, except creating print queues and doing other administrative CUPS tasks through CUPS’ web interface, which works in classically (.deb
packages) installed CUPS.
CUPS needs to create a certificate file to do login/password-authenticated operations with its web interface. The CUPS daemon, running as root creates this file in the /var/run/cups/certs
(classic installation) directory with the following permissions/ownerships:
$ ls -ld /var/run/cups/certs/
dr-x--x--x 2 lp lpadmin 60 May 25 21:26 /var/run/cups/certs/
$
The classically installed CUPS daemon has no problem creating a file in this diectory:
$ sudo ls -l /var/run/cups/certs/
total 4
-r--r----- 1 root lpadmin 32 May 25 21:26 0
$
Also one can list this directory and create and remove files there using sudo
:
$ sudo ls -l /var/run/cups/certs/
total 4
-r--r----- 1 root lpadmin 32 May 25 21:26 0
$ sudo touch /var/run/cups/certs/1
$ sudo ls -l /var/run/cups/certs/
total 4
-r--r----- 1 root lpadmin 32 May 25 21:26 0
-rw-r--r-- 1 root root 0 May 25 21:33 1
$ sudo rm /var/run/cups/certs/1
$
This does not work for the CUPS daemon in the Snap if the Snap is installed in restricted mode (--dangerous
, note that I am working with a Snap which I am locally building, not installing from the Snap Store), but in the unrestricted devmode (--devmode
) it works as with classically installed CUPS, though.
To more easily reproduce, I get into a shell equivalent to the one in which the snapped CUPS daemon is running:
$ sudo snap run --shell printing-stack-snap.cupsd
root@till-x1yoga:/home/till/printing/openprinting/printing-stack-snap/x# cd
root@till-x1yoga:~# pwd
/root/snap/printing-stack-snap/x31
root@till-x1yoga:~# env | grep SNAP
SNAP_USER_DATA=/root/snap/printing-stack-snap/x31
SNAP_REVISION=x31
SNAP_ARCH=amd64
SNAP_INSTANCE_KEY=
SNAP_USER_COMMON=/root/snap/printing-stack-snap/common
SNAP=/snap/printing-stack-snap/x31
SNAP_COMMON=/var/snap/printing-stack-snap/common
SNAP_NAME=printing-stack-snap
SNAP_INSTANCE_NAME=printing-stack-snap
SNAP_DATA=/var/snap/printing-stack-snap/x31
SNAP_COOKIE=b7gtjF67Vox-0gfeiF8zNOV7ql4zFKSIxOAoqtF9X7T0KYa5Nl5u
SNAP_REEXEC=
SNAP_CONTEXT=b7gtjF67Vox-0gfeiF8zNOV7ql4zFKSIxOAoqtF9X7T0KYa5Nl5u
SNAP_VERSION=0.1.0
SNAP_LIBRARY_PATH=/var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:/var/lib/snapd/void
root@till-x1yoga:~#
This is the directory which contains the certs
directory of the snapped CUPS. It is in the $SNAP_DATA
file system, where root is allowed to write and create files:
root@till-x1yoga:~# ls -l $SNAP_DATA/var/run
total 12
dr-x--x--x 2 snap_daemon lpadmin 4096 May 25 18:21 certs
-rw-r--r-- 1 root root 7 May 25 18:21 cups-browsed.pid
-rw-r--r-- 1 root root 7 May 25 18:21 cupsd.pid
-rw-r--r-- 1 root root 0 May 6 22:58 stop-cupsd.lock
root@till-x1yoga:~#
You see that the certs
directory has the same odd permissions and ownerships as the classic CUPS’ certs
directory has: It has no writable bit at all, not even for the owner and the owner is snap_daemon here, the standard drop-privileges user for Snaps. A Snap cannot create a new user, like ‘lp’. The group ownership is lpadmin, the Snap here checks what is available in the system to use as CUPS admin group, trying lpadmin first, then adm and resorts to root otherwise.
The $SNAP_DATA/var/run
and most other directories in the $SNAP_DATA
file system are owned and writable by root.
Now I try what CUPS wants to do, create a file in the certs
directory:
root@till-x1yoga:~# touch $SNAP_DATA/var/run/certs/0
touch: cannot touch '/var/snap/printing-stack-snap/x31/var/run/certs/0': Permission denied
root@till-x1yoga:~#
It fails with “Permission denied” as it happens also to CUPS, so I can reproduce the problem manually and exclude any further bug in CUPS. I also cannot read this directory as root:
root@till-x1yoga:~# ls -l $SNAP_DATA/var/run/certs/
ls: cannot open directory '/var/snap/printing-stack-snap/x31/var/run/certs/': Permission denied
root@till-x1yoga:~#
In the other directories it is no problem to create files:
root@till-x1yoga:~# touch $SNAP_DATA/var/run/0
root@till-x1yoga:~# less $SNAP_DATA/var/run/0
root@till-x1yoga:~# cat $SNAP_DATA/var/run/0
root@till-x1yoga:~# rm $SNAP_DATA/var/run/0
root@till-x1yoga:~#
So I try to change the ownership of the certs
directory to root, but I am still not able to create a file:
root@till-x1yoga:~# chown root $SNAP_DATA/var/run/certs
root@till-x1yoga:~# touch $SNAP_DATA/var/run/certs/0
touch: cannot touch '/var/snap/printing-stack-snap/x31/var/run/certs/0': Permission denied
root@till-x1yoga:~#
But I can at least read the directory now:
root@till-x1yoga:~# ls -l $SNAP_DATA/var/run/certs/
total 0
root@till-x1yoga:~# ls -l $SNAP_DATA/var/run/
total 12
dr-x--x--x 2 root lpadmin 4096 May 25 18:21 certs
-rw-r--r-- 1 root root 7 May 25 18:21 cups-browsed.pid
-rw-r--r-- 1 root root 7 May 25 18:21 cupsd.pid
-rw-r--r-- 1 root root 0 May 6 22:58 stop-cupsd.lock
root@till-x1yoga:~#
So change back ownership but allow only the owner to write:
root@till-x1yoga:~# chown snap_daemon $SNAP_DATA/var/run/certs
root@till-x1yoga:~# ls -l $SNAP_DATA/var/run/
total 12
dr-x--x--x 2 snap_daemon lpadmin 4096 May 25 18:21 certs
-rw-r--r-- 1 root root 7 May 25 18:21 cups-browsed.pid
-rw-r--r-- 1 root root 7 May 25 18:21 cupsd.pid
-rw-r--r-- 1 root root 0 May 6 22:58 stop-cupsd.lock
root@till-x1yoga:~# chmod u+w $SNAP_DATA/var/run/certs
chmod: changing permissions of '/var/snap/printing-stack-snap/x31/var/run/certs': Operation not permitted
root@till-x1yoga:~# chmod u-w $SNAP_DATA/var/run/cups-browsed.pid
root@till-x1yoga:~# chmod u+w $SNAP_DATA/var/run/cups-browsed.pid
root@till-x1yoga:~#
I am not allowed to change the permissions, but allowed to change the permissions of the other files. Seems that here in the Snap root can only change permissions of directories owned by root. So change ownership to root again and then set the owner’s write bit:
root@till-x1yoga:~# chown root $SNAP_DATA/var/run/certs
root@till-x1yoga:~# chmod u+w $SNAP_DATA/var/run/certs
root@till-x1yoga:~# touch $SNAP_DATA/var/run/certs/0
root@till-x1yoga:~# ls -l $SNAP_DATA/var/run/certs
total 4
-rw-r--r-- 1 root root 32 May 25 20:25 0
root@till-x1yoga:~# rm $SNAP_DATA/var/run/certs/0
root@till-x1yoga:~# ls -l $SNAP_DATA/var/run/
total 12
drwx--x--x 2 root lpadmin 4096 May 25 20:25 certs
-rw-r--r-- 1 root root 7 May 25 18:21 cups-browsed.pid
-rw-r--r-- 1 root root 7 May 25 18:21 cupsd.pid
-rw-r--r-- 1 root root 0 May 6 22:58 stop-cupsd.lock
root@till-x1yoga:~#
So with these settings I am actually able to create the file!
The Snap’s CUPS was all the time running while I did these tests, but during the tests I left CUPS idle, not doing any operations on it. Now knowing that root can create a file in my modified certs
directory, I want to know whether CUPS can do it, too. I do not restart CUPS here to avoid that it cleans up directory and file permissions and ownerships.
I simply go to the web interface of the Snap’s CUPS (http://localhost:631/
if only the Snap’s CUPS and no classic CUPS is running on the system, http://localhost:10631/
if a classic CUPS is also running) and create a print queue. When I am prompted for user name and password, I log in as a user who is in the lpadmin group. This works now! I get the queue!
And this is due to the fact that now CUPS was able to create the file in certs
:
root@till-x1yoga:~# ls -l $SNAP_DATA/var/run/certs
total 4
-r--r----- 1 root root 32 May 25 20:25 0
root@till-x1yoga:~#
You see above that I had deleted my file and also CUPS changes the permissions of the file it creates, but it stays owned by root.
Now I do another test. The certs
directory has already owner’s write permission. As I was not able to set the permission when the directory was owned by snap_daemon I switch ownership to snap_daemon now to see whether this combination actually works:
root@till-x1yoga:~# chown snap_daemon $SNAP_DATA/var/run/certs
root@till-x1yoga:~# ls -l $SNAP_DATA/var/run/
total 12
drwx--x--x 2 snap_daemon lpadmin 4096 May 25 20:43 certs
-rw-r--r-- 1 root root 7 May 25 18:21 cups-browsed.pid
-rw-r--r-- 1 root root 7 May 25 18:21 cupsd.pid
-rw-r--r-- 1 root root 0 May 6 22:58 stop-cupsd.lock
root@till-x1yoga:~# touch $SNAP_DATA/var/run/certs/1
touch: cannot touch '/var/snap/printing-stack-snap/x31/var/run/certs/1': Permission denied
root@till-x1yoga:~#
But it does not work.
So owner of the certs
directory has to be root and the owner’s write bit has to be set in addition to the other permissions.
Now my first question is, why is root in the classic system allowed to create and write files completely ignoring any ownerships and permissions and why is root in the Snap’s environment not allowed to do so?
It seems that AppArmor is not the reason, as I do not get any ...audit...DENIED...
messages in the syslog.
Can I perhaps do some configuration setting in the Snap to allow roo to ignore file permissions and ownerships without dropping the restricted mode?
If not, I will have to patch CUPS to use root ownership and owner’s write permission on its certs
directory. Does this compromise the security of my snapped CUPS?
@jdstrand, WDYT? How can I solve this problem?