qemu-8.1.3.patch (13110B)
1 diff --git a/linux-user/main.c b/linux-user/main.c 2 index 96be354897..bc4c8864c7 100644 3 --- a/linux-user/main.c 4 +++ b/linux-user/main.c 5 @@ -124,6 +124,7 @@ static void usage(int exitcode); 6 7 static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; 8 const char *qemu_uname_release; 9 +const char *qemu_execve_path; 10 11 #if !defined(TARGET_DEFAULT_STACK_SIZE) 12 /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so 13 @@ -370,6 +371,11 @@ static void handle_arg_guest_base(const char *arg) 14 have_guest_base = true; 15 } 16 17 +static void handle_arg_execve(const char *arg) 18 +{ 19 + qemu_execve_path = strdup(arg); 20 +} 21 + 22 static void handle_arg_reserved_va(const char *arg) 23 { 24 char *p; 25 @@ -486,6 +492,8 @@ static const struct qemu_argument arg_table[] = { 26 "uname", "set qemu uname release string to 'uname'"}, 27 {"B", "QEMU_GUEST_BASE", true, handle_arg_guest_base, 28 "address", "set guest_base address to 'address'"}, 29 + {"execve", "QEMU_EXECVE", true, handle_arg_execve, 30 + "", "use this interpreter when a process calls execve()"}, 31 {"R", "QEMU_RESERVED_VA", true, handle_arg_reserved_va, 32 "size", "reserve 'size' bytes for guest virtual address space"}, 33 {"d", "QEMU_LOG", true, handle_arg_log, 34 diff --git a/linux-user/syscall.c b/linux-user/syscall.c 35 index 9353268cc1..790744adfb 100644 36 --- a/linux-user/syscall.c 37 +++ b/linux-user/syscall.c 38 @@ -125,6 +125,7 @@ 39 #include <libdrm/drm.h> 40 #include <libdrm/i915_drm.h> 41 #endif 42 +#include <linux/binfmts.h> 43 #include "linux_loop.h" 44 #include "uname.h" 45 46 @@ -8680,6 +8681,137 @@ ssize_t do_guest_readlink(const char *pathname, char *buf, size_t bufsiz) 47 return ret; 48 } 49 50 +/* qemu_execve() Must return target values and target errnos. 51 + * 52 + * Although execve() is not an interruptible syscall it is 53 + * a special case where we must use the safe_syscall wrapper: 54 + * if we allow a signal to happen before we make the host 55 + * syscall then we will 'lose' it, because at the point of 56 + * execve the process leaves QEMU's control. So we use the 57 + * safe syscall wrapper to ensure that we either take the 58 + * signal as a guest signal, or else it does not happen 59 + * before the execve completes and makes it the other 60 + * program's problem. 61 + */ 62 +static abi_long qemu_execve(int dirfd, char *filename, char *argv[], 63 + char *envp[], int flags, bool is_execveat) 64 +{ 65 + char *i_arg = NULL, *i_name = NULL; 66 + char **new_argp; 67 + int argc, fd, ret, i, offset = 5; 68 + char *cp; 69 + char buf[BINPRM_BUF_SIZE]; 70 + 71 + /* normal execve case */ 72 + if (qemu_execve_path == NULL || *qemu_execve_path == 0) { 73 + return get_errno(is_execveat ? 74 + safe_execveat(dirfd, filename, argv, envp, flags) : 75 + safe_execve(filename, argv, envp)); 76 + } 77 + 78 + if (is_execveat) { 79 + return -TARGET_ENOSYS; 80 + } 81 + 82 + for (argc = 0; argv[argc] != NULL; argc++) { 83 + /* nothing */ ; 84 + } 85 + 86 + fd = open(filename, O_RDONLY); 87 + if (fd == -1) { 88 + return get_errno(fd); 89 + } 90 + 91 + ret = read(fd, buf, BINPRM_BUF_SIZE); 92 + if (ret == -1) { 93 + close(fd); 94 + return get_errno(ret); 95 + } 96 + 97 + /* if we have less than 2 bytes, we can guess it is not executable */ 98 + if (ret < 2) { 99 + close(fd); 100 + return -host_to_target_errno(ENOEXEC); 101 + } 102 + 103 + close(fd); 104 + 105 + /* adapted from the kernel 106 + * https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/binfmt_script.c 107 + */ 108 + if ((buf[0] == '#') && (buf[1] == '!')) { 109 + /* 110 + * This section does the #! interpretation. 111 + * Sorta complicated, but hopefully it will work. -TYT 112 + */ 113 + 114 + buf[BINPRM_BUF_SIZE - 1] = '\0'; 115 + cp = strchr(buf, '\n'); 116 + if (cp == NULL) { 117 + cp = buf + BINPRM_BUF_SIZE - 1; 118 + } 119 + *cp = '\0'; 120 + while (cp > buf) { 121 + cp--; 122 + if ((*cp == ' ') || (*cp == '\t')) { 123 + *cp = '\0'; 124 + } else { 125 + break; 126 + } 127 + } 128 + for (cp = buf + 2; (*cp == ' ') || (*cp == '\t'); cp++) { 129 + /* nothing */ ; 130 + } 131 + if (*cp == '\0') { 132 + return -ENOEXEC; /* No interpreter name found */ 133 + } 134 + i_name = cp; 135 + i_arg = NULL; 136 + for ( ; *cp && (*cp != ' ') && (*cp != '\t'); cp++) { 137 + /* nothing */ ; 138 + } 139 + while ((*cp == ' ') || (*cp == '\t')) { 140 + *cp++ = '\0'; 141 + } 142 + if (*cp) { 143 + i_arg = cp; 144 + } 145 + 146 + if (i_arg) { 147 + offset += 2; 148 + } else { 149 + offset += 1; 150 + } 151 + } 152 + 153 + new_argp = alloca((argc + offset + 1) * sizeof(void *)); 154 + 155 + /* Copy the original arguments with offset */ 156 + for (i = 0; i < argc; i++) { 157 + new_argp[i + offset] = argv[i]; 158 + } 159 + 160 + new_argp[0] = strdup(qemu_execve_path); 161 + new_argp[1] = strdup("--execve"); 162 + new_argp[2] = strdup(qemu_execve_path); 163 + new_argp[3] = strdup("-0"); 164 + new_argp[offset] = filename; 165 + new_argp[argc + offset] = NULL; 166 + 167 + if (i_name) { 168 + new_argp[4] = i_name; 169 + new_argp[5] = i_name; 170 + 171 + if (i_arg) { 172 + new_argp[6] = i_arg; 173 + } 174 + } else { 175 + new_argp[4] = argv[0]; 176 + } 177 + 178 + return get_errno(safe_execve(qemu_execve_path, new_argp, envp)); 179 +} 180 + 181 static int do_execv(CPUArchState *cpu_env, int dirfd, 182 abi_long pathname, abi_long guest_argp, 183 abi_long guest_envp, int flags, bool is_execveat) 184 @@ -8745,17 +8877,6 @@ static int do_execv(CPUArchState *cpu_env, int dirfd, 185 } 186 *q = NULL; 187 188 - /* 189 - * Although execve() is not an interruptible syscall it is 190 - * a special case where we must use the safe_syscall wrapper: 191 - * if we allow a signal to happen before we make the host 192 - * syscall then we will 'lose' it, because at the point of 193 - * execve the process leaves QEMU's control. So we use the 194 - * safe syscall wrapper to ensure that we either take the 195 - * signal as a guest signal, or else it does not happen 196 - * before the execve completes and makes it the other 197 - * program's problem. 198 - */ 199 p = lock_user_string(pathname); 200 if (!p) { 201 goto execve_efault; 202 @@ -8765,10 +8886,7 @@ static int do_execv(CPUArchState *cpu_env, int dirfd, 203 if (is_proc_myself(p, "exe")) { 204 exe = exec_path; 205 } 206 - ret = is_execveat 207 - ? safe_execveat(dirfd, exe, argp, envp, flags) 208 - : safe_execve(exe, argp, envp); 209 - ret = get_errno(ret); 210 + ret = qemu_execve(dirfd, exe, argp, envp, flags, is_execveat); 211 212 unlock_user(p, pathname, 0); 213 214 diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h 215 index c63ef45fc7..125e499370 100644 216 --- a/linux-user/user-internals.h 217 +++ b/linux-user/user-internals.h 218 @@ -28,6 +28,7 @@ void init_task_state(TaskState *ts); 219 void task_settid(TaskState *); 220 void stop_all_tasks(void); 221 extern const char *qemu_uname_release; 222 +extern const char *qemu_execve_path; 223 extern unsigned long mmap_min_addr; 224 225 typedef struct IOCTLEntry IOCTLEntry; 226 diff --git a/target/i386/cpu.c b/target/i386/cpu.c 227 index 97ad229d8b..408db3365d 100644 228 --- a/target/i386/cpu.c 229 +++ b/target/i386/cpu.c 230 @@ -1759,6 +1759,7 @@ typedef struct X86CPUDefinition { 231 int family; 232 int model; 233 int stepping; 234 + int brand_id; 235 FeatureWordArray features; 236 const char *model_id; 237 const CPUCaches *const cache_info; 238 @@ -2444,6 +2445,54 @@ static const X86CPUDefinition builtin_x86_defs[] = { 239 .xlevel = 0, 240 .model_id = "", 241 }, 242 + { 243 + /* http://users.atw.hu/instlatx64/AuthenticAMD/AuthenticAMD0000F4A_K8_Clawhammer_CPUID.txt */ 244 + .name = "athlon-64", 245 + .level = 1, 246 + .vendor = CPUID_VENDOR_AMD, 247 + .family = 15, 248 + .model = 4, 249 + .stepping = 10, 250 + .features[FEAT_1_EDX] = 251 + CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | 252 + CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | 253 + CPUID_CX8 | CPUID_APIC | CPUID_SEP | 254 + CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV | 255 + CPUID_PAT | CPUID_PSE36 | /*no: CPUID_PN |*/ CPUID_CLFLUSH | 256 + /*no: CPUID_DTS | CPUID_ACPI |*/ CPUID_MMX | 257 + CPUID_FXSR | CPUID_SSE | CPUID_SSE2, 258 + .features[FEAT_8000_0001_EDX] = 259 + (CPUID_EXT2_FPU | CPUID_EXT2_VME | CPUID_EXT2_DE | CPUID_EXT2_PSE | 260 + CPUID_EXT2_TSC | CPUID_EXT2_MSR | CPUID_EXT2_PAE | CPUID_EXT2_MCE | 261 + CPUID_EXT2_CX8 | CPUID_EXT2_APIC | CPUID_EXT2_SYSCALL | 262 + CPUID_EXT2_MTRR | CPUID_EXT2_PGE | CPUID_EXT2_MCA | CPUID_EXT2_CMOV | 263 + CPUID_EXT2_PAT | CPUID_EXT2_PSE36 | /*no: CPUID_EXT2_MP */ 264 + CPUID_EXT2_NX | CPUID_EXT2_MMXEXT | CPUID_EXT2_MMX | 265 + CPUID_EXT2_FXSR | /*no: CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1G | CPUID_EXT2_RTDSCP*/ 266 + CPUID_EXT2_LM | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_3DNOW) & 267 + ~CPUID_EXT2_AMD_ALIASES, 268 + /* todo cache info 0x80000005-6 */ 269 + .features[FEAT_8000_0007_EDX] = 0x0f, /*??*/ 270 + /*.phys_bits = 0x00003028,*/ 271 + .xlevel = 0x80000018, 272 + .brand_id = 0x106, 273 + .model_id = "AMD Athlon(tm) 64 Processor 2800+", 274 + }, 275 + { 276 + .name = "u3-64bit-minimal", 277 + .level = 1, 278 + .vendor = CPUID_VENDOR_AMD, 279 + .family = 15, 280 + .model = 4, 281 + .stepping = 10, 282 + .features[FEAT_1_EDX] = 283 + PENTIUM2_FEATURES | PPRO_FEATURES | CPUID_CLFLUSH /*sse2?*/, 284 + .features[FEAT_8000_0001_EDX] = 285 + /* NX: amd: since amd64, intel: P4 Prescott+ */ 286 + CPUID_EXT2_SYSCALL | CPUID_EXT2_NX | CPUID_EXT2_LM, 287 + .xlevel = 0x80000018, 288 + .model_id = "Fuck off", 289 + }, 290 { 291 .name = "athlon", 292 .level = 2, 293 @@ -5165,6 +5214,41 @@ static void x86_cpuid_version_set_stepping(Object *obj, Visitor *v, 294 env->cpuid_version |= value & 0xf; 295 } 296 297 +static void x86_cpuid_version_get_brand_id(Object *obj, Visitor *v, 298 + const char *name, void *opaque, 299 + Error **errp) 300 +{ 301 + X86CPU *cpu = X86_CPU(obj); 302 + CPUX86State *env = &cpu->env; 303 + int64_t value; 304 + 305 + value = env->cpuid_brand_id; 306 + visit_type_int(v, name, &value, errp); 307 +} 308 + 309 +static void x86_cpuid_version_set_brand_id(Object *obj, Visitor *v, 310 + const char *name, void *opaque, 311 + Error **errp) 312 +{ 313 + X86CPU *cpu = X86_CPU(obj); 314 + CPUX86State *env = &cpu->env; 315 + const int64_t min = 0; 316 + const int64_t max = 0xffff; 317 + int64_t value; 318 + 319 + if (!visit_type_int(v, name, &value, errp)) { 320 + return; 321 + } 322 + if (value < min || value > max) { 323 + error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, "", 324 + name ? name : "null", value, min, max); 325 + return; 326 + } 327 + 328 + env->cpuid_brand_id = value; 329 +} 330 + 331 + 332 static char *x86_cpuid_get_vendor(Object *obj, Error **errp) 333 { 334 X86CPU *cpu = X86_CPU(obj); 335 @@ -5877,6 +5961,8 @@ static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model) 336 &error_abort); 337 object_property_set_str(OBJECT(cpu), "model-id", def->model_id, 338 &error_abort); 339 + object_property_set_int(OBJECT(cpu), "brand-id", def->brand_id, 340 + &error_abort); 341 for (w = 0; w < FEATURE_WORDS; w++) { 342 env->features[w] = def->features[w]; 343 } 344 @@ -6488,7 +6574,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, 345 break; 346 case 0x80000001: 347 *eax = env->cpuid_version; 348 - *ebx = 0; 349 + *ebx = env->cpuid_brand_id; 350 *ecx = env->features[FEAT_8000_0001_ECX]; 351 *edx = env->features[FEAT_8000_0001_EDX]; 352 353 @@ -7982,6 +8068,9 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) 354 object_class_property_add(oc, "stepping", "int", 355 x86_cpuid_version_get_stepping, 356 x86_cpuid_version_set_stepping, NULL, NULL); 357 + object_class_property_add(oc, "brand-id", "int", 358 + x86_cpuid_version_get_brand_id, 359 + x86_cpuid_version_set_brand_id, NULL, NULL); 360 object_class_property_add_str(oc, "vendor", 361 x86_cpuid_get_vendor, 362 x86_cpuid_set_vendor); 363 diff --git a/target/i386/cpu.h b/target/i386/cpu.h 364 index e0771a1043..2b9a1aef24 100644 365 --- a/target/i386/cpu.h 366 +++ b/target/i386/cpu.h 367 @@ -1803,6 +1803,7 @@ typedef struct CPUArchState { 368 uint32_t cpuid_vendor2; 369 uint32_t cpuid_vendor3; 370 uint32_t cpuid_version; 371 + uint32_t cpuid_brand_id; 372 FeatureWordArray features; 373 /* Features that were explicitly enabled/disabled */ 374 FeatureWordArray user_features;