|
|
1.1 ! root 1: /* Code for loading Linux executables. Mostly linux kenrel code. */ ! 2: ! 3: #include <sys/types.h> ! 4: #include <sys/stat.h> ! 5: #include <fcntl.h> ! 6: #include <errno.h> ! 7: #include <unistd.h> ! 8: #include <stdio.h> ! 9: #include <stdlib.h> ! 10: ! 11: #include "qemu.h" ! 12: ! 13: #define NGROUPS 32 ! 14: ! 15: /* ??? This should really be somewhere else. */ ! 16: void memcpy_to_target(target_ulong dest, const void *src, ! 17: unsigned long len) ! 18: { ! 19: void *host_ptr; ! 20: ! 21: host_ptr = lock_user(dest, len, 0); ! 22: memcpy(host_ptr, src, len); ! 23: unlock_user(host_ptr, dest, 1); ! 24: } ! 25: ! 26: static int in_group_p(gid_t g) ! 27: { ! 28: /* return TRUE if we're in the specified group, FALSE otherwise */ ! 29: int ngroup; ! 30: int i; ! 31: gid_t grouplist[NGROUPS]; ! 32: ! 33: ngroup = getgroups(NGROUPS, grouplist); ! 34: for(i = 0; i < ngroup; i++) { ! 35: if(grouplist[i] == g) { ! 36: return 1; ! 37: } ! 38: } ! 39: return 0; ! 40: } ! 41: ! 42: static int count(char ** vec) ! 43: { ! 44: int i; ! 45: ! 46: for(i = 0; *vec; i++) { ! 47: vec++; ! 48: } ! 49: ! 50: return(i); ! 51: } ! 52: ! 53: static int prepare_binprm(struct linux_binprm *bprm) ! 54: { ! 55: struct stat st; ! 56: int mode; ! 57: int retval, id_change; ! 58: ! 59: if(fstat(bprm->fd, &st) < 0) { ! 60: return(-errno); ! 61: } ! 62: ! 63: mode = st.st_mode; ! 64: if(!S_ISREG(mode)) { /* Must be regular file */ ! 65: return(-EACCES); ! 66: } ! 67: if(!(mode & 0111)) { /* Must have at least one execute bit set */ ! 68: return(-EACCES); ! 69: } ! 70: ! 71: bprm->e_uid = geteuid(); ! 72: bprm->e_gid = getegid(); ! 73: id_change = 0; ! 74: ! 75: /* Set-uid? */ ! 76: if(mode & S_ISUID) { ! 77: bprm->e_uid = st.st_uid; ! 78: if(bprm->e_uid != geteuid()) { ! 79: id_change = 1; ! 80: } ! 81: } ! 82: ! 83: /* Set-gid? */ ! 84: /* ! 85: * If setgid is set but no group execute bit then this ! 86: * is a candidate for mandatory locking, not a setgid ! 87: * executable. ! 88: */ ! 89: if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { ! 90: bprm->e_gid = st.st_gid; ! 91: if (!in_group_p(bprm->e_gid)) { ! 92: id_change = 1; ! 93: } ! 94: } ! 95: ! 96: memset(bprm->buf, 0, sizeof(bprm->buf)); ! 97: retval = lseek(bprm->fd, 0L, SEEK_SET); ! 98: if(retval >= 0) { ! 99: retval = read(bprm->fd, bprm->buf, 128); ! 100: } ! 101: if(retval < 0) { ! 102: perror("prepare_binprm"); ! 103: exit(-1); ! 104: /* return(-errno); */ ! 105: } ! 106: else { ! 107: return(retval); ! 108: } ! 109: } ! 110: ! 111: /* Construct the envp and argv tables on the target stack. */ ! 112: target_ulong loader_build_argptr(int envc, int argc, target_ulong sp, ! 113: target_ulong stringp, int push_ptr) ! 114: { ! 115: int n = sizeof(target_ulong); ! 116: target_ulong envp; ! 117: target_ulong argv; ! 118: ! 119: sp -= (envc + 1) * n; ! 120: envp = sp; ! 121: sp -= (argc + 1) * n; ! 122: argv = sp; ! 123: if (push_ptr) { ! 124: sp -= n; tputl(sp, envp); ! 125: sp -= n; tputl(sp, argv); ! 126: } ! 127: sp -= n; tputl(sp, argc); ! 128: ! 129: while (argc-- > 0) { ! 130: tputl(argv, stringp); argv += n; ! 131: stringp += target_strlen(stringp) + 1; ! 132: } ! 133: tputl(argv, 0); ! 134: while (envc-- > 0) { ! 135: tputl(envp, stringp); envp += n; ! 136: stringp += target_strlen(stringp) + 1; ! 137: } ! 138: tputl(envp, 0); ! 139: ! 140: return sp; ! 141: } ! 142: ! 143: int loader_exec(const char * filename, char ** argv, char ** envp, ! 144: struct target_pt_regs * regs, struct image_info *infop) ! 145: { ! 146: struct linux_binprm bprm; ! 147: int retval; ! 148: int i; ! 149: ! 150: bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int); ! 151: for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */ ! 152: bprm.page[i] = 0; ! 153: retval = open(filename, O_RDONLY); ! 154: if (retval < 0) ! 155: return retval; ! 156: bprm.fd = retval; ! 157: bprm.filename = (char *)filename; ! 158: bprm.argc = count(argv); ! 159: bprm.argv = argv; ! 160: bprm.envc = count(envp); ! 161: bprm.envp = envp; ! 162: ! 163: retval = prepare_binprm(&bprm); ! 164: ! 165: if(retval>=0) { ! 166: if (bprm.buf[0] == 0x7f ! 167: && bprm.buf[1] == 'E' ! 168: && bprm.buf[2] == 'L' ! 169: && bprm.buf[3] == 'F') { ! 170: retval = load_elf_binary(&bprm,regs,infop); ! 171: #if defined(TARGET_HAS_BFLT) ! 172: } else if (bprm.buf[0] == 'b' ! 173: && bprm.buf[1] == 'F' ! 174: && bprm.buf[2] == 'L' ! 175: && bprm.buf[3] == 'T') { ! 176: retval = load_flt_binary(&bprm,regs,infop); ! 177: #endif ! 178: } else { ! 179: fprintf(stderr, "Unknown binary format\n"); ! 180: return -1; ! 181: } ! 182: } ! 183: ! 184: if(retval>=0) { ! 185: /* success. Initialize important registers */ ! 186: do_init_thread(regs, infop); ! 187: return retval; ! 188: } ! 189: ! 190: /* Something went wrong, return the inode and free the argument pages*/ ! 191: for (i=0 ; i<MAX_ARG_PAGES ; i++) { ! 192: free(bprm.page[i]); ! 193: } ! 194: return(retval); ! 195: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.