cifs.upcall: fix regression in kerberos mount
The fix for CVE-2021-20208 in commit
e461afd ("cifs.upcall: try to use
container ipc/uts/net/pid/mnt/user namespaces") introduced a
regression for kerberos mounts when cifs-utils is built with
libcap-ng. It makes mount fail with ENOKEY "Required key not
available".
Current state:
mount.cifs
'---> mount() ---> kernel
negprot, session setup (need security blob for krb)
request_key("cifs.spnego", payload="pid=%d;username=...")
upcall
/sbin/request-key <--------------'
reads /etc/request-keys.conf
dispatch cifs.spnego request
calls /usr/sbin/cifs.upcall <key id>
- drop privileges (capabilities)
- fetch keyid
- parse payload
- switch to mount.cifs namespaces
- call krb5_xxx() funcs
- generate security blob
- set key value to security blob
'-----------------------------------> kernel
put blob in session setup packet
continue auth
open tcon
get share root
setup superblock
mount.cifs mount() returns <-----------'
By the time cifs.upcall tries to switch to namespaces, enough
capabilities have dropped in trim_capabilities() that it makes setns()
fail with EPERM.
setns() requires CAP_SYS_ADMIN.
With libcap trim_capabilities() is a no-op.
This fix:
- moves the namespace switch earlier so that operations like
setgroups(), setgid(), scanning of pid environment, ... happens in the
contained namespaces.
- moves trim_capabilities() after the namespace switch
- moves the string processing to decode the key request payload in a
child process with minimum capabilities. the decoded data is shared
with the parent process via shared memory obtained with mmap().
Fixes: e461afd ("cifs.upcall: try to use container ipc/uts/net/pid/mnt/user namespaces")
Signed-off-by: Aurelien Aptel <aaptel@suse.com>