4 * (C) 1991 Linus Torvalds
12 #include <linux/sched.h>
13 #include <linux/kernel.h>
15 #include <asm/segment.h>
17 extern int sys_exit(int exit_code);
18 extern int sys_close(int fd);
21 * MAX_ARG_PAGES defines the number of pages allocated for arguments
22 * and envelope for the new program. 32 should suffice, this gives
23 * a maximum env+arg of 128kB !
25 #define MAX_ARG_PAGES 32
27 #define cp_block(from,to) \
28 __asm__("pushl $0x10\n\t" \
35 ::"c" (BLOCK_SIZE/4),"S" (from),"D" (to) \
39 * read_head() reads blocks 1-6 (not 0). Block 0 has already been
40 * read for header information.
42 int read_head(struct m_inode * inode,int blocks)
44 struct buffer_head * bh;
49 for(count = 0 ; count<blocks ; count++) {
50 if (!inode->i_zone[count+1])
52 if (!(bh=bread(inode->i_dev,inode->i_zone[count+1])))
54 cp_block(bh->b_data,count*BLOCK_SIZE);
60 int read_ind(int dev,int ind,long size,unsigned long offset)
62 struct buffer_head * ih, * bh;
63 unsigned short * table,block;
66 panic("size<=0 in read_ind");
67 if (size>512*BLOCK_SIZE)
71 if (!(ih=bread(dev,ind)))
73 table = (unsigned short *) ih->b_data;
76 if (!(bh=bread(dev,block))) {
80 cp_block(bh->b_data,offset);
91 * read_area() reads an area into %fs:mem.
93 int read_area(struct m_inode * inode,long size)
95 struct buffer_head * dind;
96 unsigned short * table;
99 if ((i=read_head(inode,(size+BLOCK_SIZE-1)/BLOCK_SIZE)) ||
100 (size -= BLOCK_SIZE*6)<=0)
102 if ((i=read_ind(inode->i_dev,inode->i_zone[7],size,BLOCK_SIZE*6)) ||
103 (size -= BLOCK_SIZE*512)<=0)
105 if (!(i=inode->i_zone[8]))
107 if (!(dind = bread(inode->i_dev,i)))
109 table = (unsigned short *) dind->b_data;
110 for(count=0 ; count<512 ; count++)
111 if ((i=read_ind(inode->i_dev,*(table++),size,
112 BLOCK_SIZE*(518+count))) || (size -= BLOCK_SIZE*512)<=0)
114 panic("Impossibly long executable");
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.
122 static unsigned long * create_tables(char * p,int argc,int envc)
124 unsigned long *argv,*envp;
127 sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
132 put_fs_long((unsigned long)envp,--sp);
133 put_fs_long((unsigned long)argv,--sp);
134 put_fs_long((unsigned long)argc,--sp);
136 put_fs_long((unsigned long) p,argv++);
137 while (get_fs_byte(p++)) /* nothing */ ;
141 put_fs_long((unsigned long) p,envp++);
142 while (get_fs_byte(p++)) /* nothing */ ;
149 * count() counts the number of arguments/envelopes
151 static int count(char ** argv)
157 while (get_fs_long((unsigned long *) (tmp++)))
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.
168 static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
175 if (!(tmp = (char *)get_fs_long(((unsigned long *) argv)+argc)))
176 panic("argc is wrong");
177 len=0; /* remember zero-padding */
180 } while (get_fs_byte(tmp++));
181 if (p-len < 0) /* this shouldn't happen - 128kB */
183 i = ((unsigned) (p-len)) >> 12;
184 while (i<MAX_ARG_PAGES && !page[i]) {
185 if (!(page[i]=get_free_page()))
191 if (!page[p/PAGE_SIZE])
192 panic("nonexistent page in exec.c");
193 ((char *) page[p/PAGE_SIZE])[p%PAGE_SIZE] =
200 static unsigned long change_ldt(unsigned long text_size,unsigned long * page)
202 unsigned long code_limit,data_limit,code_base,data_base;
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;
220 put_page(page[i],data_base);
226 * 'do_execve()' executes a new program.
228 int do_execve(unsigned long * eip,long tmp,char * filename,
229 char ** argv, char ** envp)
231 struct m_inode * inode;
232 struct buffer_head * bh;
234 unsigned long page[MAX_ARG_PAGES];
241 if ((0xffff & eip[1]) != 0x000f)
242 panic("execve called from supervisor mode");
243 for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
245 if (!(inode=namei(filename))) { /* get executables inode */
253 e_uid = current->euid; /* Note this means no setuid */
254 e_gid = current->egid; /* shell scripts! */
255 if (!S_ISREG(inode->i_mode)) { /* must be regular file */
261 e_uid = inode->i_uid;
263 e_gid = inode->i_gid;
264 if (current->euid == inode->i_uid)
266 else if (current->egid == inode->i_gid)
269 !((inode->i_mode & 111) && suser())) {
273 if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) {
277 ex = *((struct exec *) bh->b_data); /* read exec-header */
278 if ((bh->b_data[0] == '#') && (bh->b_data[1] == '!') && (interp > 3)) {
280 * This section does the #! interpretation.
281 * Gee, I hope the C compiler is intelligent about this,
282 * and only activates this sub-frame when necessary.
284 char buf[1023], *cp, *interp, *i_name, *i_arg;
287 strncpy(buf, bh->b_data+2, 1022);
291 if (!(cp = strchr(buf, '\n'))) {
296 for (cp = buf; (*cp == ' ') || (*cp == '\t'); cp++) ;
298 retval = -ENOEXEC; /* No interpreter name found */
301 interp = i_name = cp;
302 for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) {
312 * OK, we've parsed out the interpreter name and
313 * (optional) argument.
316 p = copy_strings(envc,envp,page,
317 PAGE_SIZE*MAX_ARG_PAGES-4);
318 p = copy_strings(--argc,argv+1,page,p);
321 * Copy in interpreter name
323 len = strlen(i_name) + 1;
324 i = ((unsigned) (p-len)) >> 12;
325 while (i<MAX_ARG_PAGES && !page[i]) {
326 if (!(page[i]=get_free_page())) {
334 if (!page[p/PAGE_SIZE])
335 panic("nonexistent page in exec.c");
336 ((char *) page[p/PAGE_SIZE])[p%PAGE_SIZE] =
340 * OK, now restart the process with the interpreter's inode.
342 if (!(inode=namei(interpreter))) { /* get executables inode */
349 if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize || ex.a_drsize ||
350 ex.a_text+ex.a_data+ex.a_bss>0x3000000 ||
351 inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
355 if (N_TXTOFF(ex) != BLOCK_SIZE) {
356 printk("%s: N_TXTOFF != BLOCK_SIZE. See a.out.h.", filename);
361 p = copy_strings(envc,envp,page,PAGE_SIZE*MAX_ARG_PAGES-4);
362 p = copy_strings(argc,argv,page,p);
365 for (i=0 ; i<MAX_ARG_PAGES ; i++)
370 /* OK, This is the point of no return */
371 for (i=0 ; i<32 ; i++)
372 current->sigaction[i].sa_handler = NULL;
373 for (i=0 ; i<NR_OPEN ; i++)
374 if ((current->close_on_exec>>i)&1)
376 current->close_on_exec = 0;
377 free_page_tables(get_base(current->ldt[1]),get_limit(0x0f));
378 free_page_tables(get_base(current->ldt[2]),get_limit(0x17));
379 if (last_task_used_math == current)
380 last_task_used_math = NULL;
381 current->used_math = 0;
382 p += change_ldt(ex.a_text,page)-MAX_ARG_PAGES*PAGE_SIZE;
383 p = (unsigned long) create_tables((char *)p,argc,envc);
384 current->brk = ex.a_bss +
385 (current->end_data = ex.a_data +
386 (current->end_code = ex.a_text));
387 current->start_stack = p & 0xfffff000;
388 current->euid = e_uid;
389 current->egid = e_gid;
390 i = read_area(inode,ex.a_text+ex.a_data);
394 i = ex.a_text+ex.a_data;
396 put_fs_byte(0,(char *) (i++));
397 eip[0] = ex.a_entry; /* eip, magic happens :-) */
398 eip[3] = p; /* stack pointer */
403 for (i=0 ; i<MAX_ARG_PAGES ; i++)