25299058 Xorg not receiving gdm-login user credentials for running user-ID s12_116
authorAlan Coopersmith <Alan.Coopersmith@Oracle.COM>
Wed, 11 Jan 2017 13:44:10 -0800
changeset 1688 163df3d7b55f
parent 1687 9d75ffd8fd42
child 1689 3233071f2137
25299058 Xorg not receiving gdm-login user credentials for running user-ID
open-src/xserver/xorg/21206921.patch
open-src/xserver/xorg/sun-src/os/dtlogin.c
--- a/open-src/xserver/xorg/21206921.patch	Wed Jan 04 21:31:20 2017 -0800
+++ b/open-src/xserver/xorg/21206921.patch	Wed Jan 11 13:44:10 2017 -0800
@@ -1,44 +1,53 @@
---- a/hw/xfree86/os-support/solaris/sun_vid.c	Fri Jun  5 08:19:40 2015
-+++ b/hw/xfree86/os-support/solaris/sun_vid.c	Thu Nov 12 14:44:00 2015
+diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
+index 6570f0b..85d698f 100644
+--- a/hw/xfree86/common/xf86Events.c
++++ b/hw/xfree86/common/xf86Events.c
+@@ -558,6 +558,16 @@ xf86VTEnter(void)
+     if (!xf86VTSwitchTo())
+         return;
+ 
++#ifdef __sun  /* restore root privs needed to restore device access */
++    uid_t user_id = geteuid();
++
++    if (user_id != 0) {
++        if (seteuid(0) < 0) {
++            xf86Msg(X_WARNING, "Error in resetting euid to root \n");
++        }
++    }
++#endif
++
+ #ifdef XF86PM
+     xf86OSPMClose = xf86OSPMOpen();
+ #endif
+@@ -600,6 +610,14 @@ xf86VTEnter(void)
+     xf86platformVTProbe();
+ #endif
+ 
++#ifdef __sun
++    if (user_id != 0) {               /* reset privs back to user */
++        if (seteuid(user_id) < 0) {
++            xf86Msg(X_WARNING, "Error in resetting euid to %d\n", user_id);
++        }
++    }
++#endif
++
+     xf86UpdateHasVTProperty(TRUE);
+ 
+     OsReleaseSIGIO();
+diff --git a/hw/xfree86/os-support/solaris/sun_vid.c b/hw/xfree86/os-support/solaris/sun_vid.c
+index 25f7618..7548f50 100644
+--- a/hw/xfree86/os-support/solaris/sun_vid.c
++++ b/hw/xfree86/os-support/solaris/sun_vid.c
 @@ -22,7 +22,7 @@
   * OF THIS SOFTWARE.
   *
   */
 -/* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
-+/* Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
++/* Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
   *
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"),
-@@ -81,14 +81,27 @@
- xf86EnableIO(void)
- {
- #if defined(__i386__) || defined(__i386) || defined(__x86)
-+    uid_t user_id;
-     if (ExtendedEnabled)
-         return TRUE;
-+    user_id = geteuid();
-+    if (user_id != 0) {               /* reset privs back to root */
-+        if (seteuid(0) < 0) {
-+            xf86Msg(X_WARNING, "Error in resetting euid to root \n");
-+        }
-+    }
- 
-     if (sysi86(SI86V86, V86SC_IOPL, PS_IOPL) < 0) {
-         xf86Msg(X_WARNING, "xf86EnableIOPorts: Failed to set IOPL for I/O\n");
-         return FALSE;
-     }
--    ExtendedEnabled = TRUE;
-+    else 
-+	ExtendedEnabled = TRUE;
-+    if (user_id != 0) {               /* reset privs back to user */
-+      	if (seteuid(user_id) < 0) {
-+           xf86Msg(X_WARNING, "Error in resetting euid to %d\n", user_id);
-+	}
-+    }
- #endif                          /* i386 */
-     return TRUE;
- }
-@@ -100,8 +113,9 @@
+@@ -100,8 +100,9 @@ xf86DisableIO(void)
      if (!ExtendedEnabled)
          return;
  
--- a/open-src/xserver/xorg/sun-src/os/dtlogin.c	Wed Jan 04 21:31:20 2017 -0800
+++ b/open-src/xserver/xorg/sun-src/os/dtlogin.c	Wed Jan 11 13:44:10 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -84,10 +84,10 @@
 struct dmuser {
     uid_t	uid;
     gid_t	gid;			/* Primary group */
-    gid_t	groupids[NGROUPS_UMAX];	/* Supplementary groups */
-    int		groupid_cnt;
     char *	homedir;
     projid_t	projid;
+    int		groupid_cnt;
+    gid_t	groupids[NGROUPS_UMAX];	/* Supplementary groups */
 };
 
 /* Data passed to block/wakeup handlers */
@@ -95,7 +95,7 @@
     int		pipeFD;
     char *	pipename;	/* path to pipe */
     char *	buf;		/* contains characters to be processed */
-    int		bufsize;	/* size allocated for buf */
+    size_t	bufsize;	/* size allocated for buf */
     struct dmuser user;		/* target user, to switch to on login */
 };
 
@@ -118,9 +118,12 @@
 static void dtlogin_process(struct dmuser *user, int user_logged_in);
 static void dtlogin_close_pipe(struct dmdata *);
 
-#define DtloginError(fmt, arg)	LogMessageVerb(X_ERROR, 1, fmt ": %s\n", \
-						arg, strerror(errno))
-#define DtloginInfo(fmt, arg)	LogMessageVerb(X_INFO, 5, fmt, arg)
+#define DtloginError(fmt, ...) \
+    LogMessageVerb(X_ERROR, 1, "dtlogin: " fmt ": %s\n", __VA_ARGS__, \
+		   strerror(errno))
+
+#define DtloginInfo(fmt, ...) \
+    LogMessageVerb(X_INFO,  5, "dtlogin: " fmt, __VA_ARGS__)
 
 /*
  * initialize DTLOGIN: create pipe; set handlers.
@@ -178,10 +181,7 @@
 _X_HIDDEN void
 DtloginCloseDown(void)
 {
-    if (geteuid() != 0) {		/* reset privs back to root */
-	if (seteuid(0) < 0) {
-	    DtloginError("Error in resetting euid to %d", 0);
-	}
+    if (geteuid() != originalUser.uid) {
 	dtlogin_process(&originalUser, 0);
     }
 
@@ -199,7 +199,8 @@
 
     /* Unwrap CloseScreen and call down to further levels */
     pScreenPriv = (struct dmScreenPriv *)
-	dixLookupPrivate(&pScreen->devPrivates, dmScreenKey);
+	dixGetPrivate(&pScreen->devPrivates, dmScreenKey);
+    dixSetPrivate(&pScreen->devPrivates, dmScreenKey, NULL);
 
     pScreen->CloseScreen = pScreenPriv->CloseScreen;
     free (pScreenPriv);
@@ -261,10 +262,13 @@
 
     snprintf(pipename, sizeof(pipename), "%s/%d", DTLOGIN_PATH, port);
 
-    if (mkfifo(pipename, S_IRUSR | S_IWUSR) < 0)
+    if (mkfifo(pipename, S_IRUSR | S_IWUSR) < 0) {
+	DtloginError("Cannot create display manager pipe %s", pipename);
 	return -1;
+    }
 
-    if ((pipeFD = open(pipename, O_RDONLY | O_NONBLOCK)) < 0) {
+    if ((pipeFD = open(pipename, O_RDWR | O_NONBLOCK)) < 0) {
+	DtloginError("Cannot open display manager pipe %s", pipename);
 	remove(pipename);
 	return -1;
     }
@@ -274,6 +278,7 @@
     /* To make sure root has rw permissions. */
     (void) fchmod(pipeFD, 0600);
 
+    DtloginInfo("Created display manager pipe: %s\n", dmd->pipename);
     return pipeFD;
 }
 
@@ -282,6 +287,7 @@
     RemoveBlockAndWakeupHandlers (DtloginBlockHandler,
 				  DtloginWakeupHandler, dmd);
 
+    DtloginInfo("Closing display manager pipe: %s\n", dmd->pipename);
     close(dmd->pipeFD);
     remove(dmd->pipename);
     free(dmd->pipename);
@@ -297,14 +303,22 @@
 static void
 dtlogin_receive_packet(struct dmdata *dmd)
 {
-    int bufLen, nbRead;
+    size_t bufLen;
+    ssize_t nbRead;
     char *p, *n;
     int done = 0;
 
     if (dmd->buf == NULL) {
-	dmd->bufsize = BUFLEN;
-	dmd->buf = malloc(dmd->bufsize);
-	dmd->buf[0] = '\0';
+	dmd->buf = malloc(BUFLEN);
+	if (dmd->buf != NULL) {
+	    dmd->buf[0] = '\0';
+	    dmd->bufsize = BUFLEN;
+	} else {
+	    DtloginError("Failed to allocate display manager pipe buffer of %d",
+			 BUFLEN);
+	    dtlogin_close_pipe(dmd);
+	    return;
+	}
     }
 
     /* Read data from pipe and split into tokens, buffering the rest */
@@ -316,8 +330,11 @@
 	 * delimiter yet. Keep track of alloced size.
 	 */
 	if (bufLen > (dmd->bufsize/2)) {
-	    dmd->bufsize += BUFLEN;
-	    dmd->buf = realloc(dmd->buf, dmd->bufsize);
+	    char *newbuf = realloc(dmd->buf, dmd->bufsize + BUFLEN);
+	    if (newbuf != NULL) {
+		dmd->buf = newbuf;
+		dmd->bufsize += BUFLEN;
+	    }
 	}
 
 	nbRead = read(dmd->pipeFD, dmd->buf + bufLen,
@@ -329,12 +346,16 @@
 	    } else if (errno == EAGAIN) {
 		return; 	/* return to WaitFor, wait for select() */
 	    } else {
+		DtloginError("Unexpected error on display manager pipe %s",
+			     dmd->pipename);
 		dtlogin_close_pipe(dmd);
 		return;
 	    }
 	}
 
 	if (nbRead == 0) { /* End of file */
+	    DtloginError("Unexpected EOF on display manager pipe %s",
+			 dmd->pipename);
 	    dtlogin_close_pipe(dmd);
 	    return;
 	}
@@ -350,16 +371,17 @@
 	    DtloginInfo("Next packet: %s\n", p);
 	    done = dtlogin_parse_packet(dmd, p);
 	    if (done) {
-		dtlogin_close_pipe(dmd);	/* free's dmd */
-		return;
+		break;
 	    }
 	    p = n+1;
 	}
 
 	/* save the rest for the next iteration */
-	if (p < (dmd->buf + bufLen)) {
+	if (!done && (p < (dmd->buf + bufLen))) {
 	    DtloginInfo("Left over: %s\n", p);
 	    strcpy(dmd->buf, p);
+	} else {
+	    dmd->buf[0] = '\0';
 	}
     }
 }
@@ -415,8 +437,7 @@
 
 	s = p + 1; /* start of next pair */
 
-	DtloginInfo("Received key \"%s\" =>", k);
-	DtloginInfo(" value \"%s\"\n", v);
+	DtloginInfo("Received key \"%s\" => value \"%s\"\n", k, v);
 
 	/* Found key & value, now process & put into dmd */
 	if (strcmp(k, "EOF") == 0) {
@@ -477,11 +498,18 @@
     struct passwd *ppasswd;
     const char *auth_file = NULL;
 
+    if (geteuid() != 0) {		/* reset privs back to root */
+	if (seteuid(0) < 0) {
+	    DtloginError("Error in resetting euid to %d", 0);
+	}
+    }
+
     auth_file = GetAuthFilename();
 
     if (auth_file) {
 	if (chown(auth_file, user->uid, user->gid) < 0)
-	    DtloginError("Error in changing owner to %d", user->uid);
+	    DtloginError("Error in changing owner of %s to %d",
+			 auth_file, user->uid);
     }
 
     /* This gid dance is necessary in order to make sure
@@ -524,6 +552,11 @@
 	if (ppasswd == NULL) {
 	    DtloginError("Error in getting user name for %d", user->uid);
 	} else {
+	    if (strcmp(ppasswd->pw_name, "gdm") == 0) {
+		/* Avoid trying to screenlock the login screen with a
+		   non-existent password for the gdm user */
+		user_logged_in = 0;
+	    }
 	    if (getdefaultproj(ppasswd->pw_name, &proj,
 			       (void *)&proj_buf, PROJECT_BUFSZ) == NULL) {
 		DtloginError("Error in getting project id for %s",
@@ -557,19 +590,23 @@
 		for (i = 0; i < screenInfo.numScreens; i++)
 		{
 		    ScreenPtr pScreen = screenInfo.screens[i];
-		    struct dmScreenPriv *pScreenPriv
-			= calloc(1, sizeof(struct dmScreenPriv));
+		    struct dmScreenPriv *pScreenPriv = (struct dmScreenPriv *)
+			dixLookupPrivate(&pScreen->devPrivates, dmScreenKey);
 
-		    dixSetPrivate(&pScreen->devPrivates, dmScreenKey,
-				  pScreenPriv);
+		    if (pScreenPriv == NULL) {
+			pScreenPriv = calloc(1, sizeof(struct dmScreenPriv));
 
-		    if (pScreenPriv != NULL) {
-			pScreenPriv->CloseScreen = pScreen->CloseScreen;
-			pScreen->CloseScreen = DtloginCloseScreen;
-		    } else {
-			DtloginError("Failed to allocate %d bytes"
-				     " for uid reset info",
-				     (int) sizeof(struct dmScreenPriv));
+			if (pScreenPriv != NULL) {
+			    pScreenPriv->CloseScreen = pScreen->CloseScreen;
+			    pScreen->CloseScreen = DtloginCloseScreen;
+
+			    dixSetPrivate(&pScreen->devPrivates, dmScreenKey,
+					  pScreenPriv);
+			} else {
+			    DtloginError("Failed to allocate %d bytes"
+					 " for screen privates",
+					 (int) sizeof(struct dmScreenPriv));
+			}
 		    }
 		}
 	    } else {
@@ -580,9 +617,9 @@
     }
 
     if (user->homedir != NULL) {
-	char *env_str = Xprintf("HOME=%s", user->homedir);
+	char *env_str;
 
-	if (env_str == NULL) {
+	if (asprintf(&env_str, "HOME=%s", user->homedir) == -1) {
 	    DtloginError("Not enough memory to setenv HOME=%s", user->homedir);
 	} else {
 	    DtloginInfo("Setting %s\n",env_str);