Browse Source

qrexec: add startup notification

Avoid race conditions with services ordered shortly after qrexec start.
Make systemd know when qrexec-agent is really ready to serve.

Fixes QubesOS/qubes-issues#3985
Marek Marczykowski-Górecki 5 years ago
parent
commit
426f322c58
2 changed files with 41 additions and 0 deletions
  1. 40 0
      qrexec/qrexec-agent.c
  2. 1 0
      vm-systemd/qubes-qrexec-agent.service

+ 40 - 0
qrexec/qrexec-agent.c

@@ -309,6 +309,42 @@ void handle_vchan_error(const char *op)
     exit(1);
 }
 
+int my_sd_notify(int unset_environment, const char *state) {
+    struct sockaddr_un addr;
+    int fd;
+    int ret = -1;
+
+    addr.sun_family = AF_UNIX;
+    strncpy(addr.sun_path, getenv("NOTIFY_SOCKET"), sizeof(addr.sun_path)-1);
+    addr.sun_path[sizeof(addr.sun_path)-1] = '\0';
+    if (addr.sun_path[0] == '@')
+        addr.sun_path[0] = '\0';
+
+    if (unset_environment)
+        unsetenv("NOTIFY_SOCKET");
+
+    fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+    if (fd == -1) {
+        perror("sd_notify socket");
+        return -1;
+    }
+
+    if (connect(fd, &addr, sizeof(addr)) == -1) {
+        perror("sd_notify connect");
+        goto out;
+    }
+
+    if (send(fd, state, strlen(state), 0) == -1) {
+        perror("sd_notify send");
+        goto out;
+    }
+
+    ret = 0;
+out:
+    close(fd);
+    return ret;
+}
+
 void init()
 {
     mode_t old_umask;
@@ -326,6 +362,10 @@ void init()
     /* wait for qrexec daemon */
     while (!libvchan_is_open(ctrl_vchan))
         libvchan_wait(ctrl_vchan);
+
+    if (getenv("NOTIFY_SOCKET")) {
+        my_sd_notify(1, "READY=1");
+    }
 }
 
 void wake_meminfo_writer()

+ 1 - 0
vm-systemd/qubes-qrexec-agent.service

@@ -3,6 +3,7 @@ Description=Qubes remote exec agent
 After=xendriverdomain.service
 
 [Service]
+Type=notify
 ExecStartPre=/bin/sh -c '[ -e /dev/xen/evtchn ] || modprobe xen_evtchn'
 ExecStart=/usr/lib/qubes/qrexec-agent