Convert to RST

This commit is contained in:
Marek Marczykowski-Górecki 2024-05-21 20:59:46 +02:00
parent b8f24e762e
commit b93b3c571e
No known key found for this signature in database
GPG key ID: F32894BE9684938A
412 changed files with 43831 additions and 28740 deletions

View file

@ -1,84 +0,0 @@
---
lang: en
layout: doc
permalink: /doc/architecture/
redirect_from:
- /doc/qubes-architecture/
- /en/doc/qubes-architecture/
- /doc/QubesArchitecture/
- /wiki/QubesArchitecture/
ref: 56
title: Architecture
---
Qubes implements a security-by-compartmentalization approach. To do this, Qubes
utilizes virtualization technology in order to isolate various programs from
each other and even to sandbox many system-level components, such as networking
and storage subsystems, so that the compromise of any of these programs or
components does not affect the integrity of the rest of the system.
[![qubes-schema-v2.png](/attachment/doc/qubes-schema-v2.png)](/attachment/doc/qubes-schema-v2.png)
Qubes lets the user define many secure compartments known as
[qubes](/doc/glossary/#qube), which are implemented as lightweight [virtual
machines (VMs)](/doc/glossary/#vm). For example, the user can have “personal,”
“work,” “shopping,” “bank,” and “random” app qubes and can use the applications
within those qubes 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 qubes, 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 “app qubes,” lightweight VMs based on Linux
- Centralized updates of all app qubes 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/doc/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
Qubes Core Stack is, as the name implies, the core component of Qubes OS. It's
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 admin qube 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.
[![Qubes system components](/attachment/doc/qubes-components.png)](/attachment/doc/qubes-components.png)
This diagram illustrates the location of all these components in the overall
system architecture. Unlike the other Qubes architecture diagram above, this
one takes an app-qube-centric approach.

View file

@ -0,0 +1,111 @@
============
Architecture
============
Qubes implements a security-by-compartmentalization approach. To do
this, Qubes utilizes virtualization technology in order to isolate
various programs from each other and even to sandbox many system-level
components, such as networking and storage subsystems, so that the
compromise of any of these programs or components does not affect the
integrity of the rest of the system.
|qubes-schema-v2.png|
Qubes lets the user define many secure compartments known as
:ref:`qubes <user/reference/glossary:qube>`, which are implemented as lightweight
:ref:`virtual machines (VMs) <user/reference/glossary:vm>`. For example, the user
can have “personal,” “work,” “shopping,” “bank,” and “random” app qubes
and can use the applications within those qubes 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 qubes, 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 “app qubes,” lightweight VMs based on
Linux
- Centralized updates of all app qubes 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] </_static/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 :ref:`System Documentation <index:system>`.)
Qubes Core Stack
----------------
Qubes Core Stack is, as the name implies, the core component of Qubes
OS. Its 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 admin qube 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.
|Qubes system components|
This diagram illustrates the location of all these components in the
overall system architecture. Unlike the other Qubes architecture diagram
above, this one takes an app-qube-centric approach.
.. |qubes-schema-v2.png| image:: /attachment/doc/qubes-schema-v2.png
.. |Qubes system components| image:: /attachment/doc/qubes-components.png

View file

@ -1,69 +0,0 @@
---
lang: en
layout: doc
permalink: /doc/audio-virtualization/
ref: 60
title: 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)
Protocol
--------
The protocol between these two parts is designed to be as simple as possible.
Specifically, there is no audio format negotiation, no compression, etc.
All the audio data is transferred as raw 44.1kHz samples in S16LE format, 2 channels.
These two parts are connected with two vchan links:
1. Connection on vchan port 4713 used to transfer audio from VM to dom0/Audio VM.
There is no negotiation, no headers, etc.
Only raw samples are sent over this channel.
2. Connection on vchan port 4714 used to transfer audio from dom0/Audio VM to VM.
Like the previous one, audio data is sent as raw samples.
Additionally, the second vchan connection (on port 4714) is used in the opposite direction (VM to dom0) to send simple notifications/commands about the audio state.
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.
pacat-simple-vchan
------------------
This is the dom0 (or Audio VM) part of the audio virtualization.
It is responsible for transferring audio samples between the PulseAudio daemon in dom0/Audio VM (which has access to the actual audio hardware) and a VM playing/recording sounds.
A separate `pacat-simple-vchan` process runs in dom0 for each VM with audio.
Each of them opens separate input and output streams to their local PulseAudio, which allows for controlling the volume of each VM separately (using the `pavucontrol` tool, for example).
In order to (re)create a stream for a VM in dom0, `pacat-simple-vchan` can be used. In order to find the needed parameters, domid and domain name, the command `xl list` can be used.
Audio input to the VM is not sent by default.
It needs to be both requested by the VM part and explicitly enabled in `pacat-simple-vchan`.
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)
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
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).

112
developer/system/audio.rst Normal file
View file

@ -0,0 +1,112 @@
====================
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)
Protocol
--------
The protocol between these two parts is designed to be as simple as
possible. Specifically, there is no audio format negotiation, no
compression, etc. All the audio data is transferred as raw 44.1kHz
samples in S16LE format, 2 channels.
These two parts are connected with two vchan links:
1. Connection on vchan port 4713 used to transfer audio from VM to
dom0/Audio VM. There is no negotiation, no headers, etc. Only raw
samples are sent over this channel.
2. Connection on vchan port 4714 used to transfer audio from dom0/Audio
VM to VM. Like the previous one, audio data is sent as raw samples.
Additionally, the second vchan connection (on port 4714) is used in the
opposite direction (VM to dom0) to send simple notifications/commands
about the audio state. 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.
pacat-simple-vchan
------------------
This is the dom0 (or Audio VM) part of the audio virtualization. It is
responsible for transferring audio samples between the PulseAudio daemon
in dom0/Audio VM (which has access to the actual audio hardware) and a
VM playing/recording sounds. A separate ``pacat-simple-vchan`` process
runs in dom0 for each VM with audio. Each of them opens separate input
and output streams to their local PulseAudio, which allows for
controlling the volume of each VM separately (using the ``pavucontrol``
tool, for example). In order to (re)create a stream for a VM in dom0,
``pacat-simple-vchan`` can be used. In order to find the needed
parameters, domid and domain name, the command ``xl list`` can be used.
Audio input to the VM is not sent by default. It needs to be both
requested by the VM part and explicitly enabled in
``pacat-simple-vchan``. 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
VMs 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 VMs name). Supported commands:
- ``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 VMs 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

@ -1,462 +0,0 @@
---
lang: en
layout: doc
permalink: /doc/gui/
redirect_from:
- /en/doc/gui/
- /en/doc/gui-docs/
- /doc/GUIdocs/
- /wiki/GUIdocs/
ref: 61
title: GUI virtualization
---
`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)
For each AppVM, there is a pair of `qubes-gui` (running in AppVM) and `qubes-guid` (running in the AppVMs GuiVM, dom0 by default) 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
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
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.
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.
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:
- Old `qubes-gui` versions will ask `qubes-drv` driver for the list of
physical memory frames that hold the composition buffer of a window,
and pass this to dom0 via the deprecated `MFNDUMP` message.
- New `qubes-gui` versions will rely on `qubes-drv` having allocated
memory using gntalloc, and then pass the grant table indexes gntalloc
has chosen to the GUI daemon using the `WINDOW_DUMP` message.
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` for the deprecated `MFNDUMP` message, or `xengnttab_map_domain_grant_refs` for the `WINDOW_DUMP` message.
- afterwards, we can use MIT-SHM functions, such as `XShmPutImage`, to draw onto a dom0 window. `XShmPutImage` will paint with DRAM speed, and many drivers use DMA to make this even faster.
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. Similarly, `xengnttab_map_domain_grant_refs` will only map grants from the specific domain ID specified by qubes-guid, so crafted `WINDOW_DUMP` messages are not helpful to an attacker.
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
There are two reasons that `WINDOW_DUMP` is preferred over `MFNDUMP`:
1. `xc_map_foreign_pages` can only be used by dom0, as it allows accessing all memory of any VM. Allowing any VM other than dom0 to do this would be a security vulnerability.
2. `xc_map_foreign_pages` requires the guest physical address of the pages to map, but normal userspace processes (such as `qubes-gui` or Xorg) do not have access to that information. Therefore, the translation is done via the `u2mfn` out-of-tree kernel module.
Currently, using `WINDOW_DUMP` does come at a performance cost, because the AppVMs X server must copy the pages from the application to the gntalloc-allocated memory. This will be solved by future improvements to gntalloc, which will allow exporting *any* page via gntalloc, including memory shared by another process.
![gui.png](/attachment/doc/gui.png)
Security markers on dom0 windows
--------------------------------
It is important that the user knows which AppVM a given window belongs to. This prevents a rogue AppVM from painting a window pretending to belong to other AppVM or dom0 and trying to steal, for example, passwords.
In Qubes, a custom window decorator is used that paints a colourful frame (the colour is determined during AppVM creation) around decorated windows. Additionally, the window title always starts with **[name of the AppVM]**. If a window has an `override_redirect` attribute, meaning that it should not be treated by a window manager (typical case is menu windows), `qubes-guid` draws a two-pixel colourful frame inside it manually.
Clipboard sharing implementation
--------------------------------
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.
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
-----------------------------------------
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
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`.
Include these files when reporting a bug.
AppVM -> GuiVM messages
-----------------------
Proper handling of the below messages is security-critical.
Note that all messages except for `CLIPBOARD`, `MFNDUMP`, and `WINDOW_DUMP` 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).
Window manager hints and flags are described in the [Extended Window Manager Hints (EWMH) spec](https://standards.freedesktop.org/wm-spec/latest/), especially under the `_NET_WM_STATE` section.
Each message starts with the following header:
```c
struct msghdr {
uint32_t type;
uint32_t window;
/* This field is intended for use by GUI agents to skip unknown
* messages from the (trusted) GUI daemon. GUI daemon, on the other
* hand, should never rely on this field to calculate the actual len
* of message to be read, as the (untrusted) agent can put whatever
* it wants here! */
uint32_t untrusted_len;
};
```
This header is followed by message-specific data:
<table class="table">
<tr>
<th>Message name</th>
<th>Structure after header</th>
<th>Action</th>
</tr>
<tr>
<td>MSG_CLIPBOARD_DATA</td>
<td>amorphic blob (in protocol before 1.2, length determined by the "window" field, in 1.2 and later - by untrusted_len in the header)</td>
<td>Store the received clipboard content (not parsed in any way)</td>
</tr>
<tr>
<td>MSG_CREATE</td>
<td><pre>
struct msg_create {
uint32_t x;
uint32_t y;
uint32_t width;
uint32_t height;
uint32_t parent;
uint32_t override_redirect;
};
</pre>
</td>
<td>Create a window with given parameters</td>
</tr>
<tr>
<td>MSG_DESTROY</td>
<td>None</td>
<td>Destroy a window</td>
</tr>
<tr>
<td>MSG_MAP</td>
<td><pre>
struct msg_map_info {
uint32_t transient_for;
uint32_t override_redirect;
};
</pre></td>
<td>Map a window with given parameters</td>
</tr>
<tr>
<td>MSG_UNMAP</td>
<td>None</td>
<td>Unmap a window</td>
</tr>
<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;
};
</pre></td>
<td>Change window position/size/type</td>
</tr>
<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];
};
</pre></td>
<td>Retrieve the array of mfns that constitute the composition buffer of a remote window.
The "num_mfn" 32bit integers follow the shm_cmd structure; "off" is the offset of the composite buffer start in the first frame; "shmid" and "domid" parameters are just placeholders (to be filled by `qubes-guid`), so that we can use the same structure when talking to `shmoverride.so`.
</td>
</tr>
<tr>
<td>MSG_SHMIMAGE</td>
<td><pre>
struct msg_shmimage {
uint32_t x;
uint32_t y;
uint32_t width;
uint32_t height;
};
</pre> </td>
<td>Repaint the given window fragment</td>
</tr>
<tr>
<td>MSG_WMNAME</td>
<td><pre>
struct msg_wmname {
char data[128];
};
</pre></td>
<td>Set the window name. Only printable characters are allowed, and by default non-ASCII characters are not allowed.</td>
</tr>
<tr>
<td>MSG_DOCK</td>
<td>None</td>
<td>Dock the window in the tray</td>
</tr>
<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;
};
</pre> </td>
<td>Size hints for window manager</td>
</tr>
<tr>
<td>MSG_WINDOW_FLAGS</td>
<td><pre>
struct msg_window_flags {
uint32_t flags_set;
uint32_t flags_unset;
};
</pre> </td>
<td>Change window state request; fields contains bitmask which flags request to be set and which unset</td>
</tr>
<tr>
<td>MSG_CURSOR</td>
<td><pre>
struct msg_cursor {
uint32_t cursor;
};
</pre> </td>
<td>Update cursor pointer for a window. Supported cursor IDs are default cursor (0) and <a href="https://tronche.com/gui/x/xlib/appendix/b/">X Font cursors</a> (with 0x100 bit set).</td>
</tr>
<tr>
<td>MSG_WMCLASS</td>
<td><pre>
struct msg_wmclass {
char res_class[64];
char res_name[64];
};
</pre> </td>
<td>Set the WM_CLASS property of a window.</td>
</tr>
<tr>
<td>MSG_WINDOW_DUMP</td>
<td><pre>
struct msg_window_dump_hdr {
uint32_t type;
uint32_t width;
uint32_t height;
uint32_t bpp;
};
</pre> </td>
<td>Header for shared memory dump command of type hdr.type. Currently only <pre>WINDOW_DUMP_TYPE_GRANT_REFS</pre> (0) is supported.</td>
</tr>
<tr>
<td>WINDOW_DUMP_TYPE_GRANT_REFS</td>
<td><pre>
struct msg_window_dump_grant_refs {
uint32_t refs[0];
};
</pre> </td>
<td>Grant references that should be mapped into the compositing buffer.</td>
</tr>
</tr>
</table>
GuiVM -> AppVM messages
-----------------------
Proper handling of the below messages is NOT security-critical.
Each message starts with the following header
```c
struct msghdr {
uint32_t type;
uint32_t window;
};
```
The header is followed by message-specific data:
<table class="table">
<tr>
<th>Message name</th>
<th>Structure after header</th>
<th>Action</th>
</tr>
<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;
};
</pre> </td>
<td>Tell <pre>qubes_drv</pre> driver to generate a keypress</td>
</tr>
<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;
};
</pre> </td>
<td>Tell <pre>qubes_drv</pre> driver to generate mouseclick</td>
</tr>
<tr>
<td>MSG_MOTION</td>
<td><pre>
struct msg_motion {
uint32_t x;
uint32_t y;
uint32_t state;
uint32_t is_hint;
};
</pre> </td>
<td>Tell <pre>qubes_drv</pre> driver to generate motion event</td>
</tr>
<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;
};
</pre> </td>
<td>Change window position/size/type</td>
</tr>
<tr>
<td>MSG_MAP</td>
<td><pre>
struct msg_map_info {
uint32_t transient_for;
uint32_t override_redirect;
};
</pre> </td>
<td>Map a window with given parameters</td>
</tr>
<tr>
<td>MSG_CLOSE</td>
<td>None</td>
<td>send wmDeleteMessage to the window</td>
</tr>
<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;
};
</pre> </td>
<td>Notify window about enter/leave event</td>
</tr>
<tr>
<td>MSG_FOCUS</td>
<td><pre>
struct msg_focus {
uint32_t type;
uint32_t mode;
uint32_t detail;
};
</pre> </td>
<td>Raise a window, XSetInputFocus</td>
</tr>
<tr>
<td>MSG_CLIPBOARD_REQ</td>
<td>None</td>
<td>Retrieve the local clipboard, pass contents to gui-daemon</td>
</tr>
<tr>
<td>MSG_CLIPBOARD_DATA</td>
<td>amorphic blob</td>
<td>Insert the received data into local clipboard</td>
</tr>
<tr>
<td>MSG_EXECUTE</td>
<td>Obsolete</td>
<td>Obsolete, unused</td>
</tr>
<tr>
<td>MSG_KEYMAP_NOTIFY</td>
<td> unsigned char remote_keys[32]; </td>
<td>Synchronize the keyboard state (key pressed/released) with dom0</td>
</tr>
<tr>
<td>MSG_WINDOW_FLAGS</td>
<td><pre>
struct msg_window_flags {
uint32_t flags_set;
uint32_t flags_unset;
};
</pre> </td>
<td>Window state change confirmation</td>
</tr>
</table>
`KEYPRESS`, `BUTTON`, `MOTION`, `FOCUS` messages pass information extracted from dom0 XEvent; see appropriate event documentation.

1645
developer/system/gui.rst Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,70 +0,0 @@
---
lang: en
layout: doc
permalink: /doc/networking/
redirect_from:
- /doc/qubes-net/
- /en/doc/qubes-net/
- /doc/QubesNet/
- /wiki/QubesNet/
ref: 59
title: Networking
---
## 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
VM routing table is simple:
||
|Destination|Gateway|Genmask|Flags|Metric|Ref|Use|Iface|
|0.0.0.0|0.0.0.0|0.0.0.0|U|0|0|0|eth0|
Network driver domain routing table is a bit longer:
||
|Destination|Gateway|Genmask|Flags|Metric|Ref|Use|Iface|
|10.137.0.16|0.0.0.0|255.255.255.255|UH|0|0|0|vif4.0|
|10.137.0.7|0.0.0.0|255.255.255.255|UH|0|0|0|vif10.0|
|10.137.0.9|0.0.0.0|255.255.255.255|UH|0|0|0|vif9.0|
|10.137.0.8|0.0.0.0|255.255.255.255|UH|0|0|0|vif8.0|
|10.137.0.12|0.0.0.0|255.255.255.255|UH|0|0|0|vif3.0|
|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
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.
![ipv6-1](/attachment/doc/ipv6-1.png)
In that case, system uplink connection have native IPv6. But in some cases it may not be true. Then some tunneling solution can be used (for example teredo). The same will apply when the user is connected to VPN service providing IPv6 support, regardless of user's internet connection.
Such configuration can be expressed by enabling `ipv6` feature only on some subset of Qubes networking, for example by creating separate qube to encapsulate IPv6 traffic and setting `ipv6` to `1` only there. See diagram below
![ipv6-2](/attachment/doc/ipv6-2.png)
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
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

@ -0,0 +1,201 @@
==========
Networking
==========
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
-----------------------
VM routing table is simple:
.. list-table::
:widths: 10 10 10 10 10 10 10 10
:align: center
:header-rows: 1
* - Destination
- Gateway
- Genmask
- Flags
- Metric
- Ref
- Use
- Iface
* - 0.0.0.0
- 0.0.0.0
- 0.0.0.0
- U
- 0
- 0
- 0
- eth0
Network driver domain routing table is a bit longer:
.. list-table::
:widths: 10 10 10 10 10 10 10 10
:align: center
:header-rows: 1
* - Destination
- Gateway
- Genmask
- Flags
- Metric
- Ref
- Use
- Iface
* - 10.137.0.16
- 0.0.0.0
- 255.255.255.255
- UH
- 0
- 0
- 0
- vif4.0
* - 10.137.0.7
- 0.0.0.0
- 255.255.255.255
- UH
- 0
- 0
- 0
- vif10.0
* - 10.137.0.9
- 0.0.0.0
- 255.255.255.255
- UH
- 0
- 0
- 0
- vif9.0
* - 10.137.0.8
- 0.0.0.0
- 255.255.255.255
- UH
- 0
- 0
- 0
- vif8.0
* - 10.137.0.12
- 0.0.0.0
- 255.255.255.255
- UH
- 0
- 0
- 0
- vif3.0
* - 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
----
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:
.. code:: bash
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:
.. code:: bash
qvm-features ipv4-only-qube ipv6 ''
This configuration is presented below - green qubes have IPv6 access,
red one does not.
.. figure:: /attachment/doc/ipv6-1.png
:alt: ipv6-1
ipv6-1
In that case, system uplink connection have native IPv6. But in some
cases it may not be true. Then some tunneling solution can be used (for
example teredo). The same will apply when the user is connected to VPN
service providing IPv6 support, regardless of users internet
connection. Such configuration can be expressed by enabling ``ipv6``
feature only on some subset of Qubes networking, for example by creating
separate qube to encapsulate IPv6 traffic and setting ``ipv6`` to ``1``
only there. See diagram below
.. figure:: /attachment/doc/ipv6-2.png
:alt: ipv6-2
ipv6-2
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
^^^^^^^^^^^
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

@ -1,8 +0,0 @@
---
lang: en
layout: doc
permalink: /doc/qubes-core-admin-client/
redirect_to: https://dev.qubes-os.org/projects/core-admin-client/en/latest/
ref: 245
title: Qubes core admin client
---

View file

@ -1,8 +0,0 @@
---
lang: en
layout: doc
permalink: /doc/qubes-core-admin/
redirect_to: https://dev.qubes-os.org/projects/core-admin/en/latest/
ref: 246
title: Qubes core admin
---

View file

@ -1,8 +0,0 @@
---
lang: en
layout: doc
permalink: /doc/qubes-core-stack/
redirect_to: /news/2017/10/03/core3/
ref: 247
title: Qubes core stack
---

View file

@ -1,70 +0,0 @@
---
lang: en
layout: doc
permalink: /doc/security-critical-code/
redirect_from:
- /en/doc/security-critical-code/
- /doc/SecurityCriticalCode/
- /wiki/SecurityCriticalCode/
- /trac/wiki/SecurityCriticalCode/
ref: 55
title: Security-critical code
---
Below is a list of security-critical (i.e., trusted) code components in Qubes OS.
A successful attack against any of these components could compromise the system's security.
This code can be thought of as the Trusted Computing Base (TCB) of Qubes OS.
One of the main goals of the project is to keep the TCB to an absolute minimum.
The size of the current TCB is on the order of hundreds of thousands of lines of C code, which is several orders of magnitude less than other OSes.
(In Windows, Linux, and Mac OSes, the amount of trusted code is typically on the order of tens of *millions* of lines of C code.)
For more information, see [Qubes Security Goals](/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)
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
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)
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
------------------------------
There is an important distinction between buggy code and maliciously backdoored code.
We could have the most secure architecture and the most bulletproof TCB that perfectly isolates all domains from each other, but it would all be pretty useless if all the code we ran inside our domains (e.g. the code in our email clients, word processors, and web browsers) were backdoored.
In that case, only network-isolated domains would be somewhat trustworthy.
This means that we must trust at least some of the vendors that supply the code we run inside our domains.
(We don't have to trust *all* of them, but we at least have to trust the few that provide the apps we use in the most critical domains.)
In practice, we trust the software provided by the [Fedora Project](https://getfedora.org/).
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.

View file

@ -0,0 +1,108 @@
======================
Security-critical code
======================
Below is a list of security-critical (i.e., trusted) code components in
Qubes OS. A successful attack against any of these components could
compromise the systems security. This code can be thought of as the
Trusted Computing Base (TCB) of Qubes OS. One of the main goals of the
project is to keep the TCB to an absolute minimum. The size of the
current TCB is on the order of hundreds of thousands of lines of C code,
which is several orders of magnitude less than other OSes. (In Windows,
Linux, and Mac OSes, the amount of trusted code is typically on the
order of tens of *millions* of lines of C code.)
For more information, see :doc:`Qubes Security Goals </developer/system/security-design-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)
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
- Xens xenstore backend running in Dom0
- Xens block backend running in Dom0s 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)
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
------------------------------
There is an important distinction between buggy code and maliciously
backdoored code. We could have the most secure architecture and the most
bulletproof TCB that perfectly isolates all domains from each other, but
it would all be pretty useless if all the code we ran inside our domains
(e.g. the code in our email clients, word processors, and web browsers)
were backdoored. In that case, only network-isolated domains would be
somewhat trustworthy.
This means that we must trust at least some of the vendors that supply
the code we run inside our domains. (We dont have to trust *all* of
them, but we at least have to trust the few that provide the apps we use
in the most critical domains.) In practice, we trust the software
provided by the `Fedora Project <https://getfedora.org/>`__. 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.

View file

@ -1,17 +0,0 @@
---
lang: en
layout: doc
permalink: /doc/security-design-goals/
redirect_from:
- /security/goals/
- /doc/security-goals/
- /en/doc/security-goals/
- /doc/SecurityGoals/
- /wiki/SecurityGoals/
ref: 210
title: Security design goals
---
Qubes OS implements a security-by-isolation (or security-by-compartmentalization) approach by providing the ability to easily create many security domains. These domains are implemented as lightweight Virtual Machines (VMs) running under the Xen hypervisor. Qubes' main objective is to provide strong isolation between these domains, so that even if an attacker compromises one of the domains, the others are still safe. Qubes, however, does not attempt to provide any security isolation for applications running within the same domain. For example, a buggy web browser running in a Qubes domain could still be compromised just as easily as on a regular Linux distribution. The difference that Qubes makes is that now the attacker doesn't have access to all the software running in the other domains.
Qubes also provides features that make it easy and convenient to run these multiple domains, such as seamless GUI integration into one common desktop, secure clipboard copy and paste between domains, secure file transfer between domains, disposable VMs, and much more. Qubes also provides an advanced networking infrastructure that allows for the creation of multiple network VMs which isolate all the world-facing networking stacks and proxy VMs which can be used for advanced VPN configurations and tunneling over untrusted connections.

View file

@ -0,0 +1,26 @@
=====================
Security design goals
=====================
Qubes OS implements a security-by-isolation (or
security-by-compartmentalization) approach by providing the ability to
easily create many security domains. These domains are implemented as
lightweight Virtual Machines (VMs) running under the Xen hypervisor.
Qubes main objective is to provide strong isolation between these
domains, so that even if an attacker compromises one of the domains, the
others are still safe. Qubes, however, does not attempt to provide any
security isolation for applications running within the same domain. For
example, a buggy web browser running in a Qubes domain could still be
compromised just as easily as on a regular Linux distribution. The
difference that Qubes makes is that now the attacker doesnt have access
to all the software running in the other domains.
Qubes also provides features that make it easy and convenient to run
these multiple domains, such as seamless GUI integration into one common
desktop, secure clipboard copy and paste between domains, secure file
transfer between domains, disposable VMs, and much more. Qubes also
provides an advanced networking infrastructure that allows for the
creation of multiple network VMs which isolate all the world-facing
networking stacks and proxy VMs which can be used for advanced VPN
configurations and tunneling over untrusted connections.

View file

@ -1,13 +0,0 @@
---
lang: en
layout: doc
permalink: /doc/system-doc/
redirect_from:
- /en/doc/system-doc/
- /doc/SystemDoc/
- /wiki/SystemDoc/
redirect_to:
- /doc/#developer-documentation
ref: 62
title: System documentation
---

View file

@ -1,108 +0,0 @@
---
lang: en
layout: doc
permalink: /doc/template-implementation/
redirect_from:
- /en/doc/template-implementation/
- /doc/TemplateImplementation/
- /wiki/TemplateImplementation/
ref: 58
title: Template implementation
---
## Block devices of a VM
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
### 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)
**Note:** Whenever a TemplateBasedVM is created, the contents of the `/home` directory of its parent TemplateVM [are *not* copied to the child TemplateBasedVM's `/home`](/doc/templates/#inheritance-and-persistence). The child TemplateBasedVM's `/home` is independent from its parent TemplateVM's `/home`, which means that any changes to the parent TemplateVM's `/home` will not 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)
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)
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.
## 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
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/doc/TemplateSharing2.png)
### 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
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.
When an AppVM is stopped the xen hotplug script checks whether the device is still in use if it is not, the script removes the snapshot and frees the loop device.
#### Changes to template filesystem
In order for the full potential of the snapshot device to be realized, every change in root.img must save the original version of the modified block in root-cow.img. This is achieved by a snapshot-origin device.
When TemplateVM is started, it receives the snapshot-origin device connected as a root device (in read-write mode). Therefore, every change to this device is immediately saved in root.img but remains invisible to the AppVM, which uses the snapshot.
When TemplateVM is stopped, the xen script moves root-cow.img to root-cow.img.old and creates a new one (using the `qvm-template-commit` tool). The snapshot device will remain untouched due to the loop device, which uses an actual file on the disk (by inode, not by name). Linux kernel frees the old root-cow.img files as soon as they are unused by all snapshot devices (to be exact, loop devices). The new root-cow.img file will get a new inode number, and so new AppVMs will get new snapshot devices (with different names).
#### Rollback template changes
There is possibility to rollback last template changes. Saved root-cow.img.old contains all changes made during last TemplateVM run. Rolling back changes is done by reverting this "binary patch".
This is done using snapshot-merge device-mapper target (available from 2.6.34 kernel). It requires that no other snapshot device uses underlying block devices (root.img, root-cow.img via loop device). Because of this all AppVMs based on this template must be halted during this operation.
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).
### 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
volatile.img is divided into two partitions:
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
Standalone VM enables user to modify root filesystem persistently. It can be created using *--standalone* switch to *qvm-create*.
It is implemented just like TemplateVM (has own root.img connected as R/W device), but no other VMs can be based on it.

View file

@ -0,0 +1,236 @@
=======================
Template implementation
=======================
Block devices of a VM
---------------------
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
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)
**Note:** Whenever a TemplateBasedVM is created, the contents of the
``/home`` directory of its parent TemplateVM :ref:`are not copied to the
child TemplateBasedVMs
/home <user/templates/templates:inheritance and persistence>`. The child
TemplateBasedVMs ``/home`` is independent from its parent TemplateVMs
``/home``, which means that any changes to the parent TemplateVMs
``/home`` will not affect the child TemplateBasedVMs ``/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)
^^^^^^^^^^^^^^^^^^
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)
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.
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
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.
.. figure:: /attachment/doc/TemplateSharing2.png
:alt: TemplateSharing2.png
TemplateSharing2.png
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
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 devices 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.
When an AppVM is stopped the xen hotplug script checks whether the
device is still in use if it is not, the script removes the snapshot
and frees the loop device.
Changes to template filesystem
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In order for the full potential of the snapshot device to be realized,
every change in root.img must save the original version of the modified
block in root-cow.img. This is achieved by a snapshot-origin device.
When TemplateVM is started, it receives the snapshot-origin device
connected as a root device (in read-write mode). Therefore, every change
to this device is immediately saved in root.img but remains invisible
to the AppVM, which uses the snapshot.
When TemplateVM is stopped, the xen script moves root-cow.img to
root-cow.img.old and creates a new one (using the
``qvm-template-commit`` tool). The snapshot device will remain untouched
due to the loop device, which uses an actual file on the disk (by inode,
not by name). Linux kernel frees the old root-cow.img files as soon as
they are unused by all snapshot devices (to be exact, loop devices). The
new root-cow.img file will get a new inode number, and so new AppVMs
will get new snapshot devices (with different names).
Rollback template changes
^^^^^^^^^^^^^^^^^^^^^^^^^
There is possibility to rollback last template changes. Saved
root-cow.img.old contains all changes made during last TemplateVM run.
Rolling back changes is done by reverting this “binary patch”.
This is done using snapshot-merge device-mapper target (available from
2.6.34 kernel). It requires that no other snapshot device uses
underlying block devices (root.img, root-cow.img via loop device).
Because of this all AppVMs based on this template must be halted during
this operation.
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).
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
volatile.img is divided into two partitions:
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
^^^^^^^^^^^^
Standalone VM enables user to modify root filesystem persistently. It
can be created using *standalone* switch to *qvm-create*.
It is implemented just like TemplateVM (has own root.img connected as
R/W device), but no other VMs can be based on it.

View file

@ -1,280 +0,0 @@
---
layout: doc
title: Template manager
permalink: /doc/template-manager/
---
This document discusses the designs and technical details of `qvm-template`, a
template manager application. The goal of the project is to design a new
mechanism for template distribution and a unified tool for template management.
## Motivation
This project was originally proposed in the 2020 Google Summer of Code program.
Previously, templates were distributed by RPM packages and managed by
`yum`/`dnf`. However, tracking inherently dynamic VM images with a package
manager suited for static files creates some challenges. For example, users may
accidentally update the images, overriding local changes
([#996](https://github.com/QubesOS/qubes-issues/issues/996),
[#1647](https://github.com/QubesOS/qubes-issues/issues/1647)). (Or in the case
of [#2061](https://github.com/QubesOS/qubes-issues/issues/2061), want to
specifically override the changes.) Other operations that work well on normal
VMs are also somewhat inconsistent on RPM-managed templates. This includes
actions such as renaming
([#839](https://github.com/QubesOS/qubes-issues/issues/839)), removal
([#5509](https://github.com/QubesOS/qubes-issues/issues/5509)) and
backup/restore ([#1385](https://github.com/QubesOS/qubes-issues/issues/1385),
[#1453](https://github.com/QubesOS/qubes-issues/issues/1453), [discussion
thread
1](https://groups.google.com/forum/#!topic/qubes-devel/rwc2_miCNNE/discussion),
[discussion thread
2](https://groups.google.com/forum/#!topic/qubes-users/uQEUpv4THsY/discussion)).
In turn, this creates inconveniences and confusion for users
([#1403](https://github.com/QubesOS/qubes-issues/issues/1403),
[#4518](https://github.com/QubesOS/qubes-issues/issues/4518)).
Also, the usage of RPM packages meant that installing a template results in
arbitrary code execution, which is not ideal.
Besides distribution, users may also wish to have an integrated template
management application
([#2062](https://github.com/QubesOS/qubes-issues/issues/2062),
[#2064](https://github.com/QubesOS/qubes-issues/issues/2064),
[#2534](https://github.com/QubesOS/qubes-issues/issues/2534),
[#3040](https://github.com/QubesOS/qubes-issues/issues/3040)), as opposed to
the situation where multiple programs are required for different purposes,
e.g., `qubes-dom0-update`, `dnf`, `qvm-remove`, `qubes-manager`.
To tackle these issues, `qvm-template` was created. It strives to provide not
only a better mechanism for handling template installation but also a
consistent user-facing interface to deal with template management.
## Features
- Install/reinstall/downgrade/upgrade templates, either from local packages or
remote repositories
- Ability to install templates in alternative pools
- Possibility for the template package to specify options such as the kernel
or `virt_mode` used by the resulting template
- List and show information about local and available templates
- Machine-readable output for easy extension
- Search for templates
- Remove templates
- Optionally, VMs based on the template to be removed can be either removed
or "disassociated" -- namely, have their templates changed to a "dummy"
one.
- Show available repositories
- Works in both dom0 and management VMs by utilizing the Admin API
- Works well with existing tools
- Command-line interface with DNF-like usage
- A graphical interface also available
## Package format
The RPM package format is still used. However, the contents are manually
extracted instead of installing the whole package. This allows us to take
advantage of existing tools for things like repository management. We can also
avoid the burden of dealing with verification, reducing the risk of issues like
[QSB-028](/news/2016/12/19/qsb-28/).
The package name should be in the form `qubes-template-<TEMPLATE_NAME>`.
The package metadata (summary, description, etc.) should not contain the `|`
character to avoid possibly cryptic errors. This is because of its use as an
internal separator. Note that as we already consider the repository metadata
untrusted. This should not result in security issues.
The file structure should be quite similar to previous template RPMs. Namely,
there should be the following files in the package:
- `var/lib/qubes/vm-templates/<TEMPLATE_NAME>/root.img.part.[00,01,...]`
- Split tarball of template `root.img`
- Note that the file is still split due to tools such as `rpm2cpio` not
supporting large files. (Notably, the cpio format does not support files
over 4GiB.)
- `var/lib/qubes/vm-templates/<TEMPLATE_NAME>/template.conf`
- Stores custom package metadata (as RPM does not support custom attributes).
- Uses `KEY=VALUE` format.
- Fields (corresponding to
[qvm-prefs](https://dev.qubes-os.org/projects/core-admin-client/en/stable/manpages/qvm-prefs.html#common-properties)
and
[qvm-features](https://dev.qubes-os.org/projects/core-admin-client/en/stable/manpages/qvm-features.html#list-of-known-features)
tags with the same names)
- `virt_mode`
- Setting this to `pv` requires user confirmation.
- Permitted values: `pv`, `pvh`, `hvm`.
- `kernel`
- Only allowed to be set to "" (without quotes), i.e., "none", for
PVGrub.
- Network-related flags: (Must be set to IPv4 addresses in the form of
`x.x.x.x`.)
- `net.fake-ip`
- `net.fake-gateway`
- `net.fake-netmask`
- Boolean flags: (Permitted values are "1" and "0", denoting "true" and
"false" respectively.)
- `no-monitor-layout`
- `pci-e820-host`
- `linux-stubdom`
- `gui`
- `gui-emulated`
- `qrexec`
- `var/lib/qubes/vm-templates/<TEMPLATE_NAME>/whitelisted-appmenus.list`
- Contains default app menu entries of the template itself.
- `var/lib/qubes/vm-templates/<TEMPLATE_NAME>/vm-whitelisted-appmenus.list`
- Contains default app menu entries of VMs based on the template.
- `var/lib/qubes/vm-templates/<TEMPLATE_NAME>/netvm-whitelisted-appmenus.list`
- Contains default app menu entries of NetVMs based on the template.
- These three files are the same as the current format.
- Note that the contents of these files are stored in `qvm-features` upon
installation. See the section below for details.
## Metadata storage
The template manager needs to keep metadata of installed templates such as
versions and origin. This data can be stored via `qvm-features` to keep things
consistent when, e.g., `qvm-remove` is used. Besides, backups are also more
easily handled this way.
Also, the fields can serve as an indicator of whether a template is installed
by `qvm-template`.
### Fields
Most of the fields should be fairly self-explanatory.
- `template-name`
- Note that this field needs to be consistent with the template name to be
considered valid.
- `template-epoch`
- `template-version`
- `template-release`
- `template-reponame`
- `template-buildtime`
- `template-installtime`
- The times are in UTC, and are of the format `YYYY-MM-DD HH:MM:SS`.
- `template-license`
- `template-url`
- `template-summary`
- `template-description`
- Note that the newlines in this field are converted to `|` to work better
with existing tools like `qvm-features`.
- `menu-items`
- `default-menu-items`
- `netvm-menu-items`
- The `*menu-items` entries store the contents of
`var/lib/qubes/vm-templates/<TEMPLATE_NAME>/whitelisted-appmenus.list`,
`var/lib/qubes/vm-templates/<TEMPLATE_NAME>/vm-whitelisted-appmenus.list`,
`var/lib/qubes/vm-templates/<TEMPLATE_NAME>/netvm-whitelisted-appmenus.list`
respectively.
- Note that newlines are converted to spaces, again for it to work better
with existing tools. This should not cause ambiguity as [the FreeDesktop
specifications](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html)
forbid spaces in .desktop file names.
## Repository management
For UpdateVMs to access the repository configuration, the package
[qubes-repo-templates](https://github.com/WillyPillow/qubes-repo-templates) is
created with the following contents:
- `/etc/qubes/repo-templates/*.repo`: repository configuration
- `/etc/qubes/repo-templates/keys`: PGP keys
As template keys may be less trusted, they are *not* added to the system RPM
keychain but instead managed separately.
## Qrexec protocol
Dom0 and management VMs without network access also need to interact with
template repositories. The following qrexec calls that list and download
templates are thus proposed.
- `qubes.TemplateSearch`: wraps `dnf repoquery`
- `qubes.TemplateDownload`: wraps `dnf download`
### Input
Both calls accept the following format from standard input:
```text
arg1
arg2
...
argN
package-file-spec
---
repo config
```
In other words, the input consists of two parts separated by the line `---`.
The first part contains some arguments and `package-file-spec` that indicates
the pattern to be queried or downloaded. The following arguments are allowed:
- `--enablerepo=<repoid>`
- `--disablerepo=<repoid>`
- `--repoid=<repoid>`
- `--releasever=<release>`
- `--refresh`
where the usage is identical to that of DNF.
For the exact definition of `package-file-spec`, refer to the DNF
documentation.
The second part contains the repository configurations in `yum.repos.d` format.
### Output
`qubes.TemplateSearch` prints each package in
`%{name}|%{epoch}|%{version}|%{release}|%{reponame}|%{downloadsize}|%{buildtime}|%{license}|%{url}|%{summary}|%{description}|`
format to standard output, separated by newlines. Note that there is a `|` at
the end of the line. This is because `%{description}` may contain newlines, and
doing so allows us to split the entries by `|\n`. (As we are using `dnf
repoquery --qf`, we are unable to escape the newlines in advance.)
`qubes.TemplateDownload`, on the other hand, directly outputs the downloaded
content to standard output.
## Machine-readable output
The commands `qvm-template list` and `qvm-template info` provide
machine-readable output in both pipe(`|`)-separated and JSON format. See the
`qvm-template` man page for details.
## Interactions with existing tools
### `qvm-remove`
The existing `qvm-remove` tool should behave identically to `qvm-template
remove` -- albeit without fancy features like disassociation. This is unlike
the previous situation where `qvm-remove` cannot remove RPM-installed
templates.
Notably, the metadata needs no special handling as it is stored in VM features
and thus automatically consistent.
### Renaming and cloning
A template is treated as non-manager-installed once renamed or cloned. However,
relevant metadata in the VM features is still retained for future extension and
to serve as a hint for the user.
## Further reading
Initial Google Summer of Code (2020) project proposal:
- <https://hackmd.io/aYauztkGR0iOIoh8fJLecw>
Previous design document:
- <https://gist.github.com/WillyPillow/b8a643ddbd9235a97bc187e6e44b16e4>
Discussion threads:
- <https://groups.google.com/forum/#!topic/qubes-devel/6Zb_WLy3GY4>
- <https://groups.google.com/forum/#!topic/qubes-devel/PyJogqT1TUg>
- <https://groups.google.com/forum/#!topic/qubes-devel/2XaMP4Us3kg>
- <https://groups.google.com/forum/#!topic/qubes-devel/wF_84b1BR0A>
- <https://groups.google.com/forum/#!topic/qubes-devel/pYHnihVCBM0>

View file

@ -0,0 +1,443 @@
================
Template manager
================
This document discusses the designs and technical details of
``qvm-template``, a template manager application. The goal of the
project is to design a new mechanism for template distribution and a
unified tool for template management.
Motivation
----------
This project was originally proposed in the 2020 Google Summer of Code
program.
Previously, templates were distributed by RPM packages and managed by
``yum``/``dnf``. However, tracking inherently dynamic VM images with a
package manager suited for static files creates some challenges. For
example, users may accidentally update the images, overriding local
changes (`#996 <https://github.com/QubesOS/qubes-issues/issues/996>`__,
`#1647 <https://github.com/QubesOS/qubes-issues/issues/1647>`__). (Or in
the case of
`#2061 <https://github.com/QubesOS/qubes-issues/issues/2061>`__, want to
specifically override the changes.) Other operations that work well on
normal VMs are also somewhat inconsistent on RPM-managed templates. This
includes actions such as renaming
(`#839 <https://github.com/QubesOS/qubes-issues/issues/839>`__), removal
(`#5509 <https://github.com/QubesOS/qubes-issues/issues/5509>`__) and
backup/restore
(`#1385 <https://github.com/QubesOS/qubes-issues/issues/1385>`__,
`#1453 <https://github.com/QubesOS/qubes-issues/issues/1453>`__,
`discussion thread 1 <https://groups.google.com/forum/#!topic/qubes-devel/rwc2_miCNNE/discussion>`__,
`discussion thread 2 <https://groups.google.com/forum/#!topic/qubes-users/uQEUpv4THsY/discussion>`__).
In turn, this creates inconveniences and confusion for users
(`#1403 <https://github.com/QubesOS/qubes-issues/issues/1403>`__,
`#4518 <https://github.com/QubesOS/qubes-issues/issues/4518>`__).
Also, the usage of RPM packages meant that installing a template results
in arbitrary code execution, which is not ideal.
Besides distribution, users may also wish to have an integrated template
management application
(`#2062 <https://github.com/QubesOS/qubes-issues/issues/2062>`__,
`#2064 <https://github.com/QubesOS/qubes-issues/issues/2064>`__,
`#2534 <https://github.com/QubesOS/qubes-issues/issues/2534>`__,
`#3040 <https://github.com/QubesOS/qubes-issues/issues/3040>`__), as
opposed to the situation where multiple programs are required for
different purposes, e.g., ``qubes-dom0-update``, ``dnf``,
``qvm-remove``, ``qubes-manager``.
To tackle these issues, ``qvm-template`` was created. It strives to
provide not only a better mechanism for handling template installation
but also a consistent user-facing interface to deal with template
management.
Features
--------
- Install/reinstall/downgrade/upgrade templates, either from local
packages or remote repositories
- Ability to install templates in alternative pools
- Possibility for the template package to specify options such as
the kernel or ``virt_mode`` used by the resulting template
- List and show information about local and available templates
- Machine-readable output for easy extension
- Search for templates
- Remove templates
- Optionally, VMs based on the template to be removed can be either
removed or “disassociated” namely, have their templates changed
to a “dummy” one.
- Show available repositories
- Works in both dom0 and management VMs by utilizing the Admin API
- Works well with existing tools
- Command-line interface with DNF-like usage
- A graphical interface also available
Package format
--------------
The RPM package format is still used. However, the contents are manually
extracted instead of installing the whole package. This allows us to
take advantage of existing tools for things like repository management.
We can also avoid the burden of dealing with verification, reducing the
risk of issues like `QSB-028 <https://www.qubes-os.org/news/2016/12/19/qsb-28/>`__.
The package name should be in the form
``qubes-template-<TEMPLATE_NAME>``.
The package metadata (summary, description, etc.) should not contain the
``|`` character to avoid possibly cryptic errors. This is because of its
use as an internal separator. Note that as we already consider the
repository metadata untrusted. This should not result in security
issues.
The file structure should be quite similar to previous template RPMs.
Namely, there should be the following files in the package:
- ``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/root.img.part.[00,01,...]``
- Split tarball of template ``root.img``
- Note that the file is still split due to tools such as
``rpm2cpio`` not supporting large files. (Notably, the cpio format
does not support files over 4GiB.)
- ``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/template.conf``
- Stores custom package metadata (as RPM does not support custom
attributes).
- Uses ``KEY=VALUE`` format.
- Fields (corresponding to
`qvm-prefs <https://dev.qubes-os.org/projects/core-admin-client/en/stable/manpages/qvm-prefs.html#common-properties>`__
and
`qvm-features <https://dev.qubes-os.org/projects/core-admin-client/en/stable/manpages/qvm-features.html#list-of-known-features>`__
tags with the same names)
- ``virt_mode``
- Setting this to ``pv`` requires user confirmation.
- Permitted values: ``pv``, ``pvh``, ``hvm``.
- ``kernel``
- Only allowed to be set to “” (without quotes), i.e., “none”,
for PVGrub.
- Network-related flags: (Must be set to IPv4 addresses in the
form of ``x.x.x.x``.)
- ``net.fake-ip``
- ``net.fake-gateway``
- ``net.fake-netmask``
- Boolean flags: (Permitted values are “1” and “0”, denoting
“true” and “false” respectively.)
- ``no-monitor-layout``
- ``pci-e820-host``
- ``linux-stubdom``
- ``gui``
- ``gui-emulated``
- ``qrexec``
- ``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/whitelisted-appmenus.list``
- Contains default app menu entries of the template itself.
- ``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/vm-whitelisted-appmenus.list``
- Contains default app menu entries of VMs based on the template.
- ``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/netvm-whitelisted-appmenus.list``
- Contains default app menu entries of NetVMs based on the template.
- These three files are the same as the current format.
- Note that the contents of these files are stored in
``qvm-features`` upon installation. See the section below for
details.
Metadata storage
----------------
The template manager needs to keep metadata of installed templates such
as versions and origin. This data can be stored via ``qvm-features`` to
keep things consistent when, e.g., ``qvm-remove`` is used. Besides,
backups are also more easily handled this way.
Also, the fields can serve as an indicator of whether a template is
installed by ``qvm-template``.
Fields
^^^^^^
Most of the fields should be fairly self-explanatory.
- ``template-name``
- Note that this field needs to be consistent with the template name
to be considered valid.
- ``template-epoch``
- ``template-version``
- ``template-release``
- ``template-reponame``
- ``template-buildtime``
- ``template-installtime``
- The times are in UTC, and are of the format
``YYYY-MM-DD HH:MM:SS``.
- ``template-license``
- ``template-url``
- ``template-summary``
- ``template-description``
- Note that the newlines in this field are converted to ``|`` to
work better with existing tools like ``qvm-features``.
- ``menu-items``
- ``default-menu-items``
- ``netvm-menu-items``
- The ``*menu-items`` entries store the contents of
``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/whitelisted-appmenus.list``,
``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/vm-whitelisted-appmenus.list``,
``var/lib/qubes/vm-templates/<TEMPLATE_NAME>/netvm-whitelisted-appmenus.list``
respectively.
- Note that newlines are converted to spaces, again for it to work
better with existing tools. This should not cause ambiguity as
`the FreeDesktop specifications <https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html>`__
forbid spaces in .desktop file names.
Repository management
---------------------
For UpdateVMs to access the repository configuration, the package
`qubes-repo-templates <https://github.com/WillyPillow/qubes-repo-templates>`__
is created with the following contents:
- ``/etc/qubes/repo-templates/*.repo``: repository configuration
- ``/etc/qubes/repo-templates/keys``: PGP keys
As template keys may be less trusted, they are *not* added to the system
RPM keychain but instead managed separately.
Qrexec protocol
---------------
Dom0 and management VMs without network access also need to interact
with template repositories. The following qrexec calls that list and
download templates are thus proposed.
- ``qubes.TemplateSearch``: wraps ``dnf repoquery``
- ``qubes.TemplateDownload``: wraps ``dnf download``
Input
^^^^^
Both calls accept the following format from standard input:
.. code:: bash
arg1
arg2
...
argN
package-file-spec
---
repo config
In other words, the input consists of two parts separated by the line
``---``. The first part contains some arguments and
``package-file-spec`` that indicates the pattern to be queried or
downloaded. The following arguments are allowed:
- ``--enablerepo=<repoid>``
- ``--disablerepo=<repoid>``
- ``--repoid=<repoid>``
- ``--releasever=<release>``
- ``--refresh``
where the usage is identical to that of DNF.
For the exact definition of ``package-file-spec``, refer to the DNF
documentation.
The second part contains the repository configurations in
``yum.repos.d`` format.
Output
^^^^^^
``qubes.TemplateSearch`` prints each package in
``%{name}|%{epoch}|%{version}|%{release}|%{reponame}|%{downloadsize}|%{buildtime}|%{license}|%{url}|%{summary}|%{description}|``
format to standard output, separated by newlines. Note that there is a
``|`` at the end of the line. This is because ``%{description}`` may
contain newlines, and doing so allows us to split the entries by
``|\n``. (As we are using ``dnf repoquery --qf``, we are unable to
escape the newlines in advance.)
``qubes.TemplateDownload``, on the other hand, directly outputs the
downloaded content to standard output.
Machine-readable output
-----------------------
The commands ``qvm-template list`` and ``qvm-template info`` provide
machine-readable output in both pipe(``|``)-separated and JSON format.
See the ``qvm-template`` man page for details.
Interactions with existing tools
--------------------------------
``qvm-remove``
^^^^^^^^^^^^^^
The existing ``qvm-remove`` tool should behave identically to
``qvm-template remove`` albeit without fancy features like
disassociation. This is unlike the previous situation where
``qvm-remove`` cannot remove RPM-installed templates.
Notably, the metadata needs no special handling as it is stored in VM
features and thus automatically consistent.
Renaming and cloning
^^^^^^^^^^^^^^^^^^^^
A template is treated as non-manager-installed once renamed or cloned.
However, relevant metadata in the VM features is still retained for
future extension and to serve as a hint for the user.
Further reading
---------------
Initial Google Summer of Code (2020) project proposal:
- https://hackmd.io/aYauztkGR0iOIoh8fJLecw
Previous design document:
- https://gist.github.com/WillyPillow/b8a643ddbd9235a97bc187e6e44b16e4
Discussion threads:
- https://groups.google.com/forum/#!topic/qubes-devel/6Zb_WLy3GY4
- https://groups.google.com/forum/#!topic/qubes-devel/PyJogqT1TUg
- https://groups.google.com/forum/#!topic/qubes-devel/2XaMP4Us3kg
- https://groups.google.com/forum/#!topic/qubes-devel/wF_84b1BR0A
- https://groups.google.com/forum/#!topic/qubes-devel/pYHnihVCBM0

View file

@ -1,50 +0,0 @@
---
lang: en
layout: doc
permalink: /doc/vm-sudo-implementation/
redirect_from:
- /en/doc/vm-sudo-implementation/
- /doc/VMSudo-implementation/
ref: 341
title: Passwordless root access in qubes
---
The rationale behind passwordless root in qubes is set out [here](/doc/vm-sudo). Implementation is by the qubes-core-agent-passwordless-root package.
This page sets out the configuration changes made, with (not necessary complete) list of mechanisms depending on each of them:
1. sudo (`/etc/sudoers.d/qubes`):
```
Defaults !requiretty
%qubes ALL=(ALL) ROLE=unconfined_r TYPE=unconfined_t NOPASSWD: ALL
(...)
```
- Easy user -> root access (main option for the user).
- `qvm-usb` (not really working, as of R2).
2. PolicyKit (`/etc/polkit-1/rules.d/00-qubes-allow-all.rules`):
```
//allow any action, detailed reasoning in sudoers.d/qubes
polkit.addRule(function(action,subject) { if (subject.isInGroup("qubes")) return polkit.Result.YES; });
```
PAM (`/etc/pam.d/su.qubes` or `/usr/share/pam-configs/su.qubes`)
```
auth sufficient pam_succeed_if.so use_uid user ingroup qubes
```
- NetworkManager configuration from normal user (`nm-applet`).
- Updates installation (`gpk-update-viewer`).
- User can use pkexec just like sudo Note: above is needed mostly because Qubes user GUI session isn't treated by PolicyKit/logind as "local" session because of the way in which X server and session is started.
Perhaps we will address this issue in the future, but this is really low priority.
Patches welcomed anyway.
3. Empty root password:
- Used for access to 'root' account from text console (`qvm-console-dispvm`) - the only way to access the VM when GUI isn't working.
- Can be used for easy 'su -' from user to root.

View file

@ -0,0 +1,63 @@
=================================
Passwordless root access in qubes
=================================
The rationale behind passwordless root in qubes is set out
:doc:`here </user/security-in-qubes/vm-sudo>`. Implementation is by the
qubes-core-agent-passwordless-root package.
This page sets out the configuration changes made, with (not necessary
complete) list of mechanisms depending on each of them:
1. sudo (``/etc/sudoers.d/qubes``):
.. code:: bash
Defaults !requiretty
%qubes ALL=(ALL) ROLE=unconfined_r TYPE=unconfined_t NOPASSWD: ALL
(...)
- Easy user -> root access (main option for the user).
- ``qvm-usb`` (not really working, as of R2).
2. PolicyKit (``/etc/polkit-1/rules.d/00-qubes-allow-all.rules``):
.. code:: bash
//allow any action, detailed reasoning in sudoers.d/qubes
polkit.addRule(function(action,subject) { if (subject.isInGroup("qubes")) return polkit.Result.YES; });
PAM (``/etc/pam.d/su.qubes`` or ``/usr/share/pam-configs/su.qubes``)
``auth sufficient pam_succeed_if.so use_uid user ingroup qubes``
- NetworkManager configuration from normal user (``nm-applet``).
- Updates installation (``gpk-update-viewer``).
- User can use pkexec just like sudo Note: above is needed mostly
because Qubes user GUI session isnt treated by PolicyKit/logind
as “local” session because of the way in which X server and
session is started. Perhaps we will address this issue in the
future, but this is really low priority. Patches welcomed anyway.
3. Empty root password:
- Used for access to root account from text console
(``qvm-console-dispvm``) - the only way to access the VM when GUI
isnt working.
- Can be used for easy su - from user to root.