Ilia Mirkin
2014-Jun-19 08:39 UTC
[Nouveau] [PATCH] nouveau: dup fd before passing it to device
nouveau screens are reused for the same device node. However in the scenario where we create screen 1, screen 2, and then delete screen 1, the surrounding code might also close the original device node. To protect against this, dup the fd and use the dup'd fd in the nouveau_device. Also tell the nouveau_device that it is the owner of the fd so that it will be closed on destruction. Also make sure to free the nouveau_device in case of any failure. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=79823 Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu> --- src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c index 1dfdaac..833fb9a 100644 --- a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c +++ b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c @@ -1,4 +1,5 @@ #include <sys/stat.h> +#include <unistd.h> #include "pipe/p_context.h" #include "pipe/p_state.h" #include "util/u_format.h" @@ -75,7 +76,14 @@ nouveau_drm_screen_create(int fd) return &screen->base; } - ret = nouveau_device_wrap(fd, 0, &dev); + /* Since the screen re-use is based on the device node and not the fd, + * create a copy of the fd to be owned by the device. Otherwise a + * scenario could occur where two screens are created, and the first + * one is shut down, along with the fd being closed. The second + * (identical) screen would now have a reference to the closed fd. We + * avoid this by duplicating the original fd. + */ + ret = nouveau_device_wrap(dup(fd), 1, &dev); if (ret) goto err; @@ -115,6 +123,8 @@ nouveau_drm_screen_create(int fd) return &screen->base; err: + if (dev) + nouveau_device_del(&dev); pipe_mutex_unlock(nouveau_screen_mutex); return NULL; } -- 1.8.5.5
Ilia Mirkin
2014-Jun-19 20:07 UTC
[Nouveau] [PATCH v2] nouveau: dup fd before passing it to device
nouveau screens are reused for the same device node. However in the scenario where we create screen 1, screen 2, and then delete screen 1, the surrounding code might also close the original device node. To protect against this, dup the fd and use the dup'd fd in the nouveau_device. Also tell the nouveau_device that it is the owner of the fd so that it will be closed on destruction. Also make sure to free the nouveau_device in case of any failure. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=79823 Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu> Cc: "10.2" <mesa-stable at lists.freedesktop.org> --- v1 -> v2: clean up dup fd if device creation fails src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c index 1dfdaac..0635246 100644 --- a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c +++ b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c @@ -1,4 +1,5 @@ #include <sys/stat.h> +#include <unistd.h> #include "pipe/p_context.h" #include "pipe/p_state.h" #include "util/u_format.h" @@ -59,7 +60,7 @@ nouveau_drm_screen_create(int fd) struct nouveau_device *dev = NULL; struct pipe_screen *(*init)(struct nouveau_device *); struct nouveau_screen *screen; - int ret; + int ret, dupfd = -1; pipe_mutex_lock(nouveau_screen_mutex); if (!fd_tab) { @@ -75,7 +76,17 @@ nouveau_drm_screen_create(int fd) return &screen->base; } - ret = nouveau_device_wrap(fd, 0, &dev); + /* Since the screen re-use is based on the device node and not the fd, + * create a copy of the fd to be owned by the device. Otherwise a + * scenario could occur where two screens are created, and the first + * one is shut down, along with the fd being closed. The second + * (identical) screen would now have a reference to the closed fd. We + * avoid this by duplicating the original fd. Note that + * nouveau_device_wrap does not close the fd in case of a device + * creation error. + */ + dupfd = dup(fd); + ret = nouveau_device_wrap(dupfd, 1, &dev); if (ret) goto err; @@ -115,6 +126,10 @@ nouveau_drm_screen_create(int fd) return &screen->base; err: + if (dev) + nouveau_device_del(&dev); + else if (dupfd >= 0) + close(dupfd); pipe_mutex_unlock(nouveau_screen_mutex); return NULL; } -- 1.8.5.5
Maybe Matching Threads
- [mesa v2 5/9] nouveau: fix screen creation failure paths
- [mesa v2 5/9] nouveau: fix screen creation failure paths
- [mesa 1/9] nouveau: bump required libdrm version to 2.4.66
- [mesa v3 1/9] nouveau: bump required libdrm version to 2.4.66
- [mesa v2 1/9] nouveau: bump required libdrm version to 2.4.66