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