diff --git a/pressure-vessel/wrap.c b/pressure-vessel/wrap.c index 964b1b3ceb010a2305ecfd103771fa83e551717a..3e9bf920c8acb2b807bfef7e449cf8a241da2eda 100644 --- a/pressure-vessel/wrap.c +++ b/pressure-vessel/wrap.c @@ -2524,6 +2524,58 @@ main (int argc, } } + /* Nvidia Vulkan ray-tracing requires to load the `nvidia_uvm.ko` kernel + * module, and this is usually done in `libcuda.so.1` by running the setuid + * binary `nvidia-modprobe`. But when we are inside a container we don't bind + * `nvidia-modprobe` and, even if we did, it's setuid would not be effective + * because we have `PR_SET_NO_NEW_PRIVS` and we don't have `CAP_SYS_MODULE` in + * our capability bounding set. + * For this reason if the current system is using the proprietary Nvidia + * drivers and `nvidia_uvm.ko` has not been already loaded, we execute + * `nvidia-modprobe` before entering in the container environment. */ + if (g_file_test ("/sys/module/nvidia/version", G_FILE_TEST_IS_REGULAR) + && !g_file_test ("/sys/module/nvidia_uvm", G_FILE_TEST_IS_DIR)) + { + g_autofree gchar *child_stdout = NULL; + g_autofree gchar *child_stderr = NULL; + int wait_status; + const char *nvidia_modprobe_argv[] = + { + "nvidia-modprobe", + "-u", + NULL + }; + + g_debug ("Running nvidia-modprobe..."); + + /* We use LEAVE_DESCRIPTORS_OPEN to work around a deadlock in older GLib, + * see flatpak_close_fds_workaround */ + if (!g_spawn_sync (NULL, /* cwd */ + (gchar **) nvidia_modprobe_argv, + NULL, /* environ */ + (G_SPAWN_SEARCH_PATH | + G_SPAWN_LEAVE_DESCRIPTORS_OPEN), + NULL, NULL, + &child_stdout, + &child_stderr, + &wait_status, + error)) + { + g_debug ("Cannot run nvidia-modprobe: %s", local_error->message); + g_clear_error (&local_error); + } + else if (wait_status != 0) + { + g_debug ("Cannot run nvidia-modprobe: wait status %d", wait_status); + + if (child_stdout != NULL && child_stdout[0] != '\0') + g_debug ("Output:\n%s", child_stdout); + + if (child_stderr != NULL && child_stderr[0] != '\0') + g_debug ("Diagnostic output:\n%s", child_stderr); + } + } + if (opt_only_prepare) ret = 0; else