|
|
1.1 root 1: #include <errno.h>
2: #include <sys/stat.h>
3: #include <a.out.h>
4:
5: #include <linux/fs.h>
6: #include <linux/sched.h>
7: #include <linux/kernel.h>
8: #include <linux/mm.h>
9: #include <asm/segment.h>
10:
11: extern int sys_exit(int exit_code);
12: extern int sys_close(int fd);
13:
14: /*
15: * MAX_ARG_PAGES defines the number of pages allocated for arguments
16: * and envelope for the new program. 32 should suffice, this gives
17: * a maximum env+arg of 128kB !
18: */
19: #define MAX_ARG_PAGES 32
20:
1.1.1.3 ! root 21: inline void cp_block(const void * from,void * to)
! 22: {
! 23: int d0,d1,d2;
! 24: __asm__ __volatile("pushl $0x10\n\t"
! 25: "pushl $0x17\n\t"
! 26: "pop %%es\n\t"
! 27: "cld\n\t"
! 28: "rep\n\t"
! 29: "movsl\n\t"
! 30: "pop %%es"
! 31: :"=&c" (d0), "=&S" (d1), "=&D" (d2)
! 32: :"0" (BLOCK_SIZE/4),"1" (from),"2" (to)
! 33: :"memory");
! 34: }
1.1 root 35:
36: /*
37: * read_head() reads blocks 1-6 (not 0). Block 0 has already been
38: * read for header information.
39: */
40: int read_head(struct m_inode * inode,int blocks)
41: {
42: struct buffer_head * bh;
43: int count;
44:
45: if (blocks>6)
46: blocks=6;
47: for(count = 0 ; count<blocks ; count++) {
48: if (!inode->i_zone[count+1])
49: continue;
50: if (!(bh=bread(inode->i_dev,inode->i_zone[count+1])))
51: return -1;
52: cp_block(bh->b_data,count*BLOCK_SIZE);
53: brelse(bh);
54: }
55: return 0;
56: }
57:
58: int read_ind(int dev,int ind,long size,unsigned long offset)
59: {
60: struct buffer_head * ih, * bh;
61: unsigned short * table,block;
62:
63: if (size<=0)
64: panic("size<=0 in read_ind");
65: if (size>512*BLOCK_SIZE)
66: size=512*BLOCK_SIZE;
67: if (!ind)
68: return 0;
69: if (!(ih=bread(dev,ind)))
70: return -1;
71: table = (unsigned short *) ih->b_data;
72: while (size>0) {
1.1.1.3 ! root 73: if ((block=*(table++))) {
1.1 root 74: if (!(bh=bread(dev,block))) {
75: brelse(ih);
76: return -1;
77: } else {
78: cp_block(bh->b_data,offset);
79: brelse(bh);
80: }
1.1.1.3 ! root 81: }
1.1 root 82: size -= BLOCK_SIZE;
83: offset += BLOCK_SIZE;
84: }
85: brelse(ih);
86: return 0;
87: }
88:
89: /*
90: * read_area() reads an area into %fs:mem.
91: */
92: int read_area(struct m_inode * inode,long size)
93: {
94: struct buffer_head * dind;
95: unsigned short * table;
96: int i,count;
97:
98: if ((i=read_head(inode,(size+BLOCK_SIZE-1)/BLOCK_SIZE)) ||
99: (size -= BLOCK_SIZE*6)<=0)
100: return i;
101: if ((i=read_ind(inode->i_dev,inode->i_zone[7],size,BLOCK_SIZE*6)) ||
102: (size -= BLOCK_SIZE*512)<=0)
103: return i;
104: if (!(i=inode->i_zone[8]))
105: return 0;
106: if (!(dind = bread(inode->i_dev,i)))
107: return -1;
108: table = (unsigned short *) dind->b_data;
109: for(count=0 ; count<512 ; count++)
110: if ((i=read_ind(inode->i_dev,*(table++),size,
111: BLOCK_SIZE*(518+count))) || (size -= BLOCK_SIZE*512)<=0)
112: return i;
113: panic("Impossibly long executable");
1.1.1.3 ! root 114: return -1;
1.1 root 115: }
116:
117: /*
118: * create_tables() parses the env- and arg-strings in new user
119: * memory and creates the pointer tables from them, and puts their
120: * addresses on the "stack", returning the new stack pointer value.
121: */
122: static unsigned long * create_tables(char * p,int argc,int envc)
123: {
124: unsigned long *argv,*envp;
125: unsigned long * sp;
126:
127: sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
128: sp -= envc+1;
129: envp = sp;
130: sp -= argc+1;
131: argv = sp;
132: put_fs_long((unsigned long)envp,--sp);
133: put_fs_long((unsigned long)argv,--sp);
134: put_fs_long((unsigned long)argc,--sp);
135: while (argc-->0) {
136: put_fs_long((unsigned long) p,argv++);
137: while (get_fs_byte(p++)) /* nothing */ ;
138: }
139: put_fs_long(0,argv);
140: while (envc-->0) {
141: put_fs_long((unsigned long) p,envp++);
142: while (get_fs_byte(p++)) /* nothing */ ;
143: }
144: put_fs_long(0,envp);
145: return sp;
146: }
147:
148: /*
149: * count() counts the number of arguments/envelopes
150: */
151: static int count(char ** argv)
152: {
153: int i=0;
154: char ** tmp;
155:
1.1.1.3 ! root 156: if ((tmp = argv))
1.1 root 157: while (get_fs_long((unsigned long *) (tmp++)))
158: i++;
159:
160: return i;
161: }
162:
163: /*
164: * 'copy_string()' copies argument/envelope strings from user
165: * memory to free pages in kernel mem. These are in a format ready
166: * to be put directly into the top of new user memory.
167: */
168: static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
169: unsigned long p)
170: {
171: int len,i;
172: char *tmp;
173:
174: while (argc-- > 0) {
175: if (!(tmp = (char *)get_fs_long(((unsigned long *) argv)+argc)))
176: panic("argc is wrong");
177: len=0; /* remember zero-padding */
178: do {
179: len++;
180: } while (get_fs_byte(tmp++));
181: if (p-len < 0) /* this shouldn't happen - 128kB */
182: return 0;
183: i = ((unsigned) (p-len)) >> 12;
184: while (i<MAX_ARG_PAGES && !page[i]) {
185: if (!(page[i]=get_free_page()))
186: return 0;
187: i++;
188: }
189: do {
190: --p;
191: if (!page[p/PAGE_SIZE])
192: panic("nonexistent page in exec.c");
193: ((char *) page[p/PAGE_SIZE])[p%PAGE_SIZE] =
194: get_fs_byte(--tmp);
195: } while (--len);
196: }
197: return p;
198: }
199:
200: static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
201: {
202: unsigned long code_limit,data_limit,code_base,data_base;
203: int i;
204:
205: code_limit = text_size+PAGE_SIZE -1;
206: code_limit &= 0xFFFFF000;
207: data_limit = 0x4000000;
208: code_base = get_base(current->ldt[1]);
209: data_base = code_base;
210: set_base(current->ldt[1],code_base);
211: set_limit(current->ldt[1],code_limit);
212: set_base(current->ldt[2],data_base);
213: set_limit(current->ldt[2],data_limit);
214: /* make sure fs points to the NEW data segment */
215: __asm__("pushl $0x17\n\tpop %%fs"::);
216: data_base += data_limit;
217: for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) {
218: data_base -= PAGE_SIZE;
219: if (page[i])
220: put_page(page[i],data_base);
221: }
222: return data_limit;
223: }
224:
225: /*
226: * 'do_execve()' executes a new program.
227: */
228: int do_execve(unsigned long * eip,long tmp,char * filename,
229: char ** argv, char ** envp)
230: {
231: struct m_inode * inode;
232: struct buffer_head * bh;
233: struct exec ex;
234: unsigned long page[MAX_ARG_PAGES];
235: int i,argc,envc;
236: unsigned long p;
237:
238: if ((0xffff & eip[1]) != 0x000f)
239: panic("execve called from supervisor mode");
240: for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
241: page[i]=0;
242: if (!(inode=namei(filename))) /* get executables inode */
243: return -ENOENT;
244: if (!S_ISREG(inode->i_mode)) { /* must be regular file */
245: iput(inode);
246: return -EACCES;
247: }
248: i = inode->i_mode;
249: if (current->uid && current->euid) {
250: if (current->euid == inode->i_uid)
251: i >>= 6;
252: else if (current->egid == inode->i_gid)
253: i >>= 3;
254: } else if (i & 0111)
255: i=1;
256: if (!(i & 1)) {
257: iput(inode);
258: return -ENOEXEC;
259: }
260: if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {
261: iput(inode);
262: return -EACCES;
263: }
264: ex = *((struct exec *) bh->b_data); /* read exec-header */
265: brelse(bh);
266: if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
267: ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
268: inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
269: iput(inode);
270: return -ENOEXEC;
271: }
272: if (N_TXTOFF(ex) != BLOCK_SIZE)
273: panic("N_TXTOFF != BLOCK_SIZE. See a.out.h.");
274: argc = count(argv);
275: envc = count(envp);
1.1.1.2 root 276: p = copy_strings(envc,envp,page,PAGE_SIZE*MAX_ARG_PAGES);
1.1 root 277: p = copy_strings(argc,argv,page,p);
278: if (!p) {
279: for (i=0 ; i<MAX_ARG_PAGES ; i++)
280: free_page(page[i]);
281: iput(inode);
282: return -1;
283: }
284: /* OK, This is the point of no return */
285: for (i=0 ; i<32 ; i++)
286: current->sig_fn[i] = NULL;
287: for (i=0 ; i<NR_OPEN ; i++)
288: if ((current->close_on_exec>>i)&1)
289: sys_close(i);
290: current->close_on_exec = 0;
291: free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
292: free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
293: if (last_task_used_math == current)
294: last_task_used_math = NULL;
295: current->used_math = 0;
296: p += change_ldt(ex.a_text,page)-MAX_ARG_PAGES*PAGE_SIZE;
297: p = (unsigned long) create_tables((char *)p,argc,envc);
298: current->brk = ex.a_bss +
299: (current->end_data = ex.a_data +
300: (current->end_code = ex.a_text));
301: current->start_stack = p & 0xfffff000;
302: i = read_area(inode,ex.a_text+ex.a_data);
303: iput(inode);
304: if (i<0)
305: sys_exit(-1);
306: i = ex.a_text+ex.a_data;
307: while (i&0xfff)
308: put_fs_byte(0,(char *) (i++));
309: eip[0] = ex.a_entry; /* eip, magic happens :-) */
310: eip[3] = p; /* stack pointer */
311: return 0;
312: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.