[HOME] [DOWNLOAD] [DOCS] [NEWS] [SUPPORT] [TIPS] [ISSUES] [CONTRIBUTE] [DONATE]

Whonix live mode / amnesia / amnesic / non-persistent / anti-forensics

Ok the issue was the pipe see here: http://www.linuxprogrammingblog.com/pipe-in-bash-can-be-a-trap
Below script now works. If there are no further issues I will try to build the deb package and see how it behaves. If all goes well I’ll update the package on github and the wiki page.

#!/bin/sh

set -e

case "${1}" in
        prereqs)
                exit 0
                ;;
esac

output() {
   echo "live boot test: $@"
}

## based on Stéphane Chazelas answer
## https://unix.stackexchange.com/a/417188
parse_mount_options() {
   set -o noglob # disable glob part
   IFS=","       # split on colon
   set -- $1     # split+glob
   first="$1"
   if [ "$first" = "rw" ]; then
      output "Read-write disk detected. Assuming persistent mode."
      read_write=true
   elif [ "$first" = "ro" ]; then
      output "Read-only disk detected. Assuming live mode."
      read_write=false
   else
      output "Write mode detection failed."
      read_write=error
   fi
}

## Taken from os-prober /usr/share/os-prober/common.sh and modified.
parse_proc_mounts () {
	while read -r line; do
		set -f
		set -- $line
		set +f
		true "line: $line"
		path="$1"
		mount_point="$2"
		file_system="$3"
		mount_options="$4"
		if [ "$mount_point" = "/livetest" ]; then
         parse_mount_options "$mount_options"
         return 0
      fi
	done < /proc/mounts
}

live_boot_test() {
   output "Testing for live boot."

   if [ ! -x /usr/bin/systemd-detect-virt ]; then
      output "systemd-detect-virt is missing."
      read_write=error
      return 0
   fi

   mkdir -p /livetest
   mount -t ext4 -n -o rw $ROOT /livetest

   parse_proc_mounts

   if ! umount /livetest ; then
      output "Unmounting the root disk failed."
      read_write=error
   fi

   if [ -n "$(cat /proc/mounts | grep "/livetest")" ]; then
      output "Root disk still mounted after umount."
      read_write=error
   fi
}

live_boot() {
   if [ -n "$(systemd-detect-virt | grep -i "qemu")" ]; then
      output "Detected KVM."
      echo 'live_disk=$(blkid /dev/vda1 -o value -s UUID)' >> /scripts/local
   elif [ -n "$(systemd-detect-virt | grep -i "oracle")" ]; then
      output "Detected VirtualBox."
      echo 'live_disk=$(blkid /dev/sda1 -o value -s UUID)' >> /scripts/local
   else
      output "Neither VirtualBox nor KVM detected."
      ## Don't live boot.
      return 0
   fi

   echo "BOOT=live" >> /scripts/local
   echo 'LIVE_BOOT_CMDLINE="root=/dev/disk/by-uuid/$live_disk boot=live ip=frommedia plainroot union=overlay"' >> /scripts/local

   exit 0
}

true "Setting fallback read_write=error."
read_write=error

live_boot_test

if [ "$read_write" = "error" ]; then
   output "Contents of /proc/mounts:"
   cat /proc/mounts
   ## TODO: Should we exit 0 here or is non-zero more appropriate?
   exit 0
fi

if [ "$read_write" = "false" ]; then
   live_boot
fi

output "Proceeding persistent boot."

exit 0
1 Like

Is it possible to use bash inside initramfs? I would very much like to add an error handling trap.

Perhaps leave https://github.com/Whonix/grub-live as is? I think it’s a really cool implementation.

The project name grub-live no longer applies since it’s now initramfs based. Perhaps a new package? How to call it…? initramfs-live? Or better perhaps we can find a generic name that is independent from the implementation tails grub vs initramfs based? This is only useful inside virtual machines and doesn’t look like it will be useful on bare metal? That may influence naming. I guess this could be interesting for bare metal for disks which have a physical (or BIOS / firmware) read-only on/off switch.

1 Like

A few ideas…

  • read-only-live-boot
  • live-boot-auto-detection
  • live-boot-auto-detector
  • live-boot-detector

Could you please discuss this with upstream / try to upstream this?

What would be a good place to upstream this? A few ideas:

ephemeral-mode?

Actually since you want a more descript name, why not ro-mode-init?

Certainly not impossible, but would at least require an initramfs hook. However, I’d stick to what it is in there by default. Every other script in there also uses those programs.

I can do that. We need another name anyway. ro-mode-init would give a nice abbreviation, romi.

You could maybe use a fallback option for systemd-detect-virt in case it does not detect a hypervisor to automatically assume bare metal. Or you get rid of it at all. You could always parse the underlying stuff directly from /proc or /sys which more or less each virtualization detection tool does and virt-what even suggests in the man page. More recent versions of the kernel can see very early in the boot process if the disk is write protected which could maye also be used instead. It is under /sys/block/vda/ro or similar path depending on the disk driver.
I can try to contact upstream, though in its current form it is using some rather hacky workarounds to actually not need to change the upstream packages :wink: and is basically an end-user friendly version of adding “plainroot …” to the boot options. It makes some assumptions which are rather Whonix-specific and always relies on user interaction on the host to work as intended.

2 Likes

Algernon:

Certainly not impossible, but would at least require an initramfs hook. However, I’d stick to what it is in there by default. Every other script in there also uses those programs.

Ok.

You could maybe use a fallback option for systemd-detect-virt in case it does not detect a hypervisor to automatically assume bare metal.

Ok. But how would you figure out the root disk? Read it from kernel options?

Or you get rid of it at all

How? Read it from kernel options? Why do we have to detect it by detecting the virtualizer anyhow? How would the system figure it out by itself later on? Can we use the same mechanism?

You could always parse the underlying stuff directly from /proc or /sys which more or less each virtualization detection tool does and virt-what even suggests in the man page.

Sure.

More recent versions of the kernel can see very early in the boot process if the disk is write protected which could maye also be used instead. It is under /sys/block/vda/ro or similar path depending on the disk driver.

I like that much more than mounting and parsing /proc/mounts. Seems the much more appropriate way than custom parsing code.

I can try to contact upstream,

Yes, please! I am curious what they say. They might have some good comments.

Yes.

I think the system uses whatever it sees defined as “root=” on the kernel commandline. If you make sure that the first disk is always the root disk with Whonix on it that you want to boot then this should also work. A non standard disk setup is probably an edge case. I’m going to test it in combination with /sys/block/*da/ro.

2 Likes

New script with check by the kernel if the disk is ro or rw. Works on KVM and VirtualBox.

#!/bin/sh

set -e

case "${1}" in
        prereqs)
                exit 0
                ;;
esac

output() {
   echo "live boot test: $@"
}

ro_test() {
   output "Testing for live boot."
   
   root_uuid=$(echo $ROOT | sed 's/.*=//')
   root_disk=$(blkid -U $root_uuid | sed 's/1//' | sed 's#/dev/##')
   ro_check=$(cat /sys/block/$root_disk/ro)

   if [ "$ro_check" = "0" ]; then
      output "Read-write disk detected. Assuming persistent mode."
      read_write=true
   elif [ "$ro_check" = "1" ]; then
      output "Read-only disk detected. Assuming live mode."
      read_write=false
   else
      output "Write mode detection failed."
      read_write=error
   fi
}


live_boot() {
   echo "root_uuid=$root_uuid" >> /scripts/local
   echo "BOOT=live" >> /scripts/local
   echo 'LIVE_BOOT_CMDLINE="root=/dev/disk/by-uuid/$root_uuid boot=live ip=frommedia plainroot union=overlay"' >> /scripts/local
   exit 0
}

true "Setting fallback read_write=error."
read_write=error

ro_test

if [ "$read_write" = "error" ]; then
   output "Contents of /sys/block/<disk>/ro:"
   cat /sys/block/$root_disk/ro
   ## TODO: Should we exit 0 here or is non-zero more appropriate?
   exit 0
fi

if [ "$read_write" = "false" ]; then
   live_boot
fi

output "Proceeding persistent boot."

exit 0
1 Like

Looks much better! (Although still untested by me but I trust you test and this will work. I would upload package containing this and then let users install it since the code is easily reviewed to be non-malicious so this can be opened up for wide testing.)

Remaining nitpicks:

  • set -x’ if some debug (grub) kernel boot parameter is set
  • when if [ "$read_write" = "error" ]; then matches we should still output output "Proceeding persistent boot."?
  • in live_boot before the exit 0 please add output "Proceeding live boot."?
  • Please use shellcheck. It has some false positives but adding the double quotes for the variables should be applied.
1 Like

https://phabricator.whonix.org/T714#16398

https://github.com/Whonix/grub-live/pull/1

1 Like

Uploaded to all stretch repositories.

1 Like

persistent / love mode indicator systray - graphical indication on the desktop that system is running in live mode vs persistent mode
https://phabricator.whonix.org/T819

i am looking forward to playing with grub live mode. this may allow me to remove all the “immutible” configuration steps from the guide i work on. excellent work everyone.

Regarding https://github.com/Whonix/anon-meta-packages/pull/7
Meta package whonix-gateway-rpi… Nice. Why reference a lot of these packages individually such as console-setup? Can’t that be mostly meta packages for the most part?

I guess sdwdate-gui should not be a dependency of anon-shared-packages-dependencies. That can be considered a bug. Let’s move it to anon-shared-packages-recommended? Does that help?

I mean, if we have bugs there, I much rather do the short-term more effort proper bug fix way.

https://www.whonix.org/wiki/Whonix_Live is too confusing. First users can pick:

Then for VirtualBox users can pick:

ro-mode-init method must be combined with read-only Method, otherwise:

it will always boot into persistent mode.

Too many combinations. Not all combinations are safe. Murphy’s law dictates that something will go wrong.

I guess the user only knows what platform they are using VirtualBox vs KVM and then likes to see one coherent block of instructions that has a safe result.

Maybe I am just confused by “For this option the VM disk needs to be set to read-only, otherwise it will always boot into persistent mode.” because you mean both read-only Method and Immutable Disk Method satisfy “needs to be set to read-only”?

Imho, the recommended way would be to use read-only disks combined with ro-mode-init. This would be most secure and would set up live mode automatically. The problem is when a user forgets to set the disks to read only, in this case it would automatically boot into persistent mode. The other options, however, also require some kind of user interaction.

2 Likes

https://www.whonix.org/wiki/Whonix_Live made great progress! However, it shouldn’t list alternative methods actual steps. In my experience this mostly confuses users.

Also Follow the procedures above depending on your hypervisor is hard to follow for users including myself. Usability is about reducing complexity and mental workload. “Consciousness is a low RAM environment.”

Therefore split now:

That allowed to replace the mouthful

Recommended VirtualBox Configuration with a more standarized, easier VirtualBox.

Could you please make the following instructions standalone, i.e. not having these require to apply steps from * https://www.whonix.org/wiki/Whonix_Live?

Perhaps by putting the shared bits of instructions into wiki templates?

Added advantage, if we had wiki templates we could even add this to https://www.whonix.org/wiki/VirtualBox and/or https://www.whonix.org/wiki/KVM or so.

I consider all of above details. After my today’s edits https://www.whonix.org/wiki/Whonix_Live is now ready for wider publication since instruction are non-ambiguous, straight forward.

Thanks, also to the other editors like @torjunkie and @0brand. It is always a difference when someone else who did not already test the setup dozens of times and where everything seems to be logic and straightforward, takes a look. I’m going to add the respective instructions to the two other wiki pages. Where can I read more about wiki templates?

3 Likes

A post was split to a new topic: How to use Wiki Templates?

[Imprint] [Privacy Policy] [Cookie Policy] [Terms of Use] [E-Sign Consent] [DMCA] [Contributors] [Investors] [Priority Support] [Professional Support]