#include <linux/kernel_read_file.h>
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/mm.h>
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/swap.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/sched/mm.h>
#include <linux/sched/coredump.h>
#include <linux/sched/signal.h>
#include <linux/sched/numa_balancing.h>
#include <linux/sched/task.h>
#include <linux/pagemap.h>
#include <linux/perf_event.h>
#include <linux/highmem.h>
#include <linux/spinlock.h>
#include <linux/key.h>
#include <linux/personality.h>
#include <linux/binfmts.h>
#include <linux/utsname.h>
#include <linux/pid_namespace.h>
#include <linux/module.h>
#include <linux/namei.h>
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/tsacct_kern.h>
#include <linux/cn_proc.h>
#include <linux/audit.h>
#include <linux/kmod.h>
#include <linux/fsnotify.h>
#include <linux/fs_struct.h>
#include <linux/oom.h>
#include <linux/compat.h>
#include <linux/vmalloc.h>
#include <linux/io_uring.h>
#include <linux/syscall_user_dispatch.h>
#include <linux/coredump.h>
#include <linux/time_namespace.h>
#include <linux/user_events.h>
#include <linux/rseq.h>
#include <linux/ksm.h>
#include <linux/uaccess.h>
#include <asm/mmu_context.h>
#include <asm/tlb.h>
#include <trace/events/task.h>
#include "internal.h"
#include <trace/events/sched.h>
static int bprm_creds_from_file(struct linux_binprm *bprm);
int suid_dumpable = …;
static LIST_HEAD(formats);
static DEFINE_RWLOCK(binfmt_lock);
void __register_binfmt(struct linux_binfmt * fmt, int insert)
{ … }
EXPORT_SYMBOL(…);
void unregister_binfmt(struct linux_binfmt * fmt)
{ … }
EXPORT_SYMBOL(…);
static inline void put_binfmt(struct linux_binfmt * fmt)
{ … }
bool path_noexec(const struct path *path)
{ … }
#ifdef CONFIG_USELIB
SYSCALL_DEFINE1(uselib, const char __user *, library)
{ … }
#endif
#ifdef CONFIG_MMU
static void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
{ … }
static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
int write)
{ … }
static void put_arg_page(struct page *page)
{ … }
static void free_arg_pages(struct linux_binprm *bprm)
{ … }
static void flush_arg_page(struct linux_binprm *bprm, unsigned long pos,
struct page *page)
{ … }
static int __bprm_mm_init(struct linux_binprm *bprm)
{ … }
static bool valid_arg_len(struct linux_binprm *bprm, long len)
{ … }
#else
static inline void acct_arg_size(struct linux_binprm *bprm, unsigned long pages)
{
}
static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
int write)
{
struct page *page;
page = bprm->page[pos / PAGE_SIZE];
if (!page && write) {
page = alloc_page(GFP_HIGHUSER|__GFP_ZERO);
if (!page)
return NULL;
bprm->page[pos / PAGE_SIZE] = page;
}
return page;
}
static void put_arg_page(struct page *page)
{
}
static void free_arg_page(struct linux_binprm *bprm, int i)
{
if (bprm->page[i]) {
__free_page(bprm->page[i]);
bprm->page[i] = NULL;
}
}
static void free_arg_pages(struct linux_binprm *bprm)
{
int i;
for (i = 0; i < MAX_ARG_PAGES; i++)
free_arg_page(bprm, i);
}
static void flush_arg_page(struct linux_binprm *bprm, unsigned long pos,
struct page *page)
{
}
static int __bprm_mm_init(struct linux_binprm *bprm)
{
bprm->p = PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *);
return 0;
}
static bool valid_arg_len(struct linux_binprm *bprm, long len)
{
return len <= bprm->p;
}
#endif
static int bprm_mm_init(struct linux_binprm *bprm)
{ … }
struct user_arg_ptr { … };
static const char __user *get_user_arg_ptr(struct user_arg_ptr argv, int nr)
{ … }
static int count(struct user_arg_ptr argv, int max)
{ … }
static int count_strings_kernel(const char *const *argv)
{ … }
static inline int bprm_set_stack_limit(struct linux_binprm *bprm,
unsigned long limit)
{ … }
static inline bool bprm_hit_stack_limit(struct linux_binprm *bprm)
{ … }
static int bprm_stack_limits(struct linux_binprm *bprm)
{ … }
static int copy_strings(int argc, struct user_arg_ptr argv,
struct linux_binprm *bprm)
{ … }
int copy_string_kernel(const char *arg, struct linux_binprm *bprm)
{ … }
EXPORT_SYMBOL(…);
static int copy_strings_kernel(int argc, const char *const *argv,
struct linux_binprm *bprm)
{ … }
#ifdef CONFIG_MMU
static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
{ … }
int setup_arg_pages(struct linux_binprm *bprm,
unsigned long stack_top,
int executable_stack)
{ … }
EXPORT_SYMBOL(…);
#else
int transfer_args_to_stack(struct linux_binprm *bprm,
unsigned long *sp_location)
{
unsigned long index, stop, sp;
int ret = 0;
stop = bprm->p >> PAGE_SHIFT;
sp = *sp_location;
for (index = MAX_ARG_PAGES - 1; index >= stop; index--) {
unsigned int offset = index == stop ? bprm->p & ~PAGE_MASK : 0;
char *src = kmap_local_page(bprm->page[index]) + offset;
sp -= PAGE_SIZE - offset;
if (copy_to_user((void *) sp, src, PAGE_SIZE - offset) != 0)
ret = -EFAULT;
kunmap_local(src);
if (ret)
goto out;
}
bprm->exec += *sp_location - MAX_ARG_PAGES * PAGE_SIZE;
*sp_location = sp;
out:
return ret;
}
EXPORT_SYMBOL(transfer_args_to_stack);
#endif
static struct file *do_open_execat(int fd, struct filename *name, int flags)
{ … }
struct file *open_exec(const char *name)
{ … }
EXPORT_SYMBOL(…);
#if defined(CONFIG_BINFMT_FLAT) || defined(CONFIG_BINFMT_ELF_FDPIC)
ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len)
{
ssize_t res = vfs_read(file, (void __user *)addr, len, &pos);
if (res > 0)
flush_icache_user_range(addr, addr + len);
return res;
}
EXPORT_SYMBOL(read_code);
#endif
static int exec_mmap(struct mm_struct *mm)
{ … }
static int de_thread(struct task_struct *tsk)
{ … }
static int unshare_sighand(struct task_struct *me)
{ … }
char *__get_task_comm(char *buf, size_t buf_size, struct task_struct *tsk)
{ … }
EXPORT_SYMBOL_GPL(…);
void __set_task_comm(struct task_struct *tsk, const char *buf, bool exec)
{ … }
int begin_new_exec(struct linux_binprm * bprm)
{ … }
EXPORT_SYMBOL(…);
void would_dump(struct linux_binprm *bprm, struct file *file)
{ … }
EXPORT_SYMBOL(…);
void setup_new_exec(struct linux_binprm * bprm)
{ … }
EXPORT_SYMBOL(…);
void finalize_exec(struct linux_binprm *bprm)
{ … }
EXPORT_SYMBOL(…);
static int prepare_bprm_creds(struct linux_binprm *bprm)
{ … }
static void do_close_execat(struct file *file)
{ … }
static void free_bprm(struct linux_binprm *bprm)
{ … }
static struct linux_binprm *alloc_bprm(int fd, struct filename *filename, int flags)
{ … }
int bprm_change_interp(const char *interp, struct linux_binprm *bprm)
{ … }
EXPORT_SYMBOL(…);
static void check_unsafe_exec(struct linux_binprm *bprm)
{ … }
static void bprm_fill_uid(struct linux_binprm *bprm, struct file *file)
{ … }
static int bprm_creds_from_file(struct linux_binprm *bprm)
{ … }
static int prepare_binprm(struct linux_binprm *bprm)
{ … }
int remove_arg_zero(struct linux_binprm *bprm)
{ … }
EXPORT_SYMBOL(…);
#define printable(c) …
static int search_binary_handler(struct linux_binprm *bprm)
{ … }
static int exec_binprm(struct linux_binprm *bprm)
{ … }
static int bprm_execve(struct linux_binprm *bprm)
{ … }
static int do_execveat_common(int fd, struct filename *filename,
struct user_arg_ptr argv,
struct user_arg_ptr envp,
int flags)
{ … }
int kernel_execve(const char *kernel_filename,
const char *const *argv, const char *const *envp)
{ … }
static int do_execve(struct filename *filename,
const char __user *const __user *__argv,
const char __user *const __user *__envp)
{ … }
static int do_execveat(int fd, struct filename *filename,
const char __user *const __user *__argv,
const char __user *const __user *__envp,
int flags)
{ … }
#ifdef CONFIG_COMPAT
static int compat_do_execve(struct filename *filename,
const compat_uptr_t __user *__argv,
const compat_uptr_t __user *__envp)
{ … }
static int compat_do_execveat(int fd, struct filename *filename,
const compat_uptr_t __user *__argv,
const compat_uptr_t __user *__envp,
int flags)
{ … }
#endif
void set_binfmt(struct linux_binfmt *new)
{ … }
EXPORT_SYMBOL(…);
void set_dumpable(struct mm_struct *mm, int value)
{ … }
SYSCALL_DEFINE3(execve,
const char __user *, filename,
const char __user *const __user *, argv,
const char __user *const __user *, envp)
{ … }
SYSCALL_DEFINE5(execveat,
int, fd, const char __user *, filename,
const char __user *const __user *, argv,
const char __user *const __user *, envp,
int, flags)
{ … }
#ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename,
const compat_uptr_t __user *, argv,
const compat_uptr_t __user *, envp)
{ … }
COMPAT_SYSCALL_DEFINE5(execveat, int, fd,
const char __user *, filename,
const compat_uptr_t __user *, argv,
const compat_uptr_t __user *, envp,
int, flags)
{ … }
#endif
#ifdef CONFIG_SYSCTL
static int proc_dointvec_minmax_coredump(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{ … }
static struct ctl_table fs_exec_sysctls[] = …;
static int __init init_fs_exec_sysctls(void)
{ … }
fs_initcall(init_fs_exec_sysctls);
#endif
#ifdef CONFIG_EXEC_KUNIT_TEST
#include "tests/exec_kunit.c"
#endif