root/fs/binfmt_aout.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_brk
  2. do_aout_core_dump
  3. aout_core_dump
  4. create_aout_tables
  5. do_load_aout_binary
  6. load_aout_binary
  7. do_load_aout_library
  8. load_aout_library
  9. init_aout_binfmt
  10. init_module
  11. cleanup_module

   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/fs.h>
  10 #include <linux/sched.h>
  11 #include <linux/kernel.h>
  12 #include <linux/mm.h>
  13 #include <linux/mman.h>
  14 #include <linux/a.out.h>
  15 #include <linux/errno.h>
  16 #include <linux/signal.h>
  17 #include <linux/string.h>
  18 #include <linux/stat.h>
  19 #include <linux/fcntl.h>
  20 #include <linux/ptrace.h>
  21 #include <linux/user.h>
  22 #include <linux/malloc.h>
  23 #include <linux/binfmts.h>
  24 #include <linux/personality.h>
  25 
  26 #include <asm/system.h>
  27 #include <asm/segment.h>
  28 #include <asm/pgtable.h>
  29 
  30 static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
  31 static int load_aout_library(int fd);
  32 static int aout_core_dump(long signr, struct pt_regs * regs);
  33 
  34 extern void dump_thread(struct pt_regs *, struct user *);
  35 
  36 static struct linux_binfmt aout_format = {
  37 #ifndef MODULE
  38         NULL, NULL, load_aout_binary, load_aout_library, aout_core_dump
  39 #else
  40         NULL, &mod_use_count_, load_aout_binary, load_aout_library, aout_core_dump
  41 #endif
  42 };
  43 
  44 static void set_brk(unsigned long start, unsigned long end)
     /* [previous][next][first][last][top][bottom][index][help] */
  45 {
  46         start = PAGE_ALIGN(start);
  47         end = PAGE_ALIGN(end);
  48         if (end <= start)
  49                 return;
  50         do_mmap(NULL, start, end - start,
  51                 PROT_READ | PROT_WRITE | PROT_EXEC,
  52                 MAP_FIXED | MAP_PRIVATE, 0);
  53 }
  54 
  55 /*
  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.
  58  */
  59 #define DUMP_WRITE(addr,nr) \
  60 while (file.f_op->write(inode,&file,(char *)(addr),(nr)) != (nr)) goto close_coredump
  61 
  62 #define DUMP_SEEK(offset) \
  63 if (file.f_op->lseek) { \
  64         if (file.f_op->lseek(inode,&file,(offset),0) != (offset)) \
  65                 goto close_coredump; \
  66 } else file.f_pos = (offset)            
  67 
  68 /*
  69  * Routine writes a core dump image in the current directory.
  70  * Currently only a stub-function.
  71  *
  72  * Note that setuid/setgid files won't make a core-dump if the uid/gid
  73  * changed due to the set[u|g]id. It's enforced by the "current->dumpable"
  74  * field, which also makes sure the core-dumps won't be recursive if the
  75  * dumping of the process results in another error..
  76  */
  77 
  78 static inline int
  79 do_aout_core_dump(long signr, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  80 {
  81         struct inode * inode = NULL;
  82         struct file file;
  83         unsigned short fs;
  84         int has_dumped = 0;
  85         char corefile[6+sizeof(current->comm)];
  86         unsigned long dump_start, dump_size;
  87         struct user dump;
  88 #ifdef __alpha__
  89 #       define START_DATA(u)    (u.start_data)
  90 #else
  91 #       define START_DATA(u)    (u.u_tsize << PAGE_SHIFT)
  92 #endif
  93 
  94         if (!current->dumpable)
  95                 return 0;
  96         current->dumpable = 0;
  97 
  98 /* See if we have enough room to write the upage.  */
  99         if (current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE)
 100                 return 0;
 101         fs = get_fs();
 102         set_fs(KERNEL_DS);
 103         memcpy(corefile,"core.",5);
 104 #if 0
 105         memcpy(corefile+5,current->comm,sizeof(current->comm));
 106 #else
 107         corefile[4] = '\0';
 108 #endif
 109         if (open_namei(corefile,O_CREAT | 2 | O_TRUNC,0600,&inode,NULL)) {
 110                 inode = NULL;
 111                 goto end_coredump;
 112         }
 113         if (!S_ISREG(inode->i_mode))
 114                 goto end_coredump;
 115         if (!inode->i_op || !inode->i_op->default_file_ops)
 116                 goto end_coredump;
 117         if (get_write_access(inode))
 118                 goto end_coredump;
 119         file.f_mode = 3;
 120         file.f_flags = 0;
 121         file.f_count = 1;
 122         file.f_inode = inode;
 123         file.f_pos = 0;
 124         file.f_reada = 0;
 125         file.f_op = inode->i_op->default_file_ops;
 126         if (file.f_op->open)
 127                 if (file.f_op->open(inode,&file))
 128                         goto done_coredump;
 129         if (!file.f_op->write)
 130                 goto close_coredump;
 131         has_dumped = 1;
 132         strncpy(dump.u_comm, current->comm, sizeof(current->comm));
 133         dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
 134         dump.signal = signr;
 135         dump_thread(regs, &dump);
 136 
 137 /* If the size of the dump file exceeds the rlimit, then see what would happen
 138    if we wrote the stack, but not the data area.  */
 139         if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
 140             current->rlim[RLIMIT_CORE].rlim_cur)
 141                 dump.u_dsize = 0;
 142 
 143 /* Make sure we have enough room to write the stack and data areas. */
 144         if ((dump.u_ssize+1) * PAGE_SIZE >
 145             current->rlim[RLIMIT_CORE].rlim_cur)
 146                 dump.u_ssize = 0;
 147 
 148 /* make sure we actually have a data and stack area to dump */
 149         set_fs(USER_DS);
 150         if (verify_area(VERIFY_READ, (void *) START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
 151                 dump.u_dsize = 0;
 152         if (verify_area(VERIFY_READ, (void *) dump.start_stack, dump.u_ssize << PAGE_SHIFT))
 153                 dump.u_ssize = 0;
 154 
 155         set_fs(KERNEL_DS);
 156 /* struct user */
 157         DUMP_WRITE(&dump,sizeof(dump));
 158 /* Now dump all of the user data.  Include malloced stuff as well */
 159         DUMP_SEEK(PAGE_SIZE);
 160 /* now we start writing out the user space info */
 161         set_fs(USER_DS);
 162 /* Dump the data area */
 163         if (dump.u_dsize != 0) {
 164                 dump_start = START_DATA(dump);
 165                 dump_size = dump.u_dsize << PAGE_SHIFT;
 166                 DUMP_WRITE(dump_start,dump_size);
 167         }
 168 /* Now prepare to dump the stack area */
 169         if (dump.u_ssize != 0) {
 170                 dump_start = dump.start_stack;
 171                 dump_size = dump.u_ssize << PAGE_SHIFT;
 172                 DUMP_WRITE(dump_start,dump_size);
 173         }
 174 /* Finally dump the task struct.  Not be used by gdb, but could be useful */
 175         set_fs(KERNEL_DS);
 176         DUMP_WRITE(current,sizeof(*current));
 177 close_coredump:
 178         if (file.f_op->release)
 179                 file.f_op->release(inode,&file);
 180 done_coredump:
 181         put_write_access(inode);
 182 end_coredump:
 183         set_fs(fs);
 184         iput(inode);
 185         return has_dumped;
 186 }
 187 
 188 static int
 189 aout_core_dump(long signr, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 190 {
 191         int retval;
 192 
 193         MOD_INC_USE_COUNT;
 194         retval = do_aout_core_dump(signr, regs);
 195         MOD_DEC_USE_COUNT;
 196         return retval;
 197 }
 198 
 199 /*
 200  * create_aout_tables() parses the env- and arg-strings in new user
 201  * memory and creates the pointer tables from them, and puts their
 202  * addresses on the "stack", returning the new stack pointer value.
 203  */
 204 static unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm, int ibcs)
     /* [previous][next][first][last][top][bottom][index][help] */
 205 {
 206         unsigned long *argv,*envp;
 207         unsigned long * sp;
 208         int argc = bprm->argc;
 209         int envc = bprm->envc;
 210 
 211         sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
 212 #ifdef __alpha__
 213 /* whee.. test-programs are so much fun. */
 214         put_user(0, --sp);
 215         put_user(0, --sp);
 216         if (bprm->loader) {
 217                 put_user(0, --sp);
 218                 put_user(0x3eb, --sp);
 219                 put_user(bprm->loader, --sp);
 220                 put_user(0x3ea, --sp);
 221         }
 222         put_user(bprm->exec, --sp);
 223         put_user(0x3e9, --sp);
 224 #endif
 225         sp -= envc+1;
 226         envp = sp;
 227         sp -= argc+1;
 228         argv = sp;
 229 #ifdef __i386__
 230         if (!ibcs) {
 231                 put_user(envp,--sp);
 232                 put_user(argv,--sp);
 233         }
 234 #endif
 235         put_user(argc,--sp);
 236         current->mm->arg_start = (unsigned long) p;
 237         while (argc-->0) {
 238                 put_user(p,argv++);
 239                 while (get_user(p++)) /* nothing */ ;
 240         }
 241         put_user(NULL,argv);
 242         current->mm->arg_end = current->mm->env_start = (unsigned long) p;
 243         while (envc-->0) {
 244                 put_user(p,envp++);
 245                 while (get_user(p++)) /* nothing */ ;
 246         }
 247         put_user(NULL,envp);
 248         current->mm->env_end = (unsigned long) p;
 249         return sp;
 250 }
 251 
 252 /*
 253  * These are the functions used to load a.out style executables and shared
 254  * libraries.  There is no binary dependent code anywhere else.
 255  */
 256 
 257 static inline int
 258 do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 259 {
 260         struct exec ex;
 261         struct file * file;
 262         int fd;
 263         unsigned long error;
 264         unsigned long p = bprm->p;
 265         unsigned long fd_offset;
 266         unsigned long rlim;
 267 
 268         ex = *((struct exec *) bprm->buf);              /* exec-header */
 269         if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && 
 270              N_MAGIC(ex) != QMAGIC) ||
 271             N_TRSIZE(ex) || N_DRSIZE(ex) ||
 272             bprm->inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
 273                 return -ENOEXEC;
 274         }
 275 
 276         current->personality = PER_LINUX;
 277         fd_offset = N_TXTOFF(ex);
 278 
 279 #ifdef __i386__
 280         if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
 281                 printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
 282                 return -ENOEXEC;
 283         }
 284 
 285         if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
 286             (fd_offset < bprm->inode->i_sb->s_blocksize)) {
 287                 printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
 288                 return -ENOEXEC;
 289         }
 290 #endif
 291 
 292         /* Check initial limits. This avoids letting people circumvent
 293          * size limits imposed on them by creating programs with large
 294          * arrays in the data or bss.
 295          */
 296         rlim = current->rlim[RLIMIT_DATA].rlim_cur;
 297         if (rlim >= RLIM_INFINITY)
 298                 rlim = ~0;
 299         if (ex.a_data + ex.a_bss > rlim)
 300                 return -ENOMEM;
 301 
 302         /* OK, This is the point of no return */
 303         flush_old_exec(bprm);
 304 
 305         current->mm->end_code = ex.a_text +
 306                 (current->mm->start_code = N_TXTADDR(ex));
 307         current->mm->end_data = ex.a_data +
 308                 (current->mm->start_data = N_DATADDR(ex));
 309         current->mm->brk = ex.a_bss +
 310                 (current->mm->start_brk = N_BSSADDR(ex));
 311 
 312         current->mm->rss = 0;
 313         current->mm->mmap = NULL;
 314         current->suid = current->euid = current->fsuid = bprm->e_uid;
 315         current->sgid = current->egid = current->fsgid = bprm->e_gid;
 316         if (N_MAGIC(ex) == OMAGIC) {
 317 #ifdef __alpha__
 318                 do_mmap(NULL, N_TXTADDR(ex) & PAGE_MASK,
 319                         ex.a_text+ex.a_data + PAGE_SIZE - 1,
 320                         PROT_READ|PROT_WRITE|PROT_EXEC,
 321                         MAP_FIXED|MAP_PRIVATE, 0);
 322                 read_exec(bprm->inode, fd_offset, (char *) N_TXTADDR(ex),
 323                           ex.a_text+ex.a_data, 0);
 324 #else
 325                 do_mmap(NULL, 0, ex.a_text+ex.a_data,
 326                         PROT_READ|PROT_WRITE|PROT_EXEC,
 327                         MAP_FIXED|MAP_PRIVATE, 0);
 328                 read_exec(bprm->inode, 32, (char *) 0, ex.a_text+ex.a_data, 0);
 329 #endif
 330         } else {
 331                 if (ex.a_text & 0xfff || ex.a_data & 0xfff)
 332                         printk(KERN_NOTICE "executable not page aligned\n");
 333                 
 334                 fd = open_inode(bprm->inode, O_RDONLY);
 335                 
 336                 if (fd < 0)
 337                         return fd;
 338                 file = current->files->fd[fd];
 339                 if (!file->f_op || !file->f_op->mmap) {
 340                         sys_close(fd);
 341                         do_mmap(NULL, 0, ex.a_text+ex.a_data,
 342                                 PROT_READ|PROT_WRITE|PROT_EXEC,
 343                                 MAP_FIXED|MAP_PRIVATE, 0);
 344                         read_exec(bprm->inode, fd_offset,
 345                                   (char *) N_TXTADDR(ex), ex.a_text+ex.a_data, 0);
 346                         goto beyond_if;
 347                 }
 348 
 349                 error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
 350                         PROT_READ | PROT_EXEC,
 351                         MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
 352                         fd_offset);
 353 
 354                 if (error != N_TXTADDR(ex)) {
 355                         sys_close(fd);
 356                         send_sig(SIGKILL, current, 0);
 357                         return error;
 358                 }
 359                 
 360                 error = do_mmap(file, N_DATADDR(ex), ex.a_data,
 361                                 PROT_READ | PROT_WRITE | PROT_EXEC,
 362                                 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
 363                                 fd_offset + ex.a_text);
 364                 sys_close(fd);
 365                 if (error != N_DATADDR(ex)) {
 366                         send_sig(SIGKILL, current, 0);
 367                         return error;
 368                 }
 369         }
 370 beyond_if:
 371         if (current->exec_domain && current->exec_domain->use_count)
 372                 (*current->exec_domain->use_count)--;
 373         if (current->binfmt && current->binfmt->use_count)
 374                 (*current->binfmt->use_count)--;
 375         current->exec_domain = lookup_exec_domain(current->personality);
 376         current->binfmt = &aout_format;
 377         if (current->exec_domain && current->exec_domain->use_count)
 378                 (*current->exec_domain->use_count)++;
 379         if (current->binfmt && current->binfmt->use_count)
 380                 (*current->binfmt->use_count)++;
 381 
 382         set_brk(current->mm->start_brk, current->mm->brk);
 383 
 384         p = setup_arg_pages(p, bprm);
 385         
 386         p = (unsigned long) create_aout_tables((char *)p, bprm,
 387                                         current->personality != PER_LINUX);
 388         current->mm->start_stack = p;
 389 #ifdef __alpha__
 390         regs->gp = ex.a_gpvalue;
 391 #endif
 392         start_thread(regs, ex.a_entry, p);
 393         if (current->flags & PF_PTRACED)
 394                 send_sig(SIGTRAP, current, 0);
 395         return 0;
 396 }
 397 
 398 static int
 399 load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 400 {
 401         int retval;
 402 
 403         MOD_INC_USE_COUNT;
 404         retval = do_load_aout_binary(bprm, regs);
 405         MOD_DEC_USE_COUNT;
 406         return retval;
 407 }
 408 
 409 static inline int
 410 do_load_aout_library(int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 411 {
 412         struct file * file;
 413         struct exec ex;
 414         struct  inode * inode;
 415         unsigned int len;
 416         unsigned int bss;
 417         unsigned int start_addr;
 418         unsigned long error;
 419         
 420         file = current->files->fd[fd];
 421         inode = file->f_inode;
 422         
 423         if (!file || !file->f_op)
 424                 return -EACCES;
 425 
 426         /* Seek into the file */
 427         if (file->f_op->lseek) {
 428                 if ((error = file->f_op->lseek(inode, file, 0, 0)) != 0)
 429                         return -ENOEXEC;
 430         } else
 431                 file->f_pos = 0;
 432 
 433         set_fs(KERNEL_DS);
 434         error = file->f_op->read(inode, file, (char *) &ex, sizeof(ex));
 435         set_fs(USER_DS);
 436         if (error != sizeof(ex))
 437                 return -ENOEXEC;
 438 
 439         /* We come in here for the regular a.out style of shared libraries */
 440         if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
 441             N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
 442             inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
 443                 return -ENOEXEC;
 444         }
 445         if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) && 
 446             (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
 447                 printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
 448                 return -ENOEXEC;
 449         }
 450         
 451         if (N_FLAGS(ex)) return -ENOEXEC;
 452 
 453         /* For  QMAGIC, the starting address is 0x20 into the page.  We mask
 454            this off to get the starting address for the page */
 455 
 456         start_addr =  ex.a_entry & 0xfffff000;
 457 
 458         /* Now use mmap to map the library into memory. */
 459         error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
 460                         PROT_READ | PROT_WRITE | PROT_EXEC,
 461                         MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
 462                         N_TXTOFF(ex));
 463         if (error != start_addr)
 464                 return error;
 465         len = PAGE_ALIGN(ex.a_text + ex.a_data);
 466         bss = ex.a_text + ex.a_data + ex.a_bss;
 467         if (bss > len) {
 468                 error = do_mmap(NULL, start_addr + len, bss-len,
 469                                 PROT_READ|PROT_WRITE|PROT_EXEC,
 470                                 MAP_PRIVATE|MAP_FIXED, 0);
 471                 if (error != start_addr + len)
 472                         return error;
 473         }
 474         return 0;
 475 }
 476 
 477 static int
 478 load_aout_library(int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 479 {
 480         int retval;
 481 
 482         MOD_INC_USE_COUNT;
 483         retval = do_load_aout_library(fd);
 484         MOD_DEC_USE_COUNT;
 485         return retval;
 486 }
 487 
 488 
 489 int init_aout_binfmt(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 490         return register_binfmt(&aout_format);
 491 }
 492 
 493 #ifdef MODULE
 494 int init_module(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 495         return init_aout_binfmt();
 496 }
 497 
 498 void cleanup_module( void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 499         unregister_binfmt(&aout_format);
 500 }
 501 #endif
 502 

/* [previous][next][first][last][top][bottom][index][help] */