diff --git a/Makefile b/Makefile index 54e36d99..56dea3f1 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,9 @@ selinux_policies ::= qubes-gui-daemon.pp all_targets := gui-daemon/qubes-guid gui-daemon/qubes-guid.1 \ shmoverride/shmoverride.so \ - shmoverride/X-wrapper-qubes pulse/pacat-simple-vchan \ + shmoverride/X-wrapper-qubes \ + shmoverride/Xwayland-wrapper \ + pulse/pacat-simple-vchan \ screen-layout-handler/watch-screen-layout-changes @@ -52,6 +54,9 @@ shmoverride/shmoverride.so: shmoverride/X-wrapper-qubes: (cd shmoverride; $(MAKE) X-wrapper-qubes) +shmoverride/Xwayland-wrapper: + (cd shmoverride; $(MAKE) Xwayland-wrapper) + pulse/pacat-simple-vchan: $(MAKE) -C pulse pacat-simple-vchan @@ -67,6 +72,7 @@ install: install -D pulse/pacat-simple-vchan $(DESTDIR)/usr/bin/pacat-simple-vchan install -D shmoverride/X-wrapper-qubes $(DESTDIR)/usr/bin/X-wrapper-qubes install -D shmoverride/shmoverride.so $(DESTDIR)$(LIBDIR)/qubes-gui-daemon/shmoverride.so + install -D shmoverride/Xwayland-wrapper $(DESTDIR)/usr/libexec/qubes/wrappers/Xwayland install -D -m 0644 gui-daemon/guid.conf $(DESTDIR)/etc/qubes/guid.conf install -D gui-daemon/qubes-localgroup.sh $(DESTDIR)/etc/X11/xinit/xinitrc.d/qubes-localgroup.sh install -D -m 0644 common/90-default-gui-daemon.policy $(DESTDIR)/etc/qubes/policy.d/90-default-gui-daemon.policy diff --git a/debian/qubes-gui-daemon.install b/debian/qubes-gui-daemon.install index ddf9ceb0..049ee252 100644 --- a/debian/qubes-gui-daemon.install +++ b/debian/qubes-gui-daemon.install @@ -1,6 +1,7 @@ usr/bin/X.qubes usr/bin/qubes-guid usr/libexec/qubes/watch-screen-layout-changes +usr/libexec/qubes/wrappers/Xwayland usr/share/man/man1/qubes-guid.1 usr/lib/*/qubes-gui-daemon/shmoverride.so usr/lib/qubes/icon-receiver diff --git a/rpm_spec/gui-daemon.spec.in b/rpm_spec/gui-daemon.spec.in index 961a0880..6e0f2e4a 100644 --- a/rpm_spec/gui-daemon.spec.in +++ b/rpm_spec/gui-daemon.spec.in @@ -178,6 +178,7 @@ rm -f %{name}-%{version} /etc/xdg/autostart/qubes-icon-receiver.desktop /etc/X11/xinit/xinitrc.d/qubes-localgroup.sh /usr/libexec/qubes/watch-screen-layout-changes +/usr/libexec/qubes/wrappers/Xwayland /usr/lib/qubes/icon-receiver %config %{_sysconfdir}/qubes-rpc/qubes.WindowIconUpdater %config %{_sysconfdir}/qubes/rpc-config/qubes.WindowIconUpdater diff --git a/shmoverride/.gitignore b/shmoverride/.gitignore index 979bacea..9352006f 100644 --- a/shmoverride/.gitignore +++ b/shmoverride/.gitignore @@ -1,3 +1,3 @@ X_wrapper_qubes shmoverride.so - +Xwayland-wrapper diff --git a/shmoverride/Makefile b/shmoverride/Makefile index 854742fb..a75441b1 100644 --- a/shmoverride/Makefile +++ b/shmoverride/Makefile @@ -33,7 +33,7 @@ extra_cflags := -g -O2 -I../include/ -fPIC -Wall -Wextra -Werror \ -I../include -fvisibility=hidden -pthread CC=gcc -all: shmoverride.so X-wrapper-qubes +all: shmoverride.so X-wrapper-qubes Xwayland-wrapper shmoverride.so: shmoverride.o ./list.o $(CC) $(CFLAGS) $(extra_cflags) -shared -o shmoverride.so \ @@ -43,8 +43,11 @@ vpath %.c ../common X-wrapper-qubes: X-wrapper-qubes.o +Xwayland-wrapper: Xwayland-wrapper.in + sed -e "s,@SHMOVERRIDE_LIB_PATH@,$(LIBDIR)/qubes-gui-daemon/shmoverride.so," < $< > $@ + clean: - rm -f ./*~ ./*.o shmoverride.so X-wrapper-qubes + rm -f ./*~ ./*.o shmoverride.so X-wrapper-qubes Xwayland-wrapper %.o: %.c Makefile $(CC) -MD -MP -MF $@.dep -c -o $@ $(extra_cflags) $(CFLAGS) $< diff --git a/shmoverride/Xwayland-wrapper.in b/shmoverride/Xwayland-wrapper.in new file mode 100755 index 00000000..e9139e00 --- /dev/null +++ b/shmoverride/Xwayland-wrapper.in @@ -0,0 +1,4 @@ +#!/bin/sh + +export PATH="${PATH#*/wrappers:}" +exec env LD_PRELOAD="@SHMOVERRIDE_LIB_PATH@" Xwayland "$@" diff --git a/shmoverride/shmoverride.c b/shmoverride/shmoverride.c index d399905d..ce71a29b 100644 --- a/shmoverride/shmoverride.c +++ b/shmoverride/shmoverride.c @@ -72,6 +72,8 @@ static int (*real_munmap) (void *shmaddr, size_t len); static int (*real_fstat64) (VER_ARG int fd, struct stat64 *buf); static int (*real_fstat)(VER_ARG int fd, struct stat *buf); +static int try_init(void); + static struct stat global_buf; static int gntdev_fd = -1; @@ -84,7 +86,7 @@ static int xc_hnd; static xengnttab_handle *xgt; static char __shmid_filename[SHMID_FILENAME_LEN]; static char *shmid_filename = NULL; -static int idfd = -1, display = -1; +static int idfd = -1, display = -1, init_called = 0; static uint8_t *mmap_mfns(struct shm_args_hdr *shm_args) { uint8_t *map; @@ -151,6 +153,8 @@ ASM_DEF(void *, mmap, real_fstat = FSTAT; } + try_init(); + #if defined MAP_ANON && defined MAP_ANONYMOUS && (MAP_ANONYMOUS) != (MAP_ANON) # error header bug (def mismatch) #endif @@ -217,6 +221,9 @@ ASM_DEF(int, munmap, void *addr, size_t len) { if (len > SIZE_MAX - XC_PAGE_SIZE) abort(); + + try_init(); + const uintptr_t addr_int = (uintptr_t)addr; const uintptr_t rounded_addr = addr_int & ~(uintptr_t)(XC_PAGE_SIZE - 1); return real_munmap((void *)rounded_addr, len + (addr_int - rounded_addr)); @@ -438,6 +445,7 @@ static int assign_off(off_t *off) { #define STAT(id) \ ASM_DEF(int, f ## id, int filedes, struct id *buf) { \ + try_init(); \ int res = real_f ## id(VER filedes, buf); \ if (res || \ !S_ISCHR(buf->st_mode) || \ @@ -454,6 +462,7 @@ STAT(stat64) #ifdef _STAT_VER #define STAT(id) \ ASM_DEF(int, __fx ## id, int ver, int filedes, struct id *buf) { \ + try_init(); \ if (ver != _STAT_VER) { \ fprintf(stderr, \ "Wrong _STAT_VER: got %d, expected %d, libc has incompatibly changed\n", \ @@ -467,8 +476,13 @@ STAT(stat64) #undef STAT #endif -int __attribute__ ((constructor)) initfunc(void) +static int try_init(void) { + // Ideally it is being called in constructor, if something is calling this before + // constructor - we're assuming it is not multi-threaded code. + if (__builtin_expect(init_called, 1)) return 0; + init_called = 1; + unsetenv("LD_PRELOAD"); fprintf(stderr, "shmoverride constructor running\n"); dlerror(); @@ -519,24 +533,26 @@ int __attribute__ ((constructor)) initfunc(void) fputs("snprintf() failed!\n", stderr); abort(); } - shmid_filename = __shmid_filename; - fprintf(stderr, "shmoverride: running with shm file %s\n", shmid_filename); + fprintf(stderr, "shmoverride: running with shm file %s\n", __shmid_filename); /* Try to lock the shm.id file (don't rely on whether it exists, a previous * process might have crashed). */ - idfd = open(shmid_filename, O_RDWR | O_CLOEXEC | O_CREAT | O_NOCTTY, 0600); + idfd = open(__shmid_filename, O_RDWR | O_CLOEXEC | O_CREAT | O_NOCTTY, 0600); if (idfd < 0) { fprintf(stderr, "shmoverride opening %s: %s\n", - shmid_filename, strerror(errno)); + __shmid_filename, strerror(errno)); goto cleanup; } if (flock(idfd, LOCK_EX | LOCK_NB) < 0) { fprintf(stderr, "shmoverride flock %s: %s\n", - shmid_filename, strerror(errno)); + __shmid_filename, strerror(errno)); /* There is probably an alive process holding the file, give up. */ goto cleanup; } + /* Save shmid file for cleanup only after taking the lock */ + shmid_filename = __shmid_filename; + if (ftruncate(idfd, SHM_ARGS_SIZE) < 0) { perror("shmoverride ftruncate"); goto cleanup; @@ -581,6 +597,10 @@ int __attribute__ ((constructor)) initfunc(void) shm_args = NULL; return 0; } +int __attribute__ ((constructor)) initfunc(void) +{ + return try_init(); +} int __attribute__ ((destructor)) descfunc(void) {