[Nouveau] [mesa PATCH] nouveau: fix double free when nvXX_screen_create fails

Marcin Slusarz marcin.slusarz at gmail.com
Fri Dec 2 10:46:59 PST 2011


When nvXX_screen_create fails, it destroys winsys object,
so nouveau_drm_screen_create should not try to destroy it again.

Note: This is a candidate for the 7.11 branch.
---
 src/gallium/drivers/nv50/nv50_screen.c             |    7 +++++--
 src/gallium/drivers/nvc0/nvc0_screen.c             |    7 +++++--
 src/gallium/drivers/nvfx/nvfx_screen.c             |    6 ++++--
 .../winsys/nouveau/drm/nouveau_drm_winsys.c        |   10 ++++++----
 4 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
index 3cd5fdf..156054b 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -22,6 +22,7 @@
 
 #include "util/u_format.h"
 #include "util/u_format_s3tc.h"
+#include "util/u_simple_screen.h"
 #include "pipe/p_screen.h"
 
 #include "nv50_context.h"
@@ -310,9 +311,12 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
    unsigned i, base;
 
    screen = CALLOC_STRUCT(nv50_screen);
-   if (!screen)
+   if (!screen) {
+      ws->destroy(ws);
       return NULL;
+   }
    pscreen = &screen->base.base;
+   pscreen->winsys = ws;
 
    screen->base.sysmem_bindings = PIPE_BIND_CONSTANT_BUFFER;
 
@@ -323,7 +327,6 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
    chan = screen->base.channel;
    chan->user_private = screen;
 
-   pscreen->winsys = ws;
    pscreen->destroy = nv50_screen_destroy;
    pscreen->context_create = nv50_create;
    pscreen->is_format_supported = nv50_screen_is_format_supported;
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c
index 79c3e36..9268a7a 100644
--- a/src/gallium/drivers/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nvc0/nvc0_screen.c
@@ -22,6 +22,7 @@
 
 #include "util/u_format.h"
 #include "util/u_format_s3tc.h"
+#include "util/u_simple_screen.h"
 #include "pipe/p_screen.h"
 
 #include "vl/vl_decoder.h"
@@ -376,9 +377,12 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
    unsigned i;
 
    screen = CALLOC_STRUCT(nvc0_screen);
-   if (!screen)
+   if (!screen) {
+      ws->destroy(ws);
       return NULL;
+   }
    pscreen = &screen->base.base;
+   pscreen->winsys = ws;
 
    screen->base.sysmem_bindings = PIPE_BIND_CONSTANT_BUFFER;
 
@@ -390,7 +394,6 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
    chan = screen->base.channel;
    chan->user_private = screen;
 
-   pscreen->winsys = ws;
    pscreen->destroy = nvc0_screen_destroy;
    pscreen->context_create = nvc0_create;
    pscreen->is_format_supported = nvc0_screen_is_format_supported;
diff --git a/src/gallium/drivers/nvfx/nvfx_screen.c b/src/gallium/drivers/nvfx/nvfx_screen.c
index f56c697..4085ec7 100644
--- a/src/gallium/drivers/nvfx/nvfx_screen.c
+++ b/src/gallium/drivers/nvfx/nvfx_screen.c
@@ -469,10 +469,13 @@ nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
 	unsigned eng3d_class = 0;
 	int ret, i;
 
-	if (!screen)
+	if (!screen) {
+		ws->destroy(ws);
 		return NULL;
+	}
 
 	pscreen = &screen->base.base;
+	pscreen->winsys = ws;
 
 	ret = nouveau_screen_init(&screen->base, dev);
 	if (ret) {
@@ -484,7 +487,6 @@ nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
 	chan->user_private = screen;
 	chan->flush_notify = nvfx_channel_flush_notify;
 
-	pscreen->winsys = ws;
 	pscreen->destroy = nvfx_screen_destroy;
 	pscreen->get_param = nvfx_screen_get_param;
 	pscreen->get_shader_param = nvfx_screen_get_shader_param;
diff --git a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c
index 7d7a276..d7a6bf7 100644
--- a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c
+++ b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c
@@ -30,6 +30,7 @@ nouveau_drm_screen_create(int fd)
 	struct nouveau_winsys *nvws;
 	struct pipe_winsys *ws;
 	struct nouveau_device *dev = NULL;
+	struct pipe_screen *screen;
 	struct pipe_screen *(*init)(struct pipe_winsys *,
 				    struct nouveau_device *);
 	int ret;
@@ -68,11 +69,12 @@ nouveau_drm_screen_create(int fd)
 	ws = &nvws->base;
 	ws->destroy = nouveau_drm_destroy_winsys;
 
-	nvws->pscreen = init(ws, dev);
-	if (!nvws->pscreen) {
-		ws->destroy(ws);
+	screen = init(ws, dev);
+	if (!screen)
+		/* winsys was destroyed by init */
 		return NULL;
-	}
+
+	nvws->pscreen = screen;
 
 	return nvws->pscreen;
 }
-- 
1.7.8.rc3



More information about the Nouveau mailing list