1 /* Code for loading Linux executables. Mostly linux kernel code. */ 2 3 #include "qemu/osdep.h" 4 #include "qemu.h" 5 #include "user-internals.h" 6 #include "user-mmap.h" 7 #include "loader.h" 8 #include "qapi/error.h" 9 10 #define NGROUPS 32 11 12 /* ??? This should really be somewhere else. */ 13 abi_long memcpy_to_target(abi_ulong dest, const void *src, unsigned long len) 14 { 15 void *host_ptr; 16 17 host_ptr = lock_user(VERIFY_WRITE, dest, len, 0); 18 if (!host_ptr) { 19 return -TARGET_EFAULT; 20 } 21 memcpy(host_ptr, src, len); 22 unlock_user(host_ptr, dest, 1); 23 return 0; 24 } 25 26 static int count(char **vec) 27 { 28 int i; 29 30 for (i = 0; *vec; i++) { 31 vec++; 32 } 33 return i; 34 } 35 36 static int prepare_binprm(struct linux_binprm *bprm) 37 { 38 struct stat st; 39 int mode; 40 int retval; 41 42 if (fstat(bprm->src.fd, &st) < 0) { 43 return -errno; 44 } 45 46 mode = st.st_mode; 47 if (!S_ISREG(mode)) { /* Must be regular file */ 48 return -EACCES; 49 } 50 if (!(mode & 0111)) { /* Must have at least one execute bit set */ 51 return -EACCES; 52 } 53 54 bprm->e_uid = geteuid(); 55 bprm->e_gid = getegid(); 56 57 /* Set-uid? */ 58 if (mode & S_ISUID) { 59 bprm->e_uid = st.st_uid; 60 } 61 62 /* Set-gid? */ 63 /* 64 * If setgid is set but no group execute bit then this 65 * is a candidate for mandatory locking, not a setgid 66 * executable. 67 */ 68 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { 69 bprm->e_gid = st.st_gid; 70 } 71 72 retval = read(bprm->src.fd, bprm->buf, BPRM_BUF_SIZE); 73 if (retval < 0) { 74 perror("prepare_binprm"); 75 exit(-1); 76 } 77 if (retval < BPRM_BUF_SIZE) { 78 /* Make sure the rest of the loader won't read garbage. */ 79 memset(bprm->buf + retval, 0, BPRM_BUF_SIZE - retval); 80 } 81 82 bprm->src.cache = bprm->buf; 83 bprm->src.cache_size = retval; 84 85 return retval; 86 } 87 88 /* Construct the envp and argv tables on the target stack. */ 89 abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, 90 abi_ulong stringp, int push_ptr) 91 { 92 TaskState *ts = (TaskState *)thread_cpu->opaque; 93 int n = sizeof(abi_ulong); 94 abi_ulong envp; 95 abi_ulong argv; 96 97 sp -= (envc + 1) * n; 98 envp = sp; 99 sp -= (argc + 1) * n; 100 argv = sp; 101 ts->info->envp = envp; 102 ts->info->envc = envc; 103 ts->info->argv = argv; 104 ts->info->argc = argc; 105 106 if (push_ptr) { 107 /* FIXME - handle put_user() failures */ 108 sp -= n; 109 put_user_ual(envp, sp); 110 sp -= n; 111 put_user_ual(argv, sp); 112 } 113 114 sp -= n; 115 /* FIXME - handle put_user() failures */ 116 put_user_ual(argc, sp); 117 118 ts->info->arg_strings = stringp; 119 while (argc-- > 0) { 120 /* FIXME - handle put_user() failures */ 121 put_user_ual(stringp, argv); 122 argv += n; 123 stringp += target_strlen(stringp) + 1; 124 } 125 /* FIXME - handle put_user() failures */ 126 put_user_ual(0, argv); 127 128 ts->info->env_strings = stringp; 129 while (envc-- > 0) { 130 /* FIXME - handle put_user() failures */ 131 put_user_ual(stringp, envp); 132 envp += n; 133 stringp += target_strlen(stringp) + 1; 134 } 135 /* FIXME - handle put_user() failures */ 136 put_user_ual(0, envp); 137 138 return sp; 139 } 140 141 int loader_exec(int fdexec, const char *filename, char **argv, char **envp, 142 struct target_pt_regs *regs, struct image_info *infop, 143 struct linux_binprm *bprm) 144 { 145 int retval; 146 147 bprm->src.fd = fdexec; 148 bprm->filename = (char *)filename; 149 bprm->argc = count(argv); 150 bprm->argv = argv; 151 bprm->envc = count(envp); 152 bprm->envp = envp; 153 154 retval = prepare_binprm(bprm); 155 156 if (retval < 4) { 157 return -ENOEXEC; 158 } 159 if (bprm->buf[0] == 0x7f 160 && bprm->buf[1] == 'E' 161 && bprm->buf[2] == 'L' 162 && bprm->buf[3] == 'F') { 163 retval = load_elf_binary(bprm, infop); 164 #if defined(TARGET_HAS_BFLT) 165 } else if (bprm->buf[0] == 'b' 166 && bprm->buf[1] == 'F' 167 && bprm->buf[2] == 'L' 168 && bprm->buf[3] == 'T') { 169 retval = load_flt_binary(bprm, infop); 170 #endif 171 } else { 172 return -ENOEXEC; 173 } 174 if (retval < 0) { 175 return retval; 176 } 177 178 /* Success. Initialize important registers. */ 179 do_init_thread(regs, infop); 180 return 0; 181 } 182 183 bool imgsrc_read(void *dst, off_t offset, size_t len, 184 const ImageSource *img, Error **errp) 185 { 186 ssize_t ret; 187 188 if (offset + len <= img->cache_size) { 189 memcpy(dst, img->cache + offset, len); 190 return true; 191 } 192 193 if (img->fd < 0) { 194 error_setg(errp, "read past end of buffer"); 195 return false; 196 } 197 198 ret = pread(img->fd, dst, len, offset); 199 if (ret == len) { 200 return true; 201 } 202 if (ret < 0) { 203 error_setg_errno(errp, errno, "Error reading file header"); 204 } else { 205 error_setg(errp, "Incomplete read of file header"); 206 } 207 return false; 208 } 209 210 void *imgsrc_read_alloc(off_t offset, size_t len, 211 const ImageSource *img, Error **errp) 212 { 213 void *alloc = g_malloc(len); 214 bool ok = imgsrc_read(alloc, offset, len, img, errp); 215 216 if (!ok) { 217 g_free(alloc); 218 alloc = NULL; 219 } 220 return alloc; 221 } 222 223 abi_long imgsrc_mmap(abi_ulong start, abi_ulong len, int prot, 224 int flags, const ImageSource *src, abi_ulong offset) 225 { 226 const int prot_write = PROT_READ | PROT_WRITE; 227 abi_long ret; 228 void *haddr; 229 230 assert(flags == (MAP_PRIVATE | MAP_FIXED)); 231 232 if (src->fd >= 0) { 233 return target_mmap(start, len, prot, flags, src->fd, offset); 234 } 235 236 /* 237 * This case is for the vdso; we don't expect bad images. 238 * The mmap may extend beyond the end of the image, especially 239 * to the end of the page. Zero fill. 240 */ 241 assert(offset < src->cache_size); 242 243 ret = target_mmap(start, len, prot_write, flags | MAP_ANON, -1, 0); 244 if (ret == -1) { 245 return ret; 246 } 247 248 haddr = lock_user(VERIFY_WRITE, start, len, 0); 249 assert(haddr != NULL); 250 if (offset + len <= src->cache_size) { 251 memcpy(haddr, src->cache + offset, len); 252 } else { 253 size_t rest = src->cache_size - offset; 254 memcpy(haddr, src->cache + offset, rest); 255 memset(haddr + rest, 0, len - rest); 256 } 257 unlock_user(haddr, start, len); 258 259 if (prot != prot_write) { 260 target_mprotect(start, len, prot); 261 } 262 263 return ret; 264 } 265