On Wed, 2012-07-25 at 21:15 -0700, Jorge Lucangeli Obes wrote: > On Wed, Jul 25, 2012 at 8:50 PM, Xiang, Haihao <haihao.xi...@intel.com> wrote: > > On Wed, 2012-07-25 at 15:21 -0700, Jorge Lucangeli Obes wrote: > >> Hi all, > >> > >> My name is Jorge. I'm trying to get libva to work inside the syscall > >> filtering sandbox (seccomp mode 2 [1], landed on Linux 3.5) in > >> Chromium/Chromium OS. Syscall filtering in Chromium allows us to deny > >> access to syscalls deemed "dangerous" (e.g. ptrace()), or syscalls > >> that could be used by malicious code after compromising a Chromium > >> process using a vulnerability in the code. > >> > >> More specifically, we would like to have Chromium's GPU process run > >> without unlimited access to the open() system call. To do this, we > >> have to warm up/preload some resources, including the > >> i965_drv_video.so library and /dev/dri/card0 which are legitimately > >> opened by libva. The issue I'm hitting is with /dev/dri/card0. > >> > >> The way we limit access to open() is by preopening the files needed by > >> libva, and then hooking open() when the sandbox is enabled, and > >> returning dup()'s of the original fd's opened before enabling the > >> sandbox. One of the files libva opens is /dev/dri/card0: > >> > >> http://cgit.freedesktop.org/vaapi/libva/tree/va/x11/dri2_util.c#n198 > >> va/x11/dri2_util.c > >> > >> Bool > >> isDRI2Connected(VADriverContextP ctx, char **driver_name) > >> { > >> /* snip */ > >> dri_state->fd = open(device_name, O_RDWR); <--- device_name == > >> "/dev/dri/card0" > >> assert(dri_state->fd >= 0); > >> > >> /* snip */ > >> > >> if (drmGetMagic(dri_state->fd, &magic)) > >> goto err_out; > >> > >> if (!VA_DRI2Authenticate(ctx->native_dpy, > >> RootWindow(ctx->native_dpy, ctx->x11_screen), > >> magic)) <--- failing > >> goto err_out; > >> /* snip */ > >> > >> Now, the issue that I'm seeing is the following: the call to > >> open(device_name) happens after our sandbox is on, so the call gets > >> intercepted. Instead of letting it go through, we dup() a fd for > >> |device_name| that we opened before enabling the sandbox. drmGetMagic > >> succeeds when called on that dup()'ed fd (all it does is an ioctl), > >> but for some reason the call to DRI2Authenticate fails. This makes > >> va_getDriverName() fail as well, and Chromium falls back to not using > >> libva. I've tried using the LIBVA_DRIVER_NAME env var to sidestep the > >> call to va_getDriverName() but since va_getDriverName() does a whole > >> bunch of things, sidestepping makes an assert trigger in the actual > >> libva Intel driver code. > > > > Yes, because a client can't access /dev/dri/card0 without authentication > > > >> > >> Stracing the behaviour with the open() restrictions disabled and > >> enabled, the difference appears to be in what the driver reads from fd > >> 5, which is a socket. My question would be, then, if anyone knows > >> whether reopening /dev/dri/card0 clears or resets some state, which > >> could be causing DRIAuthenticate to fail when called after calling > >> drmGetMagic on a dup()'ed fd. > >> > >> *Open hook disabled: > >> open("/dev/dri/card0", O_RDWR) = 15 > >> ... > >> dup(15) = 38 > >> ioctl(38, 0x80046402, 0x7fff7ee87360) = 0 > >> poll([{fd=5, events=POLLIN|POLLOUT}], 1, -1) = 1 ([{fd=5, > >> revents=POLLOUT}]) > >> writev(5, [{"\204\2\3\0\255\0\0\0\n\0\0\0", 12}, {NULL, 0}, {"", 0}], 3) = > >> 12 > >> poll([{fd=5, events=POLLIN}], 1, -1) = 1 ([{fd=5, revents=POLLIN}]) > >> read(5, > >> "\1\0a\1\0\0\0\0\1\0\0\0\t\0\0\0\0\0\0\0\0\0\0\0\260O\374\364y\177\0\0", > >> 4096) = 32 > >> ... > >> write(2, "libva: ", 7) = 7 > >> write(2, "va_getDriverName() returns 0\n", 29) = 29 > >> > >> *Open hook enabled: > >> open("/dev/dri/card0", O_RDWR) = 15 > >> ... > >> dup(15) = 32 > >> ioctl(32, 0x80046402, 0x7fff7ee87360) = 0 > >> poll([{fd=5, events=POLLIN|POLLOUT}], 1, -1) = 1 ([{fd=5, > >> revents=POLLOUT}]) > >> writev(5, [{"\204\2\3\0\255\0\0\0\n\0\0\0", 12}, {NULL, 0}, {"", 0}], 3) = > >> 12 > >> poll([{fd=5, events=POLLIN}], 1, -1) = 1 ([{fd=5, revents=POLLIN}]) > >> read(5, "\1\0A\4\0\0\0\0\0\0\0\0\t\0\0\0 > >> \340\n\365y\177\0\0\260O\374\364y\177\0\0", 4096) = 32 > >> ... > >> write(2, "DRI2Authenticate failed\n", 24) = 24 > >> close(32) = 0 > >> ... > >> write(2, "libva: ", 7) = 7 > >> write(2, "va_getDriverName() returns -1\n", 30) = 30 > > > > a fd and a dup()'ed fd share the same struct file and the magic number > > will be removed from master after being authenticated (drmAuthMagic()). > > > > So one possible is it has been authenticated on the fd elsewhere. > > Good, that's what we thought. It's definitely the case that the same > magic number is being used to authenticate more than once, and all > attempts after the first one predictably fail. > > So, the next question would be: is there any way, besides reopening > the card, to get a new magic number? Any other file operation that can > be done on the card fd?
If you make sure it has been authenticated, you can remove the authentication code from isDRI2Connected(). It should work. > Thanks for the help! > Jorge > > > f.g. > > > > dri_state->fd = open(device_name, O_RDWR); > > > > if (dri_state->fd < 0) > > goto err_out; > > > > if (drmGetMagic(dri_state->fd, &magic)) <<=== success, return a magic > > number. > > goto err_out; > > > > if (!VA_DRI2Authenticate(ctx->native_dpy, RootWindow(ctx->native_dpy, > > ctx->x11_screen), > > magic)) <<=== success, and remove the magic > > number from master. > > goto err_out; > > > > dri_state->fd = dup(dri_state->fd); > > assert(dri_state->fd >= 0); > > > > if (drmGetMagic(dri_state->fd, &magic)) <<=== success, return the same > > magic number because they are same the same struct file > > goto err_out; > > > > if (!VA_DRI2Authenticate(ctx->native_dpy, RootWindow(ctx->native_dpy, > > ctx->x11_screen), > > magic)) <<== fail, the magic number has been > > removed from master before this operation > > goto err_out; > > > > Regards > > Haihao > > > >> > >> Thanks! > >> Jorge > >> > >> [1] http://lwn.net/Articles/475043/ > >> _______________________________________________ > >> Libva mailing list > >> Libva@lists.freedesktop.org > >> http://lists.freedesktop.org/mailman/listinfo/libva > > > > _______________________________________________ Libva mailing list Libva@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libva