[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[linux-security] KSR[T] Advisory #2: ld.so (fwd)





---------- Forwarded message ----------
Date: Thu, 17 Jul 1997 17:15:21 -0700 (PDT)
From: "KSR[T]" <ksrt@dec.net>
Reply-To: linux-security@redhat.com
To: bugtraq@netspace.org
Cc: linux-security@redhat.com
Subject: [linux-security] KSR[T] Advisory #2: ld.so
Resent-Date: 18 Jul 1997 07:23:47 -0000
Resent-From: linux-security@redhat.com
Resent-cc: recipient list not shown: ;

                                                          KSR[T] Advisory #002
                                                          Date:   Jul 16, 1997
                                                          ID #:   lin-ldso-002

Operating System(s): Linux

Affected Program:    ld.so / ld-linux.so

Problem Description: ld.so is the run-time linker used by dynamically linked
                     executables(a.out).  Inside the error reporting function 
                     there is a call to vsprintf, which doesn't check the size 
                     of the string it is storing in an automatic buffer.  

                     The ELF version of run-time linker(ld-linux.so) is 
                     vulnerable to an almost identical stack overwrite.

Compromise:          A local user that can execute any dynamically linked
                     setuid binary and can force ld.so to error, can execute
                     arbitrary code as root.

Patch/Fix:           Upgrade your ld.so to the latest version, or apply the
                     patch below provided by Alan Cox.


[mod: Caldera, LST, Red Hat, Suse, yggdrasil, Debian, unifix, wgs? and
delix? are stressing to make a patch available in their native format.
If your vendor is not on this list, please tell me in private mail. --
R.E.Wolff@BitWizard.nl]

---- cut here ----
--- ld.so-1.7.14/d-link/boot1.c	Thu Dec 14 19:08:19 1995
+++ ld.so-1.7.14-fixed/d-link/boot1.c	Wed Jul 16 15:37:11 1997
@@ -108,10 +108,12 @@
 #include "syscall.h"
 #include "string.h"
 
+#define ELF_LDSO_IMAGE "/lib/ld-linux.so.1"
+
 static char * _dl_malloc_addr, *_dl_mmap_zero;
 char * _dl_library_path = 0; /* Where we look for libraries */
 char *_dl_preload = 0; /* Things to be loaded before the libs. */
-char *_dl_progname = "/lib/ld-linux.so.1";
+char *_dl_progname = ELF_LDSO_IMAGE;
 static char * _dl_not_lazy = 0;
 static char * _dl_warn = 0; /* Used by ldd */
 static char * _dl_trace_loaded_objects = 0;
@@ -165,6 +167,45 @@
 #endif
 
 /*
+ *	Stop argv0 overflowing vsprintf, but also try to stop false positives
+ *	We obey the following rule
+ *
+ *	If namesize < 256  keep
+ *	If name from last / < 256 use that
+ *	else use ELF_LDSO_IMAGE
+ *
+ *	This ensures /very/long/stupid/nfs/path/we/often/get/foobarcmd
+ *	comes out at least as.  
+ *
+ *	foobarcmd: someerror
+ *
+ *	Even if we fix vsprintf to be vsnprintf (which we should), this
+ *	ought to be kept to help make real size limited errors clearer.
+ */
+ 
+static char *argv_remap(char *ptr)
+{
+	char *tmp;
+	if(strlen(ptr)<256)
+		return ptr;
+	if(!*ptr)
+		return ptr;
+	tmp=ptr+strlen(ptr)-1;
+	/*
+	 *	Walk back down the chain until we find a slash
+	 */
+	while(tmp>=ptr && *tmp!='/')
+		tmp--;
+	/*
+	 *	No slash, or too long after slash and Im not playing so nyah
+	 */
+	if(*tmp!='/')
+		return ELF_LDSO_IMAGE;
+	if(strlen(tmp)>256)	/* Not off by 1 .. strlen includes the / */
+		return ELF_LDSO_IMAGE;
+	return tmp+1;
+}
+/*
  * This stub function is used by some debuggers.  The idea is that they
  * can set an internal breakpoint on it, so that we are notified when the
  * address mapping is changed in some way.
@@ -487,7 +528,7 @@
   }
 
   if (argv[0])
-    _dl_progname = argv[0];
+    _dl_progname = argv_remap(argv[0]);
 
   /* Now we need to figure out what kind of options are selected.
    Note that for SUID programs we ignore the settings in LD_LIBRARY_PATH */
--- ld.so-1.7.14/ld-so/ld.so.c	Tue Nov 14 19:15:02 1995
+++ ld.so-1.7.14-fixed/ld-so/ld.so.c	Tue Jun 24 10:55:54 1997
@@ -151,6 +151,46 @@
 }
 #endif
 
+/*
+ *	Stop argv0 overflowing vsprintf, but also try to stop false positives
+ *	We obey the following rule
+ *
+ *	If namesize < 256  keep
+ *	If name from last / < 256 use that
+ *	else use LDSO_NAME
+ *
+ *	This ensures /very/long/stupid/nfs/path/we/often/get/foobarcmd
+ *	comes out at least as.  
+ *
+ *	foobarcmd: someerror
+ *
+ *	Even if we fix vsprintf to be vsnprintf (which we should), this
+ *	ought to be kept to help make real size limited errors clearer.
+ */
+ 
+static char *argv_remap(char *ptr)
+{
+	char *tmp;
+	if(strlen(ptr)<256)
+		return ptr;
+	if(!*ptr)
+		return ptr;
+	tmp=ptr+strlen(ptr)-1;
+	/*
+	 *	Walk back down the chain until we find a slash
+	 */
+	while(tmp>=ptr && *tmp!='/')
+		tmp--;
+	/*
+	 *	No slash, or too long after slash and Im not playing so nyah
+	 */
+	if(*tmp!='/')
+		return LDSO_IMAGE;
+	if(strlen(tmp)>256)	/* Not off by 1 .. strlen includes the / */
+		return LDSO_IMAGE;
+	return tmp+1;
+}
+
 void
 shared_loader(int func, ...)
 {
@@ -207,12 +247,14 @@
 	save_mapinfo(mapinfo);
 #endif
 	argv0 = va_arg(ap, char *);
+	argv0 = arg_remap(argv0);
 	__environ = va_arg(ap, char **);
 	__SHARED_LIBRARIES__ = va_arg(ap, struct libentry **);
 	_SHARABLE_CONFLICTS__ = va_arg(ap, struct fixuplist *);
 	if (func == FUNC_LINK_AND_CALLBACK)
 	  callback = va_arg(ap, callbackptr);
 	va_end(ap);
+	
 	break;
     default:
 	/* you want me to do what? */
@@ -228,7 +270,8 @@
     /* find out who we are, in case somebody wants to know */
     if (!argv0 && !(argv0 = getenv(LDD_ARGV0)))
 	argv0 = LDSO_IMAGE;
-
+    argv0=argv_remap(argv0);
+    
     /* hmm, you want your own configuration, do you? */
     if (getuid() == geteuid() && getgid() == getegid())
     {
@@ -328,6 +371,11 @@
 		.text section. This is passed to ldpreload() below */
 	    if (preload || callback)
 	    {
+	    	if(nlibs==11)
+	    	{
+	    		fdprintf(2, "%s: too many preloads\n",argv[0]);
+	    		exit(EXIT_FATAL);
+	    	}
 	        libs[nlibs] = alloca(strlen(buffer)+1);
 	        strcpy(libs[nlibs], buffer);
 	        nlibs++;
---- cut here ----

-----
KSR[T] Website : http://www.dec.net/ksrt
E-mail: ksrt@dec.net