@@ -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;
}
@@ -716,8 +716,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;
@@ -751,7 +752,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;
@@ -764,6 +766,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 {
@@ -813,7 +816,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);
@@ -828,6 +832,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;
@@ -963,12 +968,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:
@@ -979,10 +983,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