btrfs-progs icon indicating copy to clipboard operation
btrfs-progs copied to clipboard

btrfs send/receive should not respect replaying lremovexattr on SElinux permissive and above systems

Open xenithorb opened this issue 8 years ago • 4 comments

Version of btrfs-progs: btrfs-progs-4.9.1-2.fc26.x86_64 Kernel: 4.12.12-300.fc26.x86_64 (also tested prior kernels)

Related to: https://github.com/digint/btrbk/issues/160 as that is downstream from this bug. Initially filed as a bug against btrbk, it's trivial to output the debug from btrbk and replay the commands and prove that it is in fact btrfs send/receive upstream producing the following error:

### btrfs send -p /mnt/btrfs_root/snapshots/home.20170910T150101-0400 /mnt/btrfs_root/snapshots/home.20170915T180117-0400 | btrfs receive /mnt/external1/icarus_main/
Command execution failed (exitcode=1): "{ btrfs send -p /mnt/btrfs_root/snapshots/home.20170910T150101-0400 /mnt/btrfs_root/snapshots/home.20170915T180117-0400 2>&3 | btrfs receive /mnt/external1/icarus_main/ 2>&3 ; } 3>&1"
WARNING: [send/receive] (send=/mnt/btrfs_root/snapshots/home.20170915T180117-0400, receive=/mnt/external1/icarus_main) At subvol /mnt/btrfs_root/snapshots/home.20170915T180117-0400
ERROR: lremovexattr xenith/.config/Rocket.Chat+/Cookies security.selinux failed: Permission denied

This code is breaking send/receive backup strategies for any one SELinux permissive and enabled systems.

As per what SELinux developer Stephen Smalley said on an old bug here: https://bugzilla.redhat.com/show_bug.cgi?id=450360#c1

Bug in rsync: don't try to remove the SELinux attribute. SELinux doesn't ever allow removal of its attributes if enabled; you can change the label, but all data must be labeled.

And this is still the case today (as it should be). Therefore, the bottom line is that you can't delete selinux attributes on permissive and above SElinux systems, so btrfs send/receive shouldn't even be attempting to do that on permissive and above systems. Either btrfs send is messing up by attempting to replay it, or btrfs receive is messing up by not filtering it out. This means all Fedora and RHEL/CentOS systems by default are affected (who use btrfs and send/receive).

Please fix this as this breaks many local and remote backup strategies where btrfs and selinux are concerned.

xenithorb avatar Sep 25 '17 16:09 xenithorb

A tedious yet seemingly viable workaround for this at the moment seems to be:

  1. touch /.autorelabel # to stabilize the labels beforehand
  2. Reboot, let the autorelabel happen, and it will reboot itself again
  3. Upon this second reboot, press e on the grub menu to edit the kernel entry, add selinux=0 to the linux cmdline. This completely disables SELinux for this boot, and it cannot be re-enabled until another reboot
  4. Execute btrbk run or whatever script or combination of btrfs send / receive that you use, hopefully your script knows how to "catch up" to transferred snapshots like btrbk.
  5. Reboot again. The system will always trigger an autorelabel after being disabled, so let this happen again, and it will reboot a final time with SELinux enabled, and hopefully your backups can continue for a little while until labels change again...

The thought process behind this is that you should first relabel everything to make the labels consistent, because what btrfs send/receive has issues with is in changing contexts. However, it can change those contexts when SELinux is in a disabled state. Therefore disable selinux -> take a backup -> transfer the offending snapshots and new snapshots -> re-enable selinux and you should be able to resume sending snapshots.

xenithorb avatar Sep 26 '17 17:09 xenithorb

I put the btrbk-specific workaround I've been using on btrbk#160. At least in my case I think the issue is that btrfs is removing the old label before adding the new label instead of just changing the label (if that is allowed?). The file can be created with the correct label without disabling SELinux when sending a non-incremental snapshot.

mdonoughe avatar Oct 31 '17 15:10 mdonoughe

@mdonoughe Your solution works because you're breaking the chain by transferring another full backup. That is, it doesn't need to replay anything because it just sends the subvolume as-is. What happens here only happens during incremental replays, and it's because the kernel will never allow lremovexattr on an SELinux-enabled or permissive system, ever. When it replays the incremental, it thinks for some reason that it needs to remove the context before changing it, and why that is extends beyond my knowledge. In sort, your solution is not a great choice for people who are trying to conserve space.

xenithorb avatar Jan 31 '18 22:01 xenithorb

Any updates/fixes planned? It's been a while...

ErrorNoInternet avatar Aug 01 '23 04:08 ErrorNoInternet