OSDN Git Service

[PATCH] Remove isofs useless unsigned " < 0" comparison
[linux-kernel-docs/linux-2.4.36.git] / fs / binfmt_aout.c
1 /*
2  *  linux/fs/binfmt_aout.c
3  *
4  *  Copyright (C) 1991, 1992, 1996  Linus Torvalds
5  */
6
7 #include <linux/module.h>
8
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/slab.h>
24 #include <linux/binfmts.h>
25 #include <linux/personality.h>
26 #include <linux/init.h>
27
28 #include <asm/system.h>
29 #include <asm/uaccess.h>
30 #include <asm/pgalloc.h>
31
32 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
33 static int load_aout_library(struct file*);
34 static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file);
35
36 extern void dump_thread(struct pt_regs *, struct user *);
37
38 static struct linux_binfmt aout_format = {
39         NULL, THIS_MODULE, load_aout_binary, load_aout_library, aout_core_dump, PAGE_SIZE
40 };
41
42 #define BAD_ADDR(x)     ((unsigned long)(x) >= TASK_SIZE)
43
44 static int set_brk(unsigned long start, unsigned long end)
45 {
46         start = PAGE_ALIGN(start);
47         end = PAGE_ALIGN(end);
48         if (end > start) {
49                 unsigned long addr;
50                 down_write(&current->mm->mmap_sem);
51                 addr = do_brk(start, end - start);
52                 up_write(&current->mm->mmap_sem);
53                 if (BAD_ADDR(addr))
54                         return addr;
55         }
56         return 0;
57 }
58
59 /*
60  * These are the only things you should do on a core-file: use only these
61  * macros to write out all the necessary info.
62  */
63
64 static int dump_write(struct file *file, const void *addr, int nr)
65 {
66         return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
67 }
68
69 #define DUMP_WRITE(addr, nr)    \
70         if (!dump_write(file, (void *)(addr), (nr))) \
71                 goto end_coredump;
72
73 #define DUMP_SEEK(offset) \
74 if (file->f_op->llseek) { \
75         if (file->f_op->llseek(file,(offset),0) != (offset)) \
76                 goto end_coredump; \
77 } else file->f_pos = (offset)
78
79 /*
80  * Routine writes a core dump image in the current directory.
81  * Currently only a stub-function.
82  *
83  * Note that setuid/setgid files won't make a core-dump if the uid/gid
84  * changed due to the set[u|g]id. It's enforced by the "current->mm->dumpable"
85  * field, which also makes sure the core-dumps won't be recursive if the
86  * dumping of the process results in another error..
87  */
88
89 static int aout_core_dump(long signr, struct pt_regs * regs, struct file *file)
90 {
91         mm_segment_t fs;
92         int has_dumped = 0;
93         unsigned long dump_start, dump_size;
94         struct user dump;
95 #if defined(__alpha__)
96 #       define START_DATA(u)    (u.start_data)
97 #elif defined(__arm__)
98 #       define START_DATA(u)    ((u.u_tsize << PAGE_SHIFT) + u.start_code)
99 #elif defined(__sparc__)
100 #       define START_DATA(u)    (u.u_tsize)
101 #elif defined(__i386__) || defined(__mc68000__) || defined(__arch_um__)
102 #       define START_DATA(u)    (u.u_tsize << PAGE_SHIFT)
103 #endif
104 #ifdef __sparc__
105 #       define START_STACK(u)   ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1))
106 #else
107 #       define START_STACK(u)   (u.start_stack)
108 #endif
109
110         fs = get_fs();
111         set_fs(KERNEL_DS);
112         has_dumped = 1;
113         current->flags |= PF_DUMPCORE;
114         strncpy(dump.u_comm, current->comm, sizeof(current->comm));
115 #ifndef __sparc__
116         dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
117 #endif
118         dump.signal = signr;
119         dump_thread(regs, &dump);
120
121 /* If the size of the dump file exceeds the rlimit, then see what would happen
122    if we wrote the stack, but not the data area.  */
123 #ifdef __sparc__
124         if ((dump.u_dsize+dump.u_ssize) >
125             current->rlim[RLIMIT_CORE].rlim_cur)
126                 dump.u_dsize = 0;
127 #else
128         if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
129             current->rlim[RLIMIT_CORE].rlim_cur)
130                 dump.u_dsize = 0;
131 #endif
132
133 /* Make sure we have enough room to write the stack and data areas. */
134 #ifdef __sparc__
135         if ((dump.u_ssize) >
136             current->rlim[RLIMIT_CORE].rlim_cur)
137                 dump.u_ssize = 0;
138 #else
139         if ((dump.u_ssize+1) * PAGE_SIZE >
140             current->rlim[RLIMIT_CORE].rlim_cur)
141                 dump.u_ssize = 0;
142 #endif
143
144 /* make sure we actually have a data and stack area to dump */
145         set_fs(USER_DS);
146 #ifdef __sparc__
147         if (verify_area(VERIFY_READ, (void *) START_DATA(dump), dump.u_dsize))
148                 dump.u_dsize = 0;
149         if (verify_area(VERIFY_READ, (void *) START_STACK(dump), dump.u_ssize))
150                 dump.u_ssize = 0;
151 #else
152         if (verify_area(VERIFY_READ, (void *) START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
153                 dump.u_dsize = 0;
154         if (verify_area(VERIFY_READ, (void *) START_STACK(dump), dump.u_ssize << PAGE_SHIFT))
155                 dump.u_ssize = 0;
156 #endif
157
158         set_fs(KERNEL_DS);
159 /* struct user */
160         DUMP_WRITE(&dump,sizeof(dump));
161 /* Now dump all of the user data.  Include malloced stuff as well */
162 #ifndef __sparc__
163         DUMP_SEEK(PAGE_SIZE);
164 #endif
165 /* now we start writing out the user space info */
166         set_fs(USER_DS);
167 /* Dump the data area */
168         if (dump.u_dsize != 0) {
169                 dump_start = START_DATA(dump);
170 #ifdef __sparc__
171                 dump_size = dump.u_dsize;
172 #else
173                 dump_size = dump.u_dsize << PAGE_SHIFT;
174 #endif
175                 DUMP_WRITE(dump_start,dump_size);
176         }
177 /* Now prepare to dump the stack area */
178         if (dump.u_ssize != 0) {
179                 dump_start = START_STACK(dump);
180 #ifdef __sparc__
181                 dump_size = dump.u_ssize;
182 #else
183                 dump_size = dump.u_ssize << PAGE_SHIFT;
184 #endif
185                 DUMP_WRITE(dump_start,dump_size);
186         }
187 /* Finally dump the task struct.  Not be used by gdb, but could be useful */
188         set_fs(KERNEL_DS);
189         DUMP_WRITE(current,sizeof(*current));
190 end_coredump:
191         set_fs(fs);
192         return has_dumped;
193 }
194
195 /*
196  * create_aout_tables() parses the env- and arg-strings in new user
197  * memory and creates the pointer tables from them, and puts their
198  * addresses on the "stack", returning the new stack pointer value.
199  */
200 static unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm)
201 {
202         char **argv, **envp;
203         unsigned long * sp;
204         int argc = bprm->argc;
205         int envc = bprm->envc;
206
207         sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
208 #ifdef __sparc__
209         /* This imposes the proper stack alignment for a new process. */
210         sp = (unsigned long *) (((unsigned long) sp) & ~7);
211         if ((envc+argc+3)&1) --sp;
212 #endif
213 #ifdef __alpha__
214 /* whee.. test-programs are so much fun. */
215         put_user(0, --sp);
216         put_user(0, --sp);
217         if (bprm->loader) {
218                 put_user(0, --sp);
219                 put_user(0x3eb, --sp);
220                 put_user(bprm->loader, --sp);
221                 put_user(0x3ea, --sp);
222         }
223         put_user(bprm->exec, --sp);
224         put_user(0x3e9, --sp);
225 #endif
226         sp -= envc+1;
227         envp = (char **) sp;
228         sp -= argc+1;
229         argv = (char **) sp;
230 #if defined(__i386__) || defined(__mc68000__) || defined(__arm__) || defined(__arch_um__)
231         put_user((unsigned long) envp,--sp);
232         put_user((unsigned long) argv,--sp);
233 #endif
234         put_user(argc,--sp);
235         current->mm->arg_start = (unsigned long) p;
236         while (argc-->0) {
237                 char c;
238                 put_user(p,argv++);
239                 do {
240                         get_user(c,p++);
241                 } while (c);
242         }
243         put_user(NULL,argv);
244         current->mm->arg_end = current->mm->env_start = (unsigned long) p;
245         while (envc-->0) {
246                 char c;
247                 put_user(p,envp++);
248                 do {
249                         get_user(c,p++);
250                 } while (c);
251         }
252         put_user(NULL,envp);
253         current->mm->env_end = (unsigned long) p;
254         return sp;
255 }
256
257 /*
258  * These are the functions used to load a.out style executables and shared
259  * libraries.  There is no binary dependent code anywhere else.
260  */
261
262 static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
263 {
264         struct exec ex;
265         unsigned long error;
266         unsigned long fd_offset;
267         unsigned long rlim;
268         int retval;
269
270         ex = *((struct exec *) bprm->buf);              /* exec-header */
271         if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&
272              N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||
273             N_TRSIZE(ex) || N_DRSIZE(ex) ||
274             bprm->file->f_dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
275                 return -ENOEXEC;
276         }
277
278         fd_offset = N_TXTOFF(ex);
279
280         /* Check initial limits. This avoids letting people circumvent
281          * size limits imposed on them by creating programs with large
282          * arrays in the data or bss.
283          */
284         rlim = current->rlim[RLIMIT_DATA].rlim_cur;
285         if (rlim >= RLIM_INFINITY)
286                 rlim = ~0;
287         if (ex.a_data + ex.a_bss > rlim)
288                 return -ENOMEM;
289
290         /* Flush all traces of the currently running executable */
291         retval = flush_old_exec(bprm);
292         if (retval)
293                 return retval;
294
295         /* OK, This is the point of no return */
296 #if defined(__alpha__)
297         SET_AOUT_PERSONALITY(bprm, ex);
298 #elif defined(__sparc__)
299         set_personality(PER_SUNOS);
300 #if !defined(__sparc_v9__)
301         memcpy(&current->thread.core_exec, &ex, sizeof(struct exec));
302 #endif
303 #else
304         set_personality(PER_LINUX);
305 #endif
306
307         current->mm->end_code = ex.a_text +
308                 (current->mm->start_code = N_TXTADDR(ex));
309         current->mm->end_data = ex.a_data +
310                 (current->mm->start_data = N_DATADDR(ex));
311         current->mm->brk = ex.a_bss +
312                 (current->mm->start_brk = N_BSSADDR(ex));
313
314         current->mm->rss = 0;
315         current->mm->mmap = NULL;
316         compute_creds(bprm);
317         current->flags &= ~PF_FORKNOEXEC;
318 #ifdef __sparc__
319         if (N_MAGIC(ex) == NMAGIC) {
320                 loff_t pos = fd_offset;
321                 /* Fuck me plenty... */
322                 /* <AOL></AOL> */
323                 down_write(&current->mm->mmap_sem);
324                 error = do_brk(N_TXTADDR(ex), ex.a_text);
325                 up_write(&current->mm->mmap_sem);
326                 bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex),
327                           ex.a_text, &pos);
328                 down_write(&current->mm->mmap_sem);
329                 error = do_brk(N_DATADDR(ex), ex.a_data);
330                 up_write(&current->mm->mmap_sem);
331                 bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex),
332                           ex.a_data, &pos);
333                 goto beyond_if;
334         }
335 #endif
336
337         if (N_MAGIC(ex) == OMAGIC) {
338                 unsigned long text_addr, map_size;
339                 loff_t pos;
340
341                 text_addr = N_TXTADDR(ex);
342
343 #if defined(__alpha__) || defined(__sparc__)
344                 pos = fd_offset;
345                 map_size = ex.a_text+ex.a_data + PAGE_SIZE - 1;
346 #else
347                 pos = 32;
348                 map_size = ex.a_text+ex.a_data;
349 #endif
350                 down_write(&current->mm->mmap_sem);
351                 error = do_brk(text_addr & PAGE_MASK, map_size);
352                 up_write(&current->mm->mmap_sem);
353                 if (error != (text_addr & PAGE_MASK)) {
354                         send_sig(SIGKILL, current, 0);
355                         return error;
356                 }
357
358                 error = bprm->file->f_op->read(bprm->file, (char *)text_addr,
359                           ex.a_text+ex.a_data, &pos);
360                 if ((signed long)error < 0) {
361                         send_sig(SIGKILL, current, 0);
362                         return error;
363                 }
364                          
365                 flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
366         } else {
367                 static unsigned long error_time, error_time2;
368                 if ((ex.a_text & 0xfff || ex.a_data & 0xfff) &&
369                     (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time2) > 5*HZ)
370                 {
371                         printk(KERN_NOTICE "executable not page aligned\n");
372                         error_time2 = jiffies;
373                 }
374
375                 if ((fd_offset & ~PAGE_MASK) != 0 &&
376                     (jiffies-error_time) > 5*HZ)
377                 {
378                         printk(KERN_WARNING 
379                                "fd_offset is not page aligned. Please convert program: %s\n",
380                                bprm->file->f_dentry->d_name.name);
381                         error_time = jiffies;
382                 }
383
384                 if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
385                         loff_t pos = fd_offset;
386                         down_write(&current->mm->mmap_sem);
387                         do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
388                         up_write(&current->mm->mmap_sem);
389                         bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex),
390                                         ex.a_text+ex.a_data, &pos);
391                         flush_icache_range((unsigned long) N_TXTADDR(ex),
392                                            (unsigned long) N_TXTADDR(ex) +
393                                            ex.a_text+ex.a_data);
394                         goto beyond_if;
395                 }
396
397                 down_write(&current->mm->mmap_sem);
398                 error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
399                         PROT_READ | PROT_EXEC,
400                         MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
401                         fd_offset);
402                 up_write(&current->mm->mmap_sem);
403
404                 if (error != N_TXTADDR(ex)) {
405                         send_sig(SIGKILL, current, 0);
406                         return error;
407                 }
408
409                 down_write(&current->mm->mmap_sem);
410                 error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
411                                 PROT_READ | PROT_WRITE | PROT_EXEC,
412                                 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
413                                 fd_offset + ex.a_text);
414                 up_write(&current->mm->mmap_sem);
415                 if (error != N_DATADDR(ex)) {
416                         send_sig(SIGKILL, current, 0);
417                         return error;
418                 }
419         }
420 beyond_if:
421         set_binfmt(&aout_format);
422
423         retval = set_brk(current->mm->start_brk, current->mm->brk);
424         if (retval < 0) {
425                 send_sig(SIGKILL, current, 0);
426                 return retval;
427         }
428
429         retval = setup_arg_pages(bprm); 
430         if (retval < 0) { 
431                 /* Someone check-me: is this error path enough? */ 
432                 send_sig(SIGKILL, current, 0); 
433                 return retval;
434         }
435
436         current->mm->start_stack =
437                 (unsigned long) create_aout_tables((char *) bprm->p, bprm);
438 #ifdef __alpha__
439         regs->gp = ex.a_gpvalue;
440 #endif
441         start_thread(regs, ex.a_entry, current->mm->start_stack);
442         if (current->ptrace & PT_PTRACED)
443                 send_sig(SIGTRAP, current, 0);
444         return 0;
445 }
446
447 static int load_aout_library(struct file *file)
448 {
449         struct inode * inode;
450         unsigned long bss, start_addr, len;
451         unsigned long error;
452         int retval;
453         struct exec ex;
454
455         inode = file->f_dentry->d_inode;
456
457         retval = -ENOEXEC;
458         error = kernel_read(file, 0, (char *) &ex, sizeof(ex));
459         if (error != sizeof(ex))
460                 goto out;
461
462         /* We come in here for the regular a.out style of shared libraries */
463         if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
464             N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
465             inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
466                 goto out;
467         }
468
469         if (N_FLAGS(ex))
470                 goto out;
471
472         /* For  QMAGIC, the starting address is 0x20 into the page.  We mask
473            this off to get the starting address for the page */
474
475         start_addr =  ex.a_entry & 0xfffff000;
476
477         if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) {
478                 static unsigned long error_time;
479                 loff_t pos = N_TXTOFF(ex);
480
481                 if ((jiffies-error_time) > 5*HZ)
482                 {
483                         printk(KERN_WARNING 
484                                "N_TXTOFF is not page aligned. Please convert library: %s\n",
485                                file->f_dentry->d_name.name);
486                         error_time = jiffies;
487                 }
488                 
489                 down_write(&current->mm->mmap_sem);
490                 do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
491                 up_write(&current->mm->mmap_sem);
492                 
493                 file->f_op->read(file, (char *)start_addr,
494                         ex.a_text + ex.a_data, &pos);
495                 flush_icache_range((unsigned long) start_addr,
496                                    (unsigned long) start_addr + ex.a_text + ex.a_data);
497
498                 retval = 0;
499                 goto out;
500         }
501         /* Now use mmap to map the library into memory. */
502         down_write(&current->mm->mmap_sem);
503         error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
504                         PROT_READ | PROT_WRITE | PROT_EXEC,
505                         MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
506                         N_TXTOFF(ex));
507         up_write(&current->mm->mmap_sem);
508         retval = error;
509         if (error != start_addr)
510                 goto out;
511
512         len = PAGE_ALIGN(ex.a_text + ex.a_data);
513         bss = ex.a_text + ex.a_data + ex.a_bss;
514         if (bss > len) {
515                 down_write(&current->mm->mmap_sem);
516                 error = do_brk(start_addr + len, bss - len);
517                 up_write(&current->mm->mmap_sem);
518
519                 retval = error;
520                 if (error != start_addr + len)
521                         goto out;
522         }
523         retval = 0;
524 out:
525         return retval;
526 }
527
528 static int __init init_aout_binfmt(void)
529 {
530         return register_binfmt(&aout_format);
531 }
532
533 static void __exit exit_aout_binfmt(void)
534 {
535         unregister_binfmt(&aout_format);
536 }
537
538 EXPORT_NO_SYMBOLS;
539
540 module_init(init_aout_binfmt);
541 module_exit(exit_aout_binfmt);
542 MODULE_LICENSE("GPL");