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

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

unix.superglobalmegacorp.com

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