Jelajahi Sumber

Merge branch 'configurable-ring-size'

* configurable-ring-size:
  qrexec: add qrexec-client-vm --buffer-size option
Marek Marczykowski-Górecki 6 tahun lalu
induk
melakukan
f8c40aa0f7

+ 7 - 1
doc/vm-tools/qrexec-client-vm.rst

@@ -8,7 +8,7 @@ qrexec-client-vm - call Qubes RPC service
 
 SYNOPSIS
 ========
-| qrexec-client-vm *target_vmname* *service* [*local_program* [*local program arguments*]]
+| qrexec-client-vm [--buffer-size=*BUFFER_SIZE*] *target_vmname* *service* [*local_program* [*local program arguments*]]
 
 DESCRIPTION
 ===========
@@ -27,6 +27,12 @@ stdin/stdout is connected to those of ``qrexec-client-vm``.
 OPTIONS
 =======
 
+--buffer-size=*BUFFER_SIZE*
+
+    Optional buffer size for vchan connection. This size is used as minimum
+    size for a buffer in each connection direction (read and write).
+    Default: 64KiB.
+
 *target_vmname*
 
     Name of target VM to which service is requested. Qubes RPC policy may

+ 12 - 5
qrexec/qrexec-agent-data.c

@@ -490,10 +490,14 @@ int process_child_io(libvchan_t *data_vchan,
  *  MSG_EXEC_CMDLINE - connect to vchan server, fork+exec process given by
  *    cmdline parameter, pass the data to/from that process, then return local
  *    process exit code
+ *
+ *  buffer_size is about vchan buffer allocated (only for vchan server cases),
+ *  use 0 to use built-in default (64k); needs to be power of 2
  */
 int handle_new_process_common(int type, int connect_domain, int connect_port,
                 char *cmdline, int cmdline_len, /* MSG_JUST_EXEC and MSG_EXEC_CMDLINE */
-                int stdin_fd, int stdout_fd, int stderr_fd /* MSG_SERVICE_CONNECT */)
+                int stdin_fd, int stdout_fd, int stderr_fd /* MSG_SERVICE_CONNECT */,
+                int buffer_size)
 {
     libvchan_t *data_vchan;
     int exit_code = 0;
@@ -504,9 +508,12 @@ int handle_new_process_common(int type, int connect_domain, int connect_port,
         cmdline[cmdline_len-1] = 0;
     }
 
+    if (buffer_size == 0)
+        buffer_size = VCHAN_BUFFER_SIZE;
+
     if (type == MSG_SERVICE_CONNECT) {
         data_vchan = libvchan_server_init(connect_domain, connect_port,
-                VCHAN_BUFFER_SIZE, VCHAN_BUFFER_SIZE);
+                buffer_size, buffer_size);
         if (data_vchan)
             libvchan_wait(data_vchan);
     } else {
@@ -563,7 +570,7 @@ pid_t handle_new_process(int type, int connect_domain, int connect_port,
     /* child process */
     exit_code = handle_new_process_common(type, connect_domain, connect_port,
             cmdline, cmdline_len,
-            -1, -1, -1);
+            -1, -1, -1, 0);
 
     exit(exit_code);
     /* suppress warning */
@@ -572,13 +579,13 @@ pid_t handle_new_process(int type, int connect_domain, int connect_port,
 
 /* Returns exit code of remote process */
 int handle_data_client(int type, int connect_domain, int connect_port,
-                int stdin_fd, int stdout_fd, int stderr_fd)
+                int stdin_fd, int stdout_fd, int stderr_fd, int buffer_size)
 {
     int exit_code;
 
     assert(type == MSG_SERVICE_CONNECT);
 
     exit_code = handle_new_process_common(type, connect_domain, connect_port,
-            NULL, 0, stdin_fd, stdout_fd, stderr_fd);
+            NULL, 0, stdin_fd, stdout_fd, stderr_fd, buffer_size);
     return exit_code;
 }

+ 2 - 1
qrexec/qrexec-agent.h

@@ -37,7 +37,8 @@ pid_t handle_new_process(int type,
         char *cmdline, int cmdline_len);
 int handle_data_client(int type,
         int connect_domain, int connect_port,
-        int stdin_fd, int stdout_fd, int stderr_fd);
+        int stdin_fd, int stdout_fd, int stderr_fd,
+        int buffer_size);
 
 
 struct qrexec_cmd_info {

+ 40 - 14
qrexec/qrexec-client-vm.c

@@ -27,6 +27,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <string.h>
+#include <getopt.h>
 #include "libqrexec-utils.h"
 #include "qrexec.h"
 #include "qrexec-agent.h"
@@ -85,6 +86,19 @@ void convert_target_name_keyword(char *target)
             target[i] = '@';
 }
 
+struct option longopts[] = {
+    { "buffer-size", required_argument, 0,  'b' },
+    { NULL, 0, 0, 0},
+};
+
+_Noreturn void usage(const char *argv0) {
+    fprintf(stderr,
+            "usage: %s [--buffer-size=BUFFER_SIZE] target_vmname program_ident [local_program [local program arguments]]\n",
+            argv0);
+    fprintf(stderr, "BUFFER_SIZE is minimum vchan buffer size (default: 64k)\n");
+    exit(2);
+}
+
 int main(int argc, char **argv)
 {
     int trigger_fd;
@@ -95,24 +109,36 @@ int main(int argc, char **argv)
     char *abs_exec_path;
     pid_t child_pid = 0;
     int inpipe[2], outpipe[2];
+    int buffer_size = 0;
+    int opt;
+
+    while (1) {
+        opt = getopt_long(argc, argv, "", longopts, NULL);
+        if (opt == -1)
+            break;
+        switch (opt) {
+            case 'b':
+                buffer_size = atoi(optarg);
+                break;
+            case '?':
+                usage(argv[0]);
+        }
+    }
 
-    if (argc < 3) {
-        fprintf(stderr,
-                "usage: %s target_vmname program_ident [local_program [local program arguments]]\n",
-                argv[0]);
-        exit(1);
+    if (argc - optind < 2) {
+        usage(argv[0]);
     }
-    if (argc > 3) {
+    if (argc - optind > 2) {
         start_local_process = 1;
     }
 
     trigger_fd = connect_unix_socket(QREXEC_AGENT_TRIGGER_PATH);
 
     memset(&params, 0, sizeof(params));
-    strncpy(params.service_name, argv[2], sizeof(params.service_name));
+    strncpy(params.service_name, argv[optind + 1], sizeof(params.service_name));
 
-    convert_target_name_keyword(argv[1]);
-    strncpy(params.target_domain, argv[1],
+    convert_target_name_keyword(argv[optind]);
+    strncpy(params.target_domain, argv[optind],
             sizeof(params.target_domain));
 
     snprintf(params.request_id.ident,
@@ -164,9 +190,9 @@ int main(int argc, char **argv)
                 close(inpipe[0]);
                 close(outpipe[1]);
 
-                abs_exec_path = strdup(argv[3]);
-                argv[3] = get_program_name(argv[3]);
-                execv(abs_exec_path, argv + 3);
+                abs_exec_path = strdup(argv[optind + 2]);
+                argv[optind + 2] = get_program_name(argv[optind + 2]);
+                execv(abs_exec_path, argv + optind + 2);
                 perror("execv");
                 exit(-1);
         }
@@ -175,11 +201,11 @@ int main(int argc, char **argv)
 
         ret = handle_data_client(MSG_SERVICE_CONNECT,
                 exec_params.connect_domain, exec_params.connect_port,
-                inpipe[1], outpipe[0], -1);
+                inpipe[1], outpipe[0], -1, buffer_size);
     } else {
         ret = handle_data_client(MSG_SERVICE_CONNECT,
                 exec_params.connect_domain, exec_params.connect_port,
-                1, 0, -1);
+                1, 0, -1, buffer_size);
     }
 
     close(trigger_fd);