[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200311192608.40095-5-broonie@kernel.org>
Date: Wed, 11 Mar 2020 19:25:59 +0000
From: Mark Brown <broonie@...nel.org>
To: Catalin Marinas <catalin.marinas@....com>,
Will Deacon <will@...nel.org>
Cc: Alexander Viro <viro@...iv.linux.org.uk>,
Paul Elliott <paul.elliott@....com>,
Peter Zijlstra <peterz@...radead.org>,
Yu-cheng Yu <yu-cheng.yu@...el.com>,
Amit Kachhap <amit.kachhap@....com>,
Vincenzo Frascino <vincenzo.frascino@....com>,
Marc Zyngier <maz@...nel.org>,
Eugene Syromiatnikov <esyr@...hat.com>,
Szabolcs Nagy <szabolcs.nagy@....com>,
"H . J . Lu " <hjl.tools@...il.com>,
Andrew Jones <drjones@...hat.com>,
Kees Cook <keescook@...omium.org>,
Arnd Bergmann <arnd@...db.de>, Jann Horn <jannh@...gle.com>,
Richard Henderson <richard.henderson@...aro.org>,
Kristina Martšenko <kristina.martsenko@....com>,
Thomas Gleixner <tglx@...utronix.de>,
Florian Weimer <fweimer@...hat.com>,
Sudakshina Das <sudi.das@....com>,
linux-arm-kernel@...ts.infradead.org, linux-kernel@...r.kernel.org,
linux-arch@...r.kernel.org, linux-fsdevel@...r.kernel.org,
Dave Martin <Dave.Martin@....com>,
Mark Brown <broonie@...nel.org>
Subject: [PATCH v9 04/13] elf: Allow arch to tweak initial mmap prot flags
From: Dave Martin <Dave.Martin@....com>
An arch may want to tweak the mmap prot flags for an
ELFexecutable's initial mappings. For example, arm64 is going to
need to add PROT_BTI for executable pages in an ELF process whose
executable is marked as using Branch Target Identification (an
ARMv8.5-A control flow integrity feature).
So that this can be done in a generic way, add a hook
arch_elf_adjust_prot() to modify the prot flags as desired: arches
can select CONFIG_HAVE_ELF_PROT and implement their own backend
where necessary.
By default, leave the prot flags unchanged.
Signed-off-by: Dave Martin <Dave.Martin@....com>
Reviewed-by: Kees Cook <keescook@...omium.org>
Reviewed-by: Catalin Marinas <catalin.marinas@....com>
Signed-off-by: Mark Brown <broonie@...nel.org>
---
fs/Kconfig.binfmt | 3 +++
fs/binfmt_elf.c | 18 ++++++++++++------
include/linux/elf.h | 12 ++++++++++++
3 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index d2cfe0729a73..2358368319b8 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -36,6 +36,9 @@ config COMPAT_BINFMT_ELF
config ARCH_BINFMT_ELF_STATE
bool
+config ARCH_HAVE_ELF_PROT
+ bool
+
config ARCH_USE_GNU_PROPERTY
bool
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 1fb67e506b68..cceb29d6ef1d 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -544,7 +544,8 @@ static inline int arch_check_elf(struct elfhdr *ehdr, bool has_interp,
#endif /* !CONFIG_ARCH_BINFMT_ELF_STATE */
-static inline int make_prot(u32 p_flags)
+static inline int make_prot(u32 p_flags, struct arch_elf_state *arch_state,
+ bool has_interp, bool is_interp)
{
int prot = 0;
@@ -554,7 +555,8 @@ static inline int make_prot(u32 p_flags)
prot |= PROT_WRITE;
if (p_flags & PF_X)
prot |= PROT_EXEC;
- return prot;
+
+ return arch_elf_adjust_prot(prot, arch_state, has_interp, is_interp);
}
/* This is much more generalized than the library routine read function,
@@ -564,7 +566,8 @@ static inline int make_prot(u32 p_flags)
static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
struct file *interpreter,
- unsigned long no_base, struct elf_phdr *interp_elf_phdata)
+ unsigned long no_base, struct elf_phdr *interp_elf_phdata,
+ struct arch_elf_state *arch_state)
{
struct elf_phdr *eppnt;
unsigned long load_addr = 0;
@@ -596,7 +599,8 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
if (eppnt->p_type == PT_LOAD) {
int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
- int elf_prot = make_prot(eppnt->p_flags);
+ int elf_prot = make_prot(eppnt->p_flags, arch_state,
+ true, true);
unsigned long vaddr = 0;
unsigned long k, map_addr;
@@ -1041,7 +1045,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
}
}
- elf_prot = make_prot(elf_ppnt->p_flags);
+ elf_prot = make_prot(elf_ppnt->p_flags, &arch_state,
+ !!interpreter, false);
elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE;
@@ -1184,7 +1189,8 @@ static int load_elf_binary(struct linux_binprm *bprm)
if (interpreter) {
elf_entry = load_elf_interp(&loc->interp_elf_ex,
interpreter,
- load_bias, interp_elf_phdata);
+ load_bias, interp_elf_phdata,
+ &arch_state);
if (!IS_ERR((void *)elf_entry)) {
/*
* load_elf_interp() returns relocation
diff --git a/include/linux/elf.h b/include/linux/elf.h
index db5113479f5e..5d5b0321da0b 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -87,4 +87,16 @@ extern int arch_parse_elf_property(u32 type, const void *data, size_t datasz,
bool compat, struct arch_elf_state *arch);
#endif
+#ifdef CONFIG_ARCH_HAVE_ELF_PROT
+int arch_elf_adjust_prot(int prot, const struct arch_elf_state *state,
+ bool has_interp, bool is_interp);
+#else
+static inline int arch_elf_adjust_prot(int prot,
+ const struct arch_elf_state *state,
+ bool has_interp, bool is_interp)
+{
+ return prot;
+}
+#endif
+
#endif /* _LINUX_ELF_H */
--
2.20.1
Powered by blists - more mailing lists