[PATCH v2] privates: Clear screen-specific keys during CloseScreen

Aaron Plattner aplattner at nvidia.com
Thu Sep 17 13:19:59 PDT 2015


The modesetting driver corrupts memory when used after a server regeneration
because not enough memory is allocated for its pixmap privates.  This happens
because its call to dixRegisterScreenSpecificPrivateKey() does nothing because
key->initialized is still TRUE from the first server generation.  However, the
key is not in the screen's linked list of screen-specific privates because
that's freed and reallocated during the server generation loop in dix_main().

Fix this by clearing key->initialized after CloseScreen.  Move the call to
dixFreeScreenSpecificPrivates() after the call to CloseScreen, in case a
driver's CloseScreen needs a screen private for something.

Finally, add a call to dixFreeScreenSpecificPrivates() for GPU screens.

Signed-off-by: Aaron Plattner <aplattner at nvidia.com>
---
Keith,

I was thinking about your suggestion of ignoring key->initialized backwards
yesterday.  I think that would work too, but I think this is clearer and more
explicit.

 dix/main.c     | 3 ++-
 dix/privates.c | 9 +++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/dix/main.c b/dix/main.c
index 09f9504b8acb..43f176f2d3b3 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -338,6 +338,7 @@ dix_main(int argc, char *argv[], char *envp[])
             ScreenPtr pScreen = screenInfo.gpuscreens[i];
             FreeScratchPixmapsForScreen(pScreen);
             (*pScreen->CloseScreen) (pScreen);
+            dixFreeScreenSpecificPrivates(pScreen);
             dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
             free(pScreen);
             screenInfo.numGPUScreens = i;
@@ -347,8 +348,8 @@ dix_main(int argc, char *argv[], char *envp[])
             FreeScratchPixmapsForScreen(screenInfo.screens[i]);
             FreeGCperDepth(i);
             FreeDefaultStipple(i);
-            dixFreeScreenSpecificPrivates(screenInfo.screens[i]);
             (*screenInfo.screens[i]->CloseScreen) (screenInfo.screens[i]);
+            dixFreeScreenSpecificPrivates(screenInfo.screens[i]);
             dixFreePrivates(screenInfo.screens[i]->devPrivates, PRIVATE_SCREEN);
             free(screenInfo.screens[i]);
             screenInfo.numScreens = i;
diff --git a/dix/privates.c b/dix/privates.c
index e03b2255b7f3..969d0141c844 100644
--- a/dix/privates.c
+++ b/dix/privates.c
@@ -642,6 +642,15 @@ dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key,
 void
 dixFreeScreenSpecificPrivates(ScreenPtr pScreen)
 {
+    DevPrivateType t;
+
+    for (t = PRIVATE_XSELINUX; t < PRIVATE_LAST; t++) {
+        DevPrivateKey key;
+
+        for (key = pScreen->screenSpecificPrivates[t].key; key; key = key->next) {
+            key->initialized = FALSE;
+        }
+    }
 }
 
 /* Initialize screen-specific privates in AddScreen */
-- 
2.5.2



More information about the xorg-devel mailing list