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

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

unix.superglobalmegacorp.com

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