--- pathnames.h.orig	Thu Jun  6 19:57:34 2002
+++ pathnames.h	Wed Jul 24 14:47:06 2002
@@ -146,8 +146,8 @@
 #endif
 
 /* chroot directory for unprivileged user when UsePrivilegeSeparation=yes */
-#ifndef _PATH_PRIVSEP_CHROOT_DIR
-#define _PATH_PRIVSEP_CHROOT_DIR	"/var/empty"
+#ifndef _PATH_PRIVSEP_CHROOT_TEMPLATE
+#define _PATH_PRIVSEP_CHROOT_TEMPLATE	"/var/tmp/sshd.XXXXXXXXXX"
 #endif
 
 #ifndef _PATH_LS
--- sshd.c.orig	Tue Jun 25 23:24:19 2002
+++ sshd.c	Wed Jul 24 14:52:41 2002
@@ -550,14 +550,9 @@
 	memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));
 	endpwent();
 
-	/* Change our root directory*/
-	if (chroot(_PATH_PRIVSEP_CHROOT_DIR) == -1)
-		fatal("chroot(\"%s\"): %s", _PATH_PRIVSEP_CHROOT_DIR,
-		    strerror(errno));
-	if (chdir("/") == -1)
-		fatal("chdir(\"/\"): %s", strerror(errno));
-
-	/* Drop our privileges */
+	/* Change our root directory and drop privileges */
+	if (chroot(".") < 0)
+		fatal("chroot(): %s\n", strerror(errno));
 	debug3("privsep user:group %u:%u", (u_int)pw->pw_uid,
 	    (u_int)pw->pw_gid);
 #if 0
@@ -576,6 +571,7 @@
 static Authctxt*
 privsep_preauth(void)
 {
+	char emptydir[] = _PATH_PRIVSEP_CHROOT_TEMPLATE;
 	Authctxt *authctxt = NULL;
 	int status;
 	pid_t pid;
@@ -585,12 +581,32 @@
 	/* Store a pointer to the kex for later rekeying */
 	pmonitor->m_pkex = &xxx_kex;
 
+	/*
+	 * We create a safe environment for the child by creating an empty
+	 * directory into which the child chroots, and the parent prevents
+	 * others from fooling around with it by removing the directory. We do
+	 * it this way because the child can't remove its own current working
+	 * directory (except on some systems by giving an absolute path to
+	 * rmdir, but it is highly dependent on the OS and filesystem). We
+	 * create the directory in /var/tmp in order that we are more likely
+	 * to get a well-behaved disk filesystem.
+	 */
+	if (mkdtemp(emptydir) == NULL)
+		fatal("mkdtemp(\"%s\"): %s", emptydir, strerror(errno));
+
 	pid = fork();
 	if (pid == -1) {
 		fatal("fork of unprivileged child failed");
 	} else if (pid != 0) {
 		debug2("Network child is on pid %ld", (long)pid);
 
+		/* Wait for the child to chdir then remove the directory */
+		if (read(pmonitor->m_recvfd, &status, 1) < 0)
+			fatal("read(): %s", strerror(errno));
+		if (rmdir(emptydir) < 0)
+			fatal("rmdir(\"%s\"): %s", emptydir, strerror(errno));
+		debug3("parent rmdir %s", emptydir);
+
 		close(pmonitor->m_recvfd);
 		authctxt = monitor_child_preauth(pmonitor);
 		close(pmonitor->m_sendfd);
@@ -606,6 +622,11 @@
 	} else {
 		/* child */
 
+		if (chdir(emptydir) == -1)
+			fatal("chdir(\"%s\"): %s", emptydir, strerror(errno));
+		debug3("unprivileged child chdir to %s", emptydir);
+		if (write(pmonitor->m_sendfd, &status, 1) < 0)
+			fatal("write(): %s", strerror(errno));
 		close(pmonitor->m_sendfd);
 
 		/* Demote the child */
@@ -1026,18 +1047,10 @@
 
 	if (use_privsep) {
 		struct passwd *pw;
-		struct stat st;
 
 		if ((pw = getpwnam(SSH_PRIVSEP_USER)) == NULL)
 			fatal("Privilege separation user %s does not exist",
 			    SSH_PRIVSEP_USER);
-		if ((stat(_PATH_PRIVSEP_CHROOT_DIR, &st) == -1) ||
-		    (S_ISDIR(st.st_mode) == 0))
-			fatal("Missing privilege separation directory: %s",
-			    _PATH_PRIVSEP_CHROOT_DIR);
-		if (st.st_uid != 0 || (st.st_mode & (S_IWGRP|S_IWOTH)) != 0)
-			fatal("Bad owner or mode for %s",
-			    _PATH_PRIVSEP_CHROOT_DIR);
 	}
 
 	/* Configuration looks good, so exit if in test mode. */

