qubes-doc/developer/services/qfilecopy.rst

58 lines
2.5 KiB
ReStructuredText
Raw Normal View History

2024-05-21 14:59:46 -04:00
===================================
Inter-qube file copying (qfilecopy)
===================================
There are two cases when we need a mechanism to copy files between VMs:
- “regular” file copy - when user instructs file manager to copy a
given files/directories to a different VM
- DispVM copy - user selects “open in DispVM” on a file; this file must
be copied to a DisposableVM, edited by user, and possibly a modified
file copied back from DispVM to VM.
In the early days of Qubes OS, for both cases, a block device (backed by
a file in dom0 with a vfat filesystem on it) was attached to VM, file(s)
copied there, and then the device was detached and attached to target
VM. In the DispVM case, if a edited file has been modified, another
block device is passed to requester VM in order to update the source
file.
This has the following disadvantages:
- performance - dom0 has to prepare and attach/detach block devices,
which is slow because of hotplug scripts involvement.
- security - VM kernel parses partition table and filesystem metadata
from the block device; they are controlled by (potentially untrusted)
sender VM.
In modern Qubes OS releases, we have reimplemented interVM file copy
using qrexec, which addresses the above mentioned disadvantages.
Nowadays, even more generic solution (qubes rpc) is used. See the
developer docs on qrexec and qubes rpc. In a nutshell, the file sender
and the file receiver just read/write from stdin/stdout, and the qubes
rpc layer passes data properly - so, no block devices are used.
The rpc action for regular file copy is *qubes.Filecopy*, the rpc client
is named *qfile-agent*, the rpc server is named *qfile-unpacker*. For
DispVM copy, the rpc action is *qubes.OpenInVM*, the rpc client is named
*qopen-in-vm*, rpc server is named *vm-file-editor*. Note that the
qubes.OpenInVM action can be done on a normal AppVM, too.
Being a rpc server, *qfile-unpacker* must be coded securely, as it
processes potentially untrusted data format. Particularly, we do not
want to use external tar or cpio and be prone to all vulnerabilities in
them; we want a simplified, small utility, that handles only
directory/file/symlink file type, permissions, mtime/atime, and assume
user/user ownership. In the current implementation, the code that
actually parses the data from srcVM has ca 100 lines of code and
executes chrooted to the destination directory. The latter is hardcoded
to ``~user/QubesIncoming/srcVM``; because of chroot, there is no
possibility to alter files outside of this directory.