Grub-bhyve has access to the host filesystem through the '(host)' pseudofs. Considering that the typical Linux guest would have its grub configuration on its boot partition (as the handbook suggests: https://www.freebsd.org/doc/handbook/virtualization-host-bhyve.html) this means that having root permissions on the guest allows you to access the host filesystem on the next VM boot, for example:
* Add "source (host)/root/secret.txt" to the head of grub.cfg
* Add "myvalue=$password" to the kernel command line
* Shut down VM
* On the host: "echo password=verysecret12345 > /root/secret.txt"
* Launch VM
$ cat /proc/cmdline
console=ttyS0 BOOT_IMAGE=/boot/vmlinuz-4.4.0-75-generic root=UUID=e757cf85-936a-4fe8-b099-54046961756d ro myvalue=verysecret12345
As you can see this might be a critical information leak in certain circumstances, especially because you have to (?) run grub-bhyve as root on the host system.
Perhaps an option could be added to chroot the bootloader once it is done loading libraries and opening image/disk files? Module loading is disabled so the filesystem appears to be the only remaining attack surface.
Hmm, bhyveload doesn't provide a host filesystem by default unless it is enabled via a command line argument and the argument gives a subdirectory that all requests are made within. (There's no prevision for escaping the subdirectory via .. symlinks though IIRC.) I haven't looked at grub2-bhyve, but it seems like it should similarly only enable (host) if specifically configured by the user and not by default.
The change proposed in https://github.com/grehan-freebsd/grub2-bhyve/pull/12 limits filesystem access to that available as user 'nobody' rather than 'root'. I like John's proposal as well.
bhyveload(1) uses the '-h hostdir' flag for this. This is similar to '-r host -d hostdir' in grub-bhyve syntax; however, '-r host' is the default in grub-bhyve.
'-h' is available in grub-bhyve, but I would avoid using it for anything other than '--help'.
We could treat explicit '-r host' similar to explicit '-h hostdir' in grub-bhyve. That is, do not allow host filesystem access _at all_ unless '-r host' was specifically provided as a parameter. This would retain compatibility with vm-bhyve's use of '-r host', while denying host filesystem access by default.
Thoughts? I'll propose a patch via github eventually but I view this as orthogonal to the privdrop proposal above, and will wait until that is resolved.
I think requiring -r host explicitly makes sense
The github PR has been merged, so (host) is now read-only and access limited to the unprivileged 'nobody' user. That (?)might be sufficient to resolve this bug as-reported, since most secrets will not be readable by user 'nobody'. That said, the guest should not have arbitrary 'nobody'-level read access to the host filesystem anyway, so it's still a privilege escalation that needs fixed.
Adding chroot()+chdir() (both are essential!) in the non-'-r host' case is pretty trivial, if someone wants to tackle that. I can help provide pointers but I think I'm done with grub-bhyve work myself for the time being.
Send me your pointers: I'll try and get that done.
(In reply to Peter Grehan from comment #6)
Apologies, somehow I missed this folow-up.
I think with our pre-opened fd cache, we can just chdir("/var/empty") and chroot(".") in grub_emu_bhyve_post_init() (or cap_enter() on Capsicum systems). We're already doing (host) access via fd-relative opens, I think.
I'm not sure why I didn't add that additional step back in March! It shouldn't impact much desired functionality and would complete the sandbox.
Worth mentioning there's a few more Grub cfg-running related vulnerabilities described recently here: https://eclypsium.com/2020/07/29/theres-a-hole-in-the-boot/ . The top-level lexing one likely impacts us.