| 17 | | The current solution is based on the "qrexec" mechanism. Dom0 can call //qrexec_client// |
| 18 | | program, which will execute a given program in a given VM, passing |
| 19 | | stdin/stdout/stderr/exit code over vchan connection; possibly attaching the |
| 20 | | remote stdin/stdout to a local program. In the latter case, the syntax is |
| 21 | | //qrexec_client peer_vm command_in_vm -l command_in_dom0// |
| | 17 | In Qubes Beta1, we have reimplemented interVM file copy using qrexec, which addresses the |
| | 18 | abovementioned disadvantages. In Qubes Beta2, 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. |
| 31 | | Notably, qrexec-agent possess ability to signal its |
| 32 | | qrexec-daemon peer to execute a predefined command. This way, VM-side code |
| 33 | | can initiate setup of //vm process <-> vchan <-> dom0 process// structure. As |
| 34 | | the range of dom0 commands will be predefined, there is no "arbitrary code |
| 35 | | execution" vulnerability here. |
| 36 | | |
| 37 | | In Qubes Beta1, we have reimplemented interVM file copy using qrexec, which addresses the |
| 38 | | abovementioned disadvantages. |
| 39 | | |
| 40 | | Note, the qrexec mechanism works over vchan, and vchan is a channel between |
| 41 | | VM and dom0 (not between two VMs). We could imagine vchan extension, in |
| 42 | | which instead of using facilities available for dom0 only (like |
| 43 | | //xc_map_foreign_range//), the channel would be set up over granted pages, |
| 44 | | between two AppVMs. |
| 45 | | Reimplementing vchan this way is nontrivial. Also, it creates some security |
| 46 | | design questions; currently, everything is mediated via dom0, which has the |
| 47 | | ability to allow/deny communication, possibly asking user via dialog popups. |
| 48 | | |
| 49 | | == Regular file copy == |
| 50 | | |
| 51 | | "Regular" file is implemented as follows: |
| 52 | | * in srcVM, qvm-copy-to-vm utility |
| 53 | | * stores the information on the files_to_be_copied to `~/.filecopyspool` directory |
| 54 | | * tells //qrexec-agent// (by writing to its command fifo) to send `EXECUTE_FILE_COPY` command to qrexec-daemon |
| 55 | | * //qrexec-daemon// sees `EXECUTE_FILE_COPY` command, executes (predefined) [[br]] //qrexec_client srcVM qfile-agent -l qfile-daemon// |
| 56 | | * qfile-agent inspects `~/.filecopyspool`, sees the description about the file copy request. //qfile-agent// walks the directory tree, sends destination vmname, sends file metadata and data, then exits |
| 57 | | * qfile-daemon gets the first 32 characters from stdin (copy destination vmname), then executes (execve, really turn into new process) [[br]] //qrexec_client dstVM qfile-unpacker// [[br]] At this point, two //qrexec_client// processes running in dom0 just pass data between srcVM and dstVM. When the one connected to srcVM sees incoming EOF, it just closes input to the other qrexec_client. |
| 58 | | |
| 59 | | [[Image(htdocs:../../../site/filecopy.png)]] |
| 60 | | |
| 61 | | Note that //qfile-unpacker// must be coded securely, as it processes potentially |
| | 23 | Being a rpc server, //qfile-unpacker// must be coded securely, as it processes potentially |
| 69 | | == DispVM file copy == |
| 70 | | |
| 71 | | DispVM copy is implemented as follows: |
| 72 | | * in source_VM, //qvm-open-in-dvm// utility |
| 73 | | * stores the information on file_to_be_edited in `~/.dvmspool` directory |
| 74 | | * tells //qrexec-agent// (by writing to qrexec-agent command fifo) to send `EXECUTE_FILE_COPY_FOR_DISPVM` command to //qrexec-daemon// |
| 75 | | * qrexec-daemon sees `EXECUTE_FILE_COPY_FOR_DISPVM` command, executes [[br]] //qrexec_client srcVM qfile-agent-dvm -l qfile-daemon-dvm// |
| 76 | | * //qfile-agent-dvm// inspects `~/.dvmspool`, sees the description about file_to_be_edited, sends data about it to its peer, closes stdout |
| 77 | | * //qfile-daemon-dvm// creates DispVM, then forks [[br]] //qrexec_client DispVM dvm_file_editor// [[br]] at this point, two qrexec_client processes running in dom0 just pass data between srcVM and DispVM. //qfile-daemon-dvm// just waits for its child qrexec_client process termination. |
| 78 | | * //dvm_file_editor// gets file contents (end of transfer signalled by EOF), spawns mime handler; if the file has changed, sends modified file to its stdout, closes stdout |
| 79 | | * the response from //dvm_file_editor// (terminated by EOF) is passed (via two qrexec_client processes in dom0) to //qfile-agent-dvm//. When //qfile-daemon-dvm// sees its child qrexec_client has exited (because of EOFs in both directions), it kills DispVM. |
| 80 | | * //qfile-agent-dvm// retrieves response (terminated by EOF), if nonempty, it updates the edited file. |
| 81 | | |
| 82 | | [[Image(htdocs:../../../site/dvmcopy.png)]] |