@@ -259,6 +259,7 @@ struct arch_elf_state {
static inline int arch_parse_elf_property(u32 type, const void *data,
size_t datasz, bool compat,
+ bool has_interp, bool is_interp,
struct arch_elf_state *arch)
{
/* No known properties for AArch32 yet */
@@ -271,7 +272,7 @@ static inline int arch_parse_elf_property(u32 type, const void *data,
if (datasz != sizeof(*p))
return -ENOEXEC;
- if (system_supports_bti() &&
+ if (system_supports_bti() && has_interp == is_interp &&
(*p & GNU_PROPERTY_AARCH64_FEATURE_1_BTI))
arch->flags |= ARM64_ELF_BTI;
}
@@ -717,8 +717,9 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
*/
static int parse_elf_property(const char *data, size_t *off, size_t datasz,
- struct arch_elf_state *arch,
- bool have_prev_type, u32 *prev_type)
+ struct arch_elf_state *arch, bool has_interp,
+ bool is_interp, bool have_prev_type,
+ u32 *prev_type)
{
size_t o, step;
const struct gnu_property *pr;
@@ -752,7 +753,8 @@ static int parse_elf_property(const char *data, size_t *off, size_t datasz,
*prev_type = pr->pr_type;
ret = arch_parse_elf_property(pr->pr_type, data + o,
- pr->pr_datasz, ELF_COMPAT, arch);
+ pr->pr_datasz, ELF_COMPAT,
+ has_interp, is_interp, arch);
if (ret)
return ret;
@@ -765,6 +767,7 @@ static int parse_elf_property(const char *data, size_t *off, size_t datasz,
#define NOTE_NAME_SZ (sizeof(GNU_PROPERTY_TYPE_0_NAME))
static int parse_elf_properties(struct file *f, const struct elf_phdr *phdr,
+ bool has_interp, bool is_interp,
struct arch_elf_state *arch)
{
union {
@@ -814,7 +817,8 @@ static int parse_elf_properties(struct file *f, const struct elf_phdr *phdr,
have_prev_type = false;
do {
ret = parse_elf_property(note.data, &off, datasz, arch,
- have_prev_type, &prev_type);
+ has_interp, is_interp, have_prev_type,
+ &prev_type);
have_prev_type = true;
} while (!ret);
@@ -829,6 +833,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
unsigned long error;
struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL;
struct elf_phdr *elf_property_phdata = NULL;
+ struct elf_phdr *interp_elf_property_phdata = NULL;
unsigned long elf_bss, elf_brk;
int bss_prot = 0;
int retval, i;
@@ -866,12 +871,15 @@ static int load_elf_binary(struct linux_binprm *bprm)
for (i = 0; i < elf_ex->e_phnum; i++, elf_ppnt++) {
char *elf_interpreter;
+ if (interpreter && elf_property_phdata)
+ break;
+
if (elf_ppnt->p_type == PT_GNU_PROPERTY) {
elf_property_phdata = elf_ppnt;
continue;
}
- if (elf_ppnt->p_type != PT_INTERP)
+ if (interpreter || elf_ppnt->p_type != PT_INTERP)
continue;
/*
@@ -920,7 +928,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
if (retval < 0)
goto out_free_dentry;
- break;
+ continue;
out_free_interp:
kfree(elf_interpreter);
@@ -964,12 +972,11 @@ static int load_elf_binary(struct linux_binprm *bprm)
goto out_free_dentry;
/* Pass PT_LOPROC..PT_HIPROC headers to arch code */
- elf_property_phdata = NULL;
elf_ppnt = interp_elf_phdata;
for (i = 0; i < interp_elf_ex->e_phnum; i++, elf_ppnt++)
switch (elf_ppnt->p_type) {
case PT_GNU_PROPERTY:
- elf_property_phdata = elf_ppnt;
+ interp_elf_property_phdata = elf_ppnt;
break;
case PT_LOPROC ... PT_HIPROC:
@@ -980,10 +987,17 @@ static int load_elf_binary(struct linux_binprm *bprm)
goto out_free_dentry;
break;
}
+
+ retval = parse_elf_properties(interpreter,
+ interp_elf_property_phdata,
+ true, true, &arch_state);
+ if (retval)
+ goto out_free_dentry;
+
}
- retval = parse_elf_properties(interpreter ?: bprm->file,
- elf_property_phdata, &arch_state);
+ retval = parse_elf_properties(bprm->file, elf_property_phdata,
+ interpreter, false, &arch_state);
if (retval)
goto out_free_dentry;
@@ -88,13 +88,15 @@ struct arch_elf_state;
#ifndef CONFIG_ARCH_USE_GNU_PROPERTY
static inline int arch_parse_elf_property(u32 type, const void *data,
size_t datasz, bool compat,
+ bool has_interp, bool is_interp,
struct arch_elf_state *arch)
{
return 0;
}
#else
extern int arch_parse_elf_property(u32 type, const void *data, size_t datasz,
- bool compat, struct arch_elf_state *arch);
+ bool compat, bool has_interp, bool is_interp,
+ struct arch_elf_state *arch);
#endif
#ifdef CONFIG_ARCH_HAVE_ELF_PROT