Skip to content

Commit

Permalink
add FLAG_COMPAT_VA_39_BIT to execveat()
Browse files Browse the repository at this point in the history
  • Loading branch information
muhomorr authored and thestinger committed Apr 16, 2023
1 parent 5a4ec3d commit ff8f099
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 6 deletions.
14 changes: 12 additions & 2 deletions arch/arm64/include/asm/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@
#ifdef CONFIG_ARM64_FORCE_52BIT
#define ELF_ET_DYN_BASE (2 * TASK_SIZE_64 / 3)
#else
#define ELF_ET_DYN_BASE (2 * DEFAULT_MAP_WINDOW_64 / 3)
/*
* Originally used DEFAULT_MAP_WINDOW_64, switched to DEFAULT_MAP_WINDOW for compatibility with 39-bit mode.
* Will return the value of DEFAULT_MAP_WINDOW_64 if compat_va_39_bit is not enabled.
*/
#define ELF_ET_DYN_BASE (2 * DEFAULT_MAP_WINDOW / 3)
#endif /* CONFIG_ARM64_FORCE_52BIT */

#ifndef __ASSEMBLY__
Expand Down Expand Up @@ -186,11 +190,17 @@ struct linux_binprm;
extern int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp);

// same as mmap_rnd_bits when VA_BITS == 39
#define MMAP_RND_BITS_39_BIT 24

/* 1GB of VA */
#ifdef CONFIG_COMPAT
#define STACK_RND_MASK (test_thread_flag(TIF_32BIT) ? \
((1UL << mmap_rnd_compat_bits) - 1) >> (PAGE_SHIFT - 12) : \
((1UL << mmap_rnd_bits) - 1) >> (PAGE_SHIFT - 12))
(test_thread_flag(TIF_39BIT) ? \
((1UL << MMAP_RND_BITS_39_BIT) - 1) >> (PAGE_SHIFT - 12) : \
((1UL << mmap_rnd_bits) - 1) >> (PAGE_SHIFT - 12)))

#else
#define STACK_RND_MASK (((1UL << mmap_rnd_bits) - 1) >> (PAGE_SHIFT - 12))
#endif
Expand Down
9 changes: 5 additions & 4 deletions arch/arm64/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@

#define DEFAULT_MAP_WINDOW_64 (UL(1) << VA_BITS_MIN)
#define TASK_SIZE_64 (UL(1) << vabits_actual)
#define TASK_SIZE_39 (UL(1) << 39)
#define TASK_SIZE_MAX (UL(1) << VA_BITS)

#ifdef CONFIG_COMPAT
Expand All @@ -66,11 +67,11 @@
#define TASK_SIZE_32 (UL(0x100000000) - PAGE_SIZE)
#endif /* CONFIG_ARM64_64K_PAGES */
#define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \
TASK_SIZE_32 : TASK_SIZE_64)
TASK_SIZE_32 : (test_thread_flag(TIF_39BIT) ? TASK_SIZE_39 : TASK_SIZE_64))
#define TASK_SIZE_OF(tsk) (test_tsk_thread_flag(tsk, TIF_32BIT) ? \
TASK_SIZE_32 : TASK_SIZE_64)
TASK_SIZE_32 : (test_tsk_thread_flag(tsk, TIF_39BIT) ? TASK_SIZE_39 : TASK_SIZE_64))
#define DEFAULT_MAP_WINDOW (test_thread_flag(TIF_32BIT) ? \
TASK_SIZE_32 : DEFAULT_MAP_WINDOW_64)
TASK_SIZE_32 : (test_thread_flag(TIF_39BIT) ? TASK_SIZE_39 : DEFAULT_MAP_WINDOW_64))
#else
#define TASK_SIZE TASK_SIZE_64
#define DEFAULT_MAP_WINDOW DEFAULT_MAP_WINDOW_64
Expand All @@ -87,7 +88,7 @@
#ifdef CONFIG_COMPAT
#define AARCH32_VECTORS_BASE 0xffff0000
#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
AARCH32_VECTORS_BASE : STACK_TOP_MAX)
AARCH32_VECTORS_BASE : (test_thread_flag(TIF_39BIT) ? TASK_SIZE_39 : STACK_TOP_MAX))
#else
#define STACK_TOP STACK_TOP_MAX
#endif /* CONFIG_COMPAT */
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ int arch_dup_task_struct(struct task_struct *dst,
#define TIF_SVE_VL_INHERIT 24 /* Inherit sve_vl_onexec across exec */
#define TIF_SSBD 25 /* Wants SSB mitigation */
#define TIF_TAGGED_ADDR 26 /* Allow tagged user addresses */
#define TIF_39BIT 30 /* compat_va_39_bit mode */

#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
Expand Down
7 changes: 7 additions & 0 deletions fs/binfmt_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,13 @@ static int load_elf_binary(struct linux_binprm *bprm)
/* Do this immediately, since STACK_TOP as used in setup_arg_pages
may depend on the personality. */
SET_PERSONALITY2(*elf_ex, &arch_state);

#ifdef CONFIG_ARM64
if (bprm->compat_va_39_bit) {
set_thread_flag(TIF_39BIT);
}
#endif

if (elf_read_implies_exec(*elf_ex, executable_stack))
current->personality |= READ_IMPLIES_EXEC;

Expand Down
4 changes: 4 additions & 0 deletions fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1911,6 +1911,10 @@ static int do_execveat_common(int fd, struct filename *filename,
goto out_ret;
}

#define FLAG_COMPAT_VA_39_BIT (1 << 30)
bprm->compat_va_39_bit = flags & FLAG_COMPAT_VA_39_BIT;
flags &= ~FLAG_COMPAT_VA_39_BIT; // flag validation fails when it sees an unknown flag

retval = count(argv, MAX_ARG_STRINGS);
if (retval == 0)
pr_warn_once("process '%s' launched '%s' with NULL argv: empty string added\n",
Expand Down
2 changes: 2 additions & 0 deletions include/linux/binfmts.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ struct linux_binprm {
struct cred *cred; /* new credentials */
int unsafe; /* how unsafe this exec is (mask of LSM_UNSAFE_*) */
unsigned int per_clear; /* bits to clear in current->personality */
/* if non-zero, emulate VA_BITS == 39, needed for programs that break when VA_BITS > 39 */
int compat_va_39_bit;
int argc, envc;
const char *filename; /* Name of binary as seen by procps */
const char *interp; /* Name of the binary really executed. Most
Expand Down
4 changes: 4 additions & 0 deletions mm/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,10 @@ unsigned long arch_mmap_rnd(void)
#ifdef CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS
if (is_compat_task())
rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1);
#ifdef CONFIG_ARM64
else if (test_thread_flag(TIF_39BIT))
rnd = get_random_long() & ((1UL << MMAP_RND_BITS_39_BIT) - 1);
#endif
else
#endif /* CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS */
rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1);
Expand Down

0 comments on commit ff8f099

Please sign in to comment.