From bbf5f2a1aa39fcab01000a0f3b566f1e6b788a23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 3 Apr 2020 20:11:40 +0100 Subject: linux-user: protect fcntl64 with an #ifdef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checking TARGET_ABI_BITS is sketchy - we should check for the presence of the define to be sure. Also clean up the white space while we are there. Signed-off-by: Alex Bennée Reviewed-by: Laurent Vivier Reviewed-by: Richard Henderson Message-Id: <20200403191150.863-3-alex.bennee@linaro.org> --- linux-user/syscall.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux-user') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 5af55fc..b679bc6 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -11331,11 +11331,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 +11346,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; } -- cgit v1.1 From b859040dc44b271e9ad29f729cac71d2389b05fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 3 Apr 2020 20:11:42 +0100 Subject: linux-user: more debug for init_guest_space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Searching for memory space can cause problems so lets extend the CPU_LOG_PAGE output so you can watch init_guest_space fail to allocate memory. A more involved fix is actually required to make this function play nicely with the large guard pages the sanitiser likes to use. Signed-off-by: Alex Bennée Reviewed-by: Laurent Vivier Message-Id: <20200403191150.863-5-alex.bennee@linaro.org> --- linux-user/elfload.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'linux-user') diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 8198be0..619c054 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 -- cgit v1.1 From 01ef6b9e4e4e84b106b7f934354eada8fe36674f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 3 Apr 2020 20:11:46 +0100 Subject: linux-user: factor out reading of /proc/self/maps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unfortunately reading /proc/self/maps is still considered the gold standard for a process finding out about it's own memory layout. As we will want this data in other contexts soon factor out the code to read and parse the data. Rather than just blindly copying the existing sscanf based code we use a more modern glib version of the parsing code to make a more general purpose map structure. Signed-off-by: Alex Bennée Message-Id: <20200403191150.863-9-alex.bennee@linaro.org> --- linux-user/syscall.c | 58 +++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 30 deletions(-) (limited to 'linux-user') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b679bc6..5f11787 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,45 +7233,45 @@ 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; - 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; } + 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); + " %c%c%c%c %08" PRIx64 " %s %"PRId64" %s%s\n", + 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, + path ? " " : "", path ? path : ""); } } + free_self_maps(map_info); + #ifdef TARGET_VSYSCALL_PAGE /* * We only support execution from the vsyscall page. @@ -7281,9 +7282,6 @@ static int open_self_maps(void *cpu_env, int fd) TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE); #endif - free(line); - fclose(fp); - return 0; } -- cgit v1.1 From bb55173cfb7bd69b79c4092bf524a32b0fdeddbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 3 Apr 2020 20:11:47 +0100 Subject: linux-user: clean-up padding on /proc/self/maps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't use magic spaces, calculate the justification for the file field like the kernel does with seq_pad. Signed-off-by: Alex Bennée Reviewed-by: Richard Henderson Message-Id: <20200403191150.863-10-alex.bennee@linaro.org> --- linux-user/syscall.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'linux-user') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 5f11787..6495ddc 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7235,6 +7235,7 @@ static int open_self_maps(void *cpu_env, int fd) TaskState *ts = cpu->opaque; GSList *map_info = read_self_maps(); GSList *s; + int count; for (s = map_info; s; s = g_slist_next(s)) { MapInfo *e = (MapInfo *) s->data; @@ -7253,20 +7254,24 @@ static int open_self_maps(void *cpu_env, int fd) } if (h2g(min) == ts->info->stack_limit) { - path = " [stack]"; + path = "[stack]"; } else { path = e->path; } - dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr - " %c%c%c%c %08" PRIx64 " %s %"PRId64" %s%s\n", - 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, - path ? " " : "", path ? 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"); + } } } @@ -7277,9 +7282,10 @@ static int open_self_maps(void *cpu_env, int fd) * 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 return 0; -- cgit v1.1