changeset 4730:cf546095c072

6308191 mapelfexec() may fail with ENOMEM if a non-zero p_vaddr is specified for an ET_DYN binary 6576832 lx_elfexec sets brkbase to 0 for statically linked linux binaries 6577878 IPv6 sockets in lx brand not supported but creation allowed 6581316 lx_branded processes missing AT_CLKTCK entry from auxhilary vector
author eh208807
date Wed, 25 Jul 2007 16:32:57 -0700
parents 5261ba77b352
children e202adc835b4
files usr/src/lib/brand/lx/lx_brand/common/socket.c usr/src/uts/common/brand/lx/os/lx_brand.c usr/src/uts/common/brand/lx/sys/lx_brand.h usr/src/uts/common/exec/elf/elf.c usr/src/uts/common/sys/auxv.h
diffstat 5 files changed, 110 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/brand/lx/lx_brand/common/socket.c	Wed Jul 25 16:08:46 2007 -0700
+++ b/usr/src/lib/brand/lx/lx_brand/common/socket.c	Wed Jul 25 16:32:57 2007 -0700
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -449,6 +449,10 @@
 		return (err);
 
 	lx_debug("\tsocket(%d, %d, %d)", domain, type, protocol);
+
+	/* Right now IPv6 sockets don't work */
+	if (domain == AF_INET6)
+		return (-EAFNOSUPPORT);
 	fd = socket(domain, type, protocol);
 	if (fd >= 0)
 		return (fd);
@@ -727,14 +731,14 @@
 	 * call, and resetting the action back to its previous value.
 	 */
 	if (nosigpipe) {
-	    newact.sa_handler = SIG_IGN;
-	    newact.sa_flags = 0;
-	    (void) sigemptyset(&newact.sa_mask);
+		newact.sa_handler = SIG_IGN;
+		newact.sa_flags = 0;
+		(void) sigemptyset(&newact.sa_mask);
 
-	    if (sigaction(SIGPIPE, &newact, &oact) < 0)
-		    lx_err_fatal(gettext(
-			"%s: could not ignore SIGPIPE to emulate "
-			"LX_MSG_NOSIGNAL"), "send()");
+		if (sigaction(SIGPIPE, &newact, &oact) < 0)
+			lx_err_fatal(gettext(
+			    "%s: could not ignore SIGPIPE to emulate "
+			    "LX_MSG_NOSIGNAL"), "send()");
 	}
 
 	r = send(sockfd, buf, len, flags);
@@ -774,14 +778,14 @@
 	 * call, and resetting the action back to its previous value.
 	 */
 	if (nosigpipe) {
-	    newact.sa_handler = SIG_IGN;
-	    newact.sa_flags = 0;
-	    (void) sigemptyset(&newact.sa_mask);
+		newact.sa_handler = SIG_IGN;
+		newact.sa_flags = 0;
+		(void) sigemptyset(&newact.sa_mask);
 
-	    if (sigaction(SIGPIPE, &newact, &oact) < 0)
-		    lx_err_fatal(gettext(
-			"%s: could not ignore SIGPIPE to emulate "
-			"LX_MSG_NOSIGNAL"), "recv()");
+		if (sigaction(SIGPIPE, &newact, &oact) < 0)
+			lx_err_fatal(gettext(
+			    "%s: could not ignore SIGPIPE to emulate "
+			    "LX_MSG_NOSIGNAL"), "recv()");
 	}
 
 	r = recv(sockfd, buf, len, flags);
@@ -831,14 +835,14 @@
 	 * call, and resetting the action back to its previous value.
 	 */
 	if (nosigpipe) {
-	    newact.sa_handler = SIG_IGN;
-	    newact.sa_flags = 0;
-	    (void) sigemptyset(&newact.sa_mask);
+		newact.sa_handler = SIG_IGN;
+		newact.sa_flags = 0;
+		(void) sigemptyset(&newact.sa_mask);
 
-	    if (sigaction(SIGPIPE, &newact, &oact) < 0)
-		    lx_err_fatal(gettext(
-			"%s: could not ignore SIGPIPE to emulate "
-			"LX_MSG_NOSIGNAL"), "sendto()");
+		if (sigaction(SIGPIPE, &newact, &oact) < 0)
+			lx_err_fatal(gettext(
+			    "%s: could not ignore SIGPIPE to emulate "
+			    "LX_MSG_NOSIGNAL"), "sendto()");
 	}
 
 	r = sendto(sockfd, buf, len, flags, to, tolen);
@@ -891,14 +895,14 @@
 	 * call, and resetting the action back to its previous value.
 	 */
 	if (nosigpipe) {
-	    newact.sa_handler = SIG_IGN;
-	    newact.sa_flags = 0;
-	    (void) sigemptyset(&newact.sa_mask);
+		newact.sa_handler = SIG_IGN;
+		newact.sa_flags = 0;
+		(void) sigemptyset(&newact.sa_mask);
 
-	    if (sigaction(SIGPIPE, &newact, &oact) < 0)
-		    lx_err_fatal(gettext(
-			"%s: could not ignore SIGPIPE to emulate "
-			"LX_MSG_NOSIGNAL"), "recvfrom()");
+		if (sigaction(SIGPIPE, &newact, &oact) < 0)
+			lx_err_fatal(gettext(
+			    "%s: could not ignore SIGPIPE to emulate "
+			    "LX_MSG_NOSIGNAL"), "recvfrom()");
 	}
 
 	r = recvfrom(sockfd, buf, len, flags, from, from_lenp);
@@ -1147,14 +1151,14 @@
 	 * call, and resetting the action back to its previous value.
 	 */
 	if (nosigpipe) {
-	    newact.sa_handler = SIG_IGN;
-	    newact.sa_flags = 0;
-	    (void) sigemptyset(&newact.sa_mask);
+		newact.sa_handler = SIG_IGN;
+		newact.sa_flags = 0;
+		(void) sigemptyset(&newact.sa_mask);
 
-	    if (sigaction(SIGPIPE, &newact, &oact) < 0)
-		    lx_err_fatal(gettext(
-			"%s: could not ignore SIGPIPE to emulate "
-			"LX_MSG_NOSIGNAL"), "sendmsg()");
+		if (sigaction(SIGPIPE, &newact, &oact) < 0)
+			lx_err_fatal(gettext(
+			    "%s: could not ignore SIGPIPE to emulate "
+			    "LX_MSG_NOSIGNAL"), "sendmsg()");
 	}
 
 	r = _so_sendmsg(sockfd, (struct msghdr *)&msg, flags | MSG_XPG4_2);
@@ -1225,14 +1229,14 @@
 	 * call, and resetting the action back to its previous value.
 	 */
 	if (nosigpipe) {
-	    newact.sa_handler = SIG_IGN;
-	    newact.sa_flags = 0;
-	    (void) sigemptyset(&newact.sa_mask);
+		newact.sa_handler = SIG_IGN;
+		newact.sa_flags = 0;
+		(void) sigemptyset(&newact.sa_mask);
 
-	    if (sigaction(SIGPIPE, &newact, &oact) < 0)
-		    lx_err_fatal(gettext(
-			"%s: could not ignore SIGPIPE to emulate "
-			"LX_MSG_NOSIGNAL"), "recvmsg()");
+		if (sigaction(SIGPIPE, &newact, &oact) < 0)
+			lx_err_fatal(gettext(
+			    "%s: could not ignore SIGPIPE to emulate "
+			    "LX_MSG_NOSIGNAL"), "recvmsg()");
 	}
 
 	r = _so_recvmsg(sockfd, (struct msghdr *)&msg, flags | MSG_XPG4_2);
--- a/usr/src/uts/common/brand/lx/os/lx_brand.c	Wed Jul 25 16:08:46 2007 -0700
+++ b/usr/src/uts/common/brand/lx/os/lx_brand.c	Wed Jul 25 16:32:57 2007 -0700
@@ -711,15 +711,41 @@
 			 * calculated address from above.
 			 */
 			edp->ed_ldentry = edp->ed_entry;
+
+			/*
+			 * In all situations except an ET_DYN elf object with no
+			 * interpreter, we want to leave the brk and base
+			 * values set by mapexec_brand alone. Normally when
+			 * running ET_DYN objects on Solaris (most likely
+			 * /lib/ld.so.1) the kernel sets brk and base to 0 since
+			 * it doesn't know where to put the heap, and later the
+			 * linker will call brk() to initialize the heap in:
+			 *	usr/src/cmd/sgs/rtld/common/setup.c:setup()
+			 * after it has determined where to put it.  (This
+			 * decision is made after the linker loads and inspects
+			 * elf properties of the target executable being run.)
+			 *
+			 * So for ET_DYN Linux executables, we also don't know
+			 * where the heap should go, so we'll set the brk and
+			 * base to 0.  But in this case the Solaris linker will
+			 * not initialize the heap, so when the Linux linker
+			 * starts running there is no heap allocated.  This
+			 * seems to be ok on Linux 2.4 based systems because the
+			 * Linux linker/libc fall back to using mmap() to
+			 * allocate memory. But on 2.6 systems, running
+			 * applications by specifying them as command line
+			 * arguments to the linker results in segfaults for an
+			 * as yet undetermined reason (which seems to indicatej
+			 * that a more permanent fix for heap initalization in
+			 * these cases may be necessary).
+			 */
+			if (ehdr.e_type == ET_DYN) {
+				env.ex_bssbase = (caddr_t)0;
+				env.ex_brkbase = (caddr_t)0;
+				env.ex_brksize = 0;
+			}
 		}
 
-		/*
-		 * Delay setting the brkbase until the first call to brk();
-		 * see elfexec() for details.
-		 */
-		env.ex_bssbase = (caddr_t)0;
-		env.ex_brkbase = (caddr_t)0;
-		env.ex_brksize = 0;
 	}
 
 	env.ex_vp = vp;
@@ -732,6 +758,14 @@
 	 * what's on the process stack.
 	 */
 	phdr_auxv32[0].a_un.a_val = edp->ed_phdr;
+
+	/*
+	 * Linux 2.6 programs such as ps will print an error message if the
+	 * following aux entry is missing
+	 */
+	phdr_auxv32[1].a_type = AT_CLKTCK;
+	phdr_auxv32[1].a_un.a_val = hz;
+
 	if (copyout(&phdr_auxv32, args->auxp_brand,
 	    sizeof (phdr_auxv32)) == -1)
 		return (EFAULT);
--- a/usr/src/uts/common/brand/lx/sys/lx_brand.h	Wed Jul 25 16:08:46 2007 -0700
+++ b/usr/src/uts/common/brand/lx/sys/lx_brand.h	Wed Jul 25 16:32:57 2007 -0700
@@ -80,6 +80,9 @@
 /* Aux vector containing phdr of linux executable, used by lx_librtld_db */
 #define	AT_SUN_BRAND_LX_PHDR	AT_SUN_BRAND_AUX1
 
+/* Aux vector containing hz value */
+#define	AT_CLKTCK	17
+
 #ifndef	_ASM
 
 typedef struct lx_brand_registration {
--- a/usr/src/uts/common/exec/elf/elf.c	Wed Jul 25 16:08:46 2007 -0700
+++ b/usr/src/uts/common/exec/elf/elf.c	Wed Jul 25 16:32:57 2007 -0700
@@ -1124,6 +1124,22 @@
 		if (addr == NULL)
 			return (ENOMEM);
 		*voffset = (intptr_t)addr;
+
+		/*
+		 * Calculate the minimum vaddr so it can be subtracted out.
+		 * According to the ELF specification, since PT_LOAD sections
+		 * must be sorted by increasing p_vaddr values, this is
+		 * guaranteed to be the first PT_LOAD section.
+		 */
+		phdr = (Phdr *)phdrbase;
+		for (i = nphdrs; i > 0; i--) {
+			if (phdr->p_type == PT_LOAD) {
+				*voffset -= (uintptr_t)phdr->p_vaddr;
+				break;
+			}
+			phdr = (Phdr *)((caddr_t)phdr + hsize);
+		}
+
 	} else {
 		*voffset = 0;
 	}
--- a/usr/src/uts/common/sys/auxv.h	Wed Jul 25 16:08:46 2007 -0700
+++ b/usr/src/uts/common/sys/auxv.h	Wed Jul 25 16:32:57 2007 -0700
@@ -92,7 +92,8 @@
  * in the draft amd64 ABI.
  *
  * At the time of writing, Solaris doesn't place any of these values into
- * the aux vector; we do similar things via AT_SUN_ values.
+ * the aux vector, except AT_CLKTCK which is placed on the aux vector for
+ * lx branded processes; also, we do similar things via AT_SUN_ values.
  *
  * AT_NOTELF		10	program is not ELF?
  * AT_UID		11	real user id
@@ -139,7 +140,7 @@
  * These attributes communicate performance -hints- about processor
  * hardware capabilities that might be useful to library implementations.
  */
-#define	AT_SUN_HWCAP    2009
+#define	AT_SUN_HWCAP	2009
 
 #if defined(_KERNEL)
 /*