diff --git a/.github/lockdown.yml b/.github/lockdown.yml new file mode 100644 index 0000000000..9acc393f1c --- /dev/null +++ b/.github/lockdown.yml @@ -0,0 +1,34 @@ +# Configuration for Repo Lockdown - https://github.com/dessant/repo-lockdown + +# Close issues and pull requests +close: true + +# Lock issues and pull requests +lock: true + +issues: + comment: | + Thank you for your interest in the QEMU project. + + This repository is a read-only mirror of the project's master + repostories hosted on https://git.qemu.org/git/qemu.git. + The project does not process issues filed on GitHub. + + The project issues are tracked on Launchpad: + https://bugs.launchpad.net/qemu + + QEMU welcomes bug report contributions. You can file new ones on: + https://bugs.launchpad.net/qemu/+filebug + +pulls: + comment: | + Thank you for your interest in the QEMU project. + + This repository is a read-only mirror of the project's master + repostories hosted on https://git.qemu.org/git/qemu.git. + The project does not process merge requests filed on GitHub. + + QEMU welcomes contributions of code (either fixing bugs or adding new + functionality). However, we get a lot of patches, and so we have some + guidelines about contributing on the project website: + https://www.qemu.org/contribute/ diff --git a/MAINTAINERS b/MAINTAINERS index 839959f7e4..642c8e0b6b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2834,6 +2834,7 @@ M: Alex Bennée M: Fam Zheng R: Philippe Mathieu-Daudé S: Maintained +F: .github/lockdown.yml F: .travis.yml F: scripts/travis/ F: .shippable.yml diff --git a/configure b/configure index 22870f3867..233c671aaa 100755 --- a/configure +++ b/configure @@ -2119,7 +2119,7 @@ if compile_prog "-Werror -fno-pie" "-no-pie"; then fi if test "$static" = "yes"; then - if test "$pie" != "no" && compile_prog "-fPIE -DPIE" "-static-pie"; then + if test "$pie" != "no" && compile_prog "-Werror -fPIE -DPIE" "-static-pie"; then QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS" QEMU_LDFLAGS="-static-pie $QEMU_LDFLAGS" pie="yes" @@ -2132,7 +2132,7 @@ if test "$static" = "yes"; then elif test "$pie" = "no"; then QEMU_CFLAGS="$CFLAGS_NOPIE $QEMU_CFLAGS" QEMU_LDFLAGS="$LDFLAGS_NOPIE $QEMU_LDFLAGS" -elif compile_prog "-fPIE -DPIE" "-pie"; then +elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS" QEMU_LDFLAGS="-pie $QEMU_LDFLAGS" pie="yes" diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 301ce3b537..ae6ba71854 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -5856,6 +5856,9 @@ static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, flag zSign, zSig1 = 0; zSig0 = aSig + bSig; if ( aExp == 0 ) { + if (zSig0 == 0) { + return packFloatx80(zSign, 0, 0); + } normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); goto roundAndPack; } diff --git a/gdbstub.c b/gdbstub.c index 013fb1ac0f..171e150950 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -2060,8 +2060,8 @@ static void handle_query_thread_extra(GdbCmdContext *gdb_ctx, void *user_ctx) /* Print the CPU model and name in multiprocess mode */ ObjectClass *oc = object_get_class(OBJECT(cpu)); const char *cpu_model = object_class_get_name(oc); - g_autofree char *cpu_name; - cpu_name = object_get_canonical_path_component(OBJECT(cpu)); + g_autofree char *cpu_name = + object_get_canonical_path_component(OBJECT(cpu)); g_string_printf(rs, "%s %s [%s]", cpu_model, cpu_name, cpu->halted ? "halted " : "running"); } else { diff --git a/hw/core/loader.c b/hw/core/loader.c index eeef6da9a1..8bbb1797a4 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -1447,6 +1447,7 @@ typedef struct { uint32_t current_rom_index; uint32_t rom_start_address; AddressSpace *as; + bool complete; } HexParser; /* return size or -1 if error */ @@ -1484,6 +1485,7 @@ static int handle_record_type(HexParser *parser) parser->current_rom_index, parser->rom_start_address, parser->as); } + parser->complete = true; return parser->total_size; case EXT_SEG_ADDR_RECORD: case EXT_LINEAR_ADDR_RECORD: @@ -1548,11 +1550,12 @@ static int parse_hex_blob(const char *filename, hwaddr *addr, uint8_t *hex_blob, .bin_buf = g_malloc(hex_blob_size), .start_addr = addr, .as = as, + .complete = false }; rom_transaction_begin(); - for (; hex_blob < end; ++hex_blob) { + for (; hex_blob < end && !parser.complete; ++hex_blob) { switch (*hex_blob) { case '\r': case '\n': diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h index a1411bfcab..e0bb47bb67 100644 --- a/include/hw/elf_ops.h +++ b/include/hw/elf_ops.h @@ -104,19 +104,21 @@ static int glue(symcmp, SZ)(const void *s0, const void *s1) : ((sym0->st_value > sym1->st_value) ? 1 : 0); } -static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, - int clear_lsb, symbol_fn_t sym_cb) +static void glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, + int clear_lsb, symbol_fn_t sym_cb) { - struct elf_shdr *symtab, *strtab, *shdr_table = NULL; - struct elf_sym *syms = NULL; + struct elf_shdr *symtab, *strtab; + g_autofree struct elf_shdr *shdr_table = NULL; + g_autofree struct elf_sym *syms = NULL; + g_autofree char *str = NULL; struct syminfo *s; int nsyms, i; - char *str = NULL; shdr_table = load_at(fd, ehdr->e_shoff, sizeof(struct elf_shdr) * ehdr->e_shnum); - if (!shdr_table) - return -1; + if (!shdr_table) { + return ; + } if (must_swab) { for (i = 0; i < ehdr->e_shnum; i++) { @@ -125,23 +127,25 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, } symtab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_SYMTAB); - if (!symtab) - goto fail; + if (!symtab) { + return; + } syms = load_at(fd, symtab->sh_offset, symtab->sh_size); - if (!syms) - goto fail; + if (!syms) { + return; + } nsyms = symtab->sh_size / sizeof(struct elf_sym); /* String table */ if (symtab->sh_link >= ehdr->e_shnum) { - goto fail; + return; } strtab = &shdr_table[symtab->sh_link]; str = load_at(fd, strtab->sh_offset, strtab->sh_size); if (!str) { - goto fail; + return; } i = 0; @@ -170,8 +174,13 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, } i++; } - syms = g_realloc(syms, nsyms * sizeof(*syms)); + /* check we have symbols left */ + if (nsyms == 0) { + return; + } + + syms = g_realloc(syms, nsyms * sizeof(*syms)); qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ)); for (i = 0; i < nsyms - 1; i++) { if (syms[i].st_size == 0) { @@ -182,18 +191,11 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, /* Commit */ s = g_malloc0(sizeof(*s)); s->lookup_symbol = glue(lookup_symbol, SZ); - glue(s->disas_symtab.elf, SZ) = syms; + glue(s->disas_symtab.elf, SZ) = g_steal_pointer(&syms); s->disas_num_syms = nsyms; - s->disas_strtab = str; + s->disas_strtab = g_steal_pointer(&str); s->next = syminfos; syminfos = s; - g_free(shdr_table); - return 0; - fail: - g_free(syms); - g_free(str); - g_free(shdr_table); - return -1; } static int glue(elf_reloc, SZ)(struct elfhdr *ehdr, int fd, int must_swab, diff --git a/include/qemu/selfmap.h b/include/qemu/selfmap.h new file mode 100644 index 0000000000..8382c4c779 --- /dev/null +++ b/include/qemu/selfmap.h @@ -0,0 +1,44 @@ +/* + * Utility functions to read our own memory map + * + * Copyright (c) 2020 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef _SELFMAP_H_ +#define _SELFMAP_H_ + +typedef struct { + unsigned long start; + unsigned long end; + + /* flags */ + bool is_read; + bool is_write; + bool is_exec; + bool is_priv; + + unsigned long offset; + gchar *dev; + uint64_t inode; + gchar *path; +} MapInfo; + + +/** + * read_self_maps: + * + * Read /proc/self/maps and return a list of MapInfo structures. + */ +GSList *read_self_maps(void); + +/** + * free_self_maps: + * @info: a GSlist + * + * Free a list of MapInfo structures. + */ +void free_self_maps(GSList *info); + +#endif /* _SELFMAP_H_ */ diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 8198be0446..619c054cc4 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -2172,6 +2172,8 @@ unsigned long init_guest_space(unsigned long host_start, /* Check to see if the address is valid. */ if (host_start && real_start != current_start) { + qemu_log_mask(CPU_LOG_PAGE, "invalid %lx && %lx != %lx\n", + host_start, real_start, current_start); goto try_again; } @@ -2240,7 +2242,11 @@ unsigned long init_guest_space(unsigned long host_start, * probably a bad strategy if not, which means we got here * because of trouble with ARM commpage setup. */ - munmap((void *)real_start, real_size); + if (munmap((void *)real_start, real_size) != 0) { + error_report("%s: failed to unmap %lx:%lx (%s)", __func__, + real_start, real_size, strerror(errno)); + abort(); + } current_start += align; if (host_start == current_start) { /* Theoretically possible if host doesn't have any suitably diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 5af55fca78..6495ddc4cd 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -117,6 +117,7 @@ #include "qemu.h" #include "qemu/guest-random.h" +#include "qemu/selfmap.h" #include "user/syscall-trace.h" #include "qapi/error.h" #include "fd-trans.h" @@ -7232,58 +7233,61 @@ static int open_self_maps(void *cpu_env, int fd) { CPUState *cpu = env_cpu((CPUArchState *)cpu_env); TaskState *ts = cpu->opaque; - FILE *fp; - char *line = NULL; - size_t len = 0; - ssize_t read; + GSList *map_info = read_self_maps(); + GSList *s; + int count; - fp = fopen("/proc/self/maps", "r"); - if (fp == NULL) { - return -1; - } + for (s = map_info; s; s = g_slist_next(s)) { + MapInfo *e = (MapInfo *) s->data; - while ((read = getline(&line, &len, fp)) != -1) { - int fields, dev_maj, dev_min, inode; - uint64_t min, max, offset; - char flag_r, flag_w, flag_x, flag_p; - char path[512] = ""; - fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d" - " %512s", &min, &max, &flag_r, &flag_w, &flag_x, - &flag_p, &offset, &dev_maj, &dev_min, &inode, path); - - if ((fields < 10) || (fields > 11)) { - continue; - } - if (h2g_valid(min)) { + if (h2g_valid(e->start)) { + unsigned long min = e->start; + unsigned long max = e->end; int flags = page_get_flags(h2g(min)); - max = h2g_valid(max - 1) ? max : (uintptr_t)g2h(GUEST_ADDR_MAX) + 1; + const char *path; + + max = h2g_valid(max - 1) ? + max : (uintptr_t) g2h(GUEST_ADDR_MAX) + 1; + if (page_check_range(h2g(min), max - min, flags) == -1) { continue; } + if (h2g(min) == ts->info->stack_limit) { - pstrcpy(path, sizeof(path), " [stack]"); + path = "[stack]"; + } else { + path = e->path; + } + + count = dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr + " %c%c%c%c %08" PRIx64 " %s %"PRId64, + h2g(min), h2g(max - 1) + 1, + e->is_read ? 'r' : '-', + e->is_write ? 'w' : '-', + e->is_exec ? 'x' : '-', + e->is_priv ? 'p' : '-', + (uint64_t) e->offset, e->dev, e->inode); + if (path) { + dprintf(fd, "%*s%s\n", 73 - count, "", path); + } else { + dprintf(fd, "\n"); } - dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr - " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n", - h2g(min), h2g(max - 1) + 1, flag_r, flag_w, - flag_x, flag_p, offset, dev_maj, dev_min, inode, - path[0] ? " " : "", path); } } + free_self_maps(map_info); + #ifdef TARGET_VSYSCALL_PAGE /* * We only support execution from the vsyscall page. * This is as if CONFIG_LEGACY_VSYSCALL_XONLY=y from v5.3. */ - dprintf(fd, TARGET_FMT_lx "-" TARGET_FMT_lx - " --xp 00000000 00:00 0 [vsyscall]\n", - TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE); + count = dprintf(fd, TARGET_FMT_lx "-" TARGET_FMT_lx + " --xp 00000000 00:00 0", + TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE); + dprintf(fd, "%*s%s\n", 73 - count, "", "[vsyscall]"); #endif - free(line); - fclose(fp); - return 0; } @@ -11331,11 +11335,11 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, This is a hint, so ignoring and returning success is ok. */ return 0; #endif -#if TARGET_ABI_BITS == 32 +#ifdef TARGET_NR_fcntl64 case TARGET_NR_fcntl64: { - int cmd; - struct flock64 fl; + int cmd; + struct flock64 fl; from_flock64_fn *copyfrom = copy_from_user_flock64; to_flock64_fn *copyto = copy_to_user_flock64; @@ -11346,7 +11350,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } #endif - cmd = target_to_host_fcntl_cmd(arg2); + cmd = target_to_host_fcntl_cmd(arg2); if (cmd == -TARGET_EINVAL) { return cmd; } diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 8aa972cafd..37f65b1f03 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1174,6 +1174,11 @@ static void xtensa_tr_init_disas_context(DisasContextBase *dcbase, dc->callinc = ((tb_flags & XTENSA_TBFLAG_CALLINC_MASK) >> XTENSA_TBFLAG_CALLINC_SHIFT); + /* + * FIXME: This will leak when a failed instruction load or similar + * event causes us to longjump out of the translation loop and + * hence not clean-up in xtensa_tr_tb_stop + */ if (dc->config->isa) { dc->insnbuf = xtensa_insnbuf_alloc(dc->config->isa); dc->slotbuf = xtensa_insnbuf_alloc(dc->config->isa); diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.inc.c index 7f61eeedd0..ec083bddcf 100644 --- a/tcg/i386/tcg-target.inc.c +++ b/tcg/i386/tcg-target.inc.c @@ -3737,7 +3737,7 @@ static void tcg_target_qemu_prologue(TCGContext *s) } else { /* Choose R12 because, as a base, it requires a SIB byte. */ x86_guest_base_index = TCG_REG_R12; - tcg_out_mov(s, TCG_TYPE_PTR, x86_guest_base_index, guest_base); + tcg_out_movi(s, TCG_TYPE_PTR, x86_guest_base_index, guest_base); tcg_regset_set_reg(s->reserved_regs, x86_guest_base_index); } } diff --git a/tests/tcg/x86_64/system/boot.S b/tests/tcg/x86_64/system/boot.S index 205cfbd398..73b19a2bda 100644 --- a/tests/tcg/x86_64/system/boot.S +++ b/tests/tcg/x86_64/system/boot.S @@ -41,10 +41,7 @@ #define XEN_ELFNOTE_PHYS32_ENTRY 18 #define __ASM_FORM(x) x -#define __ASM_FORM_RAW(x) x -#define __ASM_FORM_COMMA(x) x, -#define __ASM_SEL(a,b) __ASM_FORM(b) -#define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b) +#define __ASM_SEL(a,b) __ASM_FORM(b) #define _ASM_PTR __ASM_SEL(.long, .quad) ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, _ASM_PTR 0x100000) diff --git a/util/Makefile.objs b/util/Makefile.objs index 6718a38b61..fe339c2636 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -63,3 +63,4 @@ util-obj-y += guest-random.o util-obj-$(CONFIG_GIO) += dbus.o dbus.o-cflags = $(GIO_CFLAGS) dbus.o-libs = $(GIO_LIBS) +util-obj-$(CONFIG_USER_ONLY) += selfmap.o diff --git a/util/selfmap.c b/util/selfmap.c new file mode 100644 index 0000000000..2ec99dfdda --- /dev/null +++ b/util/selfmap.c @@ -0,0 +1,78 @@ +/* + * Utility function to get QEMU's own process map + * + * Copyright (c) 2020 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/cutils.h" +#include "qemu/selfmap.h" + +GSList *read_self_maps(void) +{ + gchar *maps; + GSList *map_info = NULL; + + if (g_file_get_contents("/proc/self/maps", &maps, NULL, NULL)) { + gchar **lines = g_strsplit(maps, "\n", 0); + int i, entries = g_strv_length(lines); + + for (i = 0; i < entries; i++) { + gchar **fields = g_strsplit(lines[i], " ", 6); + if (g_strv_length(fields) > 4) { + MapInfo *e = g_new0(MapInfo, 1); + int errors; + const char *end; + + errors = qemu_strtoul(fields[0], &end, 16, &e->start); + errors += qemu_strtoul(end + 1, NULL, 16, &e->end); + + e->is_read = fields[1][0] == 'r'; + e->is_write = fields[1][1] == 'w'; + e->is_exec = fields[1][2] == 'x'; + e->is_priv = fields[1][3] == 'p'; + + errors += qemu_strtoul(fields[2], NULL, 16, &e->offset); + e->dev = g_strdup(fields[3]); + errors += qemu_strtou64(fields[4], NULL, 10, &e->inode); + + /* + * The last field may have leading spaces which we + * need to strip. + */ + if (g_strv_length(fields) == 6) { + e->path = g_strdup(g_strchug(fields[5])); + } + map_info = g_slist_prepend(map_info, e); + } + + g_strfreev(fields); + } + g_strfreev(lines); + g_free(maps); + } + + /* ensure the map data is in the same order we collected it */ + return g_slist_reverse(map_info); +} + +/** + * free_self_maps: + * @info: a GSlist + * + * Free a list of MapInfo structures. + */ +static void free_info(gpointer data) +{ + MapInfo *e = (MapInfo *) data; + g_free(e->dev); + g_free(e->path); + g_free(e); +} + +void free_self_maps(GSList *info) +{ + g_slist_free_full(info, &free_info); +}