root/fs/exec.c

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

DEFINITIONS

This source file includes following definitions.
  1. core_dump
  2. sys_uselib
  3. create_tables
  4. count
  5. copy_strings
  6. change_ldt
  7. read_omagic
  8. do_execve

   1 /*
   2  *  linux/fs/exec.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 /*
   8  * #!-checking implemented by tytso.
   9  */
  10 
  11 /*
  12  * Demand-loading implemented 01.12.91 - no need to read anything but
  13  * the header into memory. The inode of the executable is put into
  14  * "current->executable", and page faults do the actual loading. Clean.
  15  *
  16  * Once more I can proudly say that linux stood up to being changed: it
  17  * was less than 2 hours work to get demand-loading completely implemented.
  18  */
  19 
  20 #include <linux/fs.h>
  21 #include <linux/sched.h>
  22 #include <linux/kernel.h>
  23 #include <linux/mm.h>
  24 #include <linux/a.out.h>
  25 #include <linux/errno.h>
  26 #include <linux/signal.h>
  27 #include <linux/string.h>
  28 #include <linux/stat.h>
  29 #include <linux/fcntl.h>
  30 #include <linux/ptrace.h>
  31 #include <linux/user.h>
  32 
  33 #include <asm/segment.h>
  34 
  35 extern int sys_exit(int exit_code);
  36 extern int sys_close(int fd);
  37 
  38 /*
  39  * MAX_ARG_PAGES defines the number of pages allocated for arguments
  40  * and envelope for the new program. 32 should suffice, this gives
  41  * a maximum env+arg of 128kB !
  42  */
  43 #define MAX_ARG_PAGES 32
  44 
  45 /*
  46  * These are the only things you should do on a core-file: use only these
  47  * macros to write out all the necessary info.
  48  */
  49 #define DUMP_WRITE(addr,nr) \
  50 while (file.f_op->write(inode,&file,(char *)(addr),(nr)) != (nr)) goto close_coredump
  51 
  52 #define DUMP_SEEK(offset) \
  53 if (file.f_op->lseek) { \
  54         if (file.f_op->lseek(inode,&file,(offset),0) != (offset)) \
  55                 goto close_coredump; \
  56 } else file.f_pos = (offset)            
  57 
  58 /*
  59  * Routine writes a core dump image in the current directory.
  60  * Currently only a stub-function.
  61  *
  62  * Note that setuid/setgid files won't make a core-dump if the uid/gid
  63  * changed due to the set[u|g]id. It's enforced by the "current->dumpable"
  64  * field, which also makes sure the core-dumps won't be recursive if the
  65  * dumping of the process results in another error..
  66  */
  67 int core_dump(long signr, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
  68 {
  69         struct inode * inode = NULL;
  70         struct file file;
  71         unsigned short fs;
  72         int has_dumped = 0;
  73         register int dump_start, dump_size;
  74         struct user dump;
  75 
  76         if (!current->dumpable)
  77                 return 0;
  78         current->dumpable = 0;
  79 /* See if we have enough room to write the upage.  */
  80         if(current->rlim[RLIMIT_CORE].rlim_cur < PAGE_SIZE/1024) return 0;
  81         __asm__("mov %%fs,%0":"=r" (fs));
  82         __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
  83         if (open_namei("core",O_CREAT | O_WRONLY | O_TRUNC,0600,&inode))
  84                 goto end_coredump;
  85         if (!S_ISREG(inode->i_mode))
  86                 goto end_coredump;
  87         if (!inode->i_op || !inode->i_op->default_file_ops)
  88                 goto end_coredump;
  89         file.f_mode = 3;
  90         file.f_flags = 0;
  91         file.f_count = 1;
  92         file.f_inode = inode;
  93         file.f_pos = 0;
  94         file.f_reada = 0;
  95         file.f_op = inode->i_op->default_file_ops;
  96         if (file.f_op->open)
  97                 if (file.f_op->open(inode,&file))
  98                         goto end_coredump;
  99         if (!file.f_op->write)
 100                 goto close_coredump;
 101         has_dumped = 1;
 102 /* write and seek example: from kernel space */
 103         __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
 104         dump.magic = CMAGIC;
 105         dump.u_tsize = current->end_code / PAGE_SIZE;
 106         dump.u_dsize = (current->brk - current->end_code) / PAGE_SIZE;
 107         dump.u_ssize =((current->start_stack +(PAGE_SIZE-1)) / PAGE_SIZE) -
 108           (regs->esp/ PAGE_SIZE);
 109 /* If the size of the dump file exceeds the rlimit, then see what would happen
 110    if we wrote the stack, but not the data area.  */
 111         if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE/1024 >
 112             current->rlim[RLIMIT_CORE].rlim_cur)
 113                 dump.u_dsize = 0;
 114 /* Make sure we have enough room to write the stack and data areas. */
 115         if ((dump.u_ssize+1) * PAGE_SIZE / 1024 >
 116             current->rlim[RLIMIT_CORE].rlim_cur)
 117                 dump.u_ssize = 0;
 118         dump.u_comm = 0;
 119         dump.u_ar0 = (struct pt_regs *)(((int)(&dump.regs)) -((int)(&dump)));
 120         dump.signal = signr;
 121         dump.regs = *regs;
 122         dump.start_code = 0;
 123         dump.start_stack = regs->esp & ~(PAGE_SIZE - 1);
 124 /* Flag indicating the math stuff is valid. */
 125         if (dump.u_fpvalid = current->used_math) {
 126                 if (last_task_used_math == current)
 127                         __asm__("clts ; fnsave %0"::"m" (dump.i387));
 128                 else
 129                         memcpy(&dump.i387,&current->tss.i387,sizeof(dump.i387));
 130         };
 131         DUMP_WRITE(&dump,sizeof(dump));
 132         DUMP_SEEK(sizeof(dump));
 133  /* Dump the task struct.  Not be used by gdb, but could be useful */
 134         DUMP_WRITE(current,sizeof(*current));
 135 /* Now dump all of the user data.  Include malloced stuff as well */
 136         DUMP_SEEK(PAGE_SIZE);
 137 /* now we start writing out the user space info */
 138         __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x17));
 139 /* Dump the data area */
 140         if (dump.u_dsize != 0) {
 141                 dump_start = current->end_code;
 142                 dump_size = current->brk - current->end_code;
 143                 DUMP_WRITE(dump_start,dump_size);
 144         };
 145 /* Now prepare to dump the stack area */
 146         if (dump.u_ssize != 0) {
 147                 dump_start = regs->esp & ~(PAGE_SIZE - 1);
 148                 dump_size = dump.u_ssize * PAGE_SIZE;
 149                 DUMP_WRITE(dump_start,dump_size);
 150         };
 151 close_coredump:
 152         if (file.f_op->release)
 153                 file.f_op->release(inode,&file);
 154 end_coredump:
 155         __asm__("mov %0,%%fs"::"r" (fs));
 156         iput(inode);
 157         return has_dumped;
 158 }
 159 
 160 /*
 161  * Note that a shared library must be both readable and executable due to
 162  * security reasons.
 163  *
 164  * Also note that we take the address to load from from the file itself.
 165  */
 166 int sys_uselib(const char * library)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168 #define libnum  (current->numlibraries)
 169         struct inode * inode;
 170         struct buffer_head * bh;
 171         struct exec ex;
 172 
 173         if (get_limit(0x17) != TASK_SIZE)
 174                 return -EINVAL;
 175         if ((libnum >= MAX_SHARED_LIBS) || (libnum < 0))
 176                 return -EINVAL;
 177         if (library)
 178                 inode = namei(library);
 179         else
 180                 inode = NULL;
 181         if (!inode)
 182                 return -ENOENT;
 183         if (!inode->i_sb || !S_ISREG(inode->i_mode) || !permission(inode,MAY_READ)) {
 184                 iput(inode);
 185                 return -EACCES;
 186         }
 187         if (!(bh = bread(inode->i_dev,bmap(inode,0),inode->i_sb->s_blocksize))) {
 188                 iput(inode);
 189                 return -EACCES;
 190         }
 191         if (!IS_RDONLY(inode)) {
 192                 inode->i_atime = CURRENT_TIME;
 193                 inode->i_dirt = 1;
 194         }
 195         ex = *(struct exec *) bh->b_data;
 196         brelse(bh);
 197         if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
 198                 ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
 199                 inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
 200                 iput(inode);
 201                 return -ENOEXEC;
 202         }
 203         current->libraries[libnum].library = inode;
 204         current->libraries[libnum].start = ex.a_entry;
 205         current->libraries[libnum].length = (ex.a_data+ex.a_text+0xfff) & 0xfffff000;
 206 #if 0
 207         printk("Loaded library %d at %08x, length %08x\n",
 208                 libnum,
 209                 current->libraries[libnum].start,
 210                 current->libraries[libnum].length);
 211 #endif
 212         libnum++;
 213         return 0;
 214 #undef libnum
 215 }
 216 
 217 /*
 218  * create_tables() parses the env- and arg-strings in new user
 219  * memory and creates the pointer tables from them, and puts their
 220  * addresses on the "stack", returning the new stack pointer value.
 221  */
 222 static unsigned long * create_tables(char * p,int argc,int envc)
     /* [previous][next][first][last][top][bottom][index][help] */
 223 {
 224         unsigned long *argv,*envp;
 225         unsigned long * sp;
 226 
 227         sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
 228         sp -= envc+1;
 229         envp = sp;
 230         sp -= argc+1;
 231         argv = sp;
 232         put_fs_long((unsigned long)envp,--sp);
 233         put_fs_long((unsigned long)argv,--sp);
 234         put_fs_long((unsigned long)argc,--sp);
 235         while (argc-->0) {
 236                 put_fs_long((unsigned long) p,argv++);
 237                 while (get_fs_byte(p++)) /* nothing */ ;
 238         }
 239         put_fs_long(0,argv);
 240         while (envc-->0) {
 241                 put_fs_long((unsigned long) p,envp++);
 242                 while (get_fs_byte(p++)) /* nothing */ ;
 243         }
 244         put_fs_long(0,envp);
 245         return sp;
 246 }
 247 
 248 /*
 249  * count() counts the number of arguments/envelopes
 250  */
 251 static int count(char ** argv)
     /* [previous][next][first][last][top][bottom][index][help] */
 252 {
 253         int i=0;
 254         char ** tmp;
 255 
 256         if (tmp = argv)
 257                 while (get_fs_long((unsigned long *) (tmp++)))
 258                         i++;
 259 
 260         return i;
 261 }
 262 
 263 /*
 264  * 'copy_string()' copies argument/envelope strings from user
 265  * memory to free pages in kernel mem. These are in a format ready
 266  * to be put directly into the top of new user memory.
 267  *
 268  * Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies
 269  * whether the string and the string array are from user or kernel segments:
 270  * 
 271  * from_kmem     argv *        argv **
 272  *    0          user space    user space
 273  *    1          kernel space  user space
 274  *    2          kernel space  kernel space
 275  * 
 276  * We do this by playing games with the fs segment register.  Since it
 277  * it is expensive to load a segment register, we try to avoid calling
 278  * set_fs() unless we absolutely have to.
 279  */
 280 static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
     /* [previous][next][first][last][top][bottom][index][help] */
 281                 unsigned long p, int from_kmem)
 282 {
 283         char *tmp, *pag = NULL;
 284         int len, offset = 0;
 285         unsigned long old_fs, new_fs;
 286 
 287         if (!p)
 288                 return 0;       /* bullet-proofing */
 289         new_fs = get_ds();
 290         old_fs = get_fs();
 291         if (from_kmem==2)
 292                 set_fs(new_fs);
 293         while (argc-- > 0) {
 294                 if (from_kmem == 1)
 295                         set_fs(new_fs);
 296                 if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc)))
 297                         panic("argc is wrong");
 298                 if (from_kmem == 1)
 299                         set_fs(old_fs);
 300                 len=0;          /* remember zero-padding */
 301                 do {
 302                         len++;
 303                 } while (get_fs_byte(tmp++));
 304                 if (p < len) {  /* this shouldn't happen - 128kB */
 305                         set_fs(old_fs);
 306                         return 0;
 307                 }
 308                 while (len) {
 309                         --p; --tmp; --len;
 310                         if (--offset < 0) {
 311                                 offset = p % PAGE_SIZE;
 312                                 if (from_kmem==2)
 313                                         set_fs(old_fs);
 314                                 if (!(pag = (char *) page[p/PAGE_SIZE]) &&
 315                                     !(pag = (char *) page[p/PAGE_SIZE] =
 316                                       (unsigned long *) get_free_page(GFP_USER))) 
 317                                         return 0;
 318                                 if (from_kmem==2)
 319                                         set_fs(new_fs);
 320 
 321                         }
 322                         *(pag + offset) = get_fs_byte(tmp);
 323                 }
 324         }
 325         if (from_kmem==2)
 326                 set_fs(old_fs);
 327         return p;
 328 }
 329 
 330 static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
     /* [previous][next][first][last][top][bottom][index][help] */
 331 {
 332         unsigned long code_limit,data_limit,code_base,data_base;
 333         int i;
 334 
 335         code_limit = TASK_SIZE;
 336         data_limit = TASK_SIZE;
 337         code_base = get_base(current->ldt[1]);
 338         data_base = code_base;
 339         set_base(current->ldt[1],code_base);
 340         set_limit(current->ldt[1],code_limit);
 341         set_base(current->ldt[2],data_base);
 342         set_limit(current->ldt[2],data_limit);
 343 /* make sure fs points to the NEW data segment */
 344         __asm__("pushl $0x17\n\tpop %%fs"::);
 345         data_base += data_limit - LIBRARY_SIZE;
 346         for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
 347                 data_base -= PAGE_SIZE;
 348                 if (page[i])
 349                         put_dirty_page(page[i],data_base);
 350         }
 351         return data_limit;
 352 }
 353 
 354 static void read_omagic(struct inode *inode, int bytes)
     /* [previous][next][first][last][top][bottom][index][help] */
 355 {
 356         struct buffer_head *bh;
 357         int n, blkno, blk = 0;
 358         char *dest = (char *) 0;
 359         unsigned int block_size;
 360 
 361         block_size = 1024;
 362         if (inode->i_sb)
 363                 block_size = inode->i_sb->s_blocksize;
 364         while (bytes > 0) {
 365                 if (!(blkno = bmap(inode, blk)))
 366                         sys_exit(-1);
 367                 if (!(bh = bread(inode->i_dev, blkno, block_size)))
 368                         sys_exit(-1);
 369                 n = (blk ? block_size : block_size - sizeof(struct exec));
 370                 if (bytes < n)
 371                         n = bytes;
 372 
 373                 memcpy_tofs(dest, (blk ? bh->b_data :
 374                                 bh->b_data + sizeof(struct exec)), n);
 375                 brelse(bh);
 376                 ++blk;
 377                 dest += n;
 378                 bytes -= n;
 379         }
 380         iput(inode);
 381         current->executable = NULL;
 382 }
 383 
 384 /*
 385  * 'do_execve()' executes a new program.
 386  *
 387  * NOTE! We leave 4MB free at the top of the data-area for a loadable
 388  * library.
 389  */
 390 int do_execve(unsigned long * eip,long tmp,char * filename,
     /* [previous][next][first][last][top][bottom][index][help] */
 391         char ** argv, char ** envp)
 392 {
 393         struct inode * inode;
 394         struct buffer_head * bh;
 395         struct exec ex;
 396         unsigned long page[MAX_ARG_PAGES];
 397         int i,argc,envc;
 398         int e_uid, e_gid;
 399         int retval;
 400         int sh_bang = 0;
 401         unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
 402         int ch;
 403 
 404         if ((0xffff & eip[1]) != 0x000f)
 405                 panic("execve called from supervisor mode");
 406         for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */
 407                 page[i]=0;
 408         if (!(inode=namei(filename)))           /* get executables inode */
 409                 return -ENOENT;
 410         argc = count(argv);
 411         envc = count(envp);
 412         
 413 restart_interp:
 414         if (!S_ISREG(inode->i_mode)) {  /* must be regular file */
 415                 retval = -EACCES;
 416                 goto exec_error2;
 417         }
 418         if (IS_NOEXEC(inode)) { /* FS mustn't be mounted noexec */
 419                 retval = -EPERM;
 420                 goto exec_error2;
 421         }
 422         if (!inode->i_sb) {
 423                 retval = -EACCES;
 424                 goto exec_error2;
 425         }
 426         i = inode->i_mode;
 427         if (IS_NOSUID(inode) && (((i & S_ISUID) && inode->i_uid != current->
 428             euid) || ((i & S_ISGID) && inode->i_gid != current->egid)) &&
 429             !suser()) {
 430                 retval = -EPERM;
 431                 goto exec_error2;
 432         }
 433         /* make sure we don't let suid, sgid files be ptraced. */
 434         if (current->flags & PF_PTRACED) {
 435                 e_uid = current->euid;
 436                 e_gid = current->egid;
 437         } else {
 438                 e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;
 439                 e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;
 440         }
 441         if (current->euid == inode->i_uid)
 442                 i >>= 6;
 443         else if (in_group_p(inode->i_gid))
 444                 i >>= 3;
 445         if (!(i & 1) &&
 446             !((inode->i_mode & 0111) && suser())) {
 447                 retval = -EACCES;
 448                 goto exec_error2;
 449         }
 450         if (!(bh = bread(inode->i_dev,bmap(inode,0),inode->i_sb->s_blocksize))) {
 451                 retval = -EACCES;
 452                 goto exec_error2;
 453         }
 454         if (!IS_RDONLY(inode)) {
 455                 inode->i_atime = CURRENT_TIME;
 456                 inode->i_dirt = 1;
 457         }
 458         ex = *((struct exec *) bh->b_data);     /* read exec-header */
 459         if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) {
 460                 /*
 461                  * This section does the #! interpretation.
 462                  * Sorta complicated, but hopefully it will work.  -TYT
 463                  */
 464 
 465                 char buf[128], *cp, *interp, *i_name, *i_arg;
 466                 unsigned long old_fs;
 467 
 468                 strncpy(buf, bh->b_data+2, 127);
 469                 brelse(bh);
 470                 iput(inode);
 471                 buf[127] = '\0';
 472                 if (cp = strchr(buf, '\n')) {
 473                         *cp = '\0';
 474                         for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);
 475                 }
 476                 if (!cp || *cp == '\0') {
 477                         retval = -ENOEXEC; /* No interpreter name found */
 478                         goto exec_error1;
 479                 }
 480                 interp = i_name = cp;
 481                 i_arg = 0;
 482                 for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
 483                         if (*cp == '/')
 484                                 i_name = cp+1;
 485                 }
 486                 if (*cp) {
 487                         *cp++ = '\0';
 488                         i_arg = cp;
 489                 }
 490                 /*
 491                  * OK, we've parsed out the interpreter name and
 492                  * (optional) argument.
 493                  */
 494                 if (sh_bang++ == 0) {
 495                         p = copy_strings(envc, envp, page, p, 0);
 496                         p = copy_strings(--argc, argv+1, page, p, 0);
 497                 }
 498                 /*
 499                  * Splice in (1) the interpreter's name for argv[0]
 500                  *           (2) (optional) argument to interpreter
 501                  *           (3) filename of shell script
 502                  *
 503                  * This is done in reverse order, because of how the
 504                  * user environment and arguments are stored.
 505                  */
 506                 p = copy_strings(1, &filename, page, p, 1);
 507                 argc++;
 508                 if (i_arg) {
 509                         p = copy_strings(1, &i_arg, page, p, 2);
 510                         argc++;
 511                 }
 512                 p = copy_strings(1, &i_name, page, p, 2);
 513                 argc++;
 514                 if (!p) {
 515                         retval = -ENOMEM;
 516                         goto exec_error1;
 517                 }
 518                 /*
 519                  * OK, now restart the process with the interpreter's inode.
 520                  */
 521                 old_fs = get_fs();
 522                 set_fs(get_ds());
 523                 if (!(inode=namei(interp))) { /* get executables inode */
 524                         set_fs(old_fs);
 525                         retval = -ENOENT;
 526                         goto exec_error1;
 527                 }
 528                 set_fs(old_fs);
 529                 goto restart_interp;
 530         }
 531         brelse(bh);
 532         if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC) ||
 533                 ex.a_trsize || ex.a_drsize ||
 534                 ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
 535                 inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
 536                 retval = -ENOEXEC;
 537                 goto exec_error2;
 538         }
 539         if (N_TXTOFF(ex) != BLOCK_SIZE && N_MAGIC(ex) != OMAGIC) {
 540                 printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
 541                 retval = -ENOEXEC;
 542                 goto exec_error2;
 543         }
 544         if (!sh_bang) {
 545                 p = copy_strings(envc,envp,page,p,0);
 546                 p = copy_strings(argc,argv,page,p,0);
 547                 if (!p) {
 548                         retval = -ENOMEM;
 549                         goto exec_error2;
 550                 }
 551         }
 552 /* OK, This is the point of no return */
 553         current->dumpable = 1;
 554         for (i=0; (ch = get_fs_byte(filename++)) != '\0';)
 555                 if (ch == '/')
 556                         i = 0;
 557                 else
 558                         if (i < 8)
 559                                 current->comm[i++] = ch;
 560         if (i < 8)
 561                 current->comm[i] = '\0';
 562         if (current->executable)
 563                 iput(current->executable);
 564         i = current->numlibraries;
 565         while (i-- > 0) {
 566                 iput(current->libraries[i].library);
 567                 current->libraries[i].library = NULL;
 568         }
 569         if (e_uid != current->euid || e_gid != current->egid ||
 570             !permission(inode,MAY_READ))
 571                 current->dumpable = 0;
 572         current->numlibraries = 0;
 573         current->executable = inode;
 574         current->signal = 0;
 575         for (i=0 ; i<32 ; i++) {
 576                 current->sigaction[i].sa_mask = 0;
 577                 current->sigaction[i].sa_flags = 0;
 578                 if (current->sigaction[i].sa_handler != SIG_IGN)
 579                         current->sigaction[i].sa_handler = NULL;
 580         }
 581         for (i=0 ; i<NR_OPEN ; i++)
 582                 if ((current->close_on_exec>>i)&1)
 583                         sys_close(i);
 584         current->close_on_exec = 0;
 585         free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
 586         free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
 587         if (last_task_used_math == current)
 588                 last_task_used_math = NULL;
 589         current->used_math = 0;
 590         p += change_ldt(ex.a_text,page);
 591         p -= LIBRARY_SIZE + MAX_ARG_PAGES*PAGE_SIZE;
 592         p = (unsigned long) create_tables((char *)p,argc,envc);
 593         current->brk = ex.a_bss +
 594                 (current->end_data = ex.a_data +
 595                 (current->end_code = ex.a_text));
 596         current->start_stack = p;
 597         current->rss = (LIBRARY_OFFSET - p + PAGE_SIZE-1) / PAGE_SIZE;
 598         current->suid = current->euid = e_uid;
 599         current->sgid = current->egid = e_gid;
 600         if (N_MAGIC(ex) == OMAGIC)
 601                 read_omagic(inode, ex.a_text+ex.a_data);
 602         eip[0] = ex.a_entry;            /* eip, magic happens :-) */
 603         eip[3] = p;                     /* stack pointer */
 604         if (current->flags & PF_PTRACED)
 605                 send_sig(SIGTRAP, current, 0);
 606         return 0;
 607 exec_error2:
 608         iput(inode);
 609 exec_error1:
 610         for (i=0 ; i<MAX_ARG_PAGES ; i++)
 611                 free_page(page[i]);
 612         return(retval);
 613 }

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