* [RFC PATCH v1 0/1] binfmt_elf: seal address zero
@ 2024-08-01 17:08 jeffxu
2024-08-01 17:08 ` [RFC PATCH v1 1/1] binfmt_elf: mseal " jeffxu
2024-08-05 21:01 ` [RFC PATCH v1 0/1] binfmt_elf: seal " Kees Cook
0 siblings, 2 replies; 5+ messages in thread
From: jeffxu @ 2024-08-01 17:08 UTC (permalink / raw)
To: akpm, keescook, jannh, sroettger, adhemerval.zanella, ojeda, adobriyan
Cc: linux-kernel, linux-mm, jorgelo, Jeff Xu
From: Jeff Xu <jeffxu@chromium.org>
In load_elf_binary as part of the execve(), when the current
task’s personality has MMAP_PAGE_ZERO set, the kernel allocates
one page at address 0. According to the comment:
/* Why this, you ask??? Well SVr4 maps page 0 as read-only,
and some applications "depend" upon this behavior.
Since we do not have the power to recompile these, we
emulate the SVr4 behavior. Sigh. */
At one point, Linus suggested removing this [1].
Sealing this is probably safe, the comment doesn’t say
the app ever wanting to change the mapping to rwx. Sealing
also ensures that never happens.
[1] https://lore.kernel.org/lkml/CAHk-=whVa=nm_GW=NVfPHqcxDbWt4JjjK1YWb0cLjO4ZSGyiDA@mail.gmail.com/
Jeff Xu (1):
binfmt_elf: mseal address zero
fs/binfmt_elf.c | 4 ++++
include/linux/mm.h | 4 ++++
mm/mseal.c | 2 +-
3 files changed, 9 insertions(+), 1 deletion(-)
--
2.46.0.rc1.232.g9752f9e123-goog
^ permalink raw reply [flat|nested] 5+ messages in thread* [RFC PATCH v1 1/1] binfmt_elf: mseal address zero 2024-08-01 17:08 [RFC PATCH v1 0/1] binfmt_elf: seal address zero jeffxu @ 2024-08-01 17:08 ` jeffxu 2024-08-05 21:05 ` Kees Cook 2024-08-05 21:01 ` [RFC PATCH v1 0/1] binfmt_elf: seal " Kees Cook 1 sibling, 1 reply; 5+ messages in thread From: jeffxu @ 2024-08-01 17:08 UTC (permalink / raw) To: akpm, keescook, jannh, sroettger, adhemerval.zanella, ojeda, adobriyan Cc: linux-kernel, linux-mm, jorgelo, Jeff Xu From: Jeff Xu <jeffxu@chromium.org> Some legacy SVr4 apps might depend on page on address zero to be readable, however I can't find a reason that the page ever becomes writeable, so seal it. If there is a compain, we can make this configurable. Signed-off-by: Jeff Xu <jeffxu@chromium.org> --- fs/binfmt_elf.c | 4 ++++ include/linux/mm.h | 4 ++++ mm/mseal.c | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 19fa49cd9907..e4d35d6f5d65 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1314,6 +1314,10 @@ static int load_elf_binary(struct linux_binprm *bprm) emulate the SVr4 behavior. Sigh. */ error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, 0); + +#ifdef CONFIG_64BIT + do_mseal(0, PAGE_SIZE, 0); +#endif } regs = current_pt_regs(); diff --git a/include/linux/mm.h b/include/linux/mm.h index c4b238a20b76..b5fed60ddcd9 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -4201,4 +4201,8 @@ void vma_pgtable_walk_end(struct vm_area_struct *vma); int reserve_mem_find_by_name(const char *name, phys_addr_t *start, phys_addr_t *size); +#ifdef CONFIG_64BIT +int do_mseal(unsigned long start, size_t len_in, unsigned long flags); +#endif + #endif /* _LINUX_MM_H */ diff --git a/mm/mseal.c b/mm/mseal.c index bf783bba8ed0..7a40a84569c8 100644 --- a/mm/mseal.c +++ b/mm/mseal.c @@ -248,7 +248,7 @@ static int apply_mm_seal(unsigned long start, unsigned long end) * * unseal() is not supported. */ -static int do_mseal(unsigned long start, size_t len_in, unsigned long flags) +int do_mseal(unsigned long start, size_t len_in, unsigned long flags) { size_t len; int ret = 0; -- 2.46.0.rc1.232.g9752f9e123-goog ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH v1 1/1] binfmt_elf: mseal address zero 2024-08-01 17:08 ` [RFC PATCH v1 1/1] binfmt_elf: mseal " jeffxu @ 2024-08-05 21:05 ` Kees Cook 2024-08-05 21:33 ` Jeff Xu 0 siblings, 1 reply; 5+ messages in thread From: Kees Cook @ 2024-08-05 21:05 UTC (permalink / raw) To: jeffxu Cc: akpm, jannh, sroettger, adhemerval.zanella, ojeda, adobriyan, linux-kernel, linux-mm, jorgelo On Thu, Aug 01, 2024 at 05:08:33PM +0000, jeffxu@chromium.org wrote: > From: Jeff Xu <jeffxu@chromium.org> > > Some legacy SVr4 apps might depend on page on address zero > to be readable, however I can't find a reason that the page > ever becomes writeable, so seal it. > > If there is a compain, we can make this configurable. > > Signed-off-by: Jeff Xu <jeffxu@chromium.org> > --- > fs/binfmt_elf.c | 4 ++++ > include/linux/mm.h | 4 ++++ > mm/mseal.c | 2 +- > 3 files changed, 9 insertions(+), 1 deletion(-) > > diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c > index 19fa49cd9907..e4d35d6f5d65 100644 > --- a/fs/binfmt_elf.c > +++ b/fs/binfmt_elf.c > @@ -1314,6 +1314,10 @@ static int load_elf_binary(struct linux_binprm *bprm) > emulate the SVr4 behavior. Sigh. */ > error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, > MAP_FIXED | MAP_PRIVATE, 0); > + > +#ifdef CONFIG_64BIT > + do_mseal(0, PAGE_SIZE, 0); > +#endif Instead of wrapping this in #ifdefs, does it make more sense to adjust the mm.h declaration instead, like this below... > } > > regs = current_pt_regs(); > diff --git a/include/linux/mm.h b/include/linux/mm.h > index c4b238a20b76..b5fed60ddcd9 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -4201,4 +4201,8 @@ void vma_pgtable_walk_end(struct vm_area_struct *vma); > > int reserve_mem_find_by_name(const char *name, phys_addr_t *start, phys_addr_t *size); > > +#ifdef CONFIG_64BIT > +int do_mseal(unsigned long start, size_t len_in, unsigned long flags); #else static inline int do_mseal(unsigned long start, size_t len_in, unsigned long flags) { return -ENOTSUPP; } > +#endif > + > #endif /* _LINUX_MM_H */ > diff --git a/mm/mseal.c b/mm/mseal.c > index bf783bba8ed0..7a40a84569c8 100644 > --- a/mm/mseal.c > +++ b/mm/mseal.c > @@ -248,7 +248,7 @@ static int apply_mm_seal(unsigned long start, unsigned long end) > * > * unseal() is not supported. > */ > -static int do_mseal(unsigned long start, size_t len_in, unsigned long flags) > +int do_mseal(unsigned long start, size_t len_in, unsigned long flags) > { > size_t len; > int ret = 0; > -- > 2.46.0.rc1.232.g9752f9e123-goog > And if it returns an error code, should we check it when used in load_elf_binary()? (And if so, should the mm.h return 0 for non-64bit?) -- Kees Cook ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH v1 1/1] binfmt_elf: mseal address zero 2024-08-05 21:05 ` Kees Cook @ 2024-08-05 21:33 ` Jeff Xu 0 siblings, 0 replies; 5+ messages in thread From: Jeff Xu @ 2024-08-05 21:33 UTC (permalink / raw) To: Kees Cook Cc: akpm, jannh, sroettger, adhemerval.zanella, ojeda, adobriyan, linux-kernel, linux-mm, jorgelo On Mon, Aug 5, 2024 at 2:05 PM Kees Cook <kees@kernel.org> wrote: > > On Thu, Aug 01, 2024 at 05:08:33PM +0000, jeffxu@chromium.org wrote: > > From: Jeff Xu <jeffxu@chromium.org> > > > > Some legacy SVr4 apps might depend on page on address zero > > to be readable, however I can't find a reason that the page > > ever becomes writeable, so seal it. > > > > If there is a compain, we can make this configurable. > > > > Signed-off-by: Jeff Xu <jeffxu@chromium.org> > > --- > > fs/binfmt_elf.c | 4 ++++ > > include/linux/mm.h | 4 ++++ > > mm/mseal.c | 2 +- > > 3 files changed, 9 insertions(+), 1 deletion(-) > > > > diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c > > index 19fa49cd9907..e4d35d6f5d65 100644 > > --- a/fs/binfmt_elf.c > > +++ b/fs/binfmt_elf.c > > @@ -1314,6 +1314,10 @@ static int load_elf_binary(struct linux_binprm *bprm) > > emulate the SVr4 behavior. Sigh. */ > > error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, > > MAP_FIXED | MAP_PRIVATE, 0); > > + > > +#ifdef CONFIG_64BIT > > + do_mseal(0, PAGE_SIZE, 0); > > +#endif > > Instead of wrapping this in #ifdefs, does it make more sense to adjust > the mm.h declaration instead, like this below... > Sure. > > } > > > > regs = current_pt_regs(); > > diff --git a/include/linux/mm.h b/include/linux/mm.h > > index c4b238a20b76..b5fed60ddcd9 100644 > > --- a/include/linux/mm.h > > +++ b/include/linux/mm.h > > @@ -4201,4 +4201,8 @@ void vma_pgtable_walk_end(struct vm_area_struct *vma); > > > > int reserve_mem_find_by_name(const char *name, phys_addr_t *start, phys_addr_t *size); > > > > +#ifdef CONFIG_64BIT > > +int do_mseal(unsigned long start, size_t len_in, unsigned long flags); > > #else > static inline int do_mseal(unsigned long start, size_t len_in, unsigned long flags) > { > return -ENOTSUPP; > } > OK. > > +#endif > > + > > #endif /* _LINUX_MM_H */ > > diff --git a/mm/mseal.c b/mm/mseal.c > > index bf783bba8ed0..7a40a84569c8 100644 > > --- a/mm/mseal.c > > +++ b/mm/mseal.c > > @@ -248,7 +248,7 @@ static int apply_mm_seal(unsigned long start, unsigned long end) > > * > > * unseal() is not supported. > > */ > > -static int do_mseal(unsigned long start, size_t len_in, unsigned long flags) > > +int do_mseal(unsigned long start, size_t len_in, unsigned long flags) > > { > > size_t len; > > int ret = 0; > > -- > > 2.46.0.rc1.232.g9752f9e123-goog > > > > And if it returns an error code, should we check it when used in > load_elf_binary()? (And if so, should the mm.h return 0 for non-64bit?) > It shouldn't fail. I can add pr_warning to handle the error case: pr_warning("pid=%d, couldn't seal the page on address 0.\n", task_pid_nr(current)); Thanks! Best regards, -Jeff > -- > Kees Cook ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH v1 0/1] binfmt_elf: seal address zero 2024-08-01 17:08 [RFC PATCH v1 0/1] binfmt_elf: seal address zero jeffxu 2024-08-01 17:08 ` [RFC PATCH v1 1/1] binfmt_elf: mseal " jeffxu @ 2024-08-05 21:01 ` Kees Cook 1 sibling, 0 replies; 5+ messages in thread From: Kees Cook @ 2024-08-05 21:01 UTC (permalink / raw) To: jeffxu Cc: akpm, jannh, sroettger, adhemerval.zanella, ojeda, adobriyan, linux-kernel, linux-mm, jorgelo On Thu, Aug 01, 2024 at 05:08:32PM +0000, jeffxu@chromium.org wrote: > From: Jeff Xu <jeffxu@chromium.org> > > In load_elf_binary as part of the execve(), when the current > task’s personality has MMAP_PAGE_ZERO set, the kernel allocates > one page at address 0. According to the comment: > > /* Why this, you ask??? Well SVr4 maps page 0 as read-only, > and some applications "depend" upon this behavior. > Since we do not have the power to recompile these, we > emulate the SVr4 behavior. Sigh. */ > > At one point, Linus suggested removing this [1]. For users, I didn't find much in a Debian Code Search: https://codesearch.debian.net/search?q=MMAP_PAGE_ZERO&literal=1&perpkg=1 I see rr uses it in testing, and some utils have it as an option, so I think maybe just leave it supported. > > Sealing this is probably safe, the comment doesn’t say > the app ever wanting to change the mapping to rwx. Sealing > also ensures that never happens. Yeah, this seems fine to me. > > [1] https://lore.kernel.org/lkml/CAHk-=whVa=nm_GW=NVfPHqcxDbWt4JjjK1YWb0cLjO4ZSGyiDA@mail.gmail.com/ > > Jeff Xu (1): > binfmt_elf: mseal address zero > > fs/binfmt_elf.c | 4 ++++ > include/linux/mm.h | 4 ++++ > mm/mseal.c | 2 +- > 3 files changed, 9 insertions(+), 1 deletion(-) > > -- > 2.46.0.rc1.232.g9752f9e123-goog > -- Kees Cook ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-08-05 21:34 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2024-08-01 17:08 [RFC PATCH v1 0/1] binfmt_elf: seal address zero jeffxu 2024-08-01 17:08 ` [RFC PATCH v1 1/1] binfmt_elf: mseal " jeffxu 2024-08-05 21:05 ` Kees Cook 2024-08-05 21:33 ` Jeff Xu 2024-08-05 21:01 ` [RFC PATCH v1 0/1] binfmt_elf: seal " Kees Cook
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox