There is another, more serious, problem. Xen virtual network devices are implemented as a client (“netfront”) and a server (“netback”), which are Linux kernel modules in sys-firewall. In a traditional Xen system, the netback driver runs in dom0 and is fully trusted. It is coded to protect itself against misbehaving client VMs. Netfront, by contrast, assumes that netback is trustworthy. The Xen developers only considers bugs in netback to be security critical.
In Qubes, NetVM acts as netback to FirewallVM, which acts as a netback in turn to its clients. But in Qubes, NetVM is supposed to be untrusted! So, we have code running in kernel mode in the (trusted) FirewallVM that is talking to and trusting the (untrusted) NetVM!
For example, as the Qubes developers point out in Qubes Security Bulletin #23, the netfront code that processes responses from netback uses the request ID quoted by netback as an index into an array without even checking if it’s in range (they have fixed this in their fork).
What can an attacker do once they’ve exploited FirewallVM’s trusting netfront driver? Presumably they now have complete control of FirewallVM. At this point, they can simply reuse the same exploit to take control of the client VMs, which are running the same trusting netfront code!
This sounds serious. Is that still true/accurate today? Has it been discussed within the community?
Also, I wonder about the reason why mirage-firewall hasn’t been included in the community templates so far. It seems popular among the community. I found a couple of old threads about including it but it seems QubesOS’ staff ignored them. (correct me if I’m wrong)
Well, I understand that the part quoted was one of the motivations for the creation of qubes-mirage-firewall. The security bulletin is from 2015 and talks about PV drivers, I suppose the situation to be already fixed now
Regarding the template, I think the Qubes team doesn’t have enough time to audit the mirageOS code so far, which slows down the integration process.
Another thing to keep in mind is that, although I don’t currently see bandwidth issues with mirage-firewall for daily network tasks (even for video meetings, the firewall CPU isn’t at 100%), mirageOS currently lacks TCP Segmentation Offload, which shows lower maximum bandwidth compared to Linux (with TSO enabled, see Slower bandwidth compared to sys-firewall · Issue #130 · mirage/qubes-mirage-firewall · GitHub) when you need a flow between IPsrc:portsrc ↔ IPdst:portdst. Unfortunately, this scenario is often used in speed comparison tests.
I have packaged the new release, available from Simple Setup, so you can
get the mirage firewall up and running by installing a package in to
dom0.
If you are already using mirage from this source, then a dom0 update will
pull in the new release.
I never presume to speak for the Qubes team.
When I comment in the Forum I speak for myself.
Since updating to this version I cannot use qvm-firewall with explicit domain names in firewall rules anymore. IP addresses are fine. Therefore this appears to be DNS related. The previous release is still fine. Can anybody reproduce this?
Oh yes now that netvm can be dynamically updated the DNS resolver code can be broken (i.e is not updated too).
I’ll try to fix that soon and cut a new release.
Thank you for the issue report!
Just in case, would you mind to test a branch on my repository: GitHub - palainp/qubes-mirage-firewall at fix-dns?
I suppose the easiest way is to clone, install podman and run ./build-with.sh podman, then upload the unikernel to dom0. My hashsum is 54b5bbf5bb8df7496fd0e04e98660b796164d339ac48121ab75eb7f35241502f.
I succesfully added dns rules to an AppVM and if it works for you too, this will be added for a soon release
This was quick! I’m perfectly fine with testing however I have not build the mirage-fw myself before. I tried it in a fedora-39 dvm with podman and followed the instructions from the READ.md but I encountered an error:
<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><>
-> installed base-bigarray.base
-> installed base-threads.base
-> installed base-unix.base
-> installed ocaml-options-vanilla.1
-> retrieved ocaml-base-compiler.4.14.1 (https://github.com/ocaml/ocaml/archive/4.14.1.tar.gz)
[ERROR] The compilation of ocaml-base-compiler.4.14.1 failed at "make -j1".
#=== ERROR while compiling ocaml-base-compiler.4.14.1 =========================#
# context 2.1.5 | linux/x86_64 | | git+https://github.com/ocaml/opam-repository.git#4399f486aa6edefdc96d5e206a65ce42288ebfdd
# path /tmp/myswitch/.opam-switch/build/ocaml-base-compiler.4.14.1
# command /usr/bin/make -j1
# exit-code 2
# env-file /tmp/log/ocaml-base-compiler-2-538a76.env
# output-file /tmp/log/ocaml-base-compiler-2-538a76.out
### output ###
# [...]
# ../boot/ocamlrun ../boot/ocamlc -g -nostdlib -I ../boot -use-prims ../runtime/primitives -I .. -I ../utils -I ../parsing -I ../typing -I ../bytecomp -I ../middle_end -I ../middle_end/closure -I ../middle_end/flambda -I ../middle_end/flambda/base_types -I ../driver -I ../toplevel -I ../file_formats -I ../lambda -I .. -o stripdebug ../compilerlibs/ocamlcommon.cma ../compilerlibs/ocamlbytecomp.c[...]
# File "_none_", line 1:
# Error: I/O error: No space left on device
# make[4]: *** [Makefile:63: stripdebug] Error 2
# make[4]: Leaving directory '/tmp/myswitch/.opam-switch/build/ocaml-base-compiler.4.14.1/tools'
# make[3]: *** [Makefile:1022: ocamltools] Error 2
# make[3]: Leaving directory '/tmp/myswitch/.opam-switch/build/ocaml-base-compiler.4.14.1'
# make[2]: *** [Makefile:187: coreall] Error 2
# make[2]: Leaving directory '/tmp/myswitch/.opam-switch/build/ocaml-base-compiler.4.14.1'
# make[1]: *** [Makefile:247: opt.opt] Error 2
# make[1]: Leaving directory '/tmp/myswitch/.opam-switch/build/ocaml-base-compiler.4.14.1'
# make: *** [Makefile:312: world.opt] Error 2
<><> Error report <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
+- The following actions failed
| - build ocaml-base-compiler 4.14.1
+-
+- The following changes have been performed (the rest was aborted)
| - install base-bigarray base
| - install base-threads base
| - install base-unix base
| - install ocaml-options-vanilla 1
+-
# Run eval $(opam env --switch=myswitch) to update the current shell environment
Switch initialisation failed: clean up? ('n' will leave the switch partially installed) [Y/n] y
Error: building at STEP "RUN opam switch create myswitch 4.14.1": while running runtime: exit status 31