Bug 231480

Summary: sysutils/grub2-bhyve: "(host)" filesystem is a potential security issue
Product: Ports & Packages Reporter: noah.bergbauer
Component: Individual Port(s)Assignee: freebsd-ports-bugs (Nobody) <ports-bugs>
Status: New ---    
Severity: Affects Only Me CC: emaste, grehan, jhb
Priority: ---    
Version: Latest   
Hardware: Any   
OS: Any   

Description noah.bergbauer 2018-09-19 14:55:41 UTC
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.
Comment 1 John Baldwin freebsd_committer freebsd_triage 2019-12-10 19:13:52 UTC
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.
Comment 2 Conrad Meyer freebsd_committer 2020-02-02 23:27:38 UTC
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.
Comment 3 Conrad Meyer freebsd_committer 2020-02-15 21:41:04 UTC
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.
Comment 4 John Baldwin freebsd_committer freebsd_triage 2020-03-19 22:57:56 UTC
I think requiring -r host explicitly makes sense
Comment 5 Conrad Meyer freebsd_committer 2020-03-30 23:45:25 UTC
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.
Comment 6 Peter Grehan freebsd_committer 2020-03-31 00:27:03 UTC
Send me your pointers: I'll try and get that done.
Comment 7 Conrad Meyer freebsd_committer 2020-07-30 15:47:36 UTC
(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.