Just before starting, I’m going to remind you how to do a chroot on a classic file system (ext4, xft, fat, etc) and then, we’ll see how to do it on our brand new standard : Btrfs.
Contrary to the manipulation to change the root password, that we will also use to repair a corrupted fstab after changing the hard drive ^_^’, we can use the chroot to mount a Linux in our Fedora in order to perform operations (updates, file recovery, debugging, etc).
A few explanations:
The chroot is a function allowing to change temporarily the root location which allows a partitioning of a service or a user in the arborescence.
When you chroot another OS, you have to mount in this chroot the special folders allowing the OS to talk with the kernel (for reminder, the kernel is Linux and Linux is just the kernel, and there, the trolls are going to unleash).
These directories are :
- /dev for the devices.
- /proc which contains the information on the system (kernel and process).
- /sys which contains the information between the system and the hardware.
Old solution (when I was younger so much younger than todaayyyyy)
In the following example, the / partition to mount is sdx which we will mount in /mnt but you can mount it on another folder than /mnt like /chroot.
mount /dev/sdx /mnt mount --bind /dev /mnt/dev #the --bind option makes the contents accessible in both locations. mount -t proc /proc /mnt/proc #with -t we specify the proc type mount -t sysfs /sys /mnt/sys #with -t we specify the sysfs type chroot /mnt #change the root location
To exit the chroot, the shell command is exit.
When finished, we unmount all folders:
exit umount /mnt/dev umount /mnt/proc umount /mnt/sys umount /mnt
the case of lvm
In the case of lvm, the partitions are not available directly and must be mapped:
fdisk -l /dev/vda2 Disk /dev/vda2: 19 GiB, 20400046080 bytes, 39843840 sectors [...] I/O size (minimum/optimal): 512 bytes / 512 bytes mount /dev/vda2 /mnt/ mount: /mnt: unknown filesystem type 'LVM2_member'.
We will use the lvm tools to locate our partitions
pvscan PV /dev/vda2 VG cl lvm2 [<19.00 GiB / 0 free] Total: 1 [<19.00 GiB] / in use: 1 [<19.00 GiB] / in no VG: 0  vgscan Found volume group "cl" using metadata type lvm2 lvscan ACTIVE '/dev/cl/root' [10.00 GiB] inherit ACTIVE '/dev/cl/swap' [2.00 GiB] inherit ACTIVE '/dev/cl/home' [1.00 GiB] inherit ACTIVE '/dev/cl/var' [<6.00 GiB] inherit
So we see where the logical volumes are mapped and we can mount these partitions with the previous method
mount /dev/cl/root /mnt/ mount /dev/cl/home /mnt/home/ mount --bind /dev /mnt/dev mount -t proc /proc /mnt/proc mount -t sysfs /sys /mnt/sys chroot /mnt
New solution (The Btrfs case)
Fdisk tells us that there are only two partitions on the physical media
Disk /dev/vda: 20 GiB, 21474836480 bytes, 41943040 sectors […] Device Boot Start End Sectors Size Id Type /dev/vda1 * 2048 2099199 2097152 1G 83 Linux /dev/vda2 2099200 41943039 39843840 19G 83 Linux
So let’s have a look at the fstab of the target OS:
UUID=3de441bd-59fc-4a12-8343-8392faab5ac7 / btrfs subvol=root,compress=zstd:1 0 0 UUID=71dc4f0f-9562-40d6-830b-bea065d4f246 /boot ext4 defaults 1 2 UUID=3de441bd-59fc-4a12-8343-8392faab5ac7 /home btrfs subvol=home,compress=zstd:1 0 0
Looking at the UUIDs, we see two partitions. One ext4 and one btrfs containing two mount points (the subvolumes) / and /home.
Let’s have a look at what is in the btrfs partition (/dev/vda2 here)
mount /dev/vda2 /mnt/ ls /mnt/ home root ls /mnt/root/ bin dev home lib64 media opt root sbin sys usr boot etc lib lost+found mnt proc run srv tmp var ls /mnt/home/ user umount /mnt #remember we are cleaning behind us ;-)
So we can see that in the mounted partition there are folders that contain our diverse partitions (the subvolumes).
or far much nicer:
mount /dev/vda2 /mnt/ btrfs subvolume list /mnt ID 256 gen 178 top level 5 path home ID 258 gen 200 top level 5 path root ID 262 gen 160 top level 258 path root/var/lib/machines umount /mnt #remember we are cleaning behind us ;-)
Now that we have seen the contents of our partition, we will mount the system by adding the mount options btrfs and subvolume subvol=SubVolumeName :
mount /dev/vda2 /mnt/ -t btrfs -o subvol=root ls /mnt/ bin dev home lib64 media opt root sbin sys usr boot etc lib lost+found mnt proc run srv tmp var ls /mnt/home/ #<it's empty yet> mount /dev/vda2 /mnt/home -t btrfs -o subvol=home ls /mnt/home/ user mount /dev/vda1 /boot mount --bind /dev /mnt/dev mount -t proc /proc /mnt/proc mount -t sysfs /sys /mnt/sys chroot /mnt
and when the job is done we exit and unmount :
exit umount /mnt/boot umount /mnt/sys umount /mnt/proc umount /mnt/sys umount /mnt
To show that this technique is not distro exclusive, I performed the same method from a Fedora security live and a Parrot OS live which is based on a Debian (see the terminal at the bottom right of the screenshot) to run a dnf update. Mind if you use a different shell between your host/client, for example zsh <-> bash (kali linux <-> Fedora), you have to make a small adjustment.
I hope this will be useful to someone in a debugging session.
Have fun \o/