Package: cifs-utils Version: 7.1
Description: The Linux SMB client kernel filesystem today depends on the upcall mechanism (request_key) to get stuff done in userspace (which is difficult in the kernel. For example: DNS resolutions, Kerberos authentication etc) and then use a binary in the userspace (which is part of cifs-utils) to do that work. The kernel upcall mechanism today does not have a way to upcall to specific user namespace and can do so only to the root namespace. So, we have the user space utility that does the switch to the "correct" namespace. With the parameters that are supplied today with the upcall, this correct namespace cannot be decided by the utility for a specific set of use cases, which is why we needed to introduce a new mount option. The idea is that we'll let the users decide what type of upcalling mechanism they need by passing this mount option differently. Once the kernel upcall mechanism has a way to upcall a specific namespace, we will use this mount option to make this decision in the kernel itself. Without this mount option, the upcall can go to a "wrong" namespace, and may not find what it needs or (worse) find something wrong (for example krb5 credentials of a wrong user). In some cases, like described below, the cifs.upcall program from the cifs-utils package makes an upcall to the wrong namespace in containerized environments. Consider the following scenario: A CIFS/SMB file share is mounted on a host node using Kerberos authentication. During the session setup phase, the Linux kernel's cifs.ko module makes an upcall to user space to retrieve the Kerberos service ticket from the credential cache. In typical (non-container) environments, this process works correctly, but in containerized environments, the upcall may be directed to a different namespace than intended, leading to issues. For example: (1) The file share is mounted on the host node at /mnt/testshare1, meaning the Kerberos credential cache is stored in the host's namespace. (2) Docker container is created, and the file share path /mnt/testshare1 is exported to the container at /sharedpath. (3) When the service ticket expires and the SMB connection is lost, before the ticket is refreshed in the credential cache, an application inside the container performs a file operation. This triggers the kernel to attempt a session reconnect. (4) During the session setup, a Kerberos ticket is needed, so the kernel invokes the cifs.upcall binary using the request_key function. However, cifs.upcall switches to the namespace of the caller (i.e., the container), causing it to attempt to read the credential cache from the container's namespace. But since the original mount happened in the host namespace, the credential cache is located on the host, not in the container. This results in the upcall failing to access the correct credential cache or accessing credential cache which doesn't belong to the correct user. I have attached the bug simulation logs, can you please take a look at this issue and backport this fix to all the affected distros.? We are in the process of publishing CVE for this issue. It fixed here by adding a new mount option in Linux kernel, based on that updating namespaces in user space cifs-utils: cifs-utils commits: Fix: https://git.samba.org/?p=cifs-utils.git;a=commit;h=89b679228cc1be9739d54203d28289b03352c174 Documentation: https://git.samba.org/?p=cifs-utils.git;a=commit;h=cf63240489431e98033e599a7c9437b59494a2e4 Linux kernel commit: https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/fs/smb?id=db363b0a1d9e6b9dc556296f1b1007aeb496a8cf Thanks, Bharath
Simulation/Repro steps: >> At the time of mount, Credential cache located at /tmp/krb5cc_0 file the >> host name space was used because by default kerberos looks for cache in >> /tmp/krb5cc_{uid}, since share is mounted as uid=0. Feb 22 12:08:06 localaadvm kernel: [ 4035.333167] CIFS: Attempting to mount //teststorageaccount.file.core.windows.net/share Feb 22 12:08:06 localaadvm cifs.upcall: key description: cifs.spnego;0;0;39010000;ver=0x2;host=teststorageaccount.file.core.windows.net;ip4=XX.239.XXX.203;sec=krb5;uid=0x0;creduid=0x0;user=root;pid=0x2dad Feb 22 12:08:06 localaadvm cifs.upcall: ver=2 Feb 22 12:08:06 localaadvm cifs.upcall: host=teststorageaccount.file.core.windows.net Feb 22 12:08:06 localaadvm cifs.upcall: ip=XX.239.XXX.203 Feb 22 12:08:06 localaadvm cifs.upcall: sec=1 Feb 22 12:08:06 localaadvm cifs.upcall: uid=0 Feb 22 12:08:06 localaadvm cifs.upcall: creduid=0 Feb 22 12:08:06 localaadvm cifs.upcall: user=root Feb 22 12:08:06 localaadvm cifs.upcall: pid=11693 Feb 22 12:08:06 localaadvm cifs.upcall: get_cachename_from_process_env: pid == 0 Feb 22 12:08:06 localaadvm cifs.upcall: get_existing_cc: default ccache is FILE:/tmp/krb5cc_0 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Feb 22 12:08:06 localaadvm cifs.upcall: main: valid service ticket exists in credential cache Feb 22 12:08:06 localaadvm cifs.upcall: handle_krb5_mech: getting service ticket for teststorageaccount.file.core.windows.net Feb 22 12:08:06 localaadvm cifs.upcall: handle_krb5_mech: using native krb5 Feb 22 12:08:06 localaadvm cifs.upcall: handle_krb5_mech: obtained service ticket Feb 22 12:08:06 localaadvm cifs.upcall: Exit status 0 >> Share mounted. root@localaadvm:/home/azureuser/# mount -t cifs //teststorageaccount.file.core.windows.net/testshare1 on /mnt/testshare1 type cifs (rw,relatime,vers=3.1.1,sec=krb5,cruid=0,cache=strict,username=root,uid=0,noforceuid,gid=0,noforcegid,addr=XX.239.XXX.203,file_mode=0777,dir_mode=0777,soft,persistenthandles,nounix,serverino,mapposix,rsize=1048576,wsize=1048576,bsize=1048576,retrans=1,echo_interval=60,nosharesock,actimeo=30,closetimeo=1) root@localaadvm:/home/azureuser# klist root@localaadvm:/home/azureuser# klist Ticket cache: FILE:/tmp/krb5cc_0 Default principal: localadminu...@azuretestdomain.onmicrosoft.com Valid starting Expires Service principal 02/22/25 12:03:45 02/22/25 22:03:45 krbtgt/azuretestdomain.onmicrosoft....@azuretestdomain.onmicrosoft.com renew until 03/01/25 12:03:45 02/22/25 12:03:45 02/22/25 22:03:45 LOCALAADVM$@AZURETESTDOMAIN.ONMICROSOFT.COM 02/22/25 12:04:59 02/22/25 22:03:45 cifs/teststorageaccount.file.core.windows.net@ renew until 03/01/25 12:03:45 Ticket server: cifs/teststorageaccount.file.core.windows....@azuretestdomain.onmicrosoft.com root@localaadvm:/home/azureuser# stat /mnt/testshare1 File: /mnt/testshare1 Size: 0 Blocks: 0 IO Block: 1048576 directory Device: 2fh/47d Inode: 13403049305088161085 Links: 2 Access: (0777/drwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2021-12-30 04:36:51.813053200 +0000 Modify: 2021-12-30 04:36:51.813053200 +0000 Change: 2021-12-30 04:36:51.813053200 +0000 Birth: 2021-12-30 04:36:51.813053200 +0000 root@localaadvm:/home/azureuser# >> Run docker container and share the host path with container: root@localaadvm:/home/azureuser/my-debian-container# root@localaadvm:/home/azureuser/my-debian-container# docker run -it -v /mnt/testshare1:/mnt/shared --name my-debian-container my-debian-with-syslog-cifs root@12d9c615199e:/# root@12d9c615199e:/# stat /mnt/shared File: /mnt/shared Size: 0 Blocks: 0 IO Block: 1048576 directory Device: 2fh/47d Inode: 13403049305088161085 Links: 2 Access: (0777/drwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2021-12-30 04:36:51.813053200 +0000 Modify: 2021-12-30 04:36:51.813053200 +0000 Change: 2021-12-30 04:36:51.813053200 +0000 Birth: 2021-12-30 04:36:51.813053200 +0000 root@12d9c615199e:/# ls /mnt/shared >> Now to simulate bug I removed the credentials from the host and triggered >> the SMB connection disconnect. >> Then I tried performing operation on container mounted path like stat >> operation on a file, which resulted upcall into container and accessing file >> /tmp/krb5cc_000 located in container. Earlier, I explicitly made a change in container's /etc/krb5.conf for a default_cache_name paramater to point to /tmp/krb5cc_000 to actually notice that upcall came to container instead of host. Note that configuration at the host is unchnaged and remained same. Feb 22 12:22:27 localaadvm kernel: [ 4896.304927] CIFS: VFS: Verify user has a krb5 ticket and keyutils is installed Feb 22 12:22:27 localaadvm kernel: [ 4896.310332] CIFS: VFS: \\teststorageaccount.file.core.windows.net Send error in SessSetup = -126 Feb 22 12:22:28 localaadvm cifs.upcall: key description: cifs.spnego;0;0;39010000;ver=0x2;host=teststorageaccount.file.core.windows.net;ip4=XX.239.XXX.203;sec=krb5;uid=0x0;creduid=0x0;user=root;pid=0x3201 Feb 22 12:22:28 localaadvm cifs.upcall: ver=2 Feb 22 12:22:28 localaadvm cifs.upcall: host=teststorageaccount.file.core.windows.net Feb 22 12:22:28 localaadvm cifs.upcall: ip=XX.239.XXX.203 Feb 22 12:22:28 localaadvm cifs.upcall: sec=1 Feb 22 12:22:28 localaadvm cifs.upcall: uid=0 Feb 22 12:22:28 localaadvm cifs.upcall: creduid=0 Feb 22 12:22:28 localaadvm cifs.upcall: user=root Feb 22 12:22:28 localaadvm cifs.upcall: pid=12801 Feb 22 12:22:28 localaadvm cifs.upcall: get_cachename_from_process_env: pid == 0 Feb 22 12:22:28 localaadvm cifs.upcall: get_existing_cc: default ccache is FILE:/tmp/krb5cc_000 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Feb 22 12:22:28 localaadvm cifs.upcall: check_service_ticket_exists: unable to get client principal from cache: No credentials cache found (filename: /tmp/krb5cc_000) Feb 22 12:22:28 localaadvm cifs.upcall: get_tgt_time: unable to get principal Feb 22 12:22:28 localaadvm cifs.upcall: main: valid TGT is not present in credential cache Feb 22 12:22:28 localaadvm cifs.upcall: krb5_parse_name: -1765328160 Feb 22 12:22:28 localaadvm cifs.upcall: handle_krb5_mech: getting service ticket for