Required key not available fix for CUPS
Testing the new EasyOS Kirkstone-series, printing worked, but after a reboot it didn’t. Looking at /var/log/cups/error_log:
PID 6981 (/usr/libexec/cups/filter/pdftopdf) stopped with status 226 (Required key not available)
execv failed: Required key not available
execv failed: Required key not available
PID 6982 (/usr/libexec/cups/filter/foomatic-rip) stopped with status 226 (Required key not available)
Ah, I recognize that “Required key not available” message!
It is because of fscrypt. This is the ext4 per-folder encryption mechanism. In the initrd, when the password is entered, a kernel "key" is acquired that decrypts the folders. This key applies to the root user after login; however, if an 'su' or 'sudo' is performed to a non-root user, the key has to be linked to the user "keyring" to be able to read/write files.
There have been numerous posts about this, for example:
https://bkhome.org/news/202109/fscrypt-broken-in-user-spot.html
https://bkhome.org/news/202109/fscrypt-now-works-in-user-spot.html
Yes, /etc/rc.d/rc.sysinit has this:
#20210912 make fscrypt work in non-root clients...
which keyctl >/dev/null
if [ $? -eq 0 ];then
FSCRYPTID="$(cat /proc/keys | tr -s ' ' | grep ' logon ' | head -n 1 | cut -f 1 -d ' ')"
if [ "$FSCRYPTID" ];then
keyctl setperm 0x${FSCRYPTID} 0x3f3f3f3f #enable everything.
keyctl chgrp 0x${FSCRYPTID} 118 #fscryptgrp, see /etc/group
fi
fi
...and 'spot' belongs to the 'fscryptgrp' group. But that is only
half of the story. When an app is run non-root, the startup
script, for example /usr/bin/chromium, has code that runs this
line, after login to the non-root user:
ID="$(grep " logon " /proc/keys | head -n 1 | cut -f 1 -d " ")"
keyctl link 0x${ID} @us
What that does is link the main "logon" key to the non-root user keyring. In plain English, it means the non-root user now has full read/write access to the encrypted folders.
Now getting onto the purpose of this post. The CUPS daemon
'cupsd' is lauched as root (see /etc/init.d/cupsd); however, it
runs the filter utilities as a non-root user, for security
reasons. The default is the 'lp' user; however, in Easy
Dunfell-series and Kirkstone-series CUPS was compiled with
configure option "--with-cups-user=spot"
Whether the filters are executed as 'lp' or 'spot' doesn't matter. Either should work. With the Dunfell-series, that first-step unlocking the encrypted folders in /etc/rc.d/rc.sysinit, should be enough. The filter utilities should be readable and executable.
But no longer. With the Kirkstone-series, now getting the "Required key not available". The Kirkstone-series has cups 2.4.2, whereas the Dunfell-series has 2.3.1. Big changes with 2.4.0, perhaps that's it.
The end of the story is that I figured out a fix. Created /root/Startup/cups_spot_fix:
#!/bin/ash
#20221229 cupsd tries to run utilities in /usr/libexec/cups/filter/ as user spot
# but fails, see /var/log/cups/error_log. this is due to fscrypt and kernel keys.
# when we run an app non-root, the startup script (ex: /usr/bin/firefox) makes
# fscrypt work in that user. however, for cupsd, it switches into spot without
# that fix. this little hack fixes...
echo "/root/Startup/cups_spot-fix:"
FSCRYPTID="$(grep ' logon ' /proc/keys | head -n 1 | cut -f 1 -d ' ')"
if [ "$FSCRYPTID" ];then
su -l spot -c "grep -q '_uid\.502' /proc/keys || keyctl link 0x${FSCRYPTID} @us"
fi
To verify, after bootup open a terminal:
# su spot
# cat /proc/keys
0078d7e5 I--Q--- 1 perm 1f3f0000 502 65534 keyring _uid_ses.502: 2
0fbd2c46 I--Q--- 2 perm 1f3f0000 502 65534 keyring _uid.502: empty
2ea1b363 I--Q--- 2 perm 3f3f3f3f 0 118 logon ext4:6db5ac6afa4a5042: 72
# keyctl show
Session Keyring
7919589 --alswrv 502 65534 keyring: _uid_ses.502
264055878 --alswrv 502 65534 \_ keyring: _uid.502
782349155 --alswrv 0 118 \_ logon: ext4:6db5ac6afa4a5042
#
...it shows that the "logon" key is now linked to the 'spot' (502) keyring. Printing now works.
I must add that my understanding of how these kernel keys work is superficial. Somehow have managed to put together a fix.
EDIT 2022-12-30:
The above fix also works for the Dunfell-series. Discussion
about this on the forum:
https://forum.puppylinux.com/viewtopic.php?t=7697
Tags: easy