Blame bash-2.05a-interpreter.patch

Petr Šabata 33fc6c
diff --git a/config.h.in b/config.h.in
DistroBaker 62c465
index ab316d4..11d1d68 100644
Petr Šabata 33fc6c
--- a/config.h.in
Petr Šabata 33fc6c
+++ b/config.h.in
DistroBaker 62c465
@@ -775,6 +775,9 @@
Petr Šabata 33fc6c
 /* Define if you have the pselect function.  */
Petr Šabata 33fc6c
 #undef HAVE_PSELECT
Petr Šabata 33fc6c
 
Petr Šabata 33fc6c
+/* Define if you have the pread function. */
Petr Šabata 33fc6c
+#undef HAVE_PREAD
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
 /* Define if you have the putenv function.  */
Petr Šabata 33fc6c
 #undef HAVE_PUTENV
Petr Šabata 33fc6c
 
DistroBaker 62c465
@@ -981,6 +984,9 @@
Petr Šabata 33fc6c
 /* Define if you have the <dlfcn.h> header file.  */
Petr Šabata 33fc6c
 #undef HAVE_DLFCN_H
Petr Šabata 33fc6c
 
Petr Šabata 33fc6c
+/* Define if you have the <elf.h> header file.  */
Petr Šabata 33fc6c
+#undef HAVE_ELF_H
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
 /* Define if you have the <grp.h> header file.  */
Petr Šabata 33fc6c
 #undef HAVE_GRP_H
Petr Šabata 33fc6c
 
Petr Šabata 33fc6c
diff --git a/configure.ac b/configure.ac
DistroBaker 62c465
index 2fe3e7d..f1b7f1b 100644
Petr Šabata 33fc6c
--- a/configure.ac
Petr Šabata 33fc6c
+++ b/configure.ac
DistroBaker 62c465
@@ -827,7 +827,7 @@ dnl checks for system calls
DistroBaker 62c465
 AC_CHECK_FUNCS(dup2 eaccess fcntl getdtablesize getentropy getgroups \
DistroBaker 62c465
 		gethostname getpagesize getpeername getrandom getrlimit \
DistroBaker 62c465
 		getrusage gettimeofday kill killpg lstat pselect readlink \
DistroBaker 62c465
-		select setdtablesize setitimer tcgetpgrp uname ulimit waitpid)
DistroBaker 62c465
+		select setdtablesize setitimer tcgetpgrp uname ulimit waitpid pread)
Petr Šabata 33fc6c
 AC_REPLACE_FUNCS(rename)
Petr Šabata 33fc6c
 
Petr Šabata 33fc6c
 dnl checks for c library functions
Petr Šabata 33fc6c
diff --git a/execute_cmd.c b/execute_cmd.c
DistroBaker 62c465
index d2a0dd7..d2555ad 100644
Petr Šabata 33fc6c
--- a/execute_cmd.c
Petr Šabata 33fc6c
+++ b/execute_cmd.c
Petr Šabata 33fc6c
@@ -41,6 +41,10 @@
Petr Šabata 33fc6c
 #  include <unistd.h>
Petr Šabata 33fc6c
 #endif
Petr Šabata 33fc6c
 
Petr Šabata 33fc6c
+#ifdef HAVE_ELF_H
Petr Šabata 33fc6c
+# include <elf.h>
Petr Šabata 33fc6c
+#endif
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
 #include "posixtime.h"
Petr Šabata 33fc6c
 
Petr Šabata 33fc6c
 #if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE)
DistroBaker 62c465
@@ -5832,6 +5836,14 @@ shell_execve (command, args, env)
Petr Šabata 33fc6c
 	{
Petr Šabata 33fc6c
 	  /* The file has the execute bits set, but the kernel refuses to
Petr Šabata 33fc6c
 	     run it for some reason.  See why. */
Petr Šabata 33fc6c
+#if defined (HAVE_HASH_BANG_EXEC) || defined (HAVE_ELF_H)
Petr Šabata 33fc6c
+       int fd = open (command, O_RDONLY);
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
+       if (fd >= 0)
Petr Šabata 33fc6c
+               sample_len = read (fd, sample, sizeof (sample));
Petr Šabata 33fc6c
+       else
Petr Šabata 33fc6c
+               sample_len = -1;
Petr Šabata 33fc6c
+#endif
Petr Šabata 33fc6c
 #if defined (HAVE_HASH_BANG_EXEC)
Petr Šabata 33fc6c
 	  READ_SAMPLE_BUF (command, sample, sample_len);
Petr Šabata 33fc6c
 	  if (sample_len > 0)
DistroBaker 62c465
@@ -5841,6 +5853,7 @@ shell_execve (command, args, env)
Petr Šabata 33fc6c
 	      char *interp;
Petr Šabata 33fc6c
 	      int ilen;
Petr Šabata 33fc6c
 
Petr Šabata 33fc6c
+          close (fd);
Petr Šabata 33fc6c
 	      interp = getinterp (sample, sample_len, (int *)NULL);
Petr Šabata 33fc6c
 	      ilen = strlen (interp);
Petr Šabata 33fc6c
 	      errno = i;
DistroBaker 62c465
@@ -5856,7 +5869,138 @@ shell_execve (command, args, env)
Petr Šabata 33fc6c
 	      return (EX_NOEXEC);
Petr Šabata 33fc6c
 	    }
Petr Šabata 33fc6c
 #endif
Petr Šabata 33fc6c
-	  errno = i;
Petr Šabata 33fc6c
+#if defined (HAVE_ELF_H)
Petr Šabata 33fc6c
+	  if (i == ENOENT
Petr Šabata 33fc6c
+	      && sample_len > EI_NIDENT
Petr Šabata 33fc6c
+	      && memcmp (sample, ELFMAG, SELFMAG) == 0)
Petr Šabata 33fc6c
+	    {
Petr Šabata 33fc6c
+	      off_t offset = -1;
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
+	      /* It is an ELF file.  Now determine whether it is dynamically
Petr Šabata 33fc6c
+		 linked and if yes, get the offset of the interpreter
Petr Šabata 33fc6c
+		 string.  */
Petr Šabata 33fc6c
+	      if (sample[EI_CLASS] == ELFCLASS32
Petr Šabata 33fc6c
+		  && sample_len > sizeof (Elf32_Ehdr))
Petr Šabata 33fc6c
+		{
Petr Šabata 33fc6c
+		  Elf32_Ehdr ehdr;
Petr Šabata 33fc6c
+		  Elf32_Phdr *phdr;
Petr Šabata 33fc6c
+		  int nphdr;
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
+		  /* We have to copy the data since the sample buffer
Petr Šabata 33fc6c
+		     might not be aligned correctly to be accessed as
Petr Šabata 33fc6c
+		     an Elf32_Ehdr struct.  */
Petr Šabata 33fc6c
+		  memcpy (&ehdr, sample, sizeof (Elf32_Ehdr));
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
+		  nphdr = ehdr.e_phnum;
Petr Šabata 33fc6c
+		  phdr = (Elf32_Phdr *) malloc (nphdr * ehdr.e_phentsize);
Petr Šabata 33fc6c
+		  if (phdr != NULL)
Petr Šabata 33fc6c
+		    {
Petr Šabata 33fc6c
+#ifdef HAVE_PREAD
Petr Šabata 33fc6c
+		      sample_len = pread (fd, phdr, nphdr * ehdr.e_phentsize,
Petr Šabata 33fc6c
+					  ehdr.e_phoff);
Petr Šabata 33fc6c
+#else
Petr Šabata 33fc6c
+		      if (lseek (fd, ehdr.e_phoff, SEEK_SET) != -1)
Petr Šabata 33fc6c
+			sample_len = read (fd, phdr,
Petr Šabata 33fc6c
+					   nphdr * ehdr.e_phentsize);
Petr Šabata 33fc6c
+		      else
Petr Šabata 33fc6c
+			sample_len = -1;
Petr Šabata 33fc6c
+#endif
Petr Šabata 33fc6c
+		      if (sample_len == nphdr * ehdr.e_phentsize)
Petr Šabata 33fc6c
+			while (nphdr-- > 0)
Petr Šabata 33fc6c
+			  if (phdr[nphdr].p_type == PT_INTERP)
Petr Šabata 33fc6c
+			    {
Petr Šabata 33fc6c
+			      offset = phdr[nphdr].p_offset;
Petr Šabata 33fc6c
+			      break;
Petr Šabata 33fc6c
+			    }
Petr Šabata 33fc6c
+		      free (phdr);
Petr Šabata 33fc6c
+		    }
Petr Šabata 33fc6c
+		}
Petr Šabata 33fc6c
+	      else if (sample[EI_CLASS] == ELFCLASS64
Petr Šabata 33fc6c
+		       && sample_len > sizeof (Elf64_Ehdr))
Petr Šabata 33fc6c
+		{
Petr Šabata 33fc6c
+		  Elf64_Ehdr ehdr;
Petr Šabata 33fc6c
+		  Elf64_Phdr *phdr;
Petr Šabata 33fc6c
+		  int nphdr;
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
+		  /* We have to copy the data since the sample buffer
Petr Šabata 33fc6c
+		     might not be aligned correctly to be accessed as
Petr Šabata 33fc6c
+		     an Elf64_Ehdr struct.  */
Petr Šabata 33fc6c
+		  memcpy (&ehdr, sample, sizeof (Elf64_Ehdr));
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
+		  nphdr = ehdr.e_phnum;
Petr Šabata 33fc6c
+		  phdr = (Elf64_Phdr *) malloc (nphdr * ehdr.e_phentsize);
Petr Šabata 33fc6c
+		  if (phdr != NULL)
Petr Šabata 33fc6c
+		    {
Petr Šabata 33fc6c
+#ifdef HAVE_PREAD
Petr Šabata 33fc6c
+		      sample_len = pread (fd, phdr, nphdr * ehdr.e_phentsize,
Petr Šabata 33fc6c
+					  ehdr.e_phoff);
Petr Šabata 33fc6c
+#else
Petr Šabata 33fc6c
+		      if (lseek (fd, ehdr.e_phoff, SEEK_SET) != -1)
Petr Šabata 33fc6c
+			sample_len = read (fd, phdr,
Petr Šabata 33fc6c
+					   nphdr * ehdr.e_phentsize);
Petr Šabata 33fc6c
+		      else
Petr Šabata 33fc6c
+			sample_len = -1;
Petr Šabata 33fc6c
+#endif
Petr Šabata 33fc6c
+		      if (sample_len == nphdr * ehdr.e_phentsize)
Petr Šabata 33fc6c
+			while (nphdr-- > 0)
Petr Šabata 33fc6c
+			  if (phdr[nphdr].p_type == PT_INTERP)
Petr Šabata 33fc6c
+			    {
Petr Šabata 33fc6c
+			      offset = phdr[nphdr].p_offset;
Petr Šabata 33fc6c
+			      break;
Petr Šabata 33fc6c
+			    }
Petr Šabata 33fc6c
+		      free (phdr);
Petr Šabata 33fc6c
+		    }
Petr Šabata 33fc6c
+		}
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
+	      if (offset != -1)
Petr Šabata 33fc6c
+		{
Petr Šabata 33fc6c
+		  size_t maxlen = 0;
Petr Šabata 33fc6c
+		  size_t actlen = 0;
Petr Šabata 33fc6c
+		  char *interp = NULL;
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
+		  do
Petr Šabata 33fc6c
+		    {
Petr Šabata 33fc6c
+		      if (actlen == maxlen)
Petr Šabata 33fc6c
+			{
Petr Šabata 33fc6c
+			  char *newinterp = realloc (interp, maxlen += 200);
Petr Šabata 33fc6c
+			  if (newinterp == NULL)
Petr Šabata 33fc6c
+			    {
Petr Šabata 33fc6c
+			      actlen = 0;
Petr Šabata 33fc6c
+			      break;
Petr Šabata 33fc6c
+			    }
Petr Šabata 33fc6c
+			  interp = newinterp;
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
+#ifdef HAVE_PREAD
Petr Šabata 33fc6c
+			  actlen = pread (fd, interp, maxlen, offset);
Petr Šabata 33fc6c
+#else
Petr Šabata 33fc6c
+			  if (lseek (fd, offset, SEEK_SET) != -1)
Petr Šabata 33fc6c
+			    actlen = read (fd, interp, maxlen);
Petr Šabata 33fc6c
+			  else
Petr Šabata 33fc6c
+			    actlen = -1;
Petr Šabata 33fc6c
+#endif
Petr Šabata 33fc6c
+			}
Petr Šabata 33fc6c
+		    }
Petr Šabata 33fc6c
+		  while (actlen > 0 && memchr (interp, '\0', actlen) == NULL);
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
+		  if (actlen > 0)
Petr Šabata 33fc6c
+		    {
Petr Šabata 33fc6c
+		      close (fd);
Petr Šabata 33fc6c
+		      errno = i;
Petr Šabata 33fc6c
+		      sys_error ("%s: %s: bad ELF interpreter", command,
Petr Šabata 33fc6c
+				 interp);
Petr Šabata 33fc6c
+		      free (interp);
Petr Šabata 33fc6c
+		      return (EX_NOEXEC);
Petr Šabata 33fc6c
+		    }
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
+		  free (interp);
Petr Šabata 33fc6c
+		}
Petr Šabata 33fc6c
+	    }
Petr Šabata 33fc6c
+#endif
Petr Šabata 33fc6c
+#if defined (HAVE_HASH_BANG_EXEC) || defined (HAVE_ELF_H)
Petr Šabata 33fc6c
+	  close (fd);
Petr Šabata 33fc6c
+#endif
Petr Šabata 33fc6c
+
Petr Šabata 33fc6c
+      errno = i;
Petr Šabata 33fc6c
 	  file_error (command);
Petr Šabata 33fc6c
 	}
Petr Šabata 33fc6c
       return (last_command_exit_value);