^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, ¤t->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) /****************************************************************************/