Annotation of linux/fs/exec.c, revision 1.1.1.3

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.