2

The problem

I cannot cryptsetup close any LUKS volume while any flatpak app is running in the background. Yes, the flatpak app just has to be running in the background, I'm not trying to use cryptsetup from within the sandbox or anything like that. Yes, this is one of those issues.

Steps to reproduce

mkdir ~/mnt
dd if=/dev/zero of=file.img bs=1MiB count=100
sudo losetup /dev/loop4 file.img
sudo cryptsetup luksFormat /dev/loop4
sudo cryptsetup open /dev/loop4 my_crypt
sudo mkfs.fat  /dev/mapper/my_crypt
sudo mount  /dev/mapper/my_crypt ~/mnt
echo ayylmao | sudo tee ~/mnt/foobar.txt
sync

# <open a flatpak app, such as flatseal, in the background>

sudo umount ~/mnt
sudo cryptsetup close my_crypt

# output:
# device-mapper: remove ioctl on my_crypt  failed: Device or resource busy
# <the above line multiple times>
# Device my_crypt is still in use.

# <now close the flatpak app>

sudo cryptsetup close my_crypt
# Now it runs successfully

sudo losetup -d /dev/loop4

Note that the same issue happens with "real" LUKS devices as opposed to loop devices, as well as with tombs.

Further diagnostics

It seems that when launching a flatpak app, it spawns a process called xdg-dbus-proxy in a new mnt namespace, which, for some reason, keeps the filesystem on the LUKS device mounted, even after it is unmounted in the "default" namespace. For example, here is the output of lsns before launching flatseal:

        NS TYPE   NPROCS   PID USER      COMMAND
4026531834 time       40  1452 renzev -bash
4026531835 cgroup     40  1452 renzev -bash
4026531836 pid        40  1452 renzev -bash
4026531837 user       40  1452 renzev -bash
4026531838 uts        40  1452 renzev -bash
4026531839 ipc        40  1452 renzev -bash
4026531840 net        40  1452 renzev -bash
4026531841 mnt        40  1452 renzev -bash

And here is the output after launching flatseal:

        NS TYPE   NPROCS   PID USER      COMMAND
4026531834 time       44  1452 renzev -bash
4026531835 cgroup     44  1452 renzev -bash
4026531836 pid        42  1452 renzev -bash
4026531837 user       41  1452 renzev -bash
4026531838 uts        44  1452 renzev -bash
4026531839 ipc        44  1452 renzev -bash
4026531840 net        42  1452 renzev -bash
4026531841 mnt        41  1452 renzev -bash
4026532233 user        1 11485 renzev xdg-dbus-proxy --args=42
4026532254 mnt         1 11485 renzev xdg-dbus-proxy --args=42
4026532256 mnt         2 11488 renzev bwrap --args 40 com.github.tchx84.
4026532257 pid         2 11488 renzev bwrap --args 40 com.github.tchx84.
4026532258 net         2 11488 renzev bwrap --args 40 com.github.tchx84.
4026532391 user        2 11488 renzev bwrap --args 40 com.github.tchx84.

If we hop into the namespace check the mounted filesystems, we can see that ~/mnt is still mounted, even after we unmount it in the "default" namespace:

sudo nsenter -t 11485 -m bash
mount | grep mnt
/dev/mapper/my_crypt on /home/renzev/mnt type vfat (ro,nosuid,nodev,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro)

Trying to manually unmount the device from within the namespace leads to a somewhat entertaining output:

mountpoint /home/renzev/mnt
/home/renzev/mnt is a mountpoint

umount /home/renzev/mnt
umount: /home/renzev/mnt: not mounted.

System Details

Void Linux. cryptsetup 2.6.1 flags: UDEV BLKID KEYRING KERNEL_CAPI. Flatpak 1.15.6. Linux 6.3.13_1.

The Question

How can I close LUKS devices without needing to close every single flatpak app?

9
  • 1
    This kind of resource busy problem is reproducible while leaving running for example unshare -m after having mounted a filesystem from a luks mapping: the luks mapping can't be removed. But I can't reproduce it with my implementation of flatpak (1.14.4-1 on Debian 12) when running from a normal user context a sleep infinity command. The ~/mnt mountpoint is not exposed in the flatpak's mount namespace and I have thus no trouble freeing resources. Btw: it appears there's no /proc/mounts available within, so: findmnt -N $(pgrep -f 'sleep infinity') . So why is your mount exposed? Commented Jan 12, 2024 at 12:52
  • 1
    ah mounts is a symlink to self/mounts but as an outsider process, there's no self after chroot or nsenter (because of pid namespace interaction) Commented Jan 12, 2024 at 13:01
  • 1
    So you could try again with your environment (where there are more mounts than usual) sudo nsenter -t 11485 -m --pid bash instead. Commented Jan 12, 2024 at 13:59
  • 1
    wikipedia "Features: Void is a notable exception to the majority of Linux distributions because it uses runit as its init system instead of the more common systemd" . systemd makes mount shared by default. I have trouble to understand how this affects something else than bind mounts (because mount namespace has so many complex details...). But I guess Void Linux keeps the kernel's default: private and there's a relation to the difference you are talking about. Anyway, I was asking to retry to umount from within by using nsenter + --pid so /proc/mounts is visible Commented Jan 12, 2024 at 19:27
  • 1
    I won't write an answer, because I would want to know how it works in the details first but it's a bit too complex for me. Please do so. You'll have to wait 48h before accepting it. Commented Jan 16, 2024 at 13:10

1 Answer 1

1

Thank you to @A.B for helping me figure this out! I want this answer to be useful to others in the future, so I'll try to give a really thorough explanation. Here goes!

Introduction

Namespaces are a Linux feature that allows isolation between processes. There are different types of namespaces for isolating different types of system resources. The one we are interested in for this problem are called mount namespaces, which can give different processes a different view of what block devices (drives, encrypted volumes, disk images, CD's, DVD's and so on) are mounted. Flatpak uses mount namespaces as part of its sandboxing functionality.

In Linux, mounts have a property called "propagation", which can be either private or shared. I don't really understand the difference between these two, but the important part is that in most modern linux distros, the root filesystem at / is mounted as shared.

The problem

On my system, the root filesystem was mounted as private, not shared. For some reason, this means that when I tried unmounting the encrypted volume, the unmount event would not propagate inside the various mount namespaces created by flatpak. So, while the volume was unmounted in the 'default' namespace, it would still be mounted inside of flatpak's namespaces, and would thus keep the LUKS partition busy, preventing cryptsetup for closeing it.

The solution

The solution is to make sure that / is mounted with shared propagation. This can be done by adding the shared option to the entry for the root filesystem in /etc/fstab and rebooting. For example, before the fix, my /etc/fstab looked like this:

PARTLABEL=VOID_ROOT / btrfs lazytime,noatime,autodefrag,compress=zstd:3,discard=async,space_cache=v2,ssd 0 1
PARTLABEL=VOID_SWAP none swap sw 0 0
PARTLABEL=VOID_ESP /mnt/esp vfat defaults,noauto 0 0
tmpfs /tmp tmpfs defaults,nosuid,nodev 0 0

And after the fix, it looked like this:

PARTLABEL=VOID_ROOT / btrfs shared,lazytime,noatime,autodefrag,compress=zstd:3,discard=async,space_cache=v2,ssd 0 1
PARTLABEL=VOID_SWAP none swap sw 0 0
PARTLABEL=VOID_ESP /mnt/esp vfat defaults,noauto 0 0
tmpfs /tmp tmpfs defaults,nosuid,nodev 0 0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.