mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-06 05:13:18 +00:00
execve updates for 6.10-rc1
- 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 -----BEGIN PGP SIGNATURE----- iQJKBAABCgA0FiEEpcP2jyKd1g9yPm4TiXL039xtwCYFAmY/xb8WHGtlZXNjb29r QGNocm9taXVtLm9yZwAKCRCJcvTf3G3AJvVnEACTW/db647prqm9FsoPB0rjjNIu JM50Z7M1Euj8FN/v4p7QjFY2v0vwk8XLfOVNncqvl0BCoAWuNVbt+tFdz0Teguza nIkMuJrtRA5q0dKaM49HiIABpEIZSpJuWwYiJhyZ5KIxc5KdzHmI7HrZDNO0ISgO iwIzAfW/2PrpsdY7Eq20gyVlSWIUZxe7gAUN/WIMn3JaYT+7d+D8pnNz8IGOrKR/ Xe9Gq1S0+8KUOJbxNsrdIA688dYsyS1XhadrOc0MPxOOyvQFein0pE6JfZRB+oLi p3FfECZgHhmvswaNeDKtLyfI0q7tXnlQugLuueRGNEJNMln0EUe813qRQvimMOWc cQY8lqN7uEIynhZZLoRxWcRFWmJ71Af32RkRdlM47+Vmv9CdHO/VCVaI9GIObx5Z DwtUlE28sz2J5xlnysm6zUxyeZibGYumFgHIUrjZR+fNgpYp8CggbKpWorI7dlaq UmJlziWLkXJmHzTv+AoaktRKbfDbpE1M3ym1KeA5y9KuEH+FejamBigGPzo+t9O7 TA2AgP5N8Fjs/dzUE0yqrQMxnjjCEXWKvPQA0A0CmyFbK9Xb0TJ6OmYcodKbmG7y /z9n01rnuK/UtXiyGfnwxbcKKOqC3wRepyw1wc8eX8pwuERUw+ztyTOyMdaxq+Ba mONnCNda7XD+wzoA7g== =GNfU -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
92f74f7f40
@ -510,6 +510,15 @@ config MMU_LAZY_TLB_SHOOTDOWN
|
|||||||
config ARCH_HAVE_NMI_SAFE_CMPXCHG
|
config ARCH_HAVE_NMI_SAFE_CMPXCHG
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config ARCH_HAVE_EXTRA_ELF_NOTES
|
||||||
|
bool
|
||||||
|
help
|
||||||
|
An architecture should select this in order to enable adding an
|
||||||
|
arch-specific ELF note section to core files. It must provide two
|
||||||
|
functions: elf_coredump_extra_notes_size() and
|
||||||
|
elf_coredump_extra_notes_write() which are invoked by the ELF core
|
||||||
|
dumper.
|
||||||
|
|
||||||
config ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
|
config ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
@ -156,6 +156,7 @@ config PPC
|
|||||||
select ARCH_HAS_UACCESS_FLUSHCACHE
|
select ARCH_HAS_UACCESS_FLUSHCACHE
|
||||||
select ARCH_HAS_UBSAN
|
select ARCH_HAS_UBSAN
|
||||||
select ARCH_HAVE_NMI_SAFE_CMPXCHG
|
select ARCH_HAVE_NMI_SAFE_CMPXCHG
|
||||||
|
select ARCH_HAVE_EXTRA_ELF_NOTES if SPU_BASE
|
||||||
select ARCH_KEEP_MEMBLOCK
|
select ARCH_KEEP_MEMBLOCK
|
||||||
select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if PPC_RADIX_MMU
|
select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if PPC_RADIX_MMU
|
||||||
select ARCH_MIGHT_HAVE_PC_PARPORT
|
select ARCH_MIGHT_HAVE_PC_PARPORT
|
||||||
|
@ -127,8 +127,6 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
|
|||||||
/* Notes used in ET_CORE. Note name is "SPU/<fd>/<filename>". */
|
/* Notes used in ET_CORE. Note name is "SPU/<fd>/<filename>". */
|
||||||
#define NT_SPU 1
|
#define NT_SPU 1
|
||||||
|
|
||||||
#define ARCH_HAVE_EXTRA_ELF_NOTES
|
|
||||||
|
|
||||||
#endif /* CONFIG_SPU_BASE */
|
#endif /* CONFIG_SPU_BASE */
|
||||||
|
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
|
@ -1262,6 +1262,9 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|||||||
if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) &&
|
if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) &&
|
||||||
elf_ex->e_type == ET_DYN && !interpreter) {
|
elf_ex->e_type == ET_DYN && !interpreter) {
|
||||||
mm->brk = mm->start_brk = ELF_ET_DYN_BASE;
|
mm->brk = mm->start_brk = ELF_ET_DYN_BASE;
|
||||||
|
} else {
|
||||||
|
/* Otherwise leave a gap between .bss and brk. */
|
||||||
|
mm->brk = mm->start_brk = mm->brk + PAGE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
mm->brk = mm->start_brk = arch_randomize_brk(mm);
|
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,
|
|||||||
fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata);
|
fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_FILE_NOTE_SIZE (4*1024*1024)
|
|
||||||
/*
|
/*
|
||||||
* Format of NT_FILE note:
|
* Format of NT_FILE note:
|
||||||
*
|
*
|
||||||
@ -1592,8 +1594,12 @@ static int fill_files_note(struct memelfnote *note, struct coredump_params *cprm
|
|||||||
|
|
||||||
names_ofs = (2 + 3 * count) * sizeof(data[0]);
|
names_ofs = (2 + 3 * count) * sizeof(data[0]);
|
||||||
alloc:
|
alloc:
|
||||||
if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */
|
/* paranoia check */
|
||||||
|
if (size >= core_file_note_size_limit) {
|
||||||
|
pr_warn_once("coredump Note size too large: %u (does kernel.core_file_note_size_limit sysctl need adjustment?\n",
|
||||||
|
size);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
size = round_up(size, PAGE_SIZE);
|
size = round_up(size, PAGE_SIZE);
|
||||||
/*
|
/*
|
||||||
* "size" can be 0 here legitimately.
|
* "size" can be 0 here legitimately.
|
||||||
|
@ -505,8 +505,9 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
|
|||||||
char *k_platform, *k_base_platform;
|
char *k_platform, *k_base_platform;
|
||||||
char __user *u_platform, *u_base_platform, *p;
|
char __user *u_platform, *u_base_platform, *p;
|
||||||
int loop;
|
int loop;
|
||||||
int nr; /* reset for each csp adjustment */
|
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
|
int ei_index;
|
||||||
|
elf_addr_t *elf_info;
|
||||||
|
|
||||||
#ifdef CONFIG_MMU
|
#ifdef CONFIG_MMU
|
||||||
/* In some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
|
/* 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,
|
|||||||
csp -= sp & 15UL;
|
csp -= sp & 15UL;
|
||||||
sp -= sp & 15UL;
|
sp -= sp & 15UL;
|
||||||
|
|
||||||
/* put the ELF interpreter info on the stack */
|
/* Create the ELF interpreter info */
|
||||||
#define NEW_AUX_ENT(id, val) \
|
elf_info = (elf_addr_t *)mm->saved_auxv;
|
||||||
do { \
|
/* update AT_VECTOR_SIZE_BASE if the number of NEW_AUX_ENT() changes */
|
||||||
struct { unsigned long _id, _val; } __user *ent, v; \
|
#define NEW_AUX_ENT(id, val) \
|
||||||
\
|
do { \
|
||||||
ent = (void __user *) csp; \
|
*elf_info++ = id; \
|
||||||
v._id = (id); \
|
*elf_info++ = val; \
|
||||||
v._val = (val); \
|
|
||||||
if (copy_to_user(ent + nr, &v, sizeof(v))) \
|
|
||||||
return -EFAULT; \
|
|
||||||
nr++; \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
nr = 0;
|
#ifdef ARCH_DLINFO
|
||||||
csp -= 2 * sizeof(unsigned long);
|
/*
|
||||||
NEW_AUX_ENT(AT_NULL, 0);
|
* ARCH_DLINFO must come first so PPC can do its special alignment of
|
||||||
if (k_platform) {
|
* AUXV.
|
||||||
nr = 0;
|
* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT() in
|
||||||
csp -= 2 * sizeof(unsigned long);
|
* ARCH_DLINFO changes
|
||||||
NEW_AUX_ENT(AT_PLATFORM,
|
*/
|
||||||
(elf_addr_t) (unsigned long) u_platform);
|
ARCH_DLINFO;
|
||||||
}
|
#endif
|
||||||
|
|
||||||
if (k_base_platform) {
|
|
||||||
nr = 0;
|
|
||||||
csp -= 2 * sizeof(unsigned long);
|
|
||||||
NEW_AUX_ENT(AT_BASE_PLATFORM,
|
|
||||||
(elf_addr_t) (unsigned long) u_base_platform);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bprm->have_execfd) {
|
|
||||||
nr = 0;
|
|
||||||
csp -= 2 * sizeof(unsigned long);
|
|
||||||
NEW_AUX_ENT(AT_EXECFD, bprm->execfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
nr = 0;
|
|
||||||
csp -= DLINFO_ITEMS * 2 * sizeof(unsigned long);
|
|
||||||
NEW_AUX_ENT(AT_HWCAP, ELF_HWCAP);
|
NEW_AUX_ENT(AT_HWCAP, ELF_HWCAP);
|
||||||
#ifdef ELF_HWCAP2
|
#ifdef ELF_HWCAP2
|
||||||
NEW_AUX_ENT(AT_HWCAP2, ELF_HWCAP2);
|
NEW_AUX_ENT(AT_HWCAP2, ELF_HWCAP2);
|
||||||
@ -659,17 +640,29 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
|
|||||||
NEW_AUX_ENT(AT_EGID, (elf_addr_t) from_kgid_munged(cred->user_ns, cred->egid));
|
NEW_AUX_ENT(AT_EGID, (elf_addr_t) from_kgid_munged(cred->user_ns, cred->egid));
|
||||||
NEW_AUX_ENT(AT_SECURE, bprm->secureexec);
|
NEW_AUX_ENT(AT_SECURE, bprm->secureexec);
|
||||||
NEW_AUX_ENT(AT_EXECFN, bprm->exec);
|
NEW_AUX_ENT(AT_EXECFN, bprm->exec);
|
||||||
|
if (k_platform)
|
||||||
#ifdef ARCH_DLINFO
|
NEW_AUX_ENT(AT_PLATFORM,
|
||||||
nr = 0;
|
(elf_addr_t)(unsigned long)u_platform);
|
||||||
csp -= AT_VECTOR_SIZE_ARCH * 2 * sizeof(unsigned long);
|
if (k_base_platform)
|
||||||
|
NEW_AUX_ENT(AT_BASE_PLATFORM,
|
||||||
/* ARCH_DLINFO must come last so platform specific code can enforce
|
(elf_addr_t)(unsigned long)u_base_platform);
|
||||||
* special alignment requirements on the AUXV if necessary (eg. PPC).
|
if (bprm->have_execfd)
|
||||||
*/
|
NEW_AUX_ENT(AT_EXECFD, bprm->execfd);
|
||||||
ARCH_DLINFO;
|
|
||||||
#endif
|
|
||||||
#undef NEW_AUX_ENT
|
#undef NEW_AUX_ENT
|
||||||
|
/* AT_NULL is zero; clear the rest too */
|
||||||
|
memset(elf_info, 0, (char *)mm->saved_auxv +
|
||||||
|
sizeof(mm->saved_auxv) - (char *)elf_info);
|
||||||
|
|
||||||
|
/* And advance past the AT_NULL entry. */
|
||||||
|
elf_info += 2;
|
||||||
|
|
||||||
|
ei_index = elf_info - (elf_addr_t *)mm->saved_auxv;
|
||||||
|
csp -= ei_index * sizeof(elf_addr_t);
|
||||||
|
|
||||||
|
/* Put the elf_info on the stack in the right place. */
|
||||||
|
if (copy_to_user((void __user *)csp, mm->saved_auxv,
|
||||||
|
ei_index * sizeof(elf_addr_t)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
/* allocate room for argv[] and envv[] */
|
/* allocate room for argv[] and envv[] */
|
||||||
csp -= (bprm->envc + 1) * sizeof(elf_caddr_t);
|
csp -= (bprm->envc + 1) * sizeof(elf_caddr_t);
|
||||||
|
@ -56,10 +56,15 @@
|
|||||||
static bool dump_vma_snapshot(struct coredump_params *cprm);
|
static bool dump_vma_snapshot(struct coredump_params *cprm);
|
||||||
static void free_vma_snapshot(struct coredump_params *cprm);
|
static void free_vma_snapshot(struct coredump_params *cprm);
|
||||||
|
|
||||||
|
#define CORE_FILE_NOTE_SIZE_DEFAULT (4*1024*1024)
|
||||||
|
/* Define a reasonable max cap */
|
||||||
|
#define CORE_FILE_NOTE_SIZE_MAX (16*1024*1024)
|
||||||
|
|
||||||
static int core_uses_pid;
|
static int core_uses_pid;
|
||||||
static unsigned int core_pipe_limit;
|
static unsigned int core_pipe_limit;
|
||||||
static char core_pattern[CORENAME_MAX_SIZE] = "core";
|
static char core_pattern[CORENAME_MAX_SIZE] = "core";
|
||||||
static int core_name_size = CORENAME_MAX_SIZE;
|
static int core_name_size = CORENAME_MAX_SIZE;
|
||||||
|
unsigned int core_file_note_size_limit = CORE_FILE_NOTE_SIZE_DEFAULT;
|
||||||
|
|
||||||
struct core_name {
|
struct core_name {
|
||||||
char *corename;
|
char *corename;
|
||||||
@ -998,6 +1003,9 @@ static int proc_dostring_coredump(struct ctl_table *table, int write,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const unsigned int core_file_note_size_min = CORE_FILE_NOTE_SIZE_DEFAULT;
|
||||||
|
static const unsigned int core_file_note_size_max = CORE_FILE_NOTE_SIZE_MAX;
|
||||||
|
|
||||||
static struct ctl_table coredump_sysctls[] = {
|
static struct ctl_table coredump_sysctls[] = {
|
||||||
{
|
{
|
||||||
.procname = "core_uses_pid",
|
.procname = "core_uses_pid",
|
||||||
@ -1020,6 +1028,15 @@ static struct ctl_table coredump_sysctls[] = {
|
|||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = proc_dointvec,
|
.proc_handler = proc_dointvec,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.procname = "core_file_note_size_limit",
|
||||||
|
.data = &core_file_note_size_limit,
|
||||||
|
.maxlen = sizeof(unsigned int),
|
||||||
|
.mode = 0644,
|
||||||
|
.proc_handler = proc_douintvec_minmax,
|
||||||
|
.extra1 = (unsigned int *)&core_file_note_size_min,
|
||||||
|
.extra2 = (unsigned int *)&core_file_note_size_max,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init init_fs_coredump_sysctls(void)
|
static int __init init_fs_coredump_sysctls(void)
|
||||||
|
@ -1267,6 +1267,14 @@ int begin_new_exec(struct linux_binprm * bprm)
|
|||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This tracepoint marks the point before flushing the old exec where
|
||||||
|
* the current task is still unchanged, but errors are fatal (point of
|
||||||
|
* no return). The later "sched_process_exec" tracepoint is called after
|
||||||
|
* the current task has successfully switched to the new exec.
|
||||||
|
*/
|
||||||
|
trace_sched_prepare_exec(current, bprm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure all future errors are fatal.
|
* Ensure all future errors are fatal.
|
||||||
*/
|
*/
|
||||||
|
@ -30,6 +30,8 @@ struct coredump_params {
|
|||||||
struct core_vma_metadata *vma_meta;
|
struct core_vma_metadata *vma_meta;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern unsigned int core_file_note_size_limit;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are the only things you should do on a core-file: use only these
|
* These are the only things you should do on a core-file: use only these
|
||||||
* functions to write out all the necessary info.
|
* functions to write out all the necessary info.
|
||||||
|
@ -65,7 +65,7 @@ extern Elf64_Dyn _DYNAMIC [];
|
|||||||
struct file;
|
struct file;
|
||||||
struct coredump_params;
|
struct coredump_params;
|
||||||
|
|
||||||
#ifndef ARCH_HAVE_EXTRA_ELF_NOTES
|
#ifndef CONFIG_ARCH_HAVE_EXTRA_ELF_NOTES
|
||||||
static inline int elf_coredump_extra_notes_size(void) { return 0; }
|
static inline int elf_coredump_extra_notes_size(void) { return 0; }
|
||||||
static inline int elf_coredump_extra_notes_write(struct coredump_params *cprm) { return 0; }
|
static inline int elf_coredump_extra_notes_write(struct coredump_params *cprm) { return 0; }
|
||||||
#else
|
#else
|
||||||
|
@ -420,6 +420,41 @@ TRACE_EVENT(sched_process_exec,
|
|||||||
__entry->pid, __entry->old_pid)
|
__entry->pid, __entry->old_pid)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sched_prepare_exec - called before setting up new exec
|
||||||
|
* @task: pointer to the current task
|
||||||
|
* @bprm: pointer to linux_binprm used for new exec
|
||||||
|
*
|
||||||
|
* Called before flushing the old exec, where @task is still unchanged, but at
|
||||||
|
* the point of no return during switching to the new exec. At the point it is
|
||||||
|
* called the exec will either succeed, or on failure terminate the task. Also
|
||||||
|
* see the "sched_process_exec" tracepoint, which is called right after @task
|
||||||
|
* has successfully switched to the new exec.
|
||||||
|
*/
|
||||||
|
TRACE_EVENT(sched_prepare_exec,
|
||||||
|
|
||||||
|
TP_PROTO(struct task_struct *task, struct linux_binprm *bprm),
|
||||||
|
|
||||||
|
TP_ARGS(task, bprm),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__string( interp, bprm->interp )
|
||||||
|
__string( filename, bprm->filename )
|
||||||
|
__field( pid_t, pid )
|
||||||
|
__string( comm, task->comm )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__assign_str(interp, bprm->interp);
|
||||||
|
__assign_str(filename, bprm->filename);
|
||||||
|
__entry->pid = task->pid;
|
||||||
|
__assign_str(comm, task->comm);
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("interp=%s filename=%s pid=%d comm=%s",
|
||||||
|
__get_str(interp), __get_str(filename),
|
||||||
|
__entry->pid, __get_str(comm))
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef CONFIG_SCHEDSTATS
|
#ifdef CONFIG_SCHEDSTATS
|
||||||
#define DEFINE_EVENT_SCHEDSTAT DEFINE_EVENT
|
#define DEFINE_EVENT_SCHEDSTAT DEFINE_EVENT
|
||||||
|
Loading…
Reference in New Issue
Block a user