open-src/xserver/xorg/sun-src/os/dtlogin.c
changeset 1688 163df3d7b55f
parent 1568 f85b5a8a5c43
--- 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);