Last active
January 31, 2022 17:00
-
-
Save azat/45cdfb46a70474449972258fce0010cf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 64f9c91766cbcaa8a61e5b633ac78e354ac3355c Mon Sep 17 00:00:00 2001 | |
From: Azat Khuzhin <a3at.mail@gmail.com> | |
Date: Mon, 31 Jan 2022 19:14:53 +0300 | |
Subject: [PATCH] fs/binfmt_elf: use ELF_ET_DYN_BASE for PIE (ET_DYN with | |
INTERP) binaries | |
Since 9630f0d60fec ELF_ET_DYN_BASE is not used as a load_bias anymore | |
and this breaks PIE binaries, since after this change data segment | |
became too nearby the stack: | |
Before 9630f0d60fec: | |
$ strace -febrk /tmp/test-stack |& head | |
brk(NULL) = 0x555555559000 | |
$ /tmp/test-stack | |
bottom_of_stack = 0x7fffffffc5c0 | |
recursion depth: 1 (stack diff: 32) | |
... | |
recursion depth: 7690 (stack diff: 8365664) | |
Segmentation fault (core dumped) | |
After 9630f0d60fec: | |
$ strace -ebrk /tmp/test-stack |& head | |
brk(NULL) = 0x7ffff7fff000 | |
$ /tmp/test-stack | |
bottom_of_stack = 0x7fffffffc640 | |
recursion depth: 1 (stack diff: 32) | |
... | |
recursion depth: 146 (stack diff: 157792) | |
Segmentation fault (core dumped) | |
Found this during compiling with clang, that started to randomly | |
SIGSEGV when it eats some heap. | |
Reproducer: | |
#include <stdio.h> | |
#include <stddef.h> | |
#include <stdlib.h> | |
static int depth = 0; | |
static void* bottom_of_stack; | |
int inner() | |
{ | |
char buffer[1024]; | |
ptrdiff_t diff; | |
int ret; | |
++depth; | |
diff = bottom_of_stack - __builtin_frame_address(0); | |
fprintf(stderr, | |
"recursion depth: %i (stack diff: %zu)\n", | |
depth, (size_t)diff); | |
for (size_t i = 0; i < 1024; ++i) | |
ret += buffer[i]; | |
ret += inner(); | |
return ret; | |
} | |
int main() | |
{ | |
for (size_t size = 0; size < 128<<20; size += 16<<10) | |
malloc(16<<10); | |
bottom_of_stack = __builtin_frame_address(0); | |
fprintf(stderr, "bottom_of_stack = %p\n", bottom_of_stack); | |
inner(); | |
} | |
Fixes: 9630f0d60fec ("fs/binfmt_elf: use PT_LOAD p_align values for static PIE") | |
Signed-off-by: Azat Khuzhin <a3at.mail@gmail.com> | |
--- | |
fs/binfmt_elf.c | 2 +- | |
1 file changed, 1 insertion(+), 1 deletion(-) | |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c | |
index 605017eb9349..9e11e6f13e83 100644 | |
--- a/fs/binfmt_elf.c | |
+++ b/fs/binfmt_elf.c | |
@@ -1117,7 +1117,7 @@ static int load_elf_binary(struct linux_binprm *bprm) | |
* without MAP_FIXED nor MAP_FIXED_NOREPLACE). | |
*/ | |
alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum); | |
- if (alignment > ELF_MIN_ALIGN) { | |
+ if (interpreter || alignment > ELF_MIN_ALIGN) { | |
load_bias = ELF_ET_DYN_BASE; | |
if (current->flags & PF_RANDOMIZE) | |
load_bias += arch_mmap_rnd(); | |
-- | |
2.35.1 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bottom_of_stack = 0x7fffffffc5c0 | |
recursion depth: 1 (stack diff: 32) | |
... | |
recursion depth: 7689 (stack diff: 8364576) | |
recursion depth: 7690 (stack diff: 8365664) | |
Segmentation fault (core dumped) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bottom_of_stack = 0x7fffffffc640 | |
recursion depth: 1 (stack diff: 32) | |
... | |
recursion depth: 146 (stack diff: 157792) | |
Segmentation fault (core dumped) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stddef.h> | |
#include <stdlib.h> | |
static int depth = 0; | |
static void* bottom_of_stack; | |
int inner() | |
{ | |
char buffer[1024]; | |
ptrdiff_t diff; | |
int ret; | |
++depth; | |
diff = bottom_of_stack - __builtin_frame_address(0); | |
fprintf(stderr, | |
"recursion depth: %i (stack diff: %zu)\n", | |
depth, (size_t)diff); | |
for (size_t i = 0; i < 1024; ++i) | |
ret += buffer[i]; | |
ret += inner(); | |
return ret; | |
} | |
int main() | |
{ | |
for (size_t size = 0; size < 128<<20; size += 16<<10) | |
malloc(16<<10); | |
bottom_of_stack = __builtin_frame_address(0); | |
fprintf(stderr, "bottom_of_stack = %p\n", bottom_of_stack); | |
inner(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment