Markdown formatting fixes

- mark all code blocks with ```
- unify empty lines between sections
- adjust list syntax (no space before dash)
- adjust headers to use Atx-style syntax
- remove trailing spaces
This commit is contained in:
Maya 2021-03-13 18:03:23 +01:00 committed by Marek Marczykowski-Górecki
parent 2bde7d07e0
commit 67a92614aa
No known key found for this signature in database
GPG key ID: F32894BE9684938A
148 changed files with 4025 additions and 3639 deletions

View file

@ -18,25 +18,23 @@ Qubes implements a Security by Isolation approach. To do this, Qubes utilizes vi
Qubes lets the user define many security domains, which are implemented as lightweight Virtual Machines (VMs), or “AppVMs.” For example, the user can have “personal,” “work,” “shopping,” “bank,” and “random” AppVMs and can use the applications within those VMs just as if they were executing on the local machine. At the same time, however, these applications are well isolated from each other. Qubes also supports secure copy-and-paste and file sharing between the AppVMs, of course.
Key Architecture features
-------------------------
- Based on a secure bare-metal hypervisor (Xen)
- Networking code sand-boxed in an unprivileged VM (using IOMMU/VT-d)
- USB stacks and drivers sand-boxed in an unprivileged VM (currently experimental feature)
- No networking code in the privileged domain (dom0)
- All user applications run in “AppVMs,” lightweight VMs based on Linux
- Centralized updates of all AppVMs based on the same template
- Qubes GUI virtualization presents applications as if they were running locally
- Qubes GUI provides isolation between apps sharing the same desktop
- Secure system boot based (optional)
- Based on a secure bare-metal hypervisor (Xen)
- Networking code sand-boxed in an unprivileged VM (using IOMMU/VT-d)
- USB stacks and drivers sand-boxed in an unprivileged VM (currently experimental feature)
- No networking code in the privileged domain (dom0)
- All user applications run in “AppVMs,” lightweight VMs based on Linux
- Centralized updates of all AppVMs based on the same template
- Qubes GUI virtualization presents applications as if they were running locally
- Qubes GUI provides isolation between apps sharing the same desktop
- Secure system boot based (optional)
(For those interested in the history of the project, [Architecture Spec v0.3 [PDF]](/attachment/wiki/QubesArchitecture/arch-spec-0.3.pdf) is the original 2009 document that started this all.
Please note that this document is for historical interest only.
For the latest information, please see the rest of the [System Documentation](/doc/#system).)
Qubes Core Stack
----------------
@ -45,26 +43,26 @@ the glue that connects all the other components together, and which allows users
and admins to interact with and configure the system. The other components of
the Qubes system include:
- VM-located core agents (implementing e.g. qrexec endpoints used by various
Qubes services)
- VM-customizations (making the VMs lightweight and working well with seamless
GUI virtualization)
- Qubes GUI virtualization (the protocol, VM-located agents, and daemons
located in the GUI domain which, for now, happens to be the same as dom0),
- GUI domain customizations (Desktop Environment customizations, decoration
coloring plugin, etc)
- The AdminVM distribution (various customizations, special services, such as
for receiving and verifying updates, in the future: custom distro)
- The Xen hypervisor (with a bunch of customization patches, occasional
hardening) or - in the future - some other virtualising or containerizing
software or technology
- Multiple "Qubes Apps" (various services built on top of Qubes qrexec
infrastructure, such as: trusted PDF and Image converters, Split GPG, safe
USB proxies for HID devices, USB proxy for offering USB devices (exposed via
qvm-usb), Yubikey support, USB Armory support, etc)
- Various ready-to-use templates (e.g. Debian-, Whonix-based), which are used
to create actual VMs, i.e. provide the root filesystem to the VMs
- Salt Stack integration
- VM-located core agents (implementing e.g. qrexec endpoints used by various
Qubes services)
- VM-customizations (making the VMs lightweight and working well with seamless
GUI virtualization)
- Qubes GUI virtualization (the protocol, VM-located agents, and daemons
located in the GUI domain which, for now, happens to be the same as dom0),
- GUI domain customizations (Desktop Environment customizations, decoration
coloring plugin, etc)
- The AdminVM distribution (various customizations, special services, such as
for receiving and verifying updates, in the future: custom distro)
- The Xen hypervisor (with a bunch of customization patches, occasional
hardening) or - in the future - some other virtualising or containerizing
software or technology
- Multiple "Qubes Apps" (various services built on top of Qubes qrexec
infrastructure, such as: trusted PDF and Image converters, Split GPG, safe
USB proxies for HID devices, USB proxy for offering USB devices (exposed via
qvm-usb), Yubikey support, USB Armory support, etc)
- Various ready-to-use templates (e.g. Debian-, Whonix-based), which are used
to create actual VMs, i.e. provide the root filesystem to the VMs
- Salt Stack integration
And all these components are "glued together" by the Qubes Core Stack.

View file

@ -10,8 +10,8 @@ Audio Virtualization
VMs on Qubes OS have access to virtualized audio through the PulseAudio module.
It consists of two parts:
- `pacat-simple-vchan` running in a dom0/Audio VM (standalone application, one per VM, connected to the PulseAudio daemon)
- `module-vchan-sink` running in a VM (loaded into the PulseAudio process)
- `pacat-simple-vchan` running in a dom0/Audio VM (standalone application, one per VM, connected to the PulseAudio daemon)
- `module-vchan-sink` running in a VM (loaded into the PulseAudio process)
Protocol
--------
@ -33,10 +33,10 @@ Each such notification is a 4-byte number in little-endian format.
List of defined codes:
- `0x00010001` -- VM wants to receive audio input (some process is listening); prior to this message, `pacat-simple-vchan` will not send any audio samples to the VM.
- `0x00010000` -- VM does not want to receive audio input (no process is listening anymore); after this message, `pacat-simple-vchan` will not send any audio samples to the VM.
- `0x00020000` -- VM does not want to send audio output; informational for dom0, to avoid buffer under runs (may affect PulseAudio calculated delays).
- `0x00020001` -- VM does want to send audio output.
- `0x00010001` -- VM wants to receive audio input (some process is listening); prior to this message, `pacat-simple-vchan` will not send any audio samples to the VM.
- `0x00010000` -- VM does not want to receive audio input (no process is listening anymore); after this message, `pacat-simple-vchan` will not send any audio samples to the VM.
- `0x00020000` -- VM does not want to send audio output; informational for dom0, to avoid buffer under runs (may affect PulseAudio calculated delays).
- `0x00020001` -- VM does want to send audio output.
pacat-simple-vchan
------------------
@ -52,20 +52,19 @@ It needs to be both requested by the VM part and explicitly enabled in `pacat-si
The mechanism to do this differs between Qubes versions.
In Qubes before R4.1, `pacat-simple-vchan` is controlled over system D-Bus:
- destination: `org.qubesos.Audio.VMNAME` (where `VMNAME` is the VM's name)
- object path: `/org/qubesos/audio`
- interface: `org.qubesos.Audio`
- property: `RecAllowed` (which can be set using the `org.freedesktop.DBus.Properties` interface)
- destination: `org.qubesos.Audio.VMNAME` (where `VMNAME` is the VM's name)
- object path: `/org/qubesos/audio`
- interface: `org.qubesos.Audio`
- property: `RecAllowed` (which can be set using the `org.freedesktop.DBus.Properties` interface)
In Qubes R4.1 and later, `pacat-simple-vchan` is controlled over a UNIX socket at `/var/run/qubes/audio-control.VMNAME` (where `VMNAME` is the VM's name).
Supported commands:
- `audio-input 1\n` - enable audio input
- `audio-input 0\n` - disable audio input
- `audio-input 1\n` - enable audio input
- `audio-input 0\n` - disable audio input
These commands can be sent using the `qubes.AudioInputEnable+VMNAME` and `qubes.AudioInputDisable+VMNAME` qrexec services, respectively.
The current status is written into QubesDB at `/audio-input/VMNAME` (where `VMNAME` is the VM's name) with either `1` or `0` values.
The lack of a key means that the `pacat-simple-vchan` for a given VM is not running.
In either version, it is exposed to the user as device of class `mic`, which can be attached to a VM (for example, using the `qvm-device mic` command).

View file

@ -17,23 +17,23 @@ qubes_gui and qubes_guid processes
All AppVM X applications connect to local (running in AppVM) Xorg servers that use the following "hardware" drivers:
- *dummyqsb_drv* - video driver, that paints onto a framebuffer located in RAM, not connected to real hardware
- *qubes_drv* - it provides a virtual keyboard and mouse (in fact, more, see below)
- *dummyqsb_drv* - video driver, that paints onto a framebuffer located in RAM, not connected to real hardware
- *qubes_drv* - it provides a virtual keyboard and mouse (in fact, more, see below)
For each AppVM, there is a pair of *qubes_gui* (running in AppVM) and *qubes_guid* (running in dom0) processes connected over vchan.
For each AppVM, there is a pair of *qubes_gui* (running in AppVM) and *qubes_guid* (running in dom0) processes connected over vchan.
The main responsibilities of *qubes_gui* are:
- call XCompositeRedirectSubwindows on the root window, so that each window has its own composition buffer
- instruct the local Xorg server to notify it about window creation, configuration and damage events; pass information on these events to dom0
- receive information about keyboard and mouse events from dom0, tell *qubes_drv* to fake appropriate events
- receive information about window size/position change, apply them to the local window
- call XCompositeRedirectSubwindows on the root window, so that each window has its own composition buffer
- instruct the local Xorg server to notify it about window creation, configuration and damage events; pass information on these events to dom0
- receive information about keyboard and mouse events from dom0, tell *qubes_drv* to fake appropriate events
- receive information about window size/position change, apply them to the local window
The main responsibilities of *qubes_guid* are:
- create a window in dom0 whenever an information on window creation in AppVM is received from *qubes_gui*
- whenever the local window receives XEvent, pass information on it to AppVM (particularly, mouse and keyboard data)
- whenever AppVM signals damage event, tell local Xorg server to repaint a given window fragment
- receive information about window size/position change, apply them to the local window
- create a window in dom0 whenever an information on window creation in AppVM is received from *qubes_gui*
- whenever the local window receives XEvent, pass information on it to AppVM (particularly, mouse and keyboard data)
- whenever AppVM signals damage event, tell local Xorg server to repaint a given window fragment
- receive information about window size/position change, apply them to the local window
Note that keyboard and mouse events are passed to AppVM only if a window belonging to this AppVM has focus.
AppVM has no way to get information on keystrokes fed to other AppVMs (e.g. XTEST extension will report the status of local AppVM keyboard only) or synthesize and pass events to other AppVMs.
@ -41,30 +41,30 @@ AppVM has no way to get information on keystrokes fed to other AppVMs (e.g. XTES
Window content updates implementation
-------------------------------------
Typical remote desktop applications, like *vnc*, pass information on all changed window content in-band (say, over tcp).
As that channel has limited throughput, this impacts video performance.
Typical remote desktop applications, like *vnc*, pass information on all changed window content in-band (say, over tcp).
As that channel has limited throughput, this impacts video performance.
In the case of Qubes, *qubes_gui* does not transfer all changed pixels via vchan. Instead, for each window, upon its creation or size change, *qubes_gui*
- asks *qubes_drv* driver for the list of physical memory frames that hold the composition buffer of a window
- passes this information via `MFNDUMP` message to *qubes_guid* in dom0
- asks *qubes_drv* driver for the list of physical memory frames that hold the composition buffer of a window
- passes this information via `MFNDUMP` message to *qubes_guid* in dom0
Now, *qubes_guid* has to tell the dom0 Xorg server about the location of the buffer.
There is no supported way (e.g. Xorg extension) to do this zero-copy style.
Now, *qubes_guid* has to tell the dom0 Xorg server about the location of the buffer.
There is no supported way (e.g. Xorg extension) to do this zero-copy style.
The following method is used in Qubes:
- in dom0, the Xorg server is started with *LD_PRELOAD*-ed library named *shmoverride.so*. This library hooks all function calls related to shared memory.
- *qubes_guid* creates a shared memory segment, and then tells Xorg to attach it via *MIT-SHM* extension
- when Xorg tries to attach the segment (via glibc *shmat*) *shmoverride.so* intercepts this call and instead maps AppVM memory via *xc_map_foreign_pages*
- since then, we can use MIT-SHM functions, e.g. *XShmPutImage* to draw onto a dom0 window. *XShmPutImage* will paint with DRAM speed; actually, many drivers use DMA for this.
- in dom0, the Xorg server is started with *LD_PRELOAD*-ed library named *shmoverride.so*. This library hooks all function calls related to shared memory.
- *qubes_guid* creates a shared memory segment, and then tells Xorg to attach it via *MIT-SHM* extension
- when Xorg tries to attach the segment (via glibc *shmat*) *shmoverride.so* intercepts this call and instead maps AppVM memory via *xc_map_foreign_pages*
- since then, we can use MIT-SHM functions, e.g. *XShmPutImage* to draw onto a dom0 window. *XShmPutImage* will paint with DRAM speed; actually, many drivers use DMA for this.
The important detail is that *xc_map_foreign_pages* verifies that a given mfn range actually belongs to a given domain id (and the latter is provided by trusted *qubes_guid*).
The important detail is that *xc_map_foreign_pages* verifies that a given mfn range actually belongs to a given domain id (and the latter is provided by trusted *qubes_guid*).
Therefore, rogue AppVM cannot gain anything by passing crafted mnfs in the `MFNDUMP` message.
To sum up, this solution has the following benefits:
- window updates at DRAM speed
- no changes to Xorg code
- minimal size of the supporting code
- window updates at DRAM speed
- no changes to Xorg code
- minimal size of the supporting code
![gui.png](/attachment/wiki/GUIdocs/gui.png)
@ -78,14 +78,14 @@ In Qubes, a custom window decorator is used that paints a colourful frame (the c
Clipboard sharing implementation
--------------------------------
Certainly, it would be insecure to allow AppVM to read/write the clipboards of other AppVMs unconditionally.
Certainly, it would be insecure to allow AppVM to read/write the clipboards of other AppVMs unconditionally.
Therefore, the following mechanism is used:
- there is a "qubes clipboard" in dom0 - its contents are stored in a regular file in dom0.
- if the user wants to copy local AppVM clipboard to qubes clipboard, she must focus on any window belonging to this AppVM, and press **Ctrl-Shift-C**. This combination is trapped by *qubes-guid*, and `CLIPBOARD_REQ` message is sent to AppVM. *qubes-gui* responds with *CLIPBOARD_DATA* message followed by clipboard contents.
- the user focuses on other AppVM window, presses **Ctrl-Shift-V**. This combination is trapped by *qubes-guid*, and `CLIPBOARD_DATA` message followed by qubes clipboard contents is sent to AppVM; *qubes_gui* copies data to the local clipboard, and then user can paste its contents to local applications normally.
- there is a "qubes clipboard" in dom0 - its contents are stored in a regular file in dom0.
- if the user wants to copy local AppVM clipboard to qubes clipboard, she must focus on any window belonging to this AppVM, and press **Ctrl-Shift-C**. This combination is trapped by *qubes-guid*, and `CLIPBOARD_REQ` message is sent to AppVM. *qubes-gui* responds with *CLIPBOARD_DATA* message followed by clipboard contents.
- the user focuses on other AppVM window, presses **Ctrl-Shift-V**. This combination is trapped by *qubes-guid*, and `CLIPBOARD_DATA` message followed by qubes clipboard contents is sent to AppVM; *qubes_gui* copies data to the local clipboard, and then user can paste its contents to local applications normally.
This way, the user can quickly copy clipboards between AppVMs.
This way, the user can quickly copy clipboards between AppVMs.
This action is fully controlled by the user, it cannot be triggered/forced by any AppVM.
*qubes_gui* and *qubes_guid* code notes
@ -93,20 +93,20 @@ This action is fully controlled by the user, it cannot be triggered/forced by an
Both applications are structured similarly. They use *select* function to wait for any of these two event sources:
- messages from the local X server
- messages from the vchan connecting to the remote party
- messages from the local X server
- messages from the vchan connecting to the remote party
The XEvents are handled by the *handle_xevent_eventname* function, and messages are handled by *handle_messagename* function. One should be very careful when altering the actual *select* loop, because both XEvents and vchan messages are buffered, and *select* will not wake for each message.
If one changes the number/order/signature of messages, one should increase the *QUBES_GUID_PROTOCOL_VERSION* constant in *messages.h* include file.
*qubes_guid* writes debugging information to */var/log/qubes/qubes.domain_id.log* file; *qubes_gui* writes debugging information to */var/log/qubes/gui_agent.log*.
*qubes_guid* writes debugging information to */var/log/qubes/qubes.domain_id.log* file; *qubes_gui* writes debugging information to */var/log/qubes/gui_agent.log*.
Include these files when reporting a bug.
AppVM -> dom0 messages
-----------------------
Proper handling of the below messages is security-critical.
Proper handling of the below messages is security-critical.
Observe that beside two messages (`CLIPBOARD` and `MFNDUMP`) the rest have fixed size, so the parsing code can be small.
The *override_redirect* window attribute is explained at [Override Redirect Flag](https://tronche.com/gui/x/xlib/window/attributes/override-redirect.html). The *transient_for* attribute is explained at [Transient_for attribute](https://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR).
@ -115,8 +115,8 @@ Window manager hints and flags are described in the [Extended Window Manager Hin
Each message starts with the following header:
~~~
struct msghdr {
```c
struct msghdr {
uint32_t type;
uint32_t window;
/* This field is intended for use by gui_agents to skip unknown
@ -126,7 +126,7 @@ struct msghdr {
* whatever it wants! */
uint32_t untrusted_len;
};
~~~
```
This header is followed by message-specific data:
@ -164,9 +164,9 @@ struct msg_create {
<tr>
<td>MSG_MAP</td>
<td><pre>
struct msg_map_info {
uint32_t transient_for;
uint32_t override_redirect;
struct msg_map_info {
uint32_t transient_for;
uint32_t override_redirect;
};
</pre></td>
<td>Map a window with given parameters</td>
@ -179,12 +179,12 @@ struct msg_map_info {
<tr>
<td>MSG_CONFIGURE</td>
<td><pre>
struct msg_configure {
uint32_t x;
uint32_t y;
uint32_t width;
uint32_t height;
uint32_t override_redirect;
struct msg_configure {
uint32_t x;
uint32_t y;
uint32_t width;
uint32_t height;
uint32_t override_redirect;
};
</pre></td>
<td>Change window position/size/type</td>
@ -192,15 +192,15 @@ struct msg_configure {
<tr>
<td>MSG_MFNDUMP</td>
<td><pre>
struct shm_cmd {
uint32_t shmid;
uint32_t width;
uint32_t height;
uint32_t bpp;
uint32_t off;
uint32_t num_mfn;
uint32_t domid;
uint32_t mfns[0];
struct shm_cmd {
uint32_t shmid;
uint32_t width;
uint32_t height;
uint32_t bpp;
uint32_t off;
uint32_t num_mfn;
uint32_t domid;
uint32_t mfns[0];
};
</pre></td>
<td>Retrieve the array of mfns that constitute the composition buffer of a remote window.
@ -211,8 +211,8 @@ struct shm_cmd {
<tr>
<td>MSG_SHMIMAGE</td>
<td><pre>
struct msg_shmimage {
uint32_t x;
struct msg_shmimage {
uint32_t x;
uint32_t y;
uint32_t width;
uint32_t height;
@ -223,8 +223,8 @@ struct msg_shmimage {
<tr>
<td>MSG_WMNAME</td>
<td><pre>
struct msg_wmname {
char data[128];
struct msg_wmname {
char data[128];
};
</pre></td>
<td>Set the window name; only printable characters are allowed</td>
@ -237,16 +237,16 @@ struct msg_wmname {
<tr>
<td>MSG_WINDOW_HINTS</td>
<td><pre>
struct msg_window_hints {
uint32_t flags;
uint32_t min_width;
uint32_t min_height;
uint32_t max_width;
uint32_t max_height;
uint32_t width_inc;
uint32_t height_inc;
uint32_t base_width;
uint32_t base_height;
struct msg_window_hints {
uint32_t flags;
uint32_t min_width;
uint32_t min_height;
uint32_t max_width;
uint32_t max_height;
uint32_t width_inc;
uint32_t height_inc;
uint32_t base_width;
uint32_t base_height;
};
</pre> </td>
<td>Size hints for window manager</td>
@ -254,7 +254,7 @@ struct msg_window_hints {
<tr>
<td>MSG_WINDOW_FLAGS</td>
<td><pre>
struct msg_window_flags {
struct msg_window_flags {
uint32_t flags_set;
uint32_t flags_unset;
};
@ -279,12 +279,12 @@ Proper handling of the below messages is NOT security-critical.
Each message starts with the following header
~~~
struct msghdr {
```c
struct msghdr {
uint32_t type;
uint32_t window;
};
~~~
```
The header is followed by message-specific data:
@ -297,12 +297,12 @@ The header is followed by message-specific data:
<tr>
<td>MSG_KEYPRESS</td>
<td><pre>
struct msg_keypress {
uint32_t type;
uint32_t x;
uint32_t y;
uint32_t state;
uint32_t keycode;
struct msg_keypress {
uint32_t type;
uint32_t x;
uint32_t y;
uint32_t state;
uint32_t keycode;
};
</pre> </td>
<td>Tell *qubes_drv* driver to generate a keypress</td>
@ -310,12 +310,12 @@ struct msg_keypress {
<tr>
<td>MSG_BUTTON</td>
<td><pre>
struct msg_button {
uint32_t type;
uint32_t x;
uint32_t y;
uint32_t state;
uint32_t button;
struct msg_button {
uint32_t type;
uint32_t x;
uint32_t y;
uint32_t state;
uint32_t button;
};
</pre> </td>
<td>Tell *qubes_drv* driver to generate mouseclick</td>
@ -323,11 +323,11 @@ struct msg_button {
<tr>
<td>MSG_MOTION</td>
<td><pre>
struct msg_motion {
uint32_t x;
uint32_t y;
uint32_t state;
uint32_t is_hint;
struct msg_motion {
uint32_t x;
uint32_t y;
uint32_t state;
uint32_t is_hint;
};
</pre> </td>
<td>Tell *qubes_drv* driver to generate motion event</td>
@ -335,12 +335,12 @@ struct msg_motion {
<tr>
<td>MSG_CONFIGURE</td>
<td><pre>
struct msg_configure {
uint32_t x;
uint32_t y;
uint32_t width;
uint32_t height;
uint32_t override_redirect;
struct msg_configure {
uint32_t x;
uint32_t y;
uint32_t width;
uint32_t height;
uint32_t override_redirect;
};
</pre> </td>
<td>Change window position/size/type</td>
@ -348,9 +348,9 @@ struct msg_configure {
<tr>
<td>MSG_MAP</td>
<td><pre>
struct msg_map_info {
uint32_t transient_for;
uint32_t override_redirect;
struct msg_map_info {
uint32_t transient_for;
uint32_t override_redirect;
};
</pre> </td>
<td>Map a window with given parameters</td>
@ -363,14 +363,14 @@ struct msg_map_info {
<tr>
<td>MSG_CROSSING</td>
<td><pre>
struct msg_crossing {
uint32_t type;
uint32_t x;
uint32_t y;
uint32_t state;
uint32_t mode;
uint32_t detail;
uint32_t focus;
struct msg_crossing {
uint32_t type;
uint32_t x;
uint32_t y;
uint32_t state;
uint32_t mode;
uint32_t detail;
uint32_t focus;
};
</pre> </td>
<td>Notify window about enter/leave event</td>
@ -378,10 +378,10 @@ struct msg_crossing {
<tr>
<td>MSG_FOCUS</td>
<td><pre>
struct msg_focus {
uint32_t type;
uint32_t mode;
uint32_t detail;
struct msg_focus {
uint32_t type;
uint32_t mode;
uint32_t detail;
};
</pre> </td>
<td>Raise a window, XSetInputFocus</td>
@ -409,8 +409,8 @@ struct msg_focus {
<tr>
<td>MSG_WINDOW_FLAGS</td>
<td><pre>
struct msg_window_flags {
uint32_t flags_set;
struct msg_window_flags {
uint32_t flags_set;
uint32_t flags_unset;
};
</pre> </td>

View file

@ -9,18 +9,15 @@ redirect_from:
- /wiki/QubesNet/
---
VM network in Qubes
===================
# VM network in Qubes
Overall description
-------------------
## Overall description
In Qubes, the standard Xen networking is used, based on backend driver in the driver domain and frontend drivers in VMs. In order to eliminate layer 2 attacks originating from a compromised VM, routed networking is used instead of the default bridging of `vif` devices and NAT is applied at each network hop. The default *vif-route* script had some deficiencies (requires `eth0` device to be up, and sets some redundant iptables rules), therefore the custom *vif-route-qubes* script is used.
The IP address of `eth0` interface in AppVM, as well as two IP addresses to be used as nameservers (`DNS1` and `DNS2`), are passed via QubesDB to AppVM during its boot (thus, there is no need for DHCP daemon in the network driver domain). `DNS1` and `DNS2` are private addresses; whenever an interface is brought up in the network driver domain, the */usr/lib/qubes/qubes\_setup\_dnat\_to\_ns* script sets up the DNAT iptables rules translating `DNS1` and `DNS2` to the newly learned real dns servers. This way AppVM networking configuration does not need to be changed when configuration in the network driver domain changes (e.g. user switches to a different WLAN). Moreover, in the network driver domain, there is no DNS server either, and consequently there are no ports open to the VMs.
Routing tables examples
-----------------------
## Routing tables examples
VM routing table is simple:
@ -40,18 +37,21 @@ Network driver domain routing table is a bit longer:
|192.168.0.0|0.0.0.0|255.255.255.0|U|1|0|0|eth0|
|0.0.0.0|192.168.0.1|0.0.0.0|UG|0|0|0|eth0|
IPv6
----
## IPv6
Starting with Qubes 4.0, there is opt-in support for IPv6 forwarding. Similar to the IPv4, traffic is routed and NAT is applied at each network gateway. This way we avoid reconfiguring every connected qube whenever uplink connection is changed, and even telling the qube what that uplink is - which may be complex when VPN or other tunneling services are employed.
The feature can be enabled on any network-providing qube, and will be propagated down the network tree, so every qube connected to it will also have IPv6 enabled.
To enable the `ipv6` feature use `qvm-features` tool and set the value to `1`. For example to enable it on `sys-net`, execute in dom0:
```
qvm-features sys-net ipv6 1
```
It is also possible to explicitly disable IPv6 support for some qubes, even if it is connected to IPv6-providing one. This can be done by setting `ipv6` feature to empty value:
```
qvm-features ipv4-only-qube ipv6 ''
```
This configuration is presented below - green qubes have IPv6 access, red one does not.
@ -64,8 +64,7 @@ Such configuration can be expressed by enabling `ipv6` feature only on some subs
Besides enabling IPv6 forwarding, standard Qubes firewall can be used to limit what network resources are available to each qube. Currently only `qvm-firewall` command support adding IPv6 rules, GUI firewall editor will have this ability later.
### Limitations ###
### Limitations
Currently only IPv4 DNS servers are configured, regardless of `ipv6` feature state. It is done this way to avoid reconfiguring all connected qubes whenever IPv6 DNS becomes available or not. Configuring qubes to always use IPv6 DNS and only fallback to IPv4 may result in relatively long timeouts and poor usability.
But note that DNS using IPv4 does not prevent to return IPv6 addresses. In practice this is only a problem for IPv6-only networks.

View file

@ -21,20 +21,18 @@ The size of the current TCB is on the order order of hundreds of thousands of li
For more information, see [Qubes Security Goals].
Security-critical Qubes-specific Components
-------------------------------------------
The following code components are security-critical in Qubes OS:
- Dom0-side of the libvchan library
- Dom0-side of the GUI virtualization code (`qubes-guid`)
- Dom0-side of the sound virtualization code (`pacat-simple-vchan`)
- Dom0-side in qrexec-related code (`qrexec_daemon`)
- VM memory manager (`qmemman`) that runs in Dom0
- Select Qubes RPC servers that run in Dom0: `qubes.ReceiveUpdates` and `qubes.SyncAppMenus`
- The `qubes.Filecopy` RPC server that runs in a VM (critical because it could allow one VM to compromise another if the user allows a file copy operation to be performed between them)
- Dom0-side of the libvchan library
- Dom0-side of the GUI virtualization code (`qubes-guid`)
- Dom0-side of the sound virtualization code (`pacat-simple-vchan`)
- Dom0-side in qrexec-related code (`qrexec_daemon`)
- VM memory manager (`qmemman`) that runs in Dom0
- Select Qubes RPC servers that run in Dom0: `qubes.ReceiveUpdates` and `qubes.SyncAppMenus`
- The `qubes.Filecopy` RPC server that runs in a VM (critical because it could allow one VM to compromise another if the user allows a file copy operation to be performed between them)
Security-critical Third-party Components
----------------------------------------
@ -42,26 +40,24 @@ Security-critical Third-party Components
We did not create these components, but Qubes OS relies on them.
At the current stage of the project, we cannot afford to spend the time to thoroughly review and audit them, so we more or less "blindly" trust that they are secure.
- The Xen hypervisor
- Xen's xenstore backend running in Dom0
- Xen's block backend running in Dom0's kernel
- The RPM program used in Dom0 for verifying signatures on dom0 updates
- Somewhat trusted: log viewing software in dom0 that parses VM-influenced logs
- The Xen hypervisor
- Xen's xenstore backend running in Dom0
- Xen's block backend running in Dom0's kernel
- The RPM program used in Dom0 for verifying signatures on dom0 updates
- Somewhat trusted: log viewing software in dom0 that parses VM-influenced logs
Attacks on Networking Components
--------------------------------
Here are two examples of networking components that an adversary might seek to attack (or in which to exploit a vulnerability as part of an attack):
- Xen network PV frontends
- VMs' core networking stacks (core TCP/IP code)
- Xen network PV frontends
- VMs' core networking stacks (core TCP/IP code)
Hypothetically, an adversary could compromise a NetVM, `sys-net-1`, and try to use it to attack the VMs connected to that NetVM.
However, Qubes allows for the existence of more than one NetVM, so the adversary would not be able to use `sys-net-1` in order to attack VMs connected to a *different* NetVM, `sys-net-2` without also compromising `sys-net-2`.
In addition, the adversary would not be able to use `sys-net-1` (or, for that matter, `sys-net-2`) to attack VMs that have networking disabled (i.e., VMs that are not connected to any NetVM).
Buggy Code vs. Backdoored Code
------------------------------
@ -74,8 +70,6 @@ This means that we must trust at least some of the vendors that supply the code
In practice, we trust the software provided by the [Fedora Project].
This software is signed by Fedora distribution keys, so it is also critical that the tools used in domains for software updates (`dnf` and `rpm`) are trustworthy.
[Qubes Security Goals]: /security/goals/
[Fedora Project]: https://getfedora.org/
[Understanding and Preventing Data Leaks]: /doc/data-leaks/

View file

@ -32,7 +32,6 @@ When installed, the system has, as you can see from the contents of
default pool is special in R3.2. It will add `dir_path=/var/lib/qubes`
configuration value from `defaults[pool_config]`, if not overwritten.
Currently the only supported driver out of the box is `xen`. The benefit of
pools (besides that you can write your own storage driver e.g. for Btrfs) in R3.2
is that you can store your domains in multiple places.
@ -50,4 +49,4 @@ argument to `qvm-create` to have the VM images stored in pool `foo`. See also
`qvm-create --help`.
While the current API is not as clean and beautiful as the R4 API, it allows
you to write your own storage drivers e.g. for Btrfs today.
you to write your own storage drivers e.g. for Btrfs today.

View file

@ -8,59 +8,54 @@ redirect_from:
- /wiki/TemplateImplementation/
---
Overview of VM block devices
============================
# Overview of VM block devices
Every VM has 4 block devices connected:
- **xvda** base root device (/) details described below
- **xvdb** private.img place where VM always can write.
- **xvdc** volatile.img, discarded at each VM restart here is placed swap and temporal "/" modifications (see below)
- **xvdd** modules.img kernel modules and firmware
- **xvda** base root device (/) details described below
- **xvdb** private.img place where VM always can write.
- **xvdc** volatile.img, discarded at each VM restart here is placed swap and temporal "/" modifications (see below)
- **xvdd** modules.img kernel modules and firmware
private.img (xvdb)
------------------
## private.img (xvdb)
This is mounted as /rw and here is placed all VM private data. This includes:
- */home* which is bind mounted to /rw/home
- */usr/local* which is symlink to /rw/usrlocal
- some config files (/rw/config) called by qubes core scripts (ex /rw/config/rc.local)
- */home* which is bind mounted to /rw/home
- */usr/local* which is symlink to /rw/usrlocal
- some config files (/rw/config) called by qubes core scripts (ex /rw/config/rc.local)
**Note:** Whenever a TemplateBasedVM is created, the contents of the `/home` directory of its parent TemplateVM are copied to the child TemplateBasedVM's `/home`. From that point onward, the child TemplateBasedVM's `/home` is independent from its parent TemplateVM's `/home`, which means that any subsequent changes to the parent TemplateVM's `/home` will no longer affect the child TemplateBasedVM's `/home`. Once a TemplateBasedVM has been created, any changes in its `/home`, `/usr/local`, or `/rw/config` directories will be persistent across reboots, which means that any files stored there will still be available after restarting the TemplateBasedVM. No changes in any other directories in TemplateBasedVMs persist in this manner. If you would like to make changes in other directories which *do* persist in this manner, you must make those changes in the parent TemplateVM.
modules.img (xvdd)
------------------
## modules.img (xvdd)
As the kernel is chosen in dom0, there must be some way to provide matching kernel modules to VM. Qubes kernel directory consists of 3 files:
- *vmlinuz* actual kernel
- *initramfs* initial ramdisk containing script to setup snapshot devices (see below) and mount /lib/modules
- *modules.img* filesystem image of /lib/modules with matching kernel modules and firmware (/lib/firmware/updates is symlinked to /lib/modules/firmware)
- *vmlinuz* actual kernel
- *initramfs* initial ramdisk containing script to setup snapshot devices (see below) and mount /lib/modules
- *modules.img* filesystem image of /lib/modules with matching kernel modules and firmware (/lib/firmware/updates is symlinked to /lib/modules/firmware)
Normally kernel "package" is common for many VMs (can be set using qvm-prefs). One of them can be set as default (qvm-set-default-kernel) to simplify kernel updates (by default all VMs use the default kernel). All installed kernels are placed in /var/lib/qubes/vm-kernels as separate subdirs. In this case, modules.img is attached to the VM as R/O device.
There is a special case when the VM can have a custom kernel when it is updateable (StandaloneVM or TemplateVM) and the kernel is set to "none" (by qvm-prefs). In this case the VM uses the kernel from the "kernels" VM subdir and modules.img is attached as R/W device. FIXME: "none" should be renamed to "custom".
Qubes TemplateVM implementation
===============================
# Qubes TemplateVM implementation
TemplateVM has a shared root.img across all AppVMs that are based on it. This mechanism has some advantages over a simple common device connected to multiple VMs:
- root.img can be modified while there are AppVMs running without corrupting the filesystem
- multiple AppVMs that are using different versions of root.img (from various points in time) can be running concurrently
- root.img can be modified while there are AppVMs running without corrupting the filesystem
- multiple AppVMs that are using different versions of root.img (from various points in time) can be running concurrently
There are two layers of the device-mapper snapshot device; the first one enables modifying root.img without stopping the AppVMs and the second one, which is contained in the AppVM, enables temporal modifications to its filesystem. These modifications will be discarded after a restart of the AppVM.
![TemplateSharing2.png](/attachment/wiki/TemplateImplementation/TemplateSharing2.png)
Snapshot device in Dom0
-----------------------
## Snapshot device in Dom0
This device consists of:
- root.img real template filesystem
- root-cow.img differences between the device as seen by AppVM and the current root.img
- root.img real template filesystem
- root-cow.img differences between the device as seen by AppVM and the current root.img
The above is achieved through creating device-mapper snapshots for each version of root.img. When an AppVM is started, a xen hotplug script (/etc/xen/scripts/block-snapshot) reads the inode numbers of root.img and root-cow.img; these numbers are used as the snapshot device's name. When a device with the same name exists the new AppVM will use it therefore, AppVMs based on the same version of root.img will use the same device. Of course, the device-mapper cannot use the files directly it must be connected through /dev/loop\*. The same mechanism detects if there is a loop device associated with a file determined by the device and inode numbers or if creating a new loop device is necessary.
@ -82,31 +77,29 @@ This is done using snapshot-merge device-mapper target (available from 2.6.34 ke
Steps performed by **qvm-revert-template-changes**:
1. Ensure that no other VMs uses this template.
2. Prepare snapshot device with ***root-cow.img.old*** instead of *root-cow.img* (*/etc/xen/scripts/block-snapshot prepare*).
3. Replace *snapshot* device-mapper target with *snapshot-merge*, other parameters (chunk size etc) remains untouched. Now kernel starts merging changes stored in *root-cow.img.old* into *root.img*. d-m device can be used normally (if needed).
4. Waits for merge completed: *dmsetup status* shows used snapshot blocks it should be equal to metadata size when completed.
5. Replace *snapshot-merge* d-m target back to *snapshot*.
6. Cleanup snapshot device (if nobody uses it at the moment).
7. Move *root-cow.img.old* to *root-cow.img* (overriding existing file).
1. Ensure that no other VMs uses this template.
2. Prepare snapshot device with ***root-cow.img.old*** instead of *root-cow.img* (*/etc/xen/scripts/block-snapshot prepare*).
3. Replace *snapshot* device-mapper target with *snapshot-merge*, other parameters (chunk size etc) remains untouched. Now kernel starts merging changes stored in *root-cow.img.old* into *root.img*. d-m device can be used normally (if needed).
4. Waits for merge completed: *dmsetup status* shows used snapshot blocks it should be equal to metadata size when completed.
5. Replace *snapshot-merge* d-m target back to *snapshot*.
6. Cleanup snapshot device (if nobody uses it at the moment).
7. Move *root-cow.img.old* to *root-cow.img* (overriding existing file).
Snapshot device in AppVM
------------------------
## Snapshot device in AppVM
Root device is exposed to AppVM in read-only mode. AppVM can write only in:
- private.img persistent storage (mounted in /rw) used for /home, /usr/local in future versions, its use may be extended
- volatile.img temporary storage, which is discarded after an AppVM restart
- private.img persistent storage (mounted in /rw) used for /home, /usr/local in future versions, its use may be extended
- volatile.img temporary storage, which is discarded after an AppVM restart
volatile.img is divided into two partitions:
1. changes to root device
2. swap partition
1. changes to root device
2. swap partition
Inside of an AppVM, the root device is wrapped by the snapshot in the first partition of volatile.img. Therefore, the AppVM can write anything to its filesystem however, such changes will be discarded after a restart.
StandaloneVM
------------
## StandaloneVM
Standalone VM enables user to modify root filesystem persistently. It can be created using *--standalone* switch to *qvm-create*.