Linux 2.2.0
[davej-history.git] / fs / binfmt_aout.c
blobc7925b23538de9e1272660cee1bfa815f2a4859b
1 /*
2 * linux/fs/binfmt_aout.c
4 * Copyright (C) 1991, 1992, 1996 Linus Torvalds
5 */
7 #include <linux/module.h>
9 #include <linux/sched.h>
10 #include <linux/kernel.h>
11 #include <linux/mm.h>
12 #include <linux/mman.h>
13 #include <linux/a.out.h>
14 #include <linux/errno.h>
15 #include <linux/signal.h>
16 #include <linux/string.h>
17 #include <linux/fs.h>
18 #include <linux/file.h>
19 #include <linux/stat.h>
20 #include <linux/fcntl.h>
21 #include <linux/ptrace.h>
22 #include <linux/user.h>
23 #include <linux/malloc.h>
24 #include <linux/binfmts.h>
25 #include <linux/personality.h>
26 #include <linux/init.h>
28 #include <asm/system.h>
29 #include <asm/uaccess.h>
30 #include <asm/pgtable.h>
32 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
33 static int load_aout_library(int fd);
34 static int aout_core_dump(long signr, struct pt_regs * regs);
36 extern void dump_thread(struct pt_regs *, struct user *);
38 static struct linux_binfmt aout_format = {
39 #ifndef MODULE
40 NULL, NULL, load_aout_binary, load_aout_library, aout_core_dump
41 #else
42 NULL, &__this_module, load_aout_binary, load_aout_library, aout_core_dump
43 #endif
46 static void set_brk(unsigned long start, unsigned long end)
48 start = PAGE_ALIGN(start);
49 end = PAGE_ALIGN(end);
50 if (end <= start)
51 return;
52 do_mmap(NULL, start, end - start,
53 PROT_READ | PROT_WRITE | PROT_EXEC,
54 MAP_FIXED | MAP_PRIVATE, 0);
58 * These are the only things you should do on a core-file: use only these
59 * macros to write out all the necessary info.
61 #define DUMP_WRITE(addr,nr) \
62 while (file.f_op->write(&file,(char *)(addr),(nr),&file.f_pos) != (nr)) goto close_coredump
64 #define DUMP_SEEK(offset) \
65 if (file.f_op->llseek) { \
66 if (file.f_op->llseek(&file,(offset),0) != (offset)) \
67 goto close_coredump; \
68 } else file.f_pos = (offset)
71 * Routine writes a core dump image in the current directory.
72 * Currently only a stub-function.
74 * Note that setuid/setgid files won't make a core-dump if the uid/gid
75 * changed due to the set[u|g]id. It's enforced by the "current->dumpable"
76 * field, which also makes sure the core-dumps won't be recursive if the
77 * dumping of the process results in another error..
80 static inline int
81 do_aout_core_dump(long signr, struct pt_regs * regs)
83 struct dentry * dentry = NULL;
84 struct inode * inode = NULL;
85 struct file file;
86 mm_segment_t fs;
87 int has_dumped = 0;
88 char corefile[6+sizeof(current->comm)];
89 unsigned long dump_start, dump_size;
90 struct user dump;
91 #if defined(__alpha__)
92 # define START_DATA(u) (u.start_data)
93 #elif defined(__sparc__)
94 # define START_DATA(u) (u.u_tsize)
95 #elif defined(__i386__) || defined(__mc68000__)
96 # define START_DATA(u) (u.u_tsize << PAGE_SHIFT)
97 #endif
98 #ifdef __sparc__
99 # define START_STACK(u) ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1))
100 #else
101 # define START_STACK(u) (u.start_stack)
102 #endif
104 if (!current->dumpable || atomic_read(&current->mm->count) != 1)
105 return 0;
106 current->dumpable = 0;
108 /* See if we have enough room to write the upage. */
109 if (current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE)
110 return 0;
111 fs = get_fs();
112 set_fs(KERNEL_DS);
113 memcpy(corefile,"core.",5);
114 #if 0
115 memcpy(corefile+5,current->comm,sizeof(current->comm));
116 #else
117 corefile[4] = '\0';
118 #endif
119 dentry = open_namei(corefile,O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600);
120 if (IS_ERR(dentry)) {
121 dentry = NULL;
122 goto end_coredump;
124 inode = dentry->d_inode;
125 if (!S_ISREG(inode->i_mode))
126 goto end_coredump;
127 if (!inode->i_op || !inode->i_op->default_file_ops)
128 goto end_coredump;
129 if (get_write_access(inode))
130 goto end_coredump;
131 if (init_private_file(&file, dentry, 3))
132 goto end_coredump_write;
133 if (!file.f_op->write)
134 goto close_coredump;
135 has_dumped = 1;
136 current->flags |= PF_DUMPCORE;
137 strncpy(dump.u_comm, current->comm, sizeof(current->comm));
138 #ifndef __sparc__
139 dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
140 #endif
141 dump.signal = signr;
142 dump_thread(regs, &dump);
144 /* If the size of the dump file exceeds the rlimit, then see what would happen
145 if we wrote the stack, but not the data area. */
146 #ifdef __sparc__
147 if ((dump.u_dsize+dump.u_ssize) >
148 current->rlim[RLIMIT_CORE].rlim_cur)
149 dump.u_dsize = 0;
150 #else
151 if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
152 current->rlim[RLIMIT_CORE].rlim_cur)
153 dump.u_dsize = 0;
154 #endif
156 /* Make sure we have enough room to write the stack and data areas. */
157 #ifdef __sparc__
158 if ((dump.u_ssize) >
159 current->rlim[RLIMIT_CORE].rlim_cur)
160 dump.u_ssize = 0;
161 #else
162 if ((dump.u_ssize+1) * PAGE_SIZE >
163 current->rlim[RLIMIT_CORE].rlim_cur)
164 dump.u_ssize = 0;
165 #endif
167 /* make sure we actually have a data and stack area to dump */
168 set_fs(USER_DS);
169 #ifdef __sparc__
170 if (verify_area(VERIFY_READ, (void *) START_DATA(dump), dump.u_dsize))
171 dump.u_dsize = 0;
172 if (verify_area(VERIFY_READ, (void *) START_STACK(dump), dump.u_ssize))
173 dump.u_ssize = 0;
174 #else
175 if (verify_area(VERIFY_READ, (void *) START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
176 dump.u_dsize = 0;
177 if (verify_area(VERIFY_READ, (void *) START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
178 dump.u_ssize = 0;
179 #endif
181 set_fs(KERNEL_DS);
182 /* struct user */
183 DUMP_WRITE(&dump,sizeof(dump));
184 /* Now dump all of the user data. Include malloced stuff as well */
185 #ifndef __sparc__
186 DUMP_SEEK(PAGE_SIZE);
187 #endif
188 /* now we start writing out the user space info */
189 set_fs(USER_DS);
190 /* Dump the data area */
191 if (dump.u_dsize != 0) {
192 dump_start = START_DATA(dump);
193 #ifdef __sparc__
194 dump_size = dump.u_dsize;
195 #else
196 dump_size = dump.u_dsize << PAGE_SHIFT;
197 #endif
198 DUMP_WRITE(dump_start,dump_size);
200 /* Now prepare to dump the stack area */
201 if (dump.u_ssize != 0) {
202 dump_start = START_STACK(dump);
203 #ifdef __sparc__
204 dump_size = dump.u_ssize;
205 #else
206 dump_size = dump.u_ssize << PAGE_SHIFT;
207 #endif
208 DUMP_WRITE(dump_start,dump_size);
210 /* Finally dump the task struct. Not be used by gdb, but could be useful */
211 set_fs(KERNEL_DS);
212 DUMP_WRITE(current,sizeof(*current));
213 close_coredump:
214 if (file.f_op->release)
215 file.f_op->release(inode,&file);
216 end_coredump_write:
217 put_write_access(inode);
218 end_coredump:
219 set_fs(fs);
220 dput(dentry);
221 return has_dumped;
224 static int
225 aout_core_dump(long signr, struct pt_regs * regs)
227 int retval;
229 MOD_INC_USE_COUNT;
230 retval = do_aout_core_dump(signr, regs);
231 MOD_DEC_USE_COUNT;
232 return retval;
236 * create_aout_tables() parses the env- and arg-strings in new user
237 * memory and creates the pointer tables from them, and puts their
238 * addresses on the "stack", returning the new stack pointer value.
240 static unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm)
242 char **argv, **envp;
243 unsigned long * sp;
244 int argc = bprm->argc;
245 int envc = bprm->envc;
247 sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
248 #ifdef __sparc__
249 /* This imposes the proper stack alignment for a new process. */
250 sp = (unsigned long *) (((unsigned long) sp) & ~7);
251 if ((envc+argc+3)&1) --sp;
252 #endif
253 #ifdef __alpha__
254 /* whee.. test-programs are so much fun. */
255 put_user(0, --sp);
256 put_user(0, --sp);
257 if (bprm->loader) {
258 put_user(0, --sp);
259 put_user(0x3eb, --sp);
260 put_user(bprm->loader, --sp);
261 put_user(0x3ea, --sp);
263 put_user(bprm->exec, --sp);
264 put_user(0x3e9, --sp);
265 #endif
266 sp -= envc+1;
267 envp = (char **) sp;
268 sp -= argc+1;
269 argv = (char **) sp;
270 #if defined(__i386__) || defined(__mc68000__)
271 put_user((unsigned long) envp,--sp);
272 put_user((unsigned long) argv,--sp);
273 #endif
274 put_user(argc,--sp);
275 current->mm->arg_start = (unsigned long) p;
276 while (argc-->0) {
277 char c;
278 put_user(p,argv++);
279 do {
280 get_user(c,p++);
281 } while (c);
283 put_user(NULL,argv);
284 current->mm->arg_end = current->mm->env_start = (unsigned long) p;
285 while (envc-->0) {
286 char c;
287 put_user(p,envp++);
288 do {
289 get_user(c,p++);
290 } while (c);
292 put_user(NULL,envp);
293 current->mm->env_end = (unsigned long) p;
294 return sp;
298 * These are the functions used to load a.out style executables and shared
299 * libraries. There is no binary dependent code anywhere else.
302 static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
304 struct exec ex;
305 struct file * file;
306 int fd;
307 unsigned long error;
308 unsigned long p = bprm->p;
309 unsigned long fd_offset;
310 unsigned long rlim;
311 int retval;
313 ex = *((struct exec *) bprm->buf); /* exec-header */
314 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
315 N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
316 N_TRSIZE(ex) || N_DRSIZE(ex) ||
317 bprm->dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
318 return -ENOEXEC;
321 fd_offset = N_TXTOFF(ex);
323 #ifdef __i386__
324 if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
325 printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
326 return -ENOEXEC;
329 if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
330 (fd_offset < bprm->dentry->d_inode->i_sb->s_blocksize)) {
331 printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
332 return -ENOEXEC;
334 #endif
336 /* Check initial limits. This avoids letting people circumvent
337 * size limits imposed on them by creating programs with large
338 * arrays in the data or bss.
340 rlim = current->rlim[RLIMIT_DATA].rlim_cur;
341 if (rlim >= RLIM_INFINITY)
342 rlim = ~0;
343 if (ex.a_data + ex.a_bss > rlim)
344 return -ENOMEM;
346 /* Flush all traces of the currently running executable */
347 retval = flush_old_exec(bprm);
348 if (retval)
349 return retval;
351 /* OK, This is the point of no return */
352 current->personality = PER_LINUX;
354 #if defined(__sparc__) && !defined(__sparc_v9__)
355 memcpy(&current->tss.core_exec, &ex, sizeof(struct exec));
356 #endif
358 current->mm->end_code = ex.a_text +
359 (current->mm->start_code = N_TXTADDR(ex));
360 current->mm->end_data = ex.a_data +
361 (current->mm->start_data = N_DATADDR(ex));
362 current->mm->brk = ex.a_bss +
363 (current->mm->start_brk = N_BSSADDR(ex));
365 current->mm->rss = 0;
366 current->mm->mmap = NULL;
367 compute_creds(bprm);
368 current->flags &= ~PF_FORKNOEXEC;
369 #ifdef __sparc__
370 if (N_MAGIC(ex) == NMAGIC) {
371 /* Fuck me plenty... */
372 error = do_mmap(NULL, N_TXTADDR(ex), ex.a_text,
373 PROT_READ|PROT_WRITE|PROT_EXEC,
374 MAP_FIXED|MAP_PRIVATE, 0);
375 read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex),
376 ex.a_text, 0);
377 error = do_mmap(NULL, N_DATADDR(ex), ex.a_data,
378 PROT_READ|PROT_WRITE|PROT_EXEC,
379 MAP_FIXED|MAP_PRIVATE, 0);
380 read_exec(bprm->dentry, fd_offset + ex.a_text, (char *) N_DATADDR(ex),
381 ex.a_data, 0);
382 goto beyond_if;
384 #endif
386 if (N_MAGIC(ex) == OMAGIC) {
387 #if defined(__alpha__) || defined(__sparc__)
388 do_mmap(NULL, N_TXTADDR(ex) & PAGE_MASK,
389 ex.a_text+ex.a_data + PAGE_SIZE - 1,
390 PROT_READ|PROT_WRITE|PROT_EXEC,
391 MAP_FIXED|MAP_PRIVATE, 0);
392 read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex),
393 ex.a_text+ex.a_data, 0);
394 #else
395 do_mmap(NULL, 0, ex.a_text+ex.a_data,
396 PROT_READ|PROT_WRITE|PROT_EXEC,
397 MAP_FIXED|MAP_PRIVATE, 0);
398 read_exec(bprm->dentry, 32, (char *) 0, ex.a_text+ex.a_data, 0);
399 #endif
400 flush_icache_range((unsigned long) 0,
401 (unsigned long) ex.a_text+ex.a_data);
402 } else {
403 if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
404 (N_MAGIC(ex) != NMAGIC))
405 printk(KERN_NOTICE "executable not page aligned\n");
407 fd = open_dentry(bprm->dentry, O_RDONLY);
408 if (fd < 0)
409 return fd;
410 file = fcheck(fd);
412 if (!file->f_op || !file->f_op->mmap) {
413 sys_close(fd);
414 do_mmap(NULL, 0, ex.a_text+ex.a_data,
415 PROT_READ|PROT_WRITE|PROT_EXEC,
416 MAP_FIXED|MAP_PRIVATE, 0);
417 read_exec(bprm->dentry, fd_offset,
418 (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0);
419 flush_icache_range((unsigned long) N_TXTADDR(ex),
420 (unsigned long) N_TXTADDR(ex) +
421 ex.a_text+ex.a_data);
422 goto beyond_if;
425 error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
426 PROT_READ | PROT_EXEC,
427 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
428 fd_offset);
430 if (error != N_TXTADDR(ex)) {
431 sys_close(fd);
432 send_sig(SIGKILL, current, 0);
433 return error;
436 error = do_mmap(file, N_DATADDR(ex), ex.a_data,
437 PROT_READ | PROT_WRITE | PROT_EXEC,
438 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
439 fd_offset + ex.a_text);
440 sys_close(fd);
441 if (error != N_DATADDR(ex)) {
442 send_sig(SIGKILL, current, 0);
443 return error;
446 beyond_if:
447 if (current->exec_domain && current->exec_domain->module)
448 __MOD_DEC_USE_COUNT(current->exec_domain->module);
449 if (current->binfmt && current->binfmt->module)
450 __MOD_DEC_USE_COUNT(current->binfmt->module);
451 current->exec_domain = lookup_exec_domain(current->personality);
452 current->binfmt = &aout_format;
453 if (current->exec_domain && current->exec_domain->module)
454 __MOD_INC_USE_COUNT(current->exec_domain->module);
455 if (current->binfmt && current->binfmt->module)
456 __MOD_INC_USE_COUNT(current->binfmt->module);
458 set_brk(current->mm->start_brk, current->mm->brk);
460 p = setup_arg_pages(p, bprm);
462 p = (unsigned long) create_aout_tables((char *)p, bprm);
463 current->mm->start_stack = p;
464 #ifdef __alpha__
465 regs->gp = ex.a_gpvalue;
466 #endif
467 start_thread(regs, ex.a_entry, p);
468 if (current->flags & PF_PTRACED)
469 send_sig(SIGTRAP, current, 0);
470 return 0;
474 static int
475 load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
477 int retval;
479 MOD_INC_USE_COUNT;
480 retval = do_load_aout_binary(bprm, regs);
481 MOD_DEC_USE_COUNT;
482 return retval;
485 static inline int
486 do_load_aout_library(int fd)
488 struct file * file;
489 struct inode * inode;
490 unsigned long bss, start_addr, len;
491 unsigned long error;
492 int retval;
493 loff_t offset = 0;
494 struct exec ex;
496 retval = -EACCES;
497 file = fget(fd);
498 if (!file)
499 goto out;
500 if (!file->f_op)
501 goto out_putf;
502 inode = file->f_dentry->d_inode;
504 retval = -ENOEXEC;
505 /* N.B. Save current fs? */
506 set_fs(KERNEL_DS);
507 error = file->f_op->read(file, (char *) &ex, sizeof(ex), &offset);
508 set_fs(USER_DS);
509 if (error != sizeof(ex))
510 goto out_putf;
512 /* We come in here for the regular a.out style of shared libraries */
513 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
514 N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
515 inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
516 goto out_putf;
519 if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
520 (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
521 printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
522 goto out_putf;
525 if (N_FLAGS(ex))
526 goto out_putf;
528 /* For QMAGIC, the starting address is 0x20 into the page. We mask
529 this off to get the starting address for the page */
531 start_addr = ex.a_entry & 0xfffff000;
533 /* Now use mmap to map the library into memory. */
534 error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
535 PROT_READ | PROT_WRITE | PROT_EXEC,
536 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
537 N_TXTOFF(ex));
538 retval = error;
539 if (error != start_addr)
540 goto out_putf;
542 len = PAGE_ALIGN(ex.a_text + ex.a_data);
543 bss = ex.a_text + ex.a_data + ex.a_bss;
544 if (bss > len) {
545 error = do_mmap(NULL, start_addr + len, bss - len,
546 PROT_READ | PROT_WRITE | PROT_EXEC,
547 MAP_PRIVATE | MAP_FIXED, 0);
548 retval = error;
549 if (error != start_addr + len)
550 goto out_putf;
552 retval = 0;
554 out_putf:
555 fput(file);
556 out:
557 return retval;
560 static int
561 load_aout_library(int fd)
563 int retval;
565 MOD_INC_USE_COUNT;
566 retval = do_load_aout_library(fd);
567 MOD_DEC_USE_COUNT;
568 return retval;
572 int __init init_aout_binfmt(void)
574 return register_binfmt(&aout_format);
577 #ifdef MODULE
578 int init_module(void) {
579 return init_aout_binfmt();
582 void cleanup_module( void) {
583 unregister_binfmt(&aout_format);
585 #endif