Skip to content

Commit 92f74f7

Browse files
committed
Merge tag 'execve-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull execve updates from Kees Cook: - Provide knob to change (previously fixed) coredump NOTES size (Allen Pais) - Add sched_prepare_exec tracepoint (Marco Elver) - Make /proc/$pid/auxv work under binfmt_elf_fdpic (Max Filippov) - Convert ARCH_HAVE_EXTRA_ELF_NOTES to proper Kconfig (Vignesh Balasubramanian) - Leave a gap between .bss and brk * tag 'execve-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: fs/coredump: Enable dynamic configuration of max file note size binfmt_elf_fdpic: fix /proc/<pid>/auxv binfmt_elf: Leave a gap between .bss and brk Replace macro "ARCH_HAVE_EXTRA_ELF_NOTES" with kconfig tracing: Add sched_prepare_exec tracepoint
2 parents 1ba58f1 + 4bbf9c3 commit 92f74f7

File tree

10 files changed

+120
-51
lines changed

10 files changed

+120
-51
lines changed

arch/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,15 @@ config MMU_LAZY_TLB_SHOOTDOWN
510510
config ARCH_HAVE_NMI_SAFE_CMPXCHG
511511
bool
512512

513+
config ARCH_HAVE_EXTRA_ELF_NOTES
514+
bool
515+
help
516+
An architecture should select this in order to enable adding an
517+
arch-specific ELF note section to core files. It must provide two
518+
functions: elf_coredump_extra_notes_size() and
519+
elf_coredump_extra_notes_write() which are invoked by the ELF core
520+
dumper.
521+
513522
config ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
514523
bool
515524

arch/powerpc/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ config PPC
156156
select ARCH_HAS_UACCESS_FLUSHCACHE
157157
select ARCH_HAS_UBSAN
158158
select ARCH_HAVE_NMI_SAFE_CMPXCHG
159+
select ARCH_HAVE_EXTRA_ELF_NOTES if SPU_BASE
159160
select ARCH_KEEP_MEMBLOCK
160161
select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if PPC_RADIX_MMU
161162
select ARCH_MIGHT_HAVE_PC_PARPORT

arch/powerpc/include/asm/elf.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,6 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
127127
/* Notes used in ET_CORE. Note name is "SPU/<fd>/<filename>". */
128128
#define NT_SPU 1
129129

130-
#define ARCH_HAVE_EXTRA_ELF_NOTES
131-
132130
#endif /* CONFIG_SPU_BASE */
133131

134132
#ifdef CONFIG_PPC64

fs/binfmt_elf.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,9 @@ static int load_elf_binary(struct linux_binprm *bprm)
12621262
if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) &&
12631263
elf_ex->e_type == ET_DYN && !interpreter) {
12641264
mm->brk = mm->start_brk = ELF_ET_DYN_BASE;
1265+
} else {
1266+
/* Otherwise leave a gap between .bss and brk. */
1267+
mm->brk = mm->start_brk = mm->brk + PAGE_SIZE;
12651268
}
12661269

12671270
mm->brk = mm->start_brk = arch_randomize_brk(mm);
@@ -1564,7 +1567,6 @@ static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata,
15641567
fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata);
15651568
}
15661569

1567-
#define MAX_FILE_NOTE_SIZE (4*1024*1024)
15681570
/*
15691571
* Format of NT_FILE note:
15701572
*
@@ -1592,8 +1594,12 @@ static int fill_files_note(struct memelfnote *note, struct coredump_params *cprm
15921594

15931595
names_ofs = (2 + 3 * count) * sizeof(data[0]);
15941596
alloc:
1595-
if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */
1597+
/* paranoia check */
1598+
if (size >= core_file_note_size_limit) {
1599+
pr_warn_once("coredump Note size too large: %u (does kernel.core_file_note_size_limit sysctl need adjustment?\n",
1600+
size);
15961601
return -EINVAL;
1602+
}
15971603
size = round_up(size, PAGE_SIZE);
15981604
/*
15991605
* "size" can be 0 here legitimately.

fs/binfmt_elf_fdpic.c

Lines changed: 39 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -505,8 +505,9 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
505505
char *k_platform, *k_base_platform;
506506
char __user *u_platform, *u_base_platform, *p;
507507
int loop;
508-
int nr; /* reset for each csp adjustment */
509508
unsigned long flags = 0;
509+
int ei_index;
510+
elf_addr_t *elf_info;
510511

511512
#ifdef CONFIG_MMU
512513
/* In some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
@@ -601,44 +602,24 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
601602
csp -= sp & 15UL;
602603
sp -= sp & 15UL;
603604

604-
/* put the ELF interpreter info on the stack */
605-
#define NEW_AUX_ENT(id, val) \
606-
do { \
607-
struct { unsigned long _id, _val; } __user *ent, v; \
608-
\
609-
ent = (void __user *) csp; \
610-
v._id = (id); \
611-
v._val = (val); \
612-
if (copy_to_user(ent + nr, &v, sizeof(v))) \
613-
return -EFAULT; \
614-
nr++; \
605+
/* Create the ELF interpreter info */
606+
elf_info = (elf_addr_t *)mm->saved_auxv;
607+
/* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */
608+
#define NEW_AUX_ENT(id, val) \
609+
do { \
610+
*elf_info++ = id; \
611+
*elf_info++ = val; \
615612
} while (0)
616613

617-
nr = 0;
618-
csp -= 2 * sizeof(unsigned long);
619-
NEW_AUX_ENT(AT_NULL, 0);
620-
if (k_platform) {
621-
nr = 0;
622-
csp -= 2 * sizeof(unsigned long);
623-
NEW_AUX_ENT(AT_PLATFORM,
624-
(elf_addr_t) (unsigned long) u_platform);
625-
}
626-
627-
if (k_base_platform) {
628-
nr = 0;
629-
csp -= 2 * sizeof(unsigned long);
630-
NEW_AUX_ENT(AT_BASE_PLATFORM,
631-
(elf_addr_t) (unsigned long) u_base_platform);
632-
}
633-
634-
if (bprm->have_execfd) {
635-
nr = 0;
636-
csp -= 2 * sizeof(unsigned long);
637-
NEW_AUX_ENT(AT_EXECFD, bprm->execfd);
638-
}
639-
640-
nr = 0;
641-
csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long);
614+
#ifdef ARCH_DLINFO
615+
/*
616+
* ARCH_DLINFO must come first so PPC can do its special alignment of
617+
* AUXV.
618+
* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT() in
619+
* ARCH_DLINFO changes
620+
*/
621+
ARCH_DLINFO;
622+
#endif
642623
NEW_AUX_ENT(AT_HWCAP, ELF_HWCAP);
643624
#ifdef ELF_HWCAP2
644625
NEW_AUX_ENT(AT_HWCAP2, ELF_HWCAP2);
@@ -659,17 +640,29 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
659640
NEW_AUX_ENT(AT_EGID, (elf_addr_t) from_kgid_munged(cred->user_ns, cred->egid));
660641
NEW_AUX_ENT(AT_SECURE, bprm->secureexec);
661642
NEW_AUX_ENT(AT_EXECFN, bprm->exec);
643+
if (k_platform)
644+
NEW_AUX_ENT(AT_PLATFORM,
645+
(elf_addr_t)(unsigned long)u_platform);
646+
if (k_base_platform)
647+
NEW_AUX_ENT(AT_BASE_PLATFORM,
648+
(elf_addr_t)(unsigned long)u_base_platform);
649+
if (bprm->have_execfd)
650+
NEW_AUX_ENT(AT_EXECFD, bprm->execfd);
651+
#undef NEW_AUX_ENT
652+
/* AT_NULL is zero; clear the rest too */
653+
memset(elf_info, 0, (char *)mm->saved_auxv +
654+
sizeof(mm->saved_auxv) - (char *)elf_info);
662655

663-
#ifdef ARCH_DLINFO
664-
nr = 0;
665-
csp -= AT_VECTOR_SIZE_ARCH * 2 * sizeof(unsigned long);
656+
/* And advance past the AT_NULL entry. */
657+
elf_info += 2;
666658

667-
/* ARCH_DLINFO must come last so platform specific code can enforce
668-
* special alignment requirements on the AUXV if necessary (eg. PPC).
669-
*/
670-
ARCH_DLINFO;
671-
#endif
672-
#undef NEW_AUX_ENT
659+
ei_index = elf_info - (elf_addr_t *)mm->saved_auxv;
660+
csp -= ei_index * sizeof(elf_addr_t);
661+
662+
/* Put the elf_info on the stack in the right place. */
663+
if (copy_to_user((void __user *)csp, mm->saved_auxv,
664+
ei_index * sizeof(elf_addr_t)))
665+
return -EFAULT;
673666

674667
/* allocate room for argv[] and envv[] */
675668
csp -= (bprm->envc + 1) * sizeof(elf_caddr_t);

fs/coredump.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,15 @@
5656
static bool dump_vma_snapshot(struct coredump_params *cprm);
5757
static void free_vma_snapshot(struct coredump_params *cprm);
5858

59+
#define CORE_FILE_NOTE_SIZE_DEFAULT (4*1024*1024)
60+
/* Define a reasonable max cap */
61+
#define CORE_FILE_NOTE_SIZE_MAX (16*1024*1024)
62+
5963
static int core_uses_pid;
6064
static unsigned int core_pipe_limit;
6165
static char core_pattern[CORENAME_MAX_SIZE] = "core";
6266
static int core_name_size = CORENAME_MAX_SIZE;
67+
unsigned int core_file_note_size_limit = CORE_FILE_NOTE_SIZE_DEFAULT;
6368

6469
struct core_name {
6570
char *corename;
@@ -998,6 +1003,9 @@ static int proc_dostring_coredump(struct ctl_table *table, int write,
9981003
return error;
9991004
}
10001005

1006+
static const unsigned int core_file_note_size_min = CORE_FILE_NOTE_SIZE_DEFAULT;
1007+
static const unsigned int core_file_note_size_max = CORE_FILE_NOTE_SIZE_MAX;
1008+
10011009
static struct ctl_table coredump_sysctls[] = {
10021010
{
10031011
.procname = "core_uses_pid",
@@ -1020,6 +1028,15 @@ static struct ctl_table coredump_sysctls[] = {
10201028
.mode = 0644,
10211029
.proc_handler = proc_dointvec,
10221030
},
1031+
{
1032+
.procname = "core_file_note_size_limit",
1033+
.data = &core_file_note_size_limit,
1034+
.maxlen = sizeof(unsigned int),
1035+
.mode = 0644,
1036+
.proc_handler = proc_douintvec_minmax,
1037+
.extra1 = (unsigned int *)&core_file_note_size_min,
1038+
.extra2 = (unsigned int *)&core_file_note_size_max,
1039+
},
10231040
};
10241041

10251042
static int __init init_fs_coredump_sysctls(void)

fs/exec.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,14 @@ int begin_new_exec(struct linux_binprm * bprm)
12671267
if (retval)
12681268
return retval;
12691269

1270+
/*
1271+
* This tracepoint marks the point before flushing the old exec where
1272+
* the current task is still unchanged, but errors are fatal (point of
1273+
* no return). The later "sched_process_exec" tracepoint is called after
1274+
* the current task has successfully switched to the new exec.
1275+
*/
1276+
trace_sched_prepare_exec(current, bprm);
1277+
12701278
/*
12711279
* Ensure all future errors are fatal.
12721280
*/

include/linux/coredump.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ struct coredump_params {
3030
struct core_vma_metadata *vma_meta;
3131
};
3232

33+
extern unsigned int core_file_note_size_limit;
34+
3335
/*
3436
* These are the only things you should do on a core-file: use only these
3537
* functions to write out all the necessary info.

include/linux/elf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ extern Elf64_Dyn _DYNAMIC [];
6565
struct file;
6666
struct coredump_params;
6767

68-
#ifndef ARCH_HAVE_EXTRA_ELF_NOTES
68+
#ifndef CONFIG_ARCH_HAVE_EXTRA_ELF_NOTES
6969
static inline int elf_coredump_extra_notes_size(void) { return 0; }
7070
static inline int elf_coredump_extra_notes_write(struct coredump_params *cprm) { return 0; }
7171
#else

include/trace/events/sched.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,41 @@ TRACE_EVENT(sched_process_exec,
420420
__entry->pid, __entry->old_pid)
421421
);
422422

423+
/**
424+
* sched_prepare_exec - called before setting up new exec
425+
* @task: pointer to the current task
426+
* @bprm: pointer to linux_binprm used for new exec
427+
*
428+
* Called before flushing the old exec, where @task is still unchanged, but at
429+
* the point of no return during switching to the new exec. At the point it is
430+
* called the exec will either succeed, or on failure terminate the task. Also
431+
* see the "sched_process_exec" tracepoint, which is called right after @task
432+
* has successfully switched to the new exec.
433+
*/
434+
TRACE_EVENT(sched_prepare_exec,
435+
436+
TP_PROTO(struct task_struct *task, struct linux_binprm *bprm),
437+
438+
TP_ARGS(task, bprm),
439+
440+
TP_STRUCT__entry(
441+
__string( interp, bprm->interp )
442+
__string( filename, bprm->filename )
443+
__field( pid_t, pid )
444+
__string( comm, task->comm )
445+
),
446+
447+
TP_fast_assign(
448+
__assign_str(interp, bprm->interp);
449+
__assign_str(filename, bprm->filename);
450+
__entry->pid = task->pid;
451+
__assign_str(comm, task->comm);
452+
),
453+
454+
TP_printk("interp=%s filename=%s pid=%d comm=%s",
455+
__get_str(interp), __get_str(filename),
456+
__entry->pid, __get_str(comm))
457+
);
423458

424459
#ifdef CONFIG_SCHEDSTATS
425460
#define DEFINE_EVENT_SCHEDSTAT DEFINE_EVENT

0 commit comments

Comments
 (0)