Skip to content

Commit 2041781

Browse files
committed
shmoverride: avoid keeping state for munmap
By sending a freshly opened Xen file descriptor at each request, the offset is guaranteed to be 0. Furthermore, there is no need to call IOCTL_GNTDEV_UNMAP_GRANT_REF after munmap() ― just calling munmap() is sufficient. The only remaining reason to override munmap() is to handle mfn-based mappings, which may have an offset that is not a multiple of the page size. These require correcting the address before the kernel will accept the munmap() call. Fortunately, there is no legitimate reason for the X.org Server to call munmap() with a non-page-aligned address, so it is safe to unconditionally align the address and pass the aligned version to the kernel, adjusting the size accordingly. Therefore, it is no longer necessary for shmoverride to maintain any state whatsoever about the current mappings, simplifying the code enormously. No mutex locking is needed, and no list of mapped pages needs to be kept. The result is that the code is simpler and less prone to bugs.
1 parent ef68375 commit 2041781

File tree

5 files changed

+147
-200
lines changed

5 files changed

+147
-200
lines changed

gui-daemon/xside.c

+51-23
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@
2828
#include <stdlib.h>
2929
#include <unistd.h>
3030
#include <err.h>
31+
#include <sys/types.h>
3132
#include <sys/shm.h>
3233
#include <sys/file.h>
33-
#include <sys/types.h>
34+
#include <sys/ioctl.h>
3435
#include <sys/stat.h>
3536
#include <sys/socket.h>
3637
#include <sys/un.h>
@@ -60,6 +61,8 @@
6061
#include <qubes-gui-protocol.h>
6162
#include <qubes-xorg-tray-defs.h>
6263
#include <libvchan.h>
64+
#include <xen/grant_table.h>
65+
#include <xen/gntdev.h>
6366
#include "xside.h"
6467
#include "txrx.h"
6568
#include "double-buffer.h"
@@ -607,19 +610,14 @@ static void mkghandles(Ghandles * g)
607610
XWindowAttributes attr;
608611
int i;
609612

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");
623621
g->screen = DefaultScreen(g->display);
624622
g->root_win = RootWindow(g->display, g->screen);
625623
g->gc = xcb_generate_id(g->cb_connection);
@@ -3164,20 +3162,50 @@ qubes_xcb_send_xen_fd(Ghandles *g,
31643162
fputs("xcb_generate_id returned QUBES_NO_SHM_SEGMENT!\n", stderr);
31653163
abort();
31663164
}
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-
}
31723165
if (shm_args_len > SHM_ARGS_SIZE)
31733166
errx(1, "shm_args_len is %zu, exceeding maximum of %zu", shm_args_len,
31743167
(size_t)SHM_ARGS_SIZE);
31753168
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);
31803205
}
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);
31813209
const xcb_void_cookie_t cookie =
31823210
check_xcb_void(
31833211
xcb_shm_attach_fd_checked(g->cb_connection, vm_window->shmseg,

gui-daemon/xside.h

+1
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ struct _global_handles {
234234
bool in_dom0; /* true if we are in dom0, otherwise false */
235235
Atom net_supported;
236236
int xen_fd; /* O_PATH file descriptor to /dev/xen/gntdev */
237+
int xen_dir_fd; /* file descriptor to /dev/xen */
237238
bool permit_subwindows : 1; /* Permit subwindows */
238239
};
239240

include/shm-args.h

+1
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,6 @@ struct shm_args_mfns {
5151

5252
struct shm_args_grant_refs {
5353
uint32_t count;
54+
uint64_t off;
5455
uint32_t refs[];
5556
};

shmoverride/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ all: shmoverride.so X-wrapper-qubes
3737

3838
shmoverride.so: shmoverride.o ./list.o
3939
$(CC) $(CFLAGS) $(extra_cflags) -shared -o shmoverride.so \
40-
shmoverride.o list.o -ldl -lxenctrl -lxengnttab
40+
shmoverride.o list.o -ldl -lxenctrl -lxengnttab -Wl,-Bsymbolic
4141

4242
vpath %.c ../common
4343

0 commit comments

Comments
 (0)