0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009
0010 #include <linux/time.h>
0011 #include <linux/kernel.h>
0012 #include <linux/mm.h>
0013 #include <linux/mman.h>
0014 #include <linux/a.out.h>
0015 #include <linux/errno.h>
0016 #include <linux/signal.h>
0017 #include <linux/string.h>
0018 #include <linux/fs.h>
0019 #include <linux/file.h>
0020 #include <linux/stat.h>
0021 #include <linux/fcntl.h>
0022 #include <linux/ptrace.h>
0023 #include <linux/user.h>
0024 #include <linux/binfmts.h>
0025 #include <linux/personality.h>
0026 #include <linux/init.h>
0027 #include <linux/coredump.h>
0028 #include <linux/slab.h>
0029 #include <linux/sched/task_stack.h>
0030
0031 #include <linux/uaccess.h>
0032 #include <asm/cacheflush.h>
0033
0034 static int load_aout_binary(struct linux_binprm *);
0035 static int load_aout_library(struct file*);
0036
0037 static struct linux_binfmt aout_format = {
0038 .module = THIS_MODULE,
0039 .load_binary = load_aout_binary,
0040 .load_shlib = load_aout_library,
0041 };
0042
0043 #define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE)
0044
0045 static int set_brk(unsigned long start, unsigned long end)
0046 {
0047 start = PAGE_ALIGN(start);
0048 end = PAGE_ALIGN(end);
0049 if (end > start)
0050 return vm_brk(start, end - start);
0051 return 0;
0052 }
0053
0054
0055
0056
0057
0058
0059 static unsigned long __user *create_aout_tables(char __user *p, struct linux_binprm * bprm)
0060 {
0061 char __user * __user *argv;
0062 char __user * __user *envp;
0063 unsigned long __user *sp;
0064 int argc = bprm->argc;
0065 int envc = bprm->envc;
0066
0067 sp = (void __user *)((-(unsigned long)sizeof(char *)) & (unsigned long) p);
0068 #ifdef __alpha__
0069
0070 put_user(0, --sp);
0071 put_user(0, --sp);
0072 if (bprm->loader) {
0073 put_user(0, --sp);
0074 put_user(1003, --sp);
0075 put_user(bprm->loader, --sp);
0076 put_user(1002, --sp);
0077 }
0078 put_user(bprm->exec, --sp);
0079 put_user(1001, --sp);
0080 #endif
0081 sp -= envc+1;
0082 envp = (char __user * __user *) sp;
0083 sp -= argc+1;
0084 argv = (char __user * __user *) sp;
0085 #ifndef __alpha__
0086 put_user((unsigned long) envp,--sp);
0087 put_user((unsigned long) argv,--sp);
0088 #endif
0089 put_user(argc,--sp);
0090 current->mm->arg_start = (unsigned long) p;
0091 while (argc-->0) {
0092 char c;
0093 put_user(p,argv++);
0094 do {
0095 get_user(c,p++);
0096 } while (c);
0097 }
0098 put_user(NULL,argv);
0099 current->mm->arg_end = current->mm->env_start = (unsigned long) p;
0100 while (envc-->0) {
0101 char c;
0102 put_user(p,envp++);
0103 do {
0104 get_user(c,p++);
0105 } while (c);
0106 }
0107 put_user(NULL,envp);
0108 current->mm->env_end = (unsigned long) p;
0109 return sp;
0110 }
0111
0112
0113
0114
0115
0116
0117 static int load_aout_binary(struct linux_binprm * bprm)
0118 {
0119 struct pt_regs *regs = current_pt_regs();
0120 struct exec ex;
0121 unsigned long error;
0122 unsigned long fd_offset;
0123 unsigned long rlim;
0124 int retval;
0125
0126 ex = *((struct exec *) bprm->buf);
0127 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
0128 N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
0129 N_TRSIZE(ex) || N_DRSIZE(ex) ||
0130 i_size_read(file_inode(bprm->file)) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
0131 return -ENOEXEC;
0132 }
0133
0134
0135
0136
0137
0138 if (!bprm->file->f_op->mmap)
0139 return -ENOEXEC;
0140
0141 fd_offset = N_TXTOFF(ex);
0142
0143
0144
0145
0146
0147 rlim = rlimit(RLIMIT_DATA);
0148 if (rlim >= RLIM_INFINITY)
0149 rlim = ~0;
0150 if (ex.a_data + ex.a_bss > rlim)
0151 return -ENOMEM;
0152
0153
0154 retval = begin_new_exec(bprm);
0155 if (retval)
0156 return retval;
0157
0158
0159 #ifdef __alpha__
0160 SET_AOUT_PERSONALITY(bprm, ex);
0161 #else
0162 set_personality(PER_LINUX);
0163 #endif
0164 setup_new_exec(bprm);
0165
0166 current->mm->end_code = ex.a_text +
0167 (current->mm->start_code = N_TXTADDR(ex));
0168 current->mm->end_data = ex.a_data +
0169 (current->mm->start_data = N_DATADDR(ex));
0170 current->mm->brk = ex.a_bss +
0171 (current->mm->start_brk = N_BSSADDR(ex));
0172
0173 retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT);
0174 if (retval < 0)
0175 return retval;
0176
0177
0178 if (N_MAGIC(ex) == OMAGIC) {
0179 unsigned long text_addr, map_size;
0180 loff_t pos;
0181
0182 text_addr = N_TXTADDR(ex);
0183
0184 #ifdef __alpha__
0185 pos = fd_offset;
0186 map_size = ex.a_text+ex.a_data + PAGE_SIZE - 1;
0187 #else
0188 pos = 32;
0189 map_size = ex.a_text+ex.a_data;
0190 #endif
0191 error = vm_brk(text_addr & PAGE_MASK, map_size);
0192 if (error)
0193 return error;
0194
0195 error = read_code(bprm->file, text_addr, pos,
0196 ex.a_text+ex.a_data);
0197 if ((signed long)error < 0)
0198 return error;
0199 } else {
0200 if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
0201 (N_MAGIC(ex) != NMAGIC) && printk_ratelimit())
0202 {
0203 printk(KERN_NOTICE "executable not page aligned\n");
0204 }
0205
0206 if ((fd_offset & ~PAGE_MASK) != 0 && printk_ratelimit())
0207 {
0208 printk(KERN_WARNING
0209 "fd_offset is not page aligned. Please convert program: %pD\n",
0210 bprm->file);
0211 }
0212
0213 if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
0214 error = vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
0215 if (error)
0216 return error;
0217
0218 read_code(bprm->file, N_TXTADDR(ex), fd_offset,
0219 ex.a_text + ex.a_data);
0220 goto beyond_if;
0221 }
0222
0223 error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
0224 PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE,
0225 fd_offset);
0226
0227 if (error != N_TXTADDR(ex))
0228 return error;
0229
0230 error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
0231 PROT_READ | PROT_WRITE | PROT_EXEC,
0232 MAP_FIXED | MAP_PRIVATE,
0233 fd_offset + ex.a_text);
0234 if (error != N_DATADDR(ex))
0235 return error;
0236 }
0237 beyond_if:
0238 set_binfmt(&aout_format);
0239
0240 retval = set_brk(current->mm->start_brk, current->mm->brk);
0241 if (retval < 0)
0242 return retval;
0243
0244 current->mm->start_stack =
0245 (unsigned long) create_aout_tables((char __user *) bprm->p, bprm);
0246 #ifdef __alpha__
0247 regs->gp = ex.a_gpvalue;
0248 #endif
0249 finalize_exec(bprm);
0250 start_thread(regs, ex.a_entry, current->mm->start_stack);
0251 return 0;
0252 }
0253
0254 static int load_aout_library(struct file *file)
0255 {
0256 struct inode * inode;
0257 unsigned long bss, start_addr, len;
0258 unsigned long error;
0259 int retval;
0260 struct exec ex;
0261 loff_t pos = 0;
0262
0263 inode = file_inode(file);
0264
0265 retval = -ENOEXEC;
0266 error = kernel_read(file, &ex, sizeof(ex), &pos);
0267 if (error != sizeof(ex))
0268 goto out;
0269
0270
0271 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
0272 N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
0273 i_size_read(inode) < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
0274 goto out;
0275 }
0276
0277
0278
0279
0280
0281 if (!file->f_op->mmap)
0282 goto out;
0283
0284 if (N_FLAGS(ex))
0285 goto out;
0286
0287
0288
0289
0290 start_addr = ex.a_entry & 0xfffff000;
0291
0292 if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
0293 if (printk_ratelimit())
0294 {
0295 printk(KERN_WARNING
0296 "N_TXTOFF is not page aligned. Please convert library: %pD\n",
0297 file);
0298 }
0299 retval = vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
0300 if (retval)
0301 goto out;
0302
0303 read_code(file, start_addr, N_TXTOFF(ex),
0304 ex.a_text + ex.a_data);
0305 retval = 0;
0306 goto out;
0307 }
0308
0309 error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
0310 PROT_READ | PROT_WRITE | PROT_EXEC,
0311 MAP_FIXED | MAP_PRIVATE,
0312 N_TXTOFF(ex));
0313 retval = error;
0314 if (error != start_addr)
0315 goto out;
0316
0317 len = PAGE_ALIGN(ex.a_text + ex.a_data);
0318 bss = ex.a_text + ex.a_data + ex.a_bss;
0319 if (bss > len) {
0320 retval = vm_brk(start_addr + len, bss - len);
0321 if (retval)
0322 goto out;
0323 }
0324 retval = 0;
0325 out:
0326 return retval;
0327 }
0328
0329 static int __init init_aout_binfmt(void)
0330 {
0331 register_binfmt(&aout_format);
0332 return 0;
0333 }
0334
0335 static void __exit exit_aout_binfmt(void)
0336 {
0337 unregister_binfmt(&aout_format);
0338 }
0339
0340 core_initcall(init_aout_binfmt);
0341 module_exit(exit_aout_binfmt);
0342 MODULE_LICENSE("GPL");