|
|
1.1.1.4 ! root 1: ! 2: /* ! 3: * linux/fs/exec.c ! 4: * ! 5: * (C) 1991 Linus Torvalds ! 6: * (C) 2007 Abdel Benamrouche : use elf binary instead of a.out ! 7: * ! 8: */ ! 9: ! 10: 1.1 root 11: #include <errno.h> 12: #include <sys/stat.h> 1.1.1.4 ! root 13: #include <elf.h> 1.1 root 14: 15: #include <linux/fs.h> 16: #include <linux/sched.h> 17: #include <linux/kernel.h> 18: #include <linux/mm.h> 19: #include <asm/segment.h> 20: 21: extern int sys_exit(int exit_code); 22: extern int sys_close(int fd); 23: 24: /* 25: * MAX_ARG_PAGES defines the number of pages allocated for arguments 26: * and envelope for the new program. 32 should suffice, this gives 27: * a maximum env+arg of 128kB ! 28: */ 29: #define MAX_ARG_PAGES 32 30: 1.1.1.4 ! root 31: inline void cp_block(const void * from,void * to, int size) 1.1.1.3 root 32: { 33: int d0,d1,d2; 34: __asm__ __volatile("pushl $0x10\n\t" 35: "pushl $0x17\n\t" 36: "pop %%es\n\t" 37: "cld\n\t" 38: "rep\n\t" 39: "movsl\n\t" 40: "pop %%es" 41: :"=&c" (d0), "=&S" (d1), "=&D" (d2) 1.1.1.4 ! root 42: :"0" (size/4),"1" (from),"2" (to) 1.1.1.3 root 43: :"memory"); 44: } 1.1 root 45: 1.1.1.4 ! root 46: typedef struct 1.1 root 47: { 1.1.1.4 ! root 48: unsigned long b_entry; ! 49: unsigned long b_size; //file size ! 50: }bin_section; 1.1 root 51: 52: 1.1.1.4 ! root 53: #include <string.h> 1.1 root 54: 55: /* 56: * create_tables() parses the env- and arg-strings in new user 57: * memory and creates the pointer tables from them, and puts their 58: * addresses on the "stack", returning the new stack pointer value. 59: */ 60: static unsigned long * create_tables(char * p,int argc,int envc) 61: { 62: unsigned long *argv,*envp; 63: unsigned long * sp; 64: 65: sp = (unsigned long *) (0xfffffffc & (unsigned long) p); 66: sp -= envc+1; 67: envp = sp; 68: sp -= argc+1; 69: argv = sp; 1.1.1.4 ! root 70: //put_fs_long((unsigned long)envp,--sp); ! 71: //put_fs_long((unsigned long)argv,--sp); 1.1 root 72: put_fs_long((unsigned long)argc,--sp); 73: while (argc-->0) { 74: put_fs_long((unsigned long) p,argv++); 75: while (get_fs_byte(p++)) /* nothing */ ; 76: } 77: put_fs_long(0,argv); 78: while (envc-->0) { 79: put_fs_long((unsigned long) p,envp++); 80: while (get_fs_byte(p++)) /* nothing */ ; 81: } 82: put_fs_long(0,envp); 83: return sp; 84: } 85: 86: /* 87: * count() counts the number of arguments/envelopes 88: */ 89: static int count(char ** argv) 90: { 91: int i=0; 92: char ** tmp; 93: 1.1.1.3 root 94: if ((tmp = argv)) 1.1 root 95: while (get_fs_long((unsigned long *) (tmp++))) 96: i++; 97: 98: return i; 99: } 100: 101: /* 102: * 'copy_string()' copies argument/envelope strings from user 103: * memory to free pages in kernel mem. These are in a format ready 104: * to be put directly into the top of new user memory. 105: */ 106: static unsigned long copy_strings(int argc,char ** argv,unsigned long *page, 107: unsigned long p) 108: { 109: int len,i; 110: char *tmp; 111: 112: while (argc-- > 0) { 113: if (!(tmp = (char *)get_fs_long(((unsigned long *) argv)+argc))) 114: panic("argc is wrong"); 115: len=0; /* remember zero-padding */ 116: do { 117: len++; 118: } while (get_fs_byte(tmp++)); 119: if (p-len < 0) /* this shouldn't happen - 128kB */ 120: return 0; 121: i = ((unsigned) (p-len)) >> 12; 122: while (i<MAX_ARG_PAGES && !page[i]) { 123: if (!(page[i]=get_free_page())) 124: return 0; 125: i++; 126: } 127: do { 128: --p; 129: if (!page[p/PAGE_SIZE]) 130: panic("nonexistent page in exec.c"); 131: ((char *) page[p/PAGE_SIZE])[p%PAGE_SIZE] = 132: get_fs_byte(--tmp); 133: } while (--len); 134: } 135: return p; 136: } 137: 138: static unsigned long change_ldt(unsigned long text_size,unsigned long * page) 139: { 140: unsigned long code_limit,data_limit,code_base,data_base; 141: int i; 142: 143: code_limit = text_size+PAGE_SIZE -1; 144: code_limit &= 0xFFFFF000; 145: data_limit = 0x4000000; 146: code_base = get_base(current->ldt[1]); 147: data_base = code_base; 148: set_base(current->ldt[1],code_base); 149: set_limit(current->ldt[1],code_limit); 150: set_base(current->ldt[2],data_base); 151: set_limit(current->ldt[2],data_limit); 152: /* make sure fs points to the NEW data segment */ 153: __asm__("pushl $0x17\n\tpop %%fs"::); 154: data_base += data_limit; 155: for (i=MAX_ARG_PAGES-1 ; i>=0 ; i--) { 156: data_base -= PAGE_SIZE; 157: if (page[i]) 158: put_page(page[i],data_base); 159: } 160: return data_limit; 161: } 162: 163: /* 1.1.1.4 ! root 164: * return 1 if ex if a valid elf executable ! 165: * */ ! 166: int is_valid_elf(Elf32_Ehdr* ex) ! 167: { ! 168: if (ex->e_ident[EI_MAG0]!=ELFMAG0 || ex->e_ident[EI_MAG1]!=ELFMAG1 || ! 169: ex->e_ident[EI_MAG2]!=ELFMAG2 || ex->e_ident[EI_MAG3]!=ELFMAG3){ ! 170: printk("not elf format\n"); ! 171: return 0; /*not elf format */ ! 172: } ! 173: ! 174: if (ex->e_type != ET_EXEC || ex->e_machine != EM_386){ ! 175: printk("bad elf binary\n"); ! 176: return 0; ! 177: } ! 178: ! 179: return 1; ! 180: } ! 181: ! 182: /* ! 183: * bread(dev,ind) is an array of block index ! 184: * So we have to get from this array our wanted index ( variable block) ! 185: * */ ! 186: struct buffer_head* read_file_block_ind(int dev,int ind,int block_num) ! 187: { ! 188: struct buffer_head * bh=NULL,*ih; ! 189: unsigned short block; ! 190: ! 191: if (!(ih=bread(dev,ind))) ! 192: { ! 193: printk("bad block tab\n"); ! 194: return NULL; ! 195: } ! 196: ! 197: if ((block = *((unsigned short *) (ih->b_data) + block_num))){ ! 198: if (!(bh=bread(dev,block))) { ! 199: brelse(ih); ! 200: printk("bad block file\n"); ! 201: return NULL; ! 202: } ! 203: } ! 204: ! 205: ! 206: brelse(ih); ! 207: return bh; ! 208: } ! 209: ! 210: /* ! 211: * if block_num=5, read file at position 5*1024. ! 212: * this work only for minix 1 fs ! 213: */ ! 214: struct buffer_head* read_file_block(struct m_inode * inode,int block_num) ! 215: { ! 216: struct buffer_head * dind; ! 217: int i; ! 218: unsigned short table; ! 219: ! 220: /* 7 1st block can be read directly */ ! 221: if (block_num<=6) ! 222: { ! 223: return bread(inode->i_dev,inode->i_zone[block_num]); ! 224: } ! 225: ! 226: block_num-=7; ! 227: ! 228: if (block_num<512) ! 229: { ! 230: /* read block at i_zone[7] is an array of block index */ ! 231: return read_file_block_ind(inode->i_dev,inode->i_zone[7],block_num); ! 232: } ! 233: ! 234: block_num-=512; ! 235: ! 236: if (block_num>512*512) ! 237: { ! 238: panic("Impossibly long executable"); ! 239: return NULL; //just to avoid warning compilation ! 240: } ! 241: ! 242: /* i_zone[8] => array of array block index */ ! 243: if (!(i=inode->i_zone[8])) ! 244: return NULL; ! 245: if (!(dind = bread(inode->i_dev,i))) ! 246: return NULL; ! 247: ! 248: table = *((unsigned short *) dind->b_data+(block_num/512)); ! 249: brelse(dind); ! 250: if (block_num>=512) ! 251: block_num-=(block_num-1)*512; ! 252: ! 253: return read_file_block_ind(inode->i_dev,table,block_num); ! 254: } ! 255: ! 256: ! 257: /* ! 258: * read an area into %fs:mem. ! 259: */ ! 260: int copy_section(struct m_inode * inode,Elf32_Off from, Elf32_Addr dest,Elf32_Word size) ! 261: { ! 262: struct buffer_head * bh; ! 263: int block_num=from/BLOCK_SIZE; ! 264: int block_offset; //only for 1st block ! 265: int cp_size; ! 266: ! 267: //read fist block ! 268: block_offset=from%BLOCK_SIZE; ! 269: bh=read_file_block(inode,block_num); ! 270: if (!bh) return -1; ! 271: cp_size=(size<BLOCK_SIZE-block_offset)?size:BLOCK_SIZE-block_offset; ! 272: //note we add 3 to size to get it aligned to word boundary ! 273: cp_block(bh->b_data+block_offset,(void*)dest,cp_size+3); ! 274: brelse(bh); ! 275: dest+=cp_size; ! 276: size-=cp_size; ! 277: block_num++; ! 278: ! 279: //read others blocks ! 280: while(size) ! 281: { ! 282: bh=read_file_block(inode,block_num); ! 283: if (!bh) return -1; ! 284: cp_size=(size<BLOCK_SIZE)?size:BLOCK_SIZE; ! 285: cp_block(bh->b_data,(void*)dest,cp_size+3); ! 286: block_num++; ! 287: size-=cp_size; ! 288: dest+=cp_size; ! 289: brelse(bh); ! 290: }; ! 291: ! 292: return 0; ! 293: } ! 294: ! 295: inline int create_bss_section(Elf32_Addr dest,Elf32_Word size) ! 296: { ! 297: while (size--) ! 298: put_fs_byte(0,(char *)dest++); ! 299: return 0; ! 300: } ! 301: ! 302: /* ! 303: * in linux 0.01 only a.out binary format was supported ! 304: * Today it's hard to compile some programs (like bach) in a.out format ! 305: * So this version of linux 0.01 support elf binary. ! 306: * nb : there is no support of shared library ! ! 307: */ ! 308: int load_elf_binary(struct m_inode *inode, struct buffer_head* bh, ! 309: bin_section* bs) ! 310: { ! 311: Elf32_Ehdr ex; ! 312: Elf32_Shdr sect; ! 313: long nsect; ! 314: int lb=0; ! 315: struct buffer_head* bht=NULL; ! 316: ! 317: ex = *((Elf32_Ehdr *) bh->b_data); /* read exec-header */ ! 318: ! 319: /* check header */ ! 320: if (!is_valid_elf(&ex)) { ! 321: return -1; ! 322: } ! 323: ! 324: bs->b_entry=ex.e_entry; ! 325: nsect=ex.e_shnum; ! 326: bs->b_size=ex.e_ehsize+nsect*ex.e_shentsize; ! 327: ! 328: if (nsect<=1){ ! 329: printk("bad nb of sections %d\n",nsect); ! 330: return -1; ! 331: } ! 332: ! 333: while(nsect--){ ! 334: ! 335: /* load block where is our table section*/ ! 336: if ((ex.e_shoff + nsect * ex.e_shentsize)/BLOCK_SIZE != lb) ! 337: { ! 338: printk(""); // gcc bug : removing this line = gcc not happy !!! ! 339: lb = (ex.e_shoff + nsect * ex.e_shentsize)/BLOCK_SIZE; ! 340: if (bht) brelse(bht); ! 341: bht=read_file_block(inode,lb); ! 342: if (!bht) return -1; ! 343: } ! 344: ! 345: /* copy this section fo %fs:mem */ ! 346: sect=*((Elf32_Shdr *)(bht->b_data + (ex.e_shoff + ! 347: nsect * ex.e_shentsize)%BLOCK_SIZE )); ! 348: ! 349: if (!sect.sh_size || !sect.sh_addr) continue; ! 350: ! 351: switch(sect.sh_type) ! 352: { ! 353: case SHT_PROGBITS: ! 354: if (copy_section(inode,sect.sh_offset,sect.sh_addr, ! 355: sect.sh_size)) ! 356: { ! 357: if (bht) brelse(bht); ! 358: return -1; ! 359: } ! 360: break; ! 361: ! 362: case SHT_NOBITS: ! 363: create_bss_section(sect.sh_addr,sect.sh_size); ! 364: break; ! 365: ! 366: default: ! 367: continue; ! 368: } ! 369: ! 370: /* find binary size */ ! 371: if (bs->b_size<sect.sh_addr + sect.sh_size) ! 372: bs->b_size=sect.sh_addr + sect.sh_size; ! 373: }; ! 374: ! 375: if (bht) brelse(bht); ! 376: return 0; ! 377: } ! 378: ! 379: /* 1.1 root 380: * 'do_execve()' executes a new program. 381: */ 382: int do_execve(unsigned long * eip,long tmp,char * filename, 383: char ** argv, char ** envp) 384: { 385: struct m_inode * inode; 386: struct buffer_head * bh; 387: unsigned long page[MAX_ARG_PAGES]; 388: int i,argc,envc; 389: unsigned long p; 1.1.1.4 ! root 390: bin_section bs; 1.1 root 391: 392: if ((0xffff & eip[1]) != 0x000f) 393: panic("execve called from supervisor mode"); 394: for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */ 395: page[i]=0; 396: if (!(inode=namei(filename))) /* get executables inode */ 397: return -ENOENT; 1.1.1.4 ! root 398: if (!S_ISREG(inode->i_mode)) { /* must be regular file */ 1.1 root 399: iput(inode); 400: return -EACCES; 401: } 402: i = inode->i_mode; 403: if (current->uid && current->euid) { 404: if (current->euid == inode->i_uid) 405: i >>= 6; 406: else if (current->egid == inode->i_gid) 407: i >>= 3; 408: } else if (i & 0111) 409: i=1; 410: if (!(i & 1)) { 411: iput(inode); 412: return -ENOEXEC; 413: } 414: if (!(bh = bread(inode->i_dev,inode->i_zone[0]))) { 415: iput(inode); 416: return -EACCES; 417: } 1.1.1.4 ! root 418: 1.1 root 419: argc = count(argv); 420: envc = count(envp); 1.1.1.2 root 421: p = copy_strings(envc,envp,page,PAGE_SIZE*MAX_ARG_PAGES); 1.1 root 422: p = copy_strings(argc,argv,page,p); 423: if (!p) { 424: for (i=0 ; i<MAX_ARG_PAGES ; i++) 425: free_page(page[i]); 426: iput(inode); 427: return -1; 428: } 429: /* OK, This is the point of no return */ 430: for (i=0 ; i<32 ; i++) 431: current->sig_fn[i] = NULL; 432: for (i=0 ; i<NR_OPEN ; i++) 433: if ((current->close_on_exec>>i)&1) 434: sys_close(i); 435: current->close_on_exec = 0; 1.1.1.4 ! root 436: 1.1 root 437: free_page_tables(get_base(current->ldt[1]),get_limit(0x0f)); 438: free_page_tables(get_base(current->ldt[2]),get_limit(0x17)); 1.1.1.4 ! root 439: ! 440: if (load_elf_binary(inode,bh,&bs)){ ! 441: brelse(bh); ! 442: iput(inode); ! 443: return -EACCES; ! 444: } ! 445: brelse(bh); ! 446: 1.1 root 447: if (last_task_used_math == current) 448: last_task_used_math = NULL; 449: current->used_math = 0; 1.1.1.4 ! root 450: p += change_ldt(bs.b_size,page)-MAX_ARG_PAGES*PAGE_SIZE; 1.1 root 451: p = (unsigned long) create_tables((char *)p,argc,envc); 1.1.1.4 ! root 452: current->brk = bs.b_size; ! 453: current->end_data = bs.b_size; ! 454: current->end_code = bs.b_size; 1.1 root 455: current->start_stack = p & 0xfffff000; 456: iput(inode); 1.1.1.4 ! root 457: ! 458: i = bs.b_size; 1.1 root 459: while (i&0xfff) 460: put_fs_byte(0,(char *) (i++)); 1.1.1.4 ! root 461: ! 462: eip[0] = bs.b_entry; /* eip, magic happens :-) */ ! 463: eip[3] = p; /* stack pointer */ ! 464: 1.1 root 465: return 0; 466: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.