~martijnbraam/transact

Run a shell in a container based on your rootfs
Add more edge cases
Don't map users when running as root
Add more explanation to the readme

clone

read-only
https://git.sr.ht/~martijnbraam/transact
read/write
git@git.sr.ht:~martijnbraam/transact

You can also use your local clone with git send-email.

#Transact

This utility uses the userns feature of the kernel in combination with overlayfs to run commands in a temporary container with your current filesystem as the starting contents. After running the commands in this container you get the choice to apply or throw away the changes made.

#Example

An example session showing the contents of the starting directory. Removing the codebase stored in this directory and adding a new file. After exiting the shell spawned by transact the changes are shown and in this example ignored.

~/P/P/transact ❯❯❯ ls
transact  transact.egg-info  README.md  setup.py
~/P/P/transact ❯❯❯ transact
(transact) ~/P/P/transact # ❯❯❯ ls
transact  transact.egg-info  README.md  setup.py
(transact) ~/P/P/transact # ❯❯❯ rm -rf transact
(transact) ~/P/P/transact # ❯❯❯ touch example
(transact) ~/P/P/transact # ❯❯❯ ls
transact.egg-info  README.md  example  setup.py
(transact) ~/P/P/transact # ❯❯❯ exit
M /home/martijn/.zhistory
D /home/martijn/Projects/Python/transact/transact
A /home/martijn/Projects/Python/transact/example
Do you want to commit these changes? [y/N] n
~/P/P/transact ❯❯❯ ls
transact  transact.egg-info  README.md  setup.py

#Acknowledgements

This project is inspired by https://github.com/binpash/try

The major differences are that this is written in Python and this allocates a PTY for the shell. This also launches a shell instead of running only one command.

#How does it work?

I used the way try works as my starting point, the steps this tool goes through are roughly:

  • Allocate a PTY to run the new shell in
  • Run unshare to create a sandbox namespace that isolates the mounts, uid/gid and pids from the main system
  • Create a scratch directory in the XDG_CACHE_HOME and create empty directories for all the dirs in /
  • Use overlayfs to create overlay mounts for the whole rootfs inside this temporary directory
  • Set-up the special mounts again (/dev, /proc, /sys, /tmp, /run) in this fake rootfs
  • Nest another instance of unshare that contrains the system to this fake rootfs
  • Launch the shell with a modified environment to inject the modified prompt through a fake rcfile

Now you're in a fake shell with root permissions that looks like your normal system but any modifications to the filesystem are written to the upper layer of the overlayfs instead. After exiting the shell both the unshare instances will be torn down and the contents of the scratch space is analyzed.

The diff is generated by comparing the files from the upper directory with the actual root filesystem with the option to commit those changes.

#Edge cases

Just like try this is far from a security sandbox. Don't use this to run untrusted binaries. Only mountpoints and basic filesystem sandboxing is done here and it assumes whatever is run inside the sandbox isn't actively trying to break the sandbox. Some of examples of the holes are:

  • Lack of network seperation
  • Access to /sys and /dev

Beside the security considerations there's also more limitations to this sandbox:

  • Not all upper and lower filesystems are supported by overlayfs. This means that for example a fat32 mountpoint won't be visible.
  • Inside the fakeroot you can make changes that normally would require root permissions on the host system. These can't be committed unless the whole transact command runs with superuser privileges.
  • No tmpfs is supported by overlayfs so any changes to any tmpfs-like mountpoint are not committed. /tmp is a seperate tmpfs from the host one.
  • For ZSH and Bash there's special handleing to add (transact) to the prompt. This is not supported on any other shell at the moment
  • Writing to raw block devices is not sandboxed, don't think running the grub installer is safe in this.
  • When running as a regular user the root user inside the sandbox still can't see files your regular user can't see. This will break applications that need to access privileged applications.