Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *  linux/fs/binfmt_flat.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *	Copyright (C) 2000-2003 David McCullough <davidm@snapgear.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *	Copyright (C) 2002 Greg Ungerer <gerg@snapgear.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *	Copyright (C) 2002 SnapGear, by Paul Dale <pauli@snapgear.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  *	Copyright (C) 2000, 2001 Lineo, by David McCullough <davidm@lineo.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)  *  based heavily on:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)  *  linux/fs/binfmt_aout.c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)  *      Copyright (C) 1991, 1992, 1996  Linus Torvalds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)  *  linux/fs/binfmt_flat.c for 2.0 kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)  *	    Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16)  *	JAN/99 -- coded full program relocation (gerg@snapgear.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <linux/sched/task_stack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include <linux/mman.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <linux/file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) #include <linux/user.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include <linux/binfmts.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #include <linux/personality.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #include <linux/flat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #include <asm/byteorder.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #include <asm/cacheflush.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #include <asm/flat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #ifndef flat_get_relocate_addr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #define flat_get_relocate_addr(rel)	(rel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54)  * User data (data section and bss) needs to be aligned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55)  * We pick 0x20 here because it is the max value elf2flt has always
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56)  * used in producing FLAT files, and because it seems to be large
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57)  * enough to make all the gcc alignment related tests happy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #define FLAT_DATA_ALIGN	(0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62)  * User data (stack) also needs to be aligned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63)  * Here we can be a bit looser than the data sections since this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64)  * needs to only meet arch ABI requirements.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) #define FLAT_STACK_ALIGN	max_t(unsigned long, sizeof(void *), ARCH_SLAB_MINALIGN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) #define RELOC_FAILED 0xff00ff01		/* Relocation incorrect somewhere */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) #define UNLOADED_LIB 0x7ff000ff		/* Placeholder for unused library */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) #ifdef CONFIG_BINFMT_SHARED_FLAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) #define	MAX_SHARED_LIBS			(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) #define	MAX_SHARED_LIBS			(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) struct lib_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 	struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 		unsigned long start_code;		/* Start of text segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 		unsigned long start_data;		/* Start of data segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 		unsigned long start_brk;		/* End of data segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 		unsigned long text_len;			/* Length of text segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 		unsigned long entry;			/* Start address for this module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 		unsigned long build_date;		/* When this one was compiled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 		bool loaded;				/* Has this library been loaded? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 	} lib_list[MAX_SHARED_LIBS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) #ifdef CONFIG_BINFMT_SHARED_FLAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) static int load_flat_shared_library(int id, struct lib_info *p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) static int load_flat_binary(struct linux_binprm *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) static int flat_core_dump(struct coredump_params *cprm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) static struct linux_binfmt flat_format = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 	.module		= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 	.load_binary	= load_flat_binary,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 	.core_dump	= flat_core_dump,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 	.min_coredump	= PAGE_SIZE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105)  * Routine writes a core dump image in the current directory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106)  * Currently only a stub-function.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) static int flat_core_dump(struct coredump_params *cprm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 	pr_warn("Process %s:%d received signr %d and should have core dumped\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 		current->comm, current->pid, cprm->siginfo->si_signo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118)  * create_flat_tables() parses the env- and arg-strings in new user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119)  * memory and creates the pointer tables from them, and puts their
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120)  * addresses on the "stack", recording the new stack pointer value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) static int create_flat_tables(struct linux_binprm *bprm, unsigned long arg_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 	char __user *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 	unsigned long __user *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 	long i, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 	p = (char __user *)arg_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	sp = (unsigned long __user *)current->mm->start_stack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 	sp -= bprm->envc + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) 	sp -= bprm->argc + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 	if (IS_ENABLED(CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) 		sp -= 2; /* argvp + envp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	sp -= 1;  /* &argc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	current->mm->start_stack = (unsigned long)sp & -FLAT_STACK_ALIGN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	sp = (unsigned long __user *)current->mm->start_stack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	if (put_user(bprm->argc, sp++))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 		return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	if (IS_ENABLED(CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 		unsigned long argv, envp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 		argv = (unsigned long)(sp + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 		envp = (unsigned long)(sp + 2 + bprm->argc + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 		if (put_user(argv, sp++) || put_user(envp, sp++))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 	current->mm->arg_start = (unsigned long)p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	for (i = bprm->argc; i > 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 		if (put_user((unsigned long)p, sp++))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 		len = strnlen_user(p, MAX_ARG_STRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 		if (!len || len > MAX_ARG_STRLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 		p += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	if (put_user(0, sp++))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 		return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	current->mm->arg_end = (unsigned long)p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	current->mm->env_start = (unsigned long) p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 	for (i = bprm->envc; i > 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 		if (put_user((unsigned long)p, sp++))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 			return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 		len = strnlen_user(p, MAX_ARG_STRLEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 		if (!len || len > MAX_ARG_STRLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 		p += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	if (put_user(0, sp++))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 		return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	current->mm->env_end = (unsigned long)p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) #ifdef CONFIG_BINFMT_ZFLAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) #include <linux/zlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) #define LBUFSIZE	4000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) /* gzip flag byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) #define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) #define ORIG_NAME    0x08 /* bit 3 set: original file name present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) #define COMMENT      0x10 /* bit 4 set: file comment present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) #define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) #define RESERVED     0xC0 /* bit 6,7:   reserved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) static int decompress_exec(struct linux_binprm *bprm, loff_t fpos, char *dst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 		long len, int fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	unsigned char *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) 	z_stream strm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 	int ret, retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	pr_debug("decompress_exec(offset=%llx,buf=%p,len=%lx)\n", fpos, dst, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	memset(&strm, 0, sizeof(strm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 	strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	if (!strm.workspace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 	buf = kmalloc(LBUFSIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 	if (!buf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) 		retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 		goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 	/* Read in first chunk of data and parse gzip header. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	ret = kernel_read(bprm->file, buf, LBUFSIZE, &fpos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	strm.next_in = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	strm.avail_in = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	strm.total_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	retval = -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	/* Check minimum size -- gzip header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	if (ret < 10) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 		pr_debug("file too small?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 		goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	/* Check gzip magic number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 	if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 		pr_debug("unknown compression magic?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 		goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	/* Check gzip method */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	if (buf[2] != 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 		pr_debug("unknown compression method?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 		goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	/* Check gzip flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	    (buf[3] & RESERVED)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 		pr_debug("unknown flags?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 		goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 	ret = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 	if (buf[3] & EXTRA_FIELD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 		ret += 2 + buf[10] + (buf[11] << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 		if (unlikely(ret >= LBUFSIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 			pr_debug("buffer overflow (EXTRA)?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 			goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 	if (buf[3] & ORIG_NAME) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 		while (ret < LBUFSIZE && buf[ret++] != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 			;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 		if (unlikely(ret == LBUFSIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 			pr_debug("buffer overflow (ORIG_NAME)?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 			goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	if (buf[3] & COMMENT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 		while (ret < LBUFSIZE && buf[ret++] != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 			;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 		if (unlikely(ret == LBUFSIZE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 			pr_debug("buffer overflow (COMMENT)?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 			goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 	strm.next_in += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	strm.avail_in -= ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	strm.next_out = dst;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	strm.avail_out = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	strm.total_out = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 	if (zlib_inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 		pr_debug("zlib init failed?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 		goto out_free_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) 		ret = kernel_read(bprm->file, buf, LBUFSIZE, &fpos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 		if (ret <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 		len -= ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 		strm.next_in = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 		strm.avail_in = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 		strm.total_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 		pr_debug("decompression failed (%d), %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 			ret, strm.msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 		goto out_zlib;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 	retval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) out_zlib:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	zlib_inflateEnd(&strm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) out_free_buf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	kfree(strm.workspace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 	return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) #endif /* CONFIG_BINFMT_ZFLAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) 	unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	unsigned long start_brk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	unsigned long start_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 	unsigned long text_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	unsigned long start_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) #ifdef CONFIG_BINFMT_SHARED_FLAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	if (r == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 		id = curid;	/* Relocs of 0 are always self referring */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 		id = (r >> 24) & 0xff;	/* Find ID for this reloc */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 		r &= 0x00ffffff;	/* Trim ID off here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 	if (id >= MAX_SHARED_LIBS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 		pr_err("reference 0x%lx to shared library %d", r, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 		goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 	if (curid != id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 		if (internalp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 			pr_err("reloc address 0x%lx not in same module "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 			       "(%d != %d)", r, curid, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 			goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 		} else if (!p->lib_list[id].loaded &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 			   load_flat_shared_library(id, p) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 			pr_err("failed to load library %d", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 			goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 		/* Check versioning information (i.e. time stamps) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 		if (p->lib_list[id].build_date && p->lib_list[curid].build_date &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 				p->lib_list[curid].build_date < p->lib_list[id].build_date) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 			pr_err("library %d is younger than %d", id, curid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 			goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	id = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 	start_brk = p->lib_list[id].start_brk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	start_data = p->lib_list[id].start_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	start_code = p->lib_list[id].start_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 	text_len = p->lib_list[id].text_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	if (r > start_brk - start_data + text_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 		pr_err("reloc outside program 0x%lx (0 - 0x%lx/0x%lx)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 		       r, start_brk-start_data+text_len, text_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 		goto failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 	if (r < text_len)			/* In text segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 		addr = r + start_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	else					/* In data segment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 		addr = r - text_len + start_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 	/* Range checked already above so doing the range tests is redundant...*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	return addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) failed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	pr_cont(", killing %s!\n", current->comm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	send_sig(SIGSEGV, current, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 	return RELOC_FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) #ifdef CONFIG_BINFMT_FLAT_OLD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) static void old_reloc(unsigned long rl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 	static const char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) 	flat_v2_reloc_t	r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 	unsigned long __user *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	unsigned long val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 	r.value = rl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) #if defined(CONFIG_COLDFIRE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 	ptr = (unsigned long __user *)(current->mm->start_code + r.reloc.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	ptr = (unsigned long __user *)(current->mm->start_data + r.reloc.offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 	get_user(val, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 	pr_debug("Relocation of variable at DATASEG+%x "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 		 "(address %p, currently %lx) into segment %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 		 r.reloc.offset, ptr, val, segment[r.reloc.type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	switch (r.reloc.type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 	case OLD_FLAT_RELOC_TYPE_TEXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 		val += current->mm->start_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	case OLD_FLAT_RELOC_TYPE_DATA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 		val += current->mm->start_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 	case OLD_FLAT_RELOC_TYPE_BSS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 		val += current->mm->end_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 		pr_err("Unknown relocation type=%x\n", r.reloc.type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 	put_user(val, ptr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	pr_debug("Relocation became %lx\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) #endif /* CONFIG_BINFMT_FLAT_OLD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) static int load_flat_file(struct linux_binprm *bprm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 		struct lib_info *libinfo, int id, unsigned long *extra_stack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	struct flat_hdr *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 	unsigned long textpos, datapos, realdatastart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	u32 text_len, data_len, bss_len, stack_len, full_data, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	unsigned long len, memp, memp_size, extra, rlim;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	__be32 __user *reloc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	u32 __user *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	int i, rev, relocs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	loff_t fpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	unsigned long start_code, end_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	ssize_t result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	hdr = ((struct flat_hdr *) bprm->buf);		/* exec-header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 	text_len  = ntohl(hdr->data_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	data_len  = ntohl(hdr->data_end) - ntohl(hdr->data_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	bss_len   = ntohl(hdr->bss_end) - ntohl(hdr->data_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 	stack_len = ntohl(hdr->stack_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 	if (extra_stack) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 		stack_len += *extra_stack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		*extra_stack = stack_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 	relocs    = ntohl(hdr->reloc_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	flags     = ntohl(hdr->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	rev       = ntohl(hdr->rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 	full_data = data_len + relocs * sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	if (strncmp(hdr->magic, "bFLT", 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 		 * Previously, here was a printk to tell people
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 		 *   "BINFMT_FLAT: bad header magic".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 		 * But for the kernel which also use ELF FD-PIC format, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 		 * error message is confusing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 		 * because a lot of people do not manage to produce good
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		ret = -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	if (flags & FLAT_FLAG_KTRACE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 		pr_info("Loading file: %s\n", bprm->filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) #ifdef CONFIG_BINFMT_FLAT_OLD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		pr_err("bad flat file version 0x%x (supported 0x%lx and 0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 		       rev, FLAT_VERSION, OLD_FLAT_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 		ret = -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	/* Don't allow old format executables to use shared libraries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	if (rev == OLD_FLAT_VERSION && id != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 		pr_err("shared libraries are not available before rev 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 		       FLAT_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 		ret = -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 	 * fix up the flags for the older format,  there were all kinds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 	 * of endian hacks,  this only works for the simple cases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	if (rev == OLD_FLAT_VERSION &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	   (flags || IS_ENABLED(CONFIG_BINFMT_FLAT_OLD_ALWAYS_RAM)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 		flags = FLAT_FLAG_RAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) #else /* CONFIG_BINFMT_FLAT_OLD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 	if (rev != FLAT_VERSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 		pr_err("bad flat file version 0x%x (supported 0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 		       rev, FLAT_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 		ret = -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) #endif /* !CONFIG_BINFMT_FLAT_OLD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 	 * Make sure the header params are sane.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	 * 28 bits (256 MB) is way more than reasonable in this case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	 * If some top bits are set we have probable binary corruption.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	if ((text_len | data_len | bss_len | stack_len | full_data) >> 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 		pr_err("bad header\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 		ret = -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) #ifndef CONFIG_BINFMT_ZFLAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 	if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 		pr_err("Support for ZFLAT executables is not enabled.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 		ret = -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 	 * Check initial limits. This avoids letting people circumvent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	 * size limits imposed on them by creating programs with large
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	 * arrays in the data or bss.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	rlim = rlimit(RLIMIT_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	if (rlim >= RLIM_INFINITY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 		rlim = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	if (data_len + bss_len > rlim) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 		ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 	/* Flush all traces of the currently running executable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	if (id == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 		ret = begin_new_exec(bprm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 		/* OK, This is the point of no return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 		set_personality(PER_LINUX_32BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 		setup_new_exec(bprm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 	 * calculate the extra space we need to map in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	extra = max_t(unsigned long, bss_len + stack_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 			relocs * sizeof(unsigned long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 	 * there are a couple of cases here,  the separate code/data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	 * case,  and then the fully copied to RAM case which lumps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 	 * it all together.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	if (!IS_ENABLED(CONFIG_MMU) && !(flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 		 * this should give us a ROM ptr,  but if it doesn't we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 		 * really care
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 		pr_debug("ROM mapping of file (we hope)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 		textpos = vm_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 				  MAP_PRIVATE|MAP_EXECUTABLE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 		if (!textpos || IS_ERR_VALUE(textpos)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 			ret = textpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 			if (!textpos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 				ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 			pr_err("Unable to mmap process text, errno %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 		len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		len = PAGE_ALIGN(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 		realdatastart = vm_mmap(NULL, 0, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 			PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 		if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 			ret = realdatastart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 			if (!realdatastart)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 				ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 			pr_err("Unable to allocate RAM for process data, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 			       "errno %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 			vm_munmap(textpos, text_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 		datapos = ALIGN(realdatastart +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 				MAX_SHARED_LIBS * sizeof(unsigned long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 				FLAT_DATA_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 		pr_debug("Allocated data+bss+stack (%u bytes): %lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 			 data_len + bss_len + stack_len, datapos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 		fpos = ntohl(hdr->data_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) #ifdef CONFIG_BINFMT_ZFLAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 		if (flags & FLAT_FLAG_GZDATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 			result = decompress_exec(bprm, fpos, (char *)datapos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 						 full_data, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 			result = read_code(bprm->file, datapos, fpos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 					full_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 		if (IS_ERR_VALUE(result)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 			ret = result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 			pr_err("Unable to read data+bss, errno %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 			vm_munmap(textpos, text_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 			vm_munmap(realdatastart, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 		reloc = (__be32 __user *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 			(datapos + (ntohl(hdr->reloc_start) - text_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 		memp = realdatastart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 		memp_size = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 		len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 		len = PAGE_ALIGN(len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 		textpos = vm_mmap(NULL, 0, len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 			PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 		if (!textpos || IS_ERR_VALUE(textpos)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 			ret = textpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 			if (!textpos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 				ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 			pr_err("Unable to allocate RAM for process text/data, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 			       "errno %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 		realdatastart = textpos + ntohl(hdr->data_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 		datapos = ALIGN(realdatastart +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 				MAX_SHARED_LIBS * sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 				FLAT_DATA_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) 		reloc = (__be32 __user *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 			(datapos + (ntohl(hdr->reloc_start) - text_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 		memp = textpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 		memp_size = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) #ifdef CONFIG_BINFMT_ZFLAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 		 * load it all in and treat it like a RAM load from now on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 		if (flags & FLAT_FLAG_GZIP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) #ifndef CONFIG_MMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 			result = decompress_exec(bprm, sizeof(struct flat_hdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 					 (((char *)textpos) + sizeof(struct flat_hdr)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 					 (text_len + full_data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 						  - sizeof(struct flat_hdr)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 					 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 			memmove((void *) datapos, (void *) realdatastart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 					full_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 			 * This is used on MMU systems mainly for testing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) 			 * Let's use a kernel buffer to simplify things.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 			long unz_text_len = text_len - sizeof(struct flat_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 			long unz_len = unz_text_len + full_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 			char *unz_data = vmalloc(unz_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 			if (!unz_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 				result = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 				result = decompress_exec(bprm, sizeof(struct flat_hdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 							 unz_data, unz_len, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 				if (result == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 				    (copy_to_user((void __user *)textpos + sizeof(struct flat_hdr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 						  unz_data, unz_text_len) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 				     copy_to_user((void __user *)datapos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 						  unz_data + unz_text_len, full_data)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 					result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 				vfree(unz_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 		} else if (flags & FLAT_FLAG_GZDATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 			result = read_code(bprm->file, textpos, 0, text_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 			if (!IS_ERR_VALUE(result)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) #ifndef CONFIG_MMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 				result = decompress_exec(bprm, text_len, (char *) datapos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 						 full_data, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 				char *unz_data = vmalloc(full_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 				if (!unz_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 					result = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 				} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 					result = decompress_exec(bprm, text_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 						       unz_data, full_data, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 					if (result == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 					    copy_to_user((void __user *)datapos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 							 unz_data, full_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 						result = -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 					vfree(unz_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) #endif /* CONFIG_BINFMT_ZFLAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 			result = read_code(bprm->file, textpos, 0, text_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 			if (!IS_ERR_VALUE(result))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 				result = read_code(bprm->file, datapos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 						   ntohl(hdr->data_start),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 						   full_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 		if (IS_ERR_VALUE(result)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 			ret = result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 			pr_err("Unable to read code+data+bss, errno %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 			vm_munmap(textpos, text_len + data_len + extra +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 				MAX_SHARED_LIBS * sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 	start_code = textpos + sizeof(struct flat_hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	end_code = textpos + text_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 	text_len -= sizeof(struct flat_hdr); /* the real code len */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	/* The main program needs a little extra setup in the task structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	if (id == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 		current->mm->start_code = start_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 		current->mm->end_code = end_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 		current->mm->start_data = datapos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 		current->mm->end_data = datapos + data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 		 * set up the brk stuff, uses any slack left in data/bss/stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 		 * allocation.  We put the brk after the bss (between the bss
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 		 * and stack) like other platforms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 		 * Userspace code relies on the stack pointer starting out at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 		 * an address right at the end of a page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 		current->mm->start_brk = datapos + data_len + bss_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 		current->mm->brk = (current->mm->start_brk + 3) & ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) #ifndef CONFIG_MMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 		current->mm->context.end_brk = memp + memp_size - stack_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 	if (flags & FLAT_FLAG_KTRACE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 		pr_info("Mapping is %lx, Entry point is %x, data_start is %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 			textpos, 0x00ffffff&ntohl(hdr->entry), ntohl(hdr->data_start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 		pr_info("%s %s: TEXT=%lx-%lx DATA=%lx-%lx BSS=%lx-%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 			id ? "Lib" : "Load", bprm->filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 			start_code, end_code, datapos, datapos + data_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 			datapos + data_len, (datapos + data_len + bss_len + 3) & ~3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 	/* Store the current module values into the global library structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 	libinfo->lib_list[id].start_code = start_code;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 	libinfo->lib_list[id].start_data = datapos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	libinfo->lib_list[id].start_brk = datapos + data_len + bss_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 	libinfo->lib_list[id].text_len = text_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 	libinfo->lib_list[id].loaded = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 	libinfo->lib_list[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	libinfo->lib_list[id].build_date = ntohl(hdr->build_date);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	 * We just load the allocations into some temporary memory to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	 * help simplify all this mumbo jumbo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	 * We've got two different sections of relocation entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 	 * The first is the GOT which resides at the beginning of the data segment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 	 * and is terminated with a -1.  This one can be relocated in place.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	 * The second is the extra relocation entries tacked after the image's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	 * data segment. These require a little more processing as the entry is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	 * really an offset into the image which contains an offset into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	 * image.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 	if (flags & FLAT_FLAG_GOTPIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 		for (rp = (u32 __user *)datapos; ; rp++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 			u32 addr, rp_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 			if (get_user(rp_val, rp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 				return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 			if (rp_val == 0xffffffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 			if (rp_val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 				addr = calc_reloc(rp_val, libinfo, id, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 				if (addr == RELOC_FAILED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 					ret = -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 					goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 				if (put_user(addr, rp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 					return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	 * Now run through the relocation entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 	 * We've got to be careful here as C++ produces relocatable zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 	 * entries in the constructor and destructor tables which are then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 	 * tested for being not zero (which will always occur unless we're
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 	 * based from address zero).  This causes an endless loop as __start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	 * is at zero.  The solution used is to not relocate zero addresses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	 * This has the negative side effect of not allowing a global data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	 * reference to be statically initialised to _stext (I've moved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	 * __start to address 4 so that is okay).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 	if (rev > OLD_FLAT_VERSION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 		for (i = 0; i < relocs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 			u32 addr, relval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 			__be32 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 			 * Get the address of the pointer to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 			 * relocated (of course, the address has to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 			 * relocated first).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 			if (get_user(tmp, reloc + i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 				return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 			relval = ntohl(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 			addr = flat_get_relocate_addr(relval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 			rp = (u32 __user *)calc_reloc(addr, libinfo, id, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 			if (rp == (u32 __user *)RELOC_FAILED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 				ret = -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 				goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 			/* Get the pointer's value.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 			ret = flat_get_addr_from_rp(rp, relval, flags, &addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 			if (unlikely(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 				goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 			if (addr != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 				/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 				 * Do the relocation.  PIC relocs in the data section are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 				 * already in target order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 				 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 				if ((flags & FLAT_FLAG_GOTPIC) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 					/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 					 * Meh, the same value can have a different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 					 * byte order based on a flag..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 					 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 					addr = ntohl((__force __be32)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 				addr = calc_reloc(addr, libinfo, id, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 				if (addr == RELOC_FAILED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 					ret = -ENOEXEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 					goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 				/* Write back the relocated pointer.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 				ret = flat_put_addr_at_rp(rp, addr, relval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 				if (unlikely(ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 					goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) #ifdef CONFIG_BINFMT_FLAT_OLD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 		for (i = 0; i < relocs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 			__be32 relval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 			if (get_user(relval, reloc + i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 				return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 			old_reloc(ntohl(relval));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) #endif /* CONFIG_BINFMT_FLAT_OLD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 	flush_icache_user_range(start_code, end_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	/* zero the BSS,  BRK and stack areas */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	if (clear_user((void __user *)(datapos + data_len), bss_len +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 		       (memp + memp_size - stack_len -		/* end brk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 		       libinfo->lib_list[id].start_brk) +	/* start brk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 		       stack_len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 		return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) #ifdef CONFIG_BINFMT_SHARED_FLAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885)  * Load a shared library into memory.  The library gets its own data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886)  * segment (including bss) but not argv/argc/environ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) static int load_flat_shared_library(int id, struct lib_info *libs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	 * This is a fake bprm struct; only the members "buf", "file" and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	 * "filename" are actually used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	struct linux_binprm bprm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	char buf[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	loff_t pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 	memset(&bprm, 0, sizeof(bprm));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 	/* Create the file name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	sprintf(buf, "/lib/lib%d.so", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 	/* Open the file up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	bprm.filename = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	bprm.file = open_exec(bprm.filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	res = PTR_ERR(bprm.file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	if (IS_ERR(bprm.file))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 		return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	res = kernel_read(bprm.file, bprm.buf, BINPRM_BUF_SIZE, &pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 	if (res >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 		res = load_flat_file(&bprm, libs, id, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 	allow_write_access(bprm.file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	fput(bprm.file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) #endif /* CONFIG_BINFMT_SHARED_FLAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927)  * These are the functions used to load flat style executables and shared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928)  * libraries.  There is no binary dependent code anywhere else.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) static int load_flat_binary(struct linux_binprm *bprm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	struct lib_info libinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 	struct pt_regs *regs = current_pt_regs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 	unsigned long stack_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 	unsigned long start_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	int res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 	int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 	memset(&libinfo, 0, sizeof(libinfo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	 * We have to add the size of our arguments to our stack size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 	 * otherwise it's too easy for users to create stack overflows
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 	 * by passing in a huge argument list.  And yes,  we have to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	 * pedantic and include space for the argv/envp array as it may have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	 * a lot of entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) #ifndef CONFIG_MMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	stack_len += PAGE_SIZE * MAX_ARG_PAGES - bprm->p; /* the strings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	stack_len += (bprm->argc + 1) * sizeof(char *);   /* the argv array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	stack_len += (bprm->envc + 1) * sizeof(char *);   /* the envp array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	stack_len = ALIGN(stack_len, FLAT_STACK_ALIGN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	res = load_flat_file(bprm, &libinfo, 0, &stack_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	if (res < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	/* Update data segment pointers for all libraries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	for (i = 0; i < MAX_SHARED_LIBS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 		if (!libinfo.lib_list[i].loaded)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 		for (j = 0; j < MAX_SHARED_LIBS; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 			unsigned long val = libinfo.lib_list[j].loaded ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 				libinfo.lib_list[j].start_data : UNLOADED_LIB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 			unsigned long __user *p = (unsigned long __user *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 				libinfo.lib_list[i].start_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 			p -= j + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 			if (put_user(val, p))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 				return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	set_binfmt(&flat_format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) #ifdef CONFIG_MMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	res = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 		res = create_flat_tables(bprm, bprm->p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 	/* Stash our initial stack pointer into the mm structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	current->mm->start_stack =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 		((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 	pr_debug("sp=%lx\n", current->mm->start_stack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 	/* copy the arg pages onto the stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	res = transfer_args_to_stack(bprm, &current->mm->start_stack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 		res = create_flat_tables(bprm, current->mm->start_stack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	if (res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 		return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	/* Fake some return addresses to ensure the call chain will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	 * initialise library in order for us.  We are required to call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	 * lib 1 first, then 2, ... and finally the main program (id 0).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	start_addr = libinfo.lib_list[0].entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) #ifdef CONFIG_BINFMT_SHARED_FLAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	for (i = MAX_SHARED_LIBS-1; i > 0; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 		if (libinfo.lib_list[i].loaded) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 			/* Push previos first to call address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 			unsigned long __user *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 			current->mm->start_stack -= sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 			sp = (unsigned long __user *)current->mm->start_stack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 			if (put_user(start_addr, sp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 				return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 			start_addr = libinfo.lib_list[i].entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) #ifdef FLAT_PLAT_INIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	FLAT_PLAT_INIT(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	finalize_exec(bprm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 	pr_debug("start_thread(regs=0x%p, entry=0x%lx, start_stack=0x%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 		 regs, start_addr, current->mm->start_stack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	start_thread(regs, start_addr, current->mm->start_stack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) /****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) static int __init init_flat_binfmt(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	register_binfmt(&flat_format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) core_initcall(init_flat_binfmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) /****************************************************************************/