Problems with OpenSSH 2.5.1p1 on Solaris 8

Drazen Kacar dave at arsdigita.com
Tue Feb 27 09:40:47 EST 2001


Hi,

I'm not subscribed, so keep me in cc. And thanks for having mailing-list
open for posting.

I had a couple of problems with OpenSSH on Solaris 8/MU3 + recent patches.

1) When I tried to use scp from any other host, sshd on Solaris host
   crashed with SIGSEGV. Here's the stack trace:

core 'core.sshd.7637' of 7637:  ./sshd -d -d -d
 fefb393c strncpy  (ffbee074, 5, 7, 0, 21f2c, ffbee074) + 65c
 ff0561a8 pam_sm_open_session (4, 0, 3e938, 0, ff076000, 0) + 17c
 ff362b80 pam_open_session (ff3765c8, 0, ff376000, 13, 13, 0) + c8
 0002e9c0 x11_connect_display (8f4a8, 0, 0, 0, 0, 0) + 104
 0003a470 ???????? (9f5b0, 8d698, 0, 0, 0, 0)
 0003941c ssh_dss_verify (88414, 9f5b0, 8d698, ffbeee50, 219b4, 38564) +
160
 0003904c ssh_dss_sign (8d698, 0, 8d290, 400, 8d26c, 8f498)
 0002a2b8 get_remote_hostname (5, 5, 28e, ffbef8c4, 4, 1) + 44
 000278d0 session_open (4, ffbef94c, ffbef960, 80c00, 0, 0) + 5c
 00024970 server_loop (0, 0, 0, 0, 0, 0) + 530


The relevant code is function do_pam_session() in auth-pam.c. The stack
trace leads me to believe that there is a bug in Solaris pam_unix
module, which is triggered if pam_open_session() is called, but PAM_TTY
is not set with pam_set_item(). I worked around the problem by disabling
pam_open_session() call if ttyname == NULL, but I haven't investigated
the problem further.

2) OpenSSH does not read the default PATH from /etc/default/login. That's
   really bad, so I implemented the feature. The patch is attached. The code
   is guarded by HAVE_ETC_DEFAULT_LOGIN. I didn't make autoconf check,
   because I don't know if it's appropriate, ie. if there is any other
   system which has /etc/default/login, but with a different syntax.
   I'm also assuming that <sys/mman.h> and mmap() will be available
   if HAVE_ETC_DEFAULT_LOGIN is defined, which might not be true for
   all systems. So integrate it as you see fit.

-- 
 .-.   .-.    Sarcasm is just one more service we offer.
(_  \ /  _)
     |        dave at arsdigita.com
     |
-------------- next part --------------
--- session.c.orig	Mon Feb 26 14:36:13 2001
+++ session.c	Mon Feb 26 17:03:10 2001
@@ -78,6 +78,10 @@
 #define is_winnt       (GetVersion() < 0x80000000)
 #endif
 
+#ifdef HAVE_ETC_DEFAULT_LOGIN
+#include <sys/mman.h>
+#endif
+
 /* AIX limits */
 #if defined(HAVE_GETUSERATTR) && !defined(S_UFSIZE_HARD) && defined(S_UFSIZE)
 # define S_UFSIZE_HARD  S_UFSIZE "_hard"
@@ -1173,6 +1177,12 @@
 #endif
 
 	if (!options.use_login) {
+#ifdef HAVE_ETC_DEFAULT_LOGIN
+	    	int fd, pagesize;
+		struct stat inode;
+		char *onemore = MAP_FAILED, *logstr = MAP_FAILED;
+		char *pathstr;
+#endif
 		/* Set basic environment. */
 		child_set_env(&env, &envsize, "USER", pw->pw_name);
 		child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
@@ -1188,7 +1198,83 @@
 		 * needed for loading shared libraries. So the path better
 		 * remains intact here.
 		 */
+#  ifdef HAVE_ETC_DEFAULT_LOGIN
+		if ((fd = open("/etc/default/login", O_RDONLY)) < 0)
+		    	goto nocando;
+
+		if (fstat(fd, &inode) != 0 || inode.st_size < 6) {
+		    	close(fd);
+			goto nocando;
+		}
+		logstr = mmap(NULL, inode.st_size, PROT_READ, MAP_SHARED,
+			      fd, 0);
+		close(fd);
+		if(logstr == MAP_FAILED)
+		    	goto nocando;
+		pagesize = getpagesize();
+		if (inode.st_size % pagesize == 0) {
+			/*
+			 * Append one more page, because we need
+			 * zero at EOF, otherwise string and memory
+			 * functions could get SIGSEGV.
+			 */
+#ifdef MAP_ANON
+			onemore = mmap(logstr + inode.st_size, pagesize,
+				       PROT_READ,
+				       MAP_SHARED | MAP_FIXED | MAP_ANON,
+				       -1, 0);
+#else
+			int fd2;
+			if ((fd2 = open("/dev/zero", O_RDONLY)) < 0)
+				goto nocando;
+			onemore = mmap(logstr + inode.st_size, pagesize,
+				       PROT_READ,
+				       MAP_SHARED | MAP_FIXED,
+				       fd2, 0);
+			close(fd2);
+#endif
+			if(onemore == MAP_FAILED)
+			    	goto nocando;
+		}
+		if (!memcmp(logstr, "PATH=", 5))
+		    	pathstr = logstr - 1;
+		else
+		    	pathstr = strstr(logstr, "\nPATH=");
+		if (pathstr) {
+		    	char *nl;
+
+		    	pathstr += 6;
+		    	nl = strchr(pathstr, '\n');
+			if (!nl) {
+			    	/*
+				 * EOF, so PATH is the last line
+				 */
+			    	child_set_env(&env, &envsize, "PATH", pathstr);
+			} else {
+			    	char *mypath;
+				size_t path_len;
+
+				path_len = nl - pathstr;
+				mypath = xmalloc(path_len + 1);
+				memcpy(mypath, pathstr, path_len);
+				*(mypath + path_len) = 0;
+				child_set_env(&env, &envsize, "PATH", mypath);
+				xfree(mypath);
+			}
+		} else {
+nocando:
+		    	child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
+		}
+		/*
+		 * Cleanup the crap
+		 */
+		if(onemore != MAP_FAILED)
+		    	munmap(onemore, pagesize);
+		if(logstr != MAP_FAILED)
+		    	munmap(logstr, inode.st_size);
+#  else /* HAVE_ETC_DEFAULT_LOGIN */
 		child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
+#  endif /* HAVE_ETC_DEFAULT_LOGIN */
 # endif /* HAVE_CYGWIN */
 #endif /* HAVE_LOGIN_CAP */
 


More information about the openssh-unix-dev mailing list