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         current->flags |= PF_DUMPCORE;
 133         strncpy(dump.u_comm, current->comm, sizeof(current->comm));
 134         dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
 135         dump.signal = signr;
 136         dump_thread(regs, &dump);
 137 
 138 /* If the size of the dump file exceeds the rlimit, then see what would happen
 139    if we wrote the stack, but not the data area.  */
 140         if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
 141             current->rlim[RLIMIT_CORE].rlim_cur)
 142                 dump.u_dsize = 0;
 143 
 144 /* Make sure we have enough room to write the stack and data areas. */
 145         if ((dump.u_ssize+1) * PAGE_SIZE >
 146             current->rlim[RLIMIT_CORE].rlim_cur)
 147                 dump.u_ssize = 0;
 148 
 149 /* make sure we actually have a data and stack area to dump */
 150         set_fs(USER_DS);
 151         if (verify_area(VERIFY_READ, (void *) START_DATA(dump), dump.u_dsize << PAGE_SHIFT))
 152                 dump.u_dsize = 0;
 153         if (verify_area(VERIFY_READ, (void *) dump.start_stack, dump.u_ssize << PAGE_SHIFT))
 154                 dump.u_ssize = 0;
 155 
 156         set_fs(KERNEL_DS);
 157 /* struct user */
 158         DUMP_WRITE(&dump,sizeof(dump));
 159 /* Now dump all of the user data.  Include malloced stuff as well */
 160         DUMP_SEEK(PAGE_SIZE);
 161 /* now we start writing out the user space info */
 162         set_fs(USER_DS);
 163 /* Dump the data area */
 164         if (dump.u_dsize != 0) {
 165                 dump_start = START_DATA(dump);
 166                 dump_size = dump.u_dsize << PAGE_SHIFT;
 167                 DUMP_WRITE(dump_start,dump_size);
 168         }
 169 /* Now prepare to dump the stack area */
 170         if (dump.u_ssize != 0) {
 171                 dump_start = dump.start_stack;
 172                 dump_size = dump.u_ssize << PAGE_SHIFT;
 173                 DUMP_WRITE(dump_start,dump_size);
 174         }
 175 /* Finally dump the task struct.  Not be used by gdb, but could be useful */
 176         set_fs(KERNEL_DS);
 177         DUMP_WRITE(current,sizeof(*current));
 178 close_coredump:
 179         if (file.f_op->release)
 180                 file.f_op->release(inode,&file);
 181 done_coredump:
 182         put_write_access(inode);
 183 end_coredump:
 184         set_fs(fs);
 185         iput(inode);
 186         return has_dumped;
 187 }
 188 
 189 static int
 190 aout_core_dump(long signr, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192         int retval;
 193 
 194         MOD_INC_USE_COUNT;
 195         retval = do_aout_core_dump(signr, regs);
 196         MOD_DEC_USE_COUNT;
 197         return retval;
 198 }
 199 
 200 /*
 201  * create_aout_tables() parses the env- and arg-strings in new user
 202  * memory and creates the pointer tables from them, and puts their
 203  * addresses on the "stack", returning the new stack pointer value.
 204  */
 205 static unsigned long * create_aout_tables(char * p, struct linux_binprm * bprm)
     /* [previous][next][first][last][top][bottom][index][help] */
 206 {
 207         unsigned long *argv,*envp;
 208         unsigned long * sp;
 209         int argc = bprm->argc;
 210         int envc = bprm->envc;
 211 
 212         sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
 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 = sp;
 228         sp -= argc+1;
 229         argv = sp;
 230 #ifdef __i386__
 231         put_user(envp,--sp);
 232         put_user(argv,--sp);
 233 #endif
 234         put_user(argc,--sp);
 235         current->mm->arg_start = (unsigned long) p;
 236         while (argc-->0) {
 237                 put_user(p,argv++);
 238                 while (get_user(p++)) /* nothing */ ;
 239         }
 240         put_user(NULL,argv);
 241         current->mm->arg_end = current->mm->env_start = (unsigned long) p;
 242         while (envc-->0) {
 243                 put_user(p,envp++);
 244                 while (get_user(p++)) /* nothing */ ;
 245         }
 246         put_user(NULL,envp);
 247         current->mm->env_end = (unsigned long) p;
 248         return sp;
 249 }
 250 
 251 /*
 252  * These are the functions used to load a.out style executables and shared
 253  * libraries.  There is no binary dependent code anywhere else.
 254  */
 255 
 256 static inline int
 257 do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 258 {
 259         struct exec ex;
 260         struct file * file;
 261         int fd;
 262         unsigned long error;
 263         unsigned long p = bprm->p;
 264         unsigned long fd_offset;
 265         unsigned long rlim;
 266 
 267         ex = *((struct exec *) bprm->buf);              /* exec-header */
 268         if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && 
 269              N_MAGIC(ex) != QMAGIC) ||
 270             N_TRSIZE(ex) || N_DRSIZE(ex) ||
 271             bprm->inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
 272                 return -ENOEXEC;
 273         }
 274 
 275         current->personality = PER_LINUX;
 276         fd_offset = N_TXTOFF(ex);
 277 
 278 #ifdef __i386__
 279         if (N_MAGIC(ex) == ZMAGIC && fd_offset != BLOCK_SIZE) {
 280                 printk(KERN_NOTICE "N_TXTOFF != BLOCK_SIZE. See a.out.h.\n");
 281                 return -ENOEXEC;
 282         }
 283 
 284         if (N_MAGIC(ex) == ZMAGIC && ex.a_text &&
 285             (fd_offset < bprm->inode->i_sb->s_blocksize)) {
 286                 printk(KERN_NOTICE "N_TXTOFF < BLOCK_SIZE. Please convert binary.\n");
 287                 return -ENOEXEC;
 288         }
 289 #endif
 290 
 291         /* Check initial limits. This avoids letting people circumvent
 292          * size limits imposed on them by creating programs with large
 293          * arrays in the data or bss.
 294          */
 295         rlim = current->rlim[RLIMIT_DATA].rlim_cur;
 296         if (rlim >= RLIM_INFINITY)
 297                 rlim = ~0;
 298         if (ex.a_data + ex.a_bss > rlim)
 299                 return -ENOMEM;
 300 
 301         /* OK, This is the point of no return */
 302         flush_old_exec(bprm);
 303 
 304         current->mm->end_code = ex.a_text +
 305                 (current->mm->start_code = N_TXTADDR(ex));
 306         current->mm->end_data = ex.a_data +
 307                 (current->mm->start_data = N_DATADDR(ex));
 308         current->mm->brk = ex.a_bss +
 309                 (current->mm->start_brk = N_BSSADDR(ex));
 310 
 311         current->mm->rss = 0;
 312         current->mm->mmap = NULL;
 313         current->suid = current->euid = current->fsuid = bprm->e_uid;
 314         current->sgid = current->egid = current->fsgid = bprm->e_gid;
 315         current->flags &= ~PF_FORKNOEXEC;
 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->mm->start_stack = p;
 388 #ifdef __alpha__
 389         regs->gp = ex.a_gpvalue;
 390 #endif
 391         start_thread(regs, ex.a_entry, p);
 392         if (current->flags & PF_PTRACED)
 393                 send_sig(SIGTRAP, current, 0);
 394         return 0;
 395 }
 396 
 397 static int
 398 load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 399 {
 400         int retval;
 401 
 402         MOD_INC_USE_COUNT;
 403         retval = do_load_aout_binary(bprm, regs);
 404         MOD_DEC_USE_COUNT;
 405         return retval;
 406 }
 407 
 408 static inline int
 409 do_load_aout_library(int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 410 {
 411         struct file * file;
 412         struct exec ex;
 413         struct  inode * inode;
 414         unsigned int len;
 415         unsigned int bss;
 416         unsigned int start_addr;
 417         unsigned long error;
 418         
 419         file = current->files->fd[fd];
 420         inode = file->f_inode;
 421         
 422         if (!file || !file->f_op)
 423                 return -EACCES;
 424 
 425         /* Seek into the file */
 426         if (file->f_op->lseek) {
 427                 if ((error = file->f_op->lseek(inode, file, 0, 0)) != 0)
 428                         return -ENOEXEC;
 429         } else
 430                 file->f_pos = 0;
 431 
 432         set_fs(KERNEL_DS);
 433         error = file->f_op->read(inode, file, (char *) &ex, sizeof(ex));
 434         set_fs(USER_DS);
 435         if (error != sizeof(ex))
 436                 return -ENOEXEC;
 437 
 438         /* We come in here for the regular a.out style of shared libraries */
 439         if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||
 440             N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
 441             inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {
 442                 return -ENOEXEC;
 443         }
 444         if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) && 
 445             (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) {
 446                 printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n");
 447                 return -ENOEXEC;
 448         }
 449         
 450         if (N_FLAGS(ex)) return -ENOEXEC;
 451 
 452         /* For  QMAGIC, the starting address is 0x20 into the page.  We mask
 453            this off to get the starting address for the page */
 454 
 455         start_addr =  ex.a_entry & 0xfffff000;
 456 
 457         /* Now use mmap to map the library into memory. */
 458         error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
 459                         PROT_READ | PROT_WRITE | PROT_EXEC,
 460                         MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
 461                         N_TXTOFF(ex));
 462         if (error != start_addr)
 463                 return error;
 464         len = PAGE_ALIGN(ex.a_text + ex.a_data);
 465         bss = ex.a_text + ex.a_data + ex.a_bss;
 466         if (bss > len) {
 467                 error = do_mmap(NULL, start_addr + len, bss-len,
 468                                 PROT_READ|PROT_WRITE|PROT_EXEC,
 469                                 MAP_PRIVATE|MAP_FIXED, 0);
 470                 if (error != start_addr + len)
 471                         return error;
 472         }
 473         return 0;
 474 }
 475 
 476 static int
 477 load_aout_library(int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 478 {
 479         int retval;
 480 
 481         MOD_INC_USE_COUNT;
 482         retval = do_load_aout_library(fd);
 483         MOD_DEC_USE_COUNT;
 484         return retval;
 485 }
 486 
 487 
 488 int init_aout_binfmt(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 489         return register_binfmt(&aout_format);
 490 }
 491 
 492 #ifdef MODULE
 493 int init_module(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 494         return init_aout_binfmt();
 495 }
 496 
 497 void cleanup_module( void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 498         unregister_binfmt(&aout_format);
 499 }
 500 #endif
 501 

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