|
|
1.1.1.2 root 1: /*
2: * linux/fs/exec.c
3: *
4: * (C) 1991 Linus Torvalds
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 <errno.h>
1.1.1.2 root 21: #include <string.h>
1.1 root 22: #include <sys/stat.h>
23: #include <a.out.h>
24:
25: #include <linux/fs.h>
26: #include <linux/sched.h>
27: #include <linux/kernel.h>
28: #include <linux/mm.h>
29: #include <asm/segment.h>
30:
31: extern int sys_exit(int exit_code);
32: extern int sys_close(int fd);
33:
34: /*
35: * MAX_ARG_PAGES defines the number of pages allocated for arguments
36: * and envelope for the new program. 32 should suffice, this gives
37: * a maximum env+arg of 128kB !
38: */
39: #define MAX_ARG_PAGES 32
40:
41: /*
42: * create_tables() parses the env- and arg-strings in new user
43: * memory and creates the pointer tables from them, and puts their
44: * addresses on the "stack", returning the new stack pointer value.
45: */
46: static unsigned long * create_tables(char * p,int argc,int envc)
47: {
48: unsigned long *argv,*envp;
49: unsigned long * sp;
50:
51: sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
52: sp -= envc+1;
53: envp = sp;
54: sp -= argc+1;
55: argv = sp;
56: put_fs_long((unsigned long)envp,--sp);
57: put_fs_long((unsigned long)argv,--sp);
58: put_fs_long((unsigned long)argc,--sp);
59: while (argc-->0) {
60: put_fs_long((unsigned long) p,argv++);
61: while (get_fs_byte(p++)) /* nothing */ ;
62: }
63: put_fs_long(0,argv);
64: while (envc-->0) {
65: put_fs_long((unsigned long) p,envp++);
66: while (get_fs_byte(p++)) /* nothing */ ;
67: }
68: put_fs_long(0,envp);
69: return sp;
70: }
71:
72: /*
73: * count() counts the number of arguments/envelopes
74: */
75: static int count(char ** argv)
76: {
77: int i=0;
78: char ** tmp;
79:
80: if (tmp = argv)
81: while (get_fs_long((unsigned long *) (tmp++)))
82: i++;
83:
84: return i;
85: }
86:
87: /*
88: * 'copy_string()' copies argument/envelope strings from user
89: * memory to free pages in kernel mem. These are in a format ready
90: * to be put directly into the top of new user memory.
1.1.1.2 root 91: *
92: * Modified by TYT, 11/24/91 to add the from_kmem argument, which specifies
93: * whether the string and the string array are from user or kernel segments:
94: *
95: * from_kmem argv * argv **
96: * 0 user space user space
97: * 1 kernel space user space
98: * 2 kernel space kernel space
99: *
100: * We do this by playing games with the fs segment register. Since it
101: * it is expensive to load a segment register, we try to avoid calling
102: * set_fs() unless we absolutely have to.
1.1 root 103: */
104: static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
1.1.1.2 root 105: unsigned long p, int from_kmem)
1.1 root 106: {
1.1.1.2 root 107: char *tmp, *pag;
108: int len, offset = 0;
109: unsigned long old_fs, new_fs;
110:
111: if (!p)
112: return 0; /* bullet-proofing */
113: new_fs = get_ds();
114: old_fs = get_fs();
115: if (from_kmem==2)
116: set_fs(new_fs);
1.1 root 117: while (argc-- > 0) {
1.1.1.2 root 118: if (from_kmem == 1)
119: set_fs(new_fs);
120: if (!(tmp = (char *)get_fs_long(((unsigned long *)argv)+argc)))
1.1 root 121: panic("argc is wrong");
1.1.1.2 root 122: if (from_kmem == 1)
123: set_fs(old_fs);
1.1 root 124: len=0; /* remember zero-padding */
125: do {
126: len++;
127: } while (get_fs_byte(tmp++));
1.1.1.2 root 128: if (p-len < 0) { /* this shouldn't happen - 128kB */
129: set_fs(old_fs);
1.1 root 130: return 0;
131: }
1.1.1.2 root 132: while (len) {
133: --p; --tmp; --len;
134: if (--offset < 0) {
135: offset = p % PAGE_SIZE;
136: if (from_kmem==2)
137: set_fs(old_fs);
138: if (!(pag = (char *) page[p/PAGE_SIZE]) &&
139: !(pag = (char *) page[p/PAGE_SIZE] =
140: (unsigned long *) get_free_page()))
141: return 0;
142: if (from_kmem==2)
143: set_fs(new_fs);
144:
145: }
146: *(pag + offset) = get_fs_byte(tmp);
147: }
1.1 root 148: }
1.1.1.2 root 149: if (from_kmem==2)
150: set_fs(old_fs);
1.1 root 151: return p;
152: }
153:
154: static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
155: {
156: unsigned long code_limit,data_limit,code_base,data_base;
157: int i;
158:
159: code_limit = text_size+PAGE_SIZE -1;
160: code_limit &= 0xFFFFF000;
161: data_limit = 0x4000000;
162: code_base = get_base(current->ldt[1]);
163: data_base = code_base;
164: set_base(current->ldt[1],code_base);
165: set_limit(current->ldt[1],code_limit);
166: set_base(current->ldt[2],data_base);
167: set_limit(current->ldt[2],data_limit);
168: /* make sure fs points to the NEW data segment */
169: __asm__("pushl $0x17\n\tpop %%fs"::);
170: data_base += data_limit;
171: for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
172: data_base -= PAGE_SIZE;
173: if (page[i])
174: put_page(page[i],data_base);
175: }
176: return data_limit;
177: }
178:
179: /*
180: * 'do_execve()' executes a new program.
181: */
182: int do_execve(unsigned long * eip,long tmp,char * filename,
183: char ** argv, char ** envp)
184: {
185: struct m_inode * inode;
186: struct buffer_head * bh;
187: struct exec ex;
188: unsigned long page[MAX_ARG_PAGES];
189: int i,argc,envc;
1.1.1.2 root 190: int e_uid, e_gid;
191: int retval;
192: int sh_bang = 0;
193: unsigned long p=PAGE_SIZE*MAX_ARG_PAGES-4;
1.1 root 194:
195: if ((0xffff & eip[1]) != 0x000f)
196: panic("execve called from supervisor mode");
197: for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
198: page[i]=0;
199: if (!(inode=namei(filename))) /* get executables inode */
200: return -ENOENT;
1.1.1.2 root 201: argc = count(argv);
202: envc = count(envp);
203:
204: restart_interp:
1.1 root 205: if (!S_ISREG(inode->i_mode)) { /* must be regular file */
1.1.1.2 root 206: retval = -EACCES;
207: goto exec_error2;
1.1 root 208: }
209: i = inode->i_mode;
1.1.1.2 root 210: e_uid = (i & S_ISUID) ? inode->i_uid : current->euid;
211: e_gid = (i & S_ISGID) ? inode->i_gid : current->egid;
212: if (current->euid == inode->i_uid)
213: i >>= 6;
214: else if (current->egid == inode->i_gid)
215: i >>= 3;
216: if (!(i & 1) &&
217: !((inode->i_mode & 0111) && suser())) {
218: retval = -ENOEXEC;
219: goto exec_error2;
1.1 root 220: }
221: if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {
1.1.1.2 root 222: retval = -EACCES;
223: goto exec_error2;
1.1 root 224: }
225: ex = *((struct exec *) bh->b_data); /* read exec-header */
1.1.1.2 root 226: if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (!sh_bang)) {
227: /*
228: * This section does the #! interpretation.
229: * Sorta complicated, but hopefully it will work. -TYT
230: */
231:
1.1.1.3 ! root 232: char buf[1023], *cp, *interp, *i_name, *i_arg;
1.1.1.2 root 233: unsigned long old_fs;
234:
235: strncpy(buf, bh->b_data+2, 1022);
236: brelse(bh);
237: iput(inode);
238: buf[1022] = '\0';
239: if (cp = strchr(buf, '\n')) {
240: *cp = '\0';
241: for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++);
242: }
243: if (!cp || *cp == '\0') {
244: retval = -ENOEXEC; /* No interpreter name found */
245: goto exec_error1;
246: }
247: interp = i_name = cp;
248: i_arg = 0;
249: for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
250: if (*cp == '/')
251: i_name = cp+1;
252: }
253: if (*cp) {
254: *cp++ = '\0';
255: i_arg = cp;
256: }
257: /*
258: * OK, we've parsed out the interpreter name and
259: * (optional) argument.
260: */
261: if (sh_bang++ == 0) {
262: p = copy_strings(envc, envp, page, p, 0);
263: p = copy_strings(--argc, argv+1, page, p, 0);
264: }
265: /*
266: * Splice in (1) the interpreter's name for argv[0]
267: * (2) (optional) argument to interpreter
268: * (3) filename of shell script
269: *
270: * This is done in reverse order, because of how the
271: * user environment and arguments are stored.
272: */
273: p = copy_strings(1, &filename, page, p, 1);
274: argc++;
275: if (i_arg) {
276: p = copy_strings(1, &i_arg, page, p, 2);
277: argc++;
278: }
279: p = copy_strings(1, &i_name, page, p, 2);
280: argc++;
281: if (!p) {
282: retval = -ENOMEM;
283: goto exec_error1;
284: }
285: /*
286: * OK, now restart the process with the interpreter's inode.
287: */
288: old_fs = get_fs();
289: set_fs(get_ds());
290: if (!(inode=namei(interp))) { /* get executables inode */
291: set_fs(old_fs);
292: retval = -ENOENT;
293: goto exec_error1;
294: }
295: set_fs(old_fs);
296: goto restart_interp;
297: }
1.1 root 298: brelse(bh);
299: if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
300: ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
301: inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
1.1.1.2 root 302: retval = -ENOEXEC;
303: goto exec_error2;
1.1 root 304: }
1.1.1.2 root 305: if (N_TXTOFF(ex) != BLOCK_SIZE) {
306: printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
307: retval = -ENOEXEC;
308: goto exec_error2;
309: }
310: if (!sh_bang) {
311: p = copy_strings(envc,envp,page,p,0);
312: p = copy_strings(argc,argv,page,p,0);
313: if (!p) {
314: retval = -ENOMEM;
315: goto exec_error2;
316: }
1.1 root 317: }
318: /* OK, This is the point of no return */
1.1.1.3 ! root 319: if (current->executable)
! 320: iput(current->executable);
! 321: current->executable = inode;
1.1 root 322: for (i=0 ; i<32 ; i++)
1.1.1.2 root 323: current->sigaction[i].sa_handler = NULL;
1.1 root 324: for (i=0 ; i<NR_OPEN ; i++)
325: if ((current->close_on_exec>>i)&1)
326: sys_close(i);
327: current->close_on_exec = 0;
328: free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
329: free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
330: if (last_task_used_math == current)
331: last_task_used_math = NULL;
332: current->used_math = 0;
333: p += change_ldt(ex.a_text,page)-MAX_ARG_PAGES*PAGE_SIZE;
334: p = (unsigned long) create_tables((char *)p,argc,envc);
335: current->brk = ex.a_bss +
336: (current->end_data = ex.a_data +
337: (current->end_code = ex.a_text));
338: current->start_stack = p & 0xfffff000;
1.1.1.2 root 339: current->euid = e_uid;
340: current->egid = e_gid;
1.1 root 341: i = ex.a_text+ex.a_data;
342: while (i&0xfff)
343: put_fs_byte(0,(char *) (i++));
344: eip[0] = ex.a_entry; /* eip, magic happens :-) */
345: eip[3] = p; /* stack pointer */
346: return 0;
1.1.1.2 root 347: exec_error2:
348: iput(inode);
349: exec_error1:
350: for (i=0 ; i<MAX_ARG_PAGES ; i++)
351: free_page(page[i]);
352: return(retval);
1.1 root 353: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.