Skip to content

Commit 44f65d9

Browse files
peaktocreekkees
authored andcommitted
binfmt_elf: mseal address zero
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]. Code search in debian didn't see much use of MMAP_PAGE_ZERO [2], it exists in util and test (rr). 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. If there is a complaint, we can make this configurable. Link: https://lore.kernel.org/lkml/CAHk-=whVa=nm_GW=NVfPHqcxDbWt4JjjK1YWb0cLjO4ZSGyiDA@mail.gmail.com/ [1] Link: https://codesearch.debian.net/search?q=MMAP_PAGE_ZERO&literal=1&perpkg=1&page=1 [2] Signed-off-by: Jeff Xu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Kees Cook <[email protected]>
1 parent 7d442a3 commit 44f65d9

File tree

3 files changed

+16
-1
lines changed

3 files changed

+16
-1
lines changed

fs/binfmt_elf.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,11 @@ static int load_elf_binary(struct linux_binprm *bprm)
13141314
emulate the SVr4 behavior. Sigh. */
13151315
error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
13161316
MAP_FIXED | MAP_PRIVATE, 0);
1317+
1318+
retval = do_mseal(0, PAGE_SIZE, 0);
1319+
if (retval)
1320+
pr_warn_ratelimited("pid=%d, couldn't seal address 0, ret=%d.\n",
1321+
task_pid_nr(current), retval);
13171322
}
13181323

13191324
regs = current_pt_regs();

include/linux/mm.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4201,4 +4201,14 @@ void vma_pgtable_walk_end(struct vm_area_struct *vma);
42014201

42024202
int reserve_mem_find_by_name(const char *name, phys_addr_t *start, phys_addr_t *size);
42034203

4204+
#ifdef CONFIG_64BIT
4205+
int do_mseal(unsigned long start, size_t len_in, unsigned long flags);
4206+
#else
4207+
static inline int do_mseal(unsigned long start, size_t len_in, unsigned long flags)
4208+
{
4209+
/* noop on 32 bit */
4210+
return 0;
4211+
}
4212+
#endif
4213+
42044214
#endif /* _LINUX_MM_H */

mm/mseal.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ static int apply_mm_seal(unsigned long start, unsigned long end)
248248
*
249249
* unseal() is not supported.
250250
*/
251-
static int do_mseal(unsigned long start, size_t len_in, unsigned long flags)
251+
int do_mseal(unsigned long start, size_t len_in, unsigned long flags)
252252
{
253253
size_t len;
254254
int ret = 0;

0 commit comments

Comments
 (0)