bash-2.05a-interpreter.patch 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. diff --git a/config.h.in b/config.h.in
  2. index a5ad9e7..62a6b32 100644
  3. --- a/config.h.in
  4. +++ b/config.h.in
  5. @@ -748,6 +748,9 @@
  6. /* Define if you have the pselect function. */
  7. #undef HAVE_PSELECT
  8. +/* Define if you have the pread function. */
  9. +#undef HAVE_PREAD
  10. +
  11. /* Define if you have the putenv function. */
  12. #undef HAVE_PUTENV
  13. @@ -946,6 +949,9 @@
  14. /* Define if you have the <dlfcn.h> header file. */
  15. #undef HAVE_DLFCN_H
  16. +/* Define if you have the <elf.h> header file. */
  17. +#undef HAVE_ELF_H
  18. +
  19. /* Define if you have the <grp.h> header file. */
  20. #undef HAVE_GRP_H
  21. diff --git a/configure.ac b/configure.ac
  22. index ce4e9b6..eda95d6 100644
  23. --- a/configure.ac
  24. +++ b/configure.ac
  25. @@ -700,7 +700,7 @@ BASH_HEADER_INTTYPES
  26. AC_CHECK_HEADERS(unistd.h stdlib.h stdarg.h varargs.h limits.h string.h \
  27. memory.h locale.h termcap.h termio.h termios.h dlfcn.h \
  28. stdbool.h stddef.h stdint.h netdb.h pwd.h grp.h strings.h \
  29. - regex.h syslog.h ulimit.h)
  30. + regex.h syslog.h ulimit.h elf.h)
  31. AC_CHECK_HEADERS(sys/pte.h sys/stream.h sys/select.h sys/file.h sys/ioctl.h \
  32. sys/param.h sys/socket.h sys/stat.h \
  33. sys/time.h sys/times.h sys/types.h sys/wait.h)
  34. @@ -771,7 +771,7 @@ dnl checks for system calls
  35. AC_CHECK_FUNCS(dup2 eaccess fcntl getdtablesize getgroups gethostname \
  36. getpagesize getpeername getrlimit getrusage gettimeofday \
  37. kill killpg lstat pselect readlink sbrk select setdtablesize \
  38. - setitimer tcgetpgrp uname ulimit waitpid)
  39. + setitimer tcgetpgrp uname ulimit waitpid pread)
  40. AC_REPLACE_FUNCS(rename)
  41. dnl checks for c library functions
  42. diff --git a/execute_cmd.c b/execute_cmd.c
  43. index 2a3df6d..b5cd405 100644
  44. --- a/execute_cmd.c
  45. +++ b/execute_cmd.c
  46. @@ -41,6 +41,10 @@
  47. # include <unistd.h>
  48. #endif
  49. +#ifdef HAVE_ELF_H
  50. +# include <elf.h>
  51. +#endif
  52. +
  53. #include "posixtime.h"
  54. #if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE)
  55. @@ -5486,6 +5490,14 @@ shell_execve (command, args, env)
  56. {
  57. /* The file has the execute bits set, but the kernel refuses to
  58. run it for some reason. See why. */
  59. +#if defined (HAVE_HASH_BANG_EXEC) || defined (HAVE_ELF_H)
  60. + int fd = open (command, O_RDONLY);
  61. +
  62. + if (fd >= 0)
  63. + sample_len = read (fd, sample, sizeof (sample));
  64. + else
  65. + sample_len = -1;
  66. +#endif
  67. #if defined (HAVE_HASH_BANG_EXEC)
  68. READ_SAMPLE_BUF (command, sample, sample_len);
  69. if (sample_len > 0)
  70. @@ -5495,6 +5507,7 @@ shell_execve (command, args, env)
  71. char *interp;
  72. int ilen;
  73. + close (fd);
  74. interp = getinterp (sample, sample_len, (int *)NULL);
  75. ilen = strlen (interp);
  76. errno = i;
  77. @@ -5510,6 +5523,136 @@ shell_execve (command, args, env)
  78. return (EX_NOEXEC);
  79. }
  80. #endif
  81. +#if defined (HAVE_ELF_H)
  82. + if (i == ENOENT
  83. + && sample_len > EI_NIDENT
  84. + && memcmp (sample, ELFMAG, SELFMAG) == 0)
  85. + {
  86. + off_t offset = -1;
  87. +
  88. + /* It is an ELF file. Now determine whether it is dynamically
  89. + linked and if yes, get the offset of the interpreter
  90. + string. */
  91. + if (sample[EI_CLASS] == ELFCLASS32
  92. + && sample_len > sizeof (Elf32_Ehdr))
  93. + {
  94. + Elf32_Ehdr ehdr;
  95. + Elf32_Phdr *phdr;
  96. + int nphdr;
  97. +
  98. + /* We have to copy the data since the sample buffer
  99. + might not be aligned correctly to be accessed as
  100. + an Elf32_Ehdr struct. */
  101. + memcpy (&ehdr, sample, sizeof (Elf32_Ehdr));
  102. +
  103. + nphdr = ehdr.e_phnum;
  104. + phdr = (Elf32_Phdr *) malloc (nphdr * ehdr.e_phentsize);
  105. + if (phdr != NULL)
  106. + {
  107. +#ifdef HAVE_PREAD
  108. + sample_len = pread (fd, phdr, nphdr * ehdr.e_phentsize,
  109. + ehdr.e_phoff);
  110. +#else
  111. + if (lseek (fd, ehdr.e_phoff, SEEK_SET) != -1)
  112. + sample_len = read (fd, phdr,
  113. + nphdr * ehdr.e_phentsize);
  114. + else
  115. + sample_len = -1;
  116. +#endif
  117. + if (sample_len == nphdr * ehdr.e_phentsize)
  118. + while (nphdr-- > 0)
  119. + if (phdr[nphdr].p_type == PT_INTERP)
  120. + {
  121. + offset = phdr[nphdr].p_offset;
  122. + break;
  123. + }
  124. + free (phdr);
  125. + }
  126. + }
  127. + else if (sample[EI_CLASS] == ELFCLASS64
  128. + && sample_len > sizeof (Elf64_Ehdr))
  129. + {
  130. + Elf64_Ehdr ehdr;
  131. + Elf64_Phdr *phdr;
  132. + int nphdr;
  133. +
  134. + /* We have to copy the data since the sample buffer
  135. + might not be aligned correctly to be accessed as
  136. + an Elf64_Ehdr struct. */
  137. + memcpy (&ehdr, sample, sizeof (Elf64_Ehdr));
  138. +
  139. + nphdr = ehdr.e_phnum;
  140. + phdr = (Elf64_Phdr *) malloc (nphdr * ehdr.e_phentsize);
  141. + if (phdr != NULL)
  142. + {
  143. +#ifdef HAVE_PREAD
  144. + sample_len = pread (fd, phdr, nphdr * ehdr.e_phentsize,
  145. + ehdr.e_phoff);
  146. +#else
  147. + if (lseek (fd, ehdr.e_phoff, SEEK_SET) != -1)
  148. + sample_len = read (fd, phdr,
  149. + nphdr * ehdr.e_phentsize);
  150. + else
  151. + sample_len = -1;
  152. +#endif
  153. + if (sample_len == nphdr * ehdr.e_phentsize)
  154. + while (nphdr-- > 0)
  155. + if (phdr[nphdr].p_type == PT_INTERP)
  156. + {
  157. + offset = phdr[nphdr].p_offset;
  158. + break;
  159. + }
  160. + free (phdr);
  161. + }
  162. + }
  163. +
  164. + if (offset != -1)
  165. + {
  166. + size_t maxlen = 0;
  167. + size_t actlen = 0;
  168. + char *interp = NULL;
  169. +
  170. + do
  171. + {
  172. + if (actlen == maxlen)
  173. + {
  174. + char *newinterp = realloc (interp, maxlen += 200);
  175. + if (newinterp == NULL)
  176. + {
  177. + actlen = 0;
  178. + break;
  179. + }
  180. + interp = newinterp;
  181. +
  182. +#ifdef HAVE_PREAD
  183. + actlen = pread (fd, interp, maxlen, offset);
  184. +#else
  185. + if (lseek (fd, offset, SEEK_SET) != -1)
  186. + actlen = read (fd, interp, maxlen);
  187. + else
  188. + actlen = -1;
  189. +#endif
  190. + }
  191. + }
  192. + while (actlen > 0 && memchr (interp, '\0', actlen) == NULL);
  193. +
  194. + if (actlen > 0)
  195. + {
  196. + close (fd);
  197. + errno = i;
  198. + sys_error ("%s: %s: bad ELF interpreter", command,
  199. + interp);
  200. + free (interp);
  201. + return (EX_NOEXEC);
  202. + }
  203. +
  204. + free (interp);
  205. + }
  206. + }
  207. +#endif
  208. +#if defined (HAVE_HASH_BANG_EXEC) || defined (HAVE_ELF_H)
  209. + close (fd);
  210. +#endif
  211. errno = i;
  212. file_error (command);
  213. }
  214. --
  215. 2.9.3