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

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