Import 2.3.7pre7
[davej-history.git] / fs / binfmt_aout.c
blob2b886a147ead099df933b541aeecd53d2c6552b3
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_brk(start, end - start);
56 * These are the only things you should do on a core-file: use only these
57 * macros to write out all the necessary info.
60 static int dump_write(struct file *file, const void *addr, int nr)
62 return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
65 #define DUMP_WRITE(addr, nr) \
66 if (!dump_write(file, (void *)(addr), (nr))) \
67 goto close_coredump;
69 #define DUMP_SEEK(offset) \
70 if (file->f_op->llseek) { \
71 if (file->f_op->llseek(file,(offset),0) != (offset)) \
72 goto close_coredump; \
73 } else file->f_pos = (offset)
76 * Routine writes a core dump image in the current directory.
77 * Currently only a stub-function.
79 * Note that setuid/setgid files won't make a core-dump if the uid/gid
80 * changed due to the set[u|g]id. It's enforced by the "current->dumpable"
81 * field, which also makes sure the core-dumps won't be recursive if the
82 * dumping of the process results in another error..
85 static inline int
86 do_aout_core_dump(long signr, struct pt_regs * regs)
88 struct dentry * dentry = NULL;
89 struct inode * inode = NULL;
90 struct file * file;
91 mm_segment_t fs;
92 int has_dumped = 0;
93 char corefile[6+sizeof(current->comm)];
94 unsigned long dump_start, dump_size;
95 struct user dump;
96 #if defined(__alpha__)
97 # define START_DATA(u) (u.start_data)
98 #elif defined(__sparc__)
99 # define START_DATA(u) (u.u_tsize)
100 #elif defined(__i386__) || defined(__mc68000__)
101 # define START_DATA(u) (u.u_tsize << PAGE_SHIFT)
102 #endif
103 #ifdef __sparc__
104 # define START_STACK(u) ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1))
105 #else
106 # define START_STACK(u) (u.start_stack)
107 #endif
109 if (!current->dumpable || atomic_read(&current->mm->count) != 1)
110 return 0;
111 current->dumpable = 0;
113 /* See if we have enough room to write the upage. */
114 if (current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE)
115 return 0;
116 fs = get_fs();
117 set_fs(KERNEL_DS);
118 memcpy(corefile,"core.",5);
119 #if 0
120 memcpy(corefile+5,current->comm,sizeof(current->comm));
121 #else
122 corefile[4] = '\0';
123 #endif
124 file = filp_open(corefile,O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600);
125 if (IS_ERR(file))
126 goto end_coredump;
127 dentry = file->f_dentry;
128 inode = dentry->d_inode;
129 if (!S_ISREG(inode->i_mode))
130 goto close_coredump;
131 if (!inode->i_op || !inode->i_op->default_file_ops)
132 goto close_coredump;
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 filp_close(file, NULL);
215 end_coredump:
216 set_fs(fs);
217 return has_dumped;
220 static int
221 aout_core_dump(long signr, struct pt_regs * regs)
223 int retval;
225 MOD_INC_USE_COUNT;
226 retval = do_aout_core_dump(signr, regs);
227 MOD_DEC_USE_COUNT;
228 return retval;
232 * create_aout_tables() parses the env- and arg-strings in new user
233 * memory and creates the pointer tables from them, and puts their
234 * addresses on the "stack", returning the new stack pointer value.
236 static unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm)
238 char **argv, **envp;
239 unsigned long * sp;
240 int argc = bprm->argc;
241 int envc = bprm->envc;
243 sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
244 #ifdef __sparc__
245 /* This imposes the proper stack alignment for a new process. */
246 sp = (unsigned long *) (((unsigned long) sp) & ~7);
247 if ((envc+argc+3)&1) --sp;
248 #endif
249 #ifdef __alpha__
250 /* whee.. test-programs are so much fun. */
251 put_user(0, --sp);
252 put_user(0, --sp);
253 if (bprm->loader) {
254 put_user(0, --sp);
255 put_user(0x3eb, --sp);
256 put_user(bprm->loader, --sp);
257 put_user(0x3ea, --sp);
259 put_user(bprm->exec, --sp);
260 put_user(0x3e9, --sp);
261 #endif
262 sp -= envc+1;
263 envp = (char **) sp;
264 sp -= argc+1;
265 argv = (char **) sp;
266 #if defined(__i386__) || defined(__mc68000__)
267 put_user((unsigned long) envp,--sp);
268 put_user((unsigned long) argv,--sp);
269 #endif
270 put_user(argc,--sp);
271 current->mm->arg_start = (unsigned long) p;
272 while (argc-->0) {
273 char c;
274 put_user(p,argv++);
275 do {
276 get_user(c,p++);
277 } while (c);
279 put_user(NULL,argv);
280 current->mm->arg_end = current->mm->env_start = (unsigned long) p;
281 while (envc-->0) {
282 char c;
283 put_user(p,envp++);
284 do {
285 get_user(c,p++);
286 } while (c);
288 put_user(NULL,envp);
289 current->mm->env_end = (unsigned long) p;
290 return sp;
294 * These are the functions used to load a.out style executables and shared
295 * libraries. There is no binary dependent code anywhere else.
298 static inline int do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
300 struct exec ex;
301 struct file * file;
302 int fd;
303 unsigned long error;
304 unsigned long fd_offset;
305 unsigned long rlim;
306 int retval;
308 ex = *((struct exec *) bprm->buf); /* exec-header */
309 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
310 N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
311 N_TRSIZE(ex) || N_DRSIZE(ex) ||
312 bprm->dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
313 return -ENOEXEC;
316 fd_offset = N_TXTOFF(ex);
318 #ifdef __i386__
319 if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
320 printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
321 return -ENOEXEC;
324 if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
325 bprm->dentry->d_inode->i_op &&
326 bprm->dentry->d_inode->i_op->bmap &&
327 (fd_offset < bprm->dentry->d_inode->i_sb->s_blocksize)) {
328 printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
329 return -ENOEXEC;
331 #endif
333 /* Check initial limits. This avoids letting people circumvent
334 * size limits imposed on them by creating programs with large
335 * arrays in the data or bss.
337 rlim = current->rlim[RLIMIT_DATA].rlim_cur;
338 if (rlim >= RLIM_INFINITY)
339 rlim = ~0;
340 if (ex.a_data + ex.a_bss > rlim)
341 return -ENOMEM;
343 /* Flush all traces of the currently running executable */
344 retval = flush_old_exec(bprm);
345 if (retval)
346 return retval;
348 /* OK, This is the point of no return */
349 current->personality = PER_LINUX;
351 #if defined(__sparc__) && !defined(__sparc_v9__)
352 memcpy(&current->tss.core_exec, &ex, sizeof(struct exec));
353 #endif
355 current->mm->end_code = ex.a_text +
356 (current->mm->start_code = N_TXTADDR(ex));
357 current->mm->end_data = ex.a_data +
358 (current->mm->start_data = N_DATADDR(ex));
359 current->mm->brk = ex.a_bss +
360 (current->mm->start_brk = N_BSSADDR(ex));
362 current->mm->rss = 0;
363 current->mm->mmap = NULL;
364 compute_creds(bprm);
365 current->flags &= ~PF_FORKNOEXEC;
366 #ifdef __sparc__
367 if (N_MAGIC(ex) == NMAGIC) {
368 /* Fuck me plenty... */
369 error = do_brk(N_TXTADDR(ex), ex.a_text);
370 read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex),
371 ex.a_text, 0);
372 error = do_brk(N_DATADDR(ex), ex.a_data);
373 read_exec(bprm->dentry, fd_offset + ex.a_text, (char *) N_DATADDR(ex),
374 ex.a_data, 0);
375 goto beyond_if;
377 #endif
379 if (N_MAGIC(ex) == OMAGIC) {
380 #if defined(__alpha__) || defined(__sparc__)
381 do_brk(N_TXTADDR(ex) & PAGE_MASK,
382 ex.a_text+ex.a_data + PAGE_SIZE - 1);
383 read_exec(bprm->dentry, fd_offset, (char *) N_TXTADDR(ex),
384 ex.a_text+ex.a_data, 0);
385 #else
386 do_brk(0, ex.a_text+ex.a_data);
387 read_exec(bprm->dentry, 32, (char *) 0, ex.a_text+ex.a_data, 0);
388 #endif
389 flush_icache_range((unsigned long) 0,
390 (unsigned long) ex.a_text+ex.a_data);
391 } else {
392 if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
393 (N_MAGIC(ex) != NMAGIC))
394 printk(KERN_NOTICE "executable not page aligned\n");
396 fd = open_dentry(bprm->dentry, O_RDONLY);
397 if (fd < 0)
398 return fd;
399 file = fcheck(fd);
401 if ((fd_offset & ~PAGE_MASK) != 0) {
402 printk(KERN_WARNING
403 "fd_offset is not page aligned. Please convert program: %s\n",
404 file->f_dentry->d_name.name
408 if (!file->f_op || !file->f_op->mmap || ((fd_offset & ~PAGE_MASK) != 0)) {
409 sys_close(fd);
410 do_brk(0, ex.a_text+ex.a_data);
411 read_exec(bprm->dentry, fd_offset,
412 (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0);
413 flush_icache_range((unsigned long) N_TXTADDR(ex),
414 (unsigned long) N_TXTADDR(ex) +
415 ex.a_text+ex.a_data);
416 goto beyond_if;
419 error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
420 PROT_READ | PROT_EXEC,
421 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
422 fd_offset);
424 if (error != N_TXTADDR(ex)) {
425 sys_close(fd);
426 send_sig(SIGKILL, current, 0);
427 return error;
430 error = do_mmap(file, N_DATADDR(ex), ex.a_data,
431 PROT_READ | PROT_WRITE | PROT_EXEC,
432 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
433 fd_offset + ex.a_text);
434 sys_close(fd);
435 if (error != N_DATADDR(ex)) {
436 send_sig(SIGKILL, current, 0);
437 return error;
440 beyond_if:
441 if (current->exec_domain && current->exec_domain->module)
442 __MOD_DEC_USE_COUNT(current->exec_domain->module);
443 if (current->binfmt && current->binfmt->module)
444 __MOD_DEC_USE_COUNT(current->binfmt->module);
445 current->exec_domain = lookup_exec_domain(current->personality);
446 current->binfmt = &aout_format;
447 if (current->exec_domain && current->exec_domain->module)
448 __MOD_INC_USE_COUNT(current->exec_domain->module);
449 if (current->binfmt && current->binfmt->module)
450 __MOD_INC_USE_COUNT(current->binfmt->module);
452 set_brk(current->mm->start_brk, current->mm->brk);
454 retval = setup_arg_pages(bprm);
455 if (retval < 0) {
456 /* Someone check-me: is this error path enough? */
457 send_sig(SIGKILL, current, 0);
458 return retval;
461 current->mm->start_stack = create_aout_tables(bprm->p, bprm);
462 #ifdef __alpha__
463 regs->gp = ex.a_gpvalue;
464 #endif
465 start_thread(regs, ex.a_entry, current->mm->start_stack);
466 if (current->flags & PF_PTRACED)
467 send_sig(SIGTRAP, current, 0);
468 return 0;
472 static int
473 load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
475 int retval;
477 MOD_INC_USE_COUNT;
478 retval = do_load_aout_binary(bprm, regs);
479 MOD_DEC_USE_COUNT;
480 return retval;
483 static inline int
484 do_load_aout_library(int fd)
486 struct file * file;
487 struct inode * inode;
488 unsigned long bss, start_addr, len;
489 unsigned long error;
490 int retval;
491 loff_t offset = 0;
492 struct exec ex;
494 retval = -EACCES;
495 file = fget(fd);
496 if (!file)
497 goto out;
498 if (!file->f_op)
499 goto out_putf;
500 inode = file->f_dentry->d_inode;
502 retval = -ENOEXEC;
503 /* N.B. Save current fs? */
504 set_fs(KERNEL_DS);
505 error = file->f_op->read(file, (char *) &ex, sizeof(ex), &offset);
506 set_fs(USER_DS);
507 if (error != sizeof(ex))
508 goto out_putf;
510 /* We come in here for the regular a.out style of shared libraries */
511 if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
512 N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
513 inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
514 goto out_putf;
517 if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
518 (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
519 printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
520 goto out_putf;
523 if (N_FLAGS(ex))
524 goto out_putf;
526 /* For QMAGIC, the starting address is 0x20 into the page. We mask
527 this off to get the starting address for the page */
529 start_addr = ex.a_entry & 0xfffff000;
531 if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
532 printk(KERN_WARNING
533 "N_TXTOFF is not page aligned. Please convert library: %s\n",
534 file->f_dentry->d_name.name
537 do_mmap(NULL, start_addr & PAGE_MASK, ex.a_text + ex.a_data + ex.a_bss,
538 PROT_READ | PROT_WRITE | PROT_EXEC,
539 MAP_FIXED| MAP_PRIVATE, 0);
541 read_exec(file->f_dentry, N_TXTOFF(ex),
542 (char *)start_addr, ex.a_text + ex.a_data, 0);
543 flush_icache_range((unsigned long) start_addr,
544 (unsigned long) start_addr + ex.a_text + ex.a_data);
546 retval = 0;
547 goto out_putf;
549 /* Now use mmap to map the library into memory. */
550 error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
551 PROT_READ | PROT_WRITE | PROT_EXEC,
552 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
553 N_TXTOFF(ex));
554 retval = error;
555 if (error != start_addr)
556 goto out_putf;
558 len = PAGE_ALIGN(ex.a_text + ex.a_data);
559 bss = ex.a_text + ex.a_data + ex.a_bss;
560 if (bss > len) {
561 error = do_brk(start_addr + len, bss - len);
562 retval = error;
563 if (error != start_addr + len)
564 goto out_putf;
566 retval = 0;
568 out_putf:
569 fput(file);
570 out:
571 return retval;
574 static int
575 load_aout_library(int fd)
577 int retval;
579 MOD_INC_USE_COUNT;
580 retval = do_load_aout_library(fd);
581 MOD_DEC_USE_COUNT;
582 return retval;
586 int __init init_aout_binfmt(void)
588 return register_binfmt(&aout_format);
591 #ifdef MODULE
592 int init_module(void) {
593 return init_aout_binfmt();
596 void cleanup_module( void) {
597 unregister_binfmt(&aout_format);
599 #endif