tcsh/tcsh-6.18.01-elf-interpreter.patch
2015-05-27 11:04:03 +02:00

199 lines
5.1 KiB
Diff

From b913dff5f7c123691b9aea3cee4bf270bc56659b Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Wed, 27 Aug 2014 13:55:10 +0200
Subject: [PATCH 12/14] report missing ELF interpreter
Resolves: #711066
Adjusted for tcsh-6.19.00 by Fridolin Pokorny <fpokorny@redhat.com>
---
configure.in | 5 ++-
sh.err.c | 4 +-
sh.exec.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 152 insertions(+), 3 deletions(-)
diff --git a/sh.err.c b/sh.err.c
index 29d41c3..262f9bf 100644
--- a/sh.err.c
+++ b/sh.err.c
@@ -189,7 +189,8 @@ char *seterr = NULL; /* Holds last error if there was one */
#define ERR_INVALID 133
#define ERR_BADCOLORVAR 134
#define ERR_EOF 135
-#define NO_ERRORS 136
+#define ERR_ELFINTERP 136
+#define NO_ERRORS 137
static const char *elst[NO_ERRORS] INIT_ZERO_STRUCT;
@@ -367,6 +368,7 @@ errinit(void)
elst[ERR_BADJOB] = CSAVS(1, 136, "No such job (badjob)");
elst[ERR_BADCOLORVAR] = CSAVS(1, 137, "Unknown colorls variable `%c%c'");
elst[ERR_EOF] = CSAVS(1, 138, "Unexpected end of file");
+ elst[ERR_ELFINTERP] = CSAVS(1, 139, "No such ELF interpreter");
}
/* Cleanup data. */
diff --git a/sh.exec.c b/sh.exec.c
index 2b41a53..c1f4b7e 100644
--- a/sh.exec.c
+++ b/sh.exec.c
@@ -40,6 +40,10 @@ RCSID("$tcsh: sh.exec.c,v 3.79 2011/02/25 23:58:34 christos Exp $")
#include <nt.const.h>
#endif /*WINNT_NATIVE*/
+#ifdef HAVE_ELF_H
+#include <elf.h>
+#endif /*HAVE_ELF_H*/
+
/*
* C shell
*/
@@ -509,6 +513,142 @@ texec(Char *sf, Char **st)
case 0: /* execv fails and returns 0! */
#endif /* _IBMR2 */
case ENOENT:
+#ifdef HAVE_ELF_H
+ /*
+ * If dynamically linked ELF binary is not executed and exists,
+ * the real reason ENOENT is that ELF interpreter is missing.
+ *
+ * Written by Ulrich Drepper for bash
+ * adopted by Fridolin Pokorny <fpokorny@redhat.com>
+ */
+ if ((fd = xopen(f, O_RDONLY|O_LARGEFILE)) != -1) {
+ int nread;
+ char *sample;
+ int offset = -1;
+ int sample_size;
+
+ /* Inspect 32 and 64 ELF */
+ if (sizeof(Elf64_Ehdr) > sizeof(Elf32_Ehdr))
+ sample_size = sizeof(Elf64_Ehdr);
+ else
+ sample_size = sizeof(Elf32_Ehdr);
+
+ sample = xmalloc(sample_size);
+
+ if (sample != 0 &&
+ (nread = xread(fd, sample, sample_size)) == sample_size) {
+ if (memcmp(sample, ELFMAG, SELFMAG) == 0) {
+ if (sample[EI_CLASS] == ELFCLASS32 &&
+ sample_size >= sizeof(Elf32_Ehdr)) {
+ Elf32_Ehdr ehdr;
+ Elf32_Phdr *phdr;
+ int nphdr;
+
+ /*
+ * We have to copy the data since the sample buffer
+ * might not be aligned correctly to be accessed as
+ * an Elf32_Ehdr struct.
+ */
+ memcpy(&ehdr, sample, sizeof(Elf32_Ehdr));
+
+ nphdr = ehdr.e_phnum;
+ phdr = xmalloc(nphdr * ehdr.e_phentsize);
+ if(phdr != NULL) {
+#ifdef HAVE_PREAD
+ nread = pread(fd, phdr, nphdr * ehdr.e_phentsize,
+ ehdr.e_phoff);
+#else /* !HAVE_PREAD */
+ if (lseek(fd, ehdr.e_phoff, SEEK_SET) != -1)
+ nread = read(fd, phdr,
+ nphdr * ehdr.e_phentsize);
+ else
+ nread = -1;
+#endif /* HAVE_PREAD */
+ if (nread == nphdr * ehdr.e_phentsize) {
+ while (nphdr-- > 0) {
+ if (phdr[nphdr].p_type == PT_INTERP) {
+ offset = phdr[nphdr].p_offset;
+ break;
+ }
+ }
+ }
+ xfree(phdr);
+ }
+ } else if (sample[EI_CLASS] == ELFCLASS64 &&
+ sample_size >= sizeof(Elf64_Ehdr)) {
+ Elf64_Ehdr ehdr;
+ Elf64_Phdr *phdr;
+ int nphdr;
+
+ /*
+ * We have to copy the data since the sample buffer
+ * might not be aligned correctly to be accessed as
+ * an Elf64_Ehdr struct.
+ */
+ memcpy(&ehdr, sample, sizeof(Elf64_Ehdr));
+
+ nphdr = ehdr.e_phnum;
+ phdr = xmalloc(nphdr * ehdr.e_phentsize);
+ if (phdr != NULL) {
+#ifdef HAVE_PREAD
+ nread = pread (fd, phdr, nphdr * ehdr.e_phentsize,
+ ehdr.e_phoff);
+#else /* !HAVE_PREAD */
+ if (lseek(fd, ehdr.e_phoff, SEEK_SET) != -1)
+ nread = read (fd, phdr,
+ nphdr * ehdr.e_phentsize);
+ else
+ nread = -1;
+#endif /* HAVE_PREAD */
+ if (nread == nphdr * ehdr.e_phentsize) {
+ while (nphdr-- > 0) {
+ if (phdr[nphdr].p_type == PT_INTERP) {
+ offset = phdr[nphdr].p_offset;
+ break;
+ }
+ }
+ }
+ xfree (phdr);
+ }
+ }
+
+ if (offset != -1) {
+ size_t maxlen = 0;
+ size_t actlen = 0;
+ char *interp = NULL;
+
+ do {
+ if (actlen == maxlen) {
+ char *newinterp = xrealloc(interp, maxlen += 200);
+ if (newinterp == NULL) {
+ actlen = 0;
+ break;
+ }
+ interp = newinterp;
+#ifdef HAVE_PREAD
+ actlen = pread (fd, interp, maxlen, offset);
+#else /* !HAVE_PREAD */
+ if (lseek (fd, offset, SEEK_SET) != -1)
+ actlen = read (fd, interp, maxlen);
+ else
+ actlen = -1;
+#endif /* HAVE_PREAD */
+ }
+ } while (actlen > 0 &&
+ memchr (interp, '\0', actlen) == NULL);
+
+ if (actlen > 0) {
+ xclose (fd);
+ xfree (interp);
+ setname(f);
+ stderror(ERR_NAME | ERR_ELFINTERP);
+ }
+ }
+ }
+ }
+ xfree(sample);
+ }
+#endif /* HAVE_ELF_H */
break;
default:
--
1.9.3