|
28 | 28 | #include <stdlib.h>
|
29 | 29 | #include <unistd.h>
|
30 | 30 | #include <err.h>
|
| 31 | +#include <sys/types.h> |
31 | 32 | #include <sys/shm.h>
|
32 | 33 | #include <sys/file.h>
|
33 |
| -#include <sys/types.h> |
| 34 | +#include <sys/ioctl.h> |
34 | 35 | #include <sys/stat.h>
|
35 | 36 | #include <sys/socket.h>
|
36 | 37 | #include <sys/un.h>
|
|
60 | 61 | #include <qubes-gui-protocol.h>
|
61 | 62 | #include <qubes-xorg-tray-defs.h>
|
62 | 63 | #include <libvchan.h>
|
| 64 | +#include <xen/grant_table.h> |
| 65 | +#include <xen/gntdev.h> |
63 | 66 | #include "xside.h"
|
64 | 67 | #include "txrx.h"
|
65 | 68 | #include "double-buffer.h"
|
@@ -607,19 +610,14 @@ static void mkghandles(Ghandles * g)
|
607 | 610 | XWindowAttributes attr;
|
608 | 611 | int i;
|
609 | 612 |
|
610 |
| - g->display = XOpenDisplay(NULL); |
611 |
| - if (!g->display) { |
612 |
| - perror("XOpenDisplay"); |
613 |
| - exit(1); |
614 |
| - } |
615 |
| - if (!(g->cb_connection = XGetXCBConnection(g->display))) { |
616 |
| - perror("XGetXCBConnection"); |
617 |
| - exit(1); |
618 |
| - } |
619 |
| - if ((g->xen_fd = open("/dev/xen/gntdev", O_PATH|O_CLOEXEC|O_NOCTTY)) < 0) { |
620 |
| - perror("open /dev/xen/gntdev"); |
621 |
| - exit(1); |
622 |
| - } |
| 613 | + if (!(g->display = XOpenDisplay(NULL))) |
| 614 | + err(1, "XOpenDisplay"); |
| 615 | + if (!(g->cb_connection = XGetXCBConnection(g->display))) |
| 616 | + err(1, "XGetXCBConnection"); |
| 617 | + if ((g->xen_dir_fd = open("/dev/xen", O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_RDONLY)) == -1) |
| 618 | + err(1, "open /dev/xen"); |
| 619 | + if ((g->xen_fd = openat(g->xen_dir_fd, "gntdev", O_PATH|O_CLOEXEC|O_NOCTTY)) == -1) |
| 620 | + err(1, "open /dev/xen/gntdev"); |
623 | 621 | g->screen = DefaultScreen(g->display);
|
624 | 622 | g->root_win = RootWindow(g->display, g->screen);
|
625 | 623 | g->gc = xcb_generate_id(g->cb_connection);
|
@@ -3164,20 +3162,50 @@ qubes_xcb_send_xen_fd(Ghandles *g,
|
3164 | 3162 | fputs("xcb_generate_id returned QUBES_NO_SHM_SEGMENT!\n", stderr);
|
3165 | 3163 | abort();
|
3166 | 3164 | }
|
3167 |
| - int dup_fd = fcntl(g->xen_fd, F_DUPFD_CLOEXEC, 3); |
3168 |
| - if (dup_fd < 3) { |
3169 |
| - assert(dup_fd == -1); |
3170 |
| - err(1, "fcntl(F_DUPFD_CLOEXEC)"); |
3171 |
| - } |
3172 | 3165 | if (shm_args_len > SHM_ARGS_SIZE)
|
3173 | 3166 | errx(1, "shm_args_len is %zu, exceeding maximum of %zu", shm_args_len,
|
3174 | 3167 | (size_t)SHM_ARGS_SIZE);
|
3175 | 3168 | inter_appviewer_lock(g, 1);
|
3176 |
| - memcpy(g->shm_args, shm_args, shm_args_len); |
3177 |
| - if (shm_args_len < SHM_ARGS_SIZE) { |
3178 |
| - memset(((uint8_t *) g->shm_args) + shm_args_len, 0, |
3179 |
| - SHM_ARGS_SIZE - shm_args_len); |
| 3169 | + int dup_fd; |
| 3170 | + switch (shm_args->type) { |
| 3171 | + case SHM_ARGS_TYPE_MFNS: |
| 3172 | + if ((dup_fd = fcntl(g->xen_fd, F_DUPFD_CLOEXEC, 3)) < 3) { |
| 3173 | + assert(dup_fd == -1); |
| 3174 | + err(1, "fcntl(F_DUPFD_CLOEXEC)"); |
| 3175 | + } |
| 3176 | + break; |
| 3177 | + default: |
| 3178 | + fputs("internal wrong command type (this is a bug)\n", stderr); |
| 3179 | + abort(); |
| 3180 | + case SHM_ARGS_TYPE_GRANT_REFS: |
| 3181 | + if ((dup_fd = openat(g->xen_dir_fd, "gntdev", O_RDWR|O_CLOEXEC|O_NOCTTY)) == -1) |
| 3182 | + err(1, "open(\"/dev/xen/gntdev\")"); |
| 3183 | + struct shm_args_grant_refs *s = |
| 3184 | + (struct shm_args_grant_refs *)((uint8_t *)shm_args + sizeof(struct shm_args_hdr)); |
| 3185 | + struct ioctl_gntdev_map_grant_ref *gref = malloc( |
| 3186 | + s->count * sizeof(struct ioctl_gntdev_grant_ref) + |
| 3187 | + offsetof(struct ioctl_gntdev_map_grant_ref, refs)); |
| 3188 | + if (!gref) |
| 3189 | + err(1, "malloc failed"); |
| 3190 | + gref->count = s->count; |
| 3191 | + gref->pad = 0; |
| 3192 | + gref->index = UINT64_MAX; |
| 3193 | + for (size_t i = 0; i < s->count; ++i) { |
| 3194 | + gref->refs[i].domid = g->domid; |
| 3195 | + gref->refs[i].ref = s->refs[i]; |
| 3196 | + } |
| 3197 | + if (ioctl(dup_fd, IOCTL_GNTDEV_MAP_GRANT_REF, gref) != 0) |
| 3198 | + err(1, "ioctl(IOCTL_GNTDEV_MAP_GRANT_REF)"); |
| 3199 | + if (gref->index != 0) |
| 3200 | + fprintf(stderr, |
| 3201 | + "ioctl(IOCTL_GNTDEV_MAP_GRANT_REF) set index to nonzero value %" PRIu64 "\n", |
| 3202 | + (uint64_t)gref->index); |
| 3203 | + s->off = gref->index; |
| 3204 | + free(gref); |
3180 | 3205 | }
|
| 3206 | + memcpy(g->shm_args, shm_args, shm_args_len); |
| 3207 | + memset(((uint8_t *) g->shm_args) + shm_args_len, 0, |
| 3208 | + SHM_ARGS_SIZE - shm_args_len); |
3181 | 3209 | const xcb_void_cookie_t cookie =
|
3182 | 3210 | check_xcb_void(
|
3183 | 3211 | xcb_shm_attach_fd_checked(g->cb_connection, vm_window->shmseg,
|
|
0 commit comments