From 42b1355957f83715cd27229e6dd1e90a7a9c9c91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Sat, 26 May 2018 01:41:16 +0200 Subject: [PATCH] qvm-open-in-vm: mark file as read-only if opened with --view-only This will cause most applications to disallow changing the file and also add some visual indication about the view being read only. This will avoid making the changes that would be discarded later. QubesOS/qubes-issues#1118 --- qubes-rpc/dvm2.h | 1 + qubes-rpc/qopen-in-vm.c | 19 ++++++++++++------- qubes-rpc/vm-file-editor.c | 18 ++++++++++++++---- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/qubes-rpc/dvm2.h b/qubes-rpc/dvm2.h index 0e5922c..72b73f7 100644 --- a/qubes-rpc/dvm2.h +++ b/qubes-rpc/dvm2.h @@ -1,2 +1,3 @@ #define DVM_FILENAME_SIZE 256 #define DVM_SPOOL "/home/user/.dvmspool" +#define DVM_VIEW_ONLY_PREFIX "view-only-" diff --git a/qubes-rpc/qopen-in-vm.c b/qubes-rpc/qopen-in-vm.c index 8d2b24f..5e796a5 100644 --- a/qubes-rpc/qopen-in-vm.c +++ b/qubes-rpc/qopen-in-vm.c @@ -13,22 +13,27 @@ #include #include "dvm2.h" -void send_file(const char *fname) +void send_file(const char *fname, int view_only) { const char *base; - char sendbuf[DVM_FILENAME_SIZE]; + char sendbuf[DVM_FILENAME_SIZE] = {0}; + size_t sendbuf_size = DVM_FILENAME_SIZE; int fd = open(fname, O_RDONLY); if (fd < 0) gui_fatal("open %s", fname); + if (view_only) { + strncpy(sendbuf, DVM_VIEW_ONLY_PREFIX, sendbuf_size); + sendbuf_size -= strlen(DVM_VIEW_ONLY_PREFIX); + } base = rindex(fname, '/'); if (!base) base = fname; else base++; - if (strlen(base) >= DVM_FILENAME_SIZE) - base += strlen(base) - DVM_FILENAME_SIZE + 1; - strncpy(sendbuf,base,DVM_FILENAME_SIZE - 1); /* fills out with NULs */ - sendbuf[DVM_FILENAME_SIZE - 1] = '\0'; + if (strlen(base) >= sendbuf_size) + base += strlen(base) - sendbuf_size + 1; + strncat(sendbuf,base,sendbuf_size - 1); /* fills out with NULs */ + sendbuf[DVM_FILENAME_SIZE - 1] = '\0'; if (!write_all(1, sendbuf, DVM_FILENAME_SIZE)) gui_fatal("send filename to dispVM"); if (!copy_fd_all(1, fd)) @@ -114,7 +119,7 @@ int main(int argc, char ** argv) if (optind >= argc) gui_fatal("OpenInVM - no file given?"); fname = argv[optind]; - send_file(fname); + send_file(fname, view_only); if (!view_only) { recv_file(fname); } else { diff --git a/qubes-rpc/vm-file-editor.c b/qubes-rpc/vm-file-editor.c index 054fef3..45004e8 100644 --- a/qubes-rpc/vm-file-editor.c +++ b/qubes-rpc/vm-file-editor.c @@ -79,9 +79,10 @@ fail: exit(1); } -char *get_filename(void) +char *get_filename(int *view_only) { char buf[DVM_FILENAME_SIZE]; + char *fname = buf; static char *retname; int i; char *directory; @@ -100,13 +101,17 @@ char *get_filename(void) if (index(" !?\"#$%^&*()[]<>;`~|", buf[i])) buf[i]='_'; } - len = strlen(directory)+1+strlen(buf)+1; + if (strncmp(buf, DVM_VIEW_ONLY_PREFIX, strlen(DVM_VIEW_ONLY_PREFIX)) == 0) { + *view_only = 1; + fname += strlen(DVM_VIEW_ONLY_PREFIX); + } + len = strlen(directory)+1+strlen(fname)+1; retname = malloc(len); if (!retname) { fprintf(stderr, "Cannot allocate memory\n"); exit(1); } - snprintf(retname, len, "%s/%s", directory, buf); + snprintf(retname, len, "%s/%s", directory, fname); free(directory); return retname; } @@ -143,11 +148,16 @@ int main() { struct stat stat_pre, stat_post, session_stat; - char *filename = get_filename(); + int view_only = 0; + char *filename = get_filename(&view_only); int child, status, log_fd, null_fd; FILE *waiter_pidfile; copy_file_by_name(filename); + if (view_only) { + // mark file as read-only so applications will signal it to the user + chmod(filename, 0400); + } if (stat(filename, &stat_pre)) { perror("stat pre"); exit(1);