From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=3.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,HTML_MESSAGE,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id D4520C433E1 for ; Sun, 16 Aug 2020 22:22:39 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8AECB2078D for ; Sun, 16 Aug 2020 22:22:39 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OlySxjlT" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8AECB2078D Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:47974 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1k7R30-0007tl-Rx for qemu-devel@archiver.kernel.org; Sun, 16 Aug 2020 18:22:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:55496) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1k7R2A-0007Ab-N7 for qemu-devel@nongnu.org; Sun, 16 Aug 2020 18:21:46 -0400 Received: from mail-pj1-x1044.google.com ([2607:f8b0:4864:20::1044]:55136) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1k7R27-0004v4-S8 for qemu-devel@nongnu.org; Sun, 16 Aug 2020 18:21:46 -0400 Received: by mail-pj1-x1044.google.com with SMTP id mt12so6839103pjb.4 for ; Sun, 16 Aug 2020 15:21:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=b0SdwrsYedY049tu9iuSLzX/MrMDD/JbZ6cFFYG/7v8=; b=OlySxjlTLNSIrr7lFHINnQ6yUO4jjaZOwnwf+QZI7QHs327l4Nyt8EbVOKAkjUUrcw VAooQFTHAIEeNL99F+SNT9Kg2eNBiVGEP8GT9HZdf5oCi3OninPVjyHwxq5qW5nl/++I 9sm3G7v2aidjppzydTa7TCsjJiCkFmfXqXKYSIoHdIEJ1HNJK13TaZcmuisCs6ywEs3a /m2pOZyLegBOfteQER3pvkGNbNl/B83oVmBI7Dbi8oYgiLPgrIf+eufasKsUReji0gip MYrzVvk3Qag71Qrm7pgHK8pNlptLiS2D8GVnD/zDZo2XHo3UFxW0gY2TmadNqjWFiU1h MVqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=b0SdwrsYedY049tu9iuSLzX/MrMDD/JbZ6cFFYG/7v8=; b=p+7jqqu8sp7EzcJEjL/lwKDQJIUIeApCPudlEt96Mge2z5lWwK3em9/pXLLcDZmcWr Q82yLe3Zl8IroApBu31tw65ouLHYc5cC4tgiXuzINjwDZ8BIZKvEioqo+sQOFkiKLzIk C6ErgA1h2Jd6roxPAU9nQVA9kvBf37DnHPfQ3MgYbnhNl8lkdop5wiCcIM5uNB7No1cp 6FvRlbXkwdo7x7/DVENYGMPy/ZSW6QU4u3eMz5k0AxsRa9Q4yopQh/trLiVWIazICyJN byHJClZ2qGmzQH3abPX4lLNpRFJWthPozodWoSn4KXeEi8S8F3ScZpiQlLSsLaa7USCj HLRA== X-Gm-Message-State: AOAM531twL1s4xn7X8UewOfV0iUd35Tqa2n70nW/JPbut0Hg2bJ29Dw0 75nlO3k7UOMmZ0i7w02GqWkl/ufQcLV48FeGgkE= X-Google-Smtp-Source: ABdhPJzd/Ze8CUiGcWa2zdQDgoNCbSBZL4nyj3WtJgDlnVLclrnPrQ60+u3415IdAdxnEm85CljHq65gfiG3A6zG2+U= X-Received: by 2002:a17:90a:19c2:: with SMTP id 2mr9982106pjj.6.1597616501968; Sun, 16 Aug 2020 15:21:41 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: =?UTF-8?B?0JDQvdC00YDQtdC5INCQ0LvQsNC00YzQtdCy?= Date: Mon, 17 Aug 2020 01:21:30 +0300 Message-ID: Subject: Re: [PATCH] fixed proc myself (linux user) for musl To: =?UTF-8?Q?Philippe_Mathieu=2DDaud=C3=A9?= Content-Type: multipart/alternative; boundary="0000000000001651fc05ad06148b" Received-SPF: pass client-ip=2607:f8b0:4864:20::1044; envelope-from=aladjev.andrew@gmail.com; helo=mail-pj1-x1044.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Richard Henderson , qemu-devel@nongnu.org, Laurent Vivier Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" --0000000000001651fc05ad06148b Content-Type: text/plain; charset="UTF-8" >From 738f6ec4598b4618acd7ecbd11e5d250a82f28b7 Mon Sep 17 00:00:00 2001 From: Andrew Aladjev Date: Mon, 17 Aug 2020 01:20:03 +0300 Subject: [PATCH] fixed proc myself (linux user) for musl Signed-off-by: Andrew Aladjev --- linux-user/Makefile.objs | 5 +- linux-user/elfload.c | 7 ++- linux-user/exit.c | 7 ++- linux-user/main.c | 2 +- linux-user/qemu.h | 1 + linux-user/syscall.c | 63 ++++++++--------------- linux-user/syscall_proc.c | 102 ++++++++++++++++++++++++++++++++++++++ linux-user/syscall_proc.h | 8 +++ 8 files changed, 146 insertions(+), 49 deletions(-) create mode 100644 linux-user/syscall_proc.c create mode 100644 linux-user/syscall_proc.h diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs index 1940910a73..ad84380738 100644 --- a/linux-user/Makefile.objs +++ b/linux-user/Makefile.objs @@ -1,7 +1,8 @@ obj-y = main.o syscall.o strace.o mmap.o signal.o \ elfload.o linuxload.o uaccess.o uname.o \ - safe-syscall.o $(TARGET_ABI_DIR)/signal.o \ - $(TARGET_ABI_DIR)/cpu_loop.o exit.o fd-trans.o + safe-syscall.o syscall_proc.o \ + $(TARGET_ABI_DIR)/cpu_loop.o $(TARGET_ABI_DIR)/signal.o \ + exit.o fd-trans.o obj-$(TARGET_HAS_BFLT) += flatload.o obj-$(TARGET_I386) += vm86.o diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 619c054cc4..201db61d91 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -2319,7 +2319,10 @@ exit_errmsg: buffer is sufficiently aligned to present no problems to the host in accessing data at aligned offsets within the buffer. - On return: INFO values will be filled in, as necessary or available. */ + On return: INFO values will be filled in, as necessary or available. + + WARNING: this function won't close "image_fd". +*/ static void load_elf_image(const char *image_name, int image_fd, struct image_info *info, char **pinterp_name, @@ -2576,7 +2579,6 @@ static void load_elf_image(const char *image_name, int image_fd, mmap_unlock(); - close(image_fd); return; exit_read: @@ -2610,6 +2612,7 @@ static void load_elf_interp(const char *filename, struct image_info *info, } load_elf_image(filename, fd, info, NULL, bprm_buf); + close(fd); return; exit_perror: diff --git a/linux-user/exit.c b/linux-user/exit.c index 1594015444..f0626fc432 100644 --- a/linux-user/exit.c +++ b/linux-user/exit.c @@ -28,12 +28,15 @@ extern void __gcov_dump(void); void preexit_cleanup(CPUArchState *env, int code) { + close(execfd); + #ifdef CONFIG_GPROF _mcleanup(); #endif #ifdef CONFIG_GCOV __gcov_dump(); #endif - gdb_exit(env, code); - qemu_plugin_atexit_cb(); + + gdb_exit(env, code); + qemu_plugin_atexit_cb(); } diff --git a/linux-user/main.c b/linux-user/main.c index 22578b1633..9cc6c1e6da 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -48,6 +48,7 @@ #include "crypto/init.h" char *exec_path; +int execfd; int singlestep; static const char *argv0; @@ -628,7 +629,6 @@ int main(int argc, char **argv, char **envp) int target_argc; int i; int ret; - int execfd; int log_mask; unsigned long max_reserved_va; diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 792c74290f..d822f2b9df 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -156,6 +156,7 @@ typedef struct TaskState { } __attribute__((aligned(16))) TaskState; extern char *exec_path; +extern int execfd; void init_task_state(TaskState *ts); void task_settid(TaskState *); void stop_all_tasks(void); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 05f03919ff..af86385281 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -122,6 +122,7 @@ #include "qapi/error.h" #include "fd-trans.h" #include "tcg/tcg.h" +#include "syscall_proc.h" #ifndef CLONE_IO #define CLONE_IO 0x80000000 /* Clone io context */ @@ -7353,38 +7354,6 @@ static int open_self_auxv(void *cpu_env, int fd) return 0; } -static int is_proc_myself(const char *filename, const char *entry) -{ - if (!strncmp(filename, "/proc/", strlen("/proc/"))) { - filename += strlen("/proc/"); - if (!strncmp(filename, "self/", strlen("self/"))) { - filename += strlen("self/"); - } else if (*filename >= '1' && *filename <= '9') { - char myself[80]; - snprintf(myself, sizeof(myself), "%d/", getpid()); - if (!strncmp(filename, myself, strlen(myself))) { - filename += strlen(myself); - } else { - return 0; - } - } else { - return 0; - } - if (!strcmp(filename, entry)) { - return 1; - } - } - return 0; -} - -#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) || \ - defined(TARGET_SPARC) || defined(TARGET_M68K) -static int is_proc(const char *filename, const char *entry) -{ - return strcmp(filename, entry) == 0; -} -#endif - #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) static int open_net_route(void *cpu_env, int fd) { @@ -7460,20 +7429,19 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, { "auxv", open_self_auxv, is_proc_myself }, { "cmdline", open_self_cmdline, is_proc_myself }, #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) - { "/proc/net/route", open_net_route, is_proc }, + { "net/route", open_net_route, is_proc }, #endif #if defined(TARGET_SPARC) - { "/proc/cpuinfo", open_cpuinfo, is_proc }, + { "cpuinfo", open_cpuinfo, is_proc }, #endif #if defined(TARGET_M68K) - { "/proc/hardware", open_hardware, is_proc }, + { "hardware", open_hardware, is_proc }, #endif { NULL, NULL, NULL } }; - if (is_proc_myself(pathname, "exe")) { - int execfd = qemu_getauxval(AT_EXECFD); - return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mode); + if (is_proc_myself_exe(pathname)) { + return execfd; } for (fake_open = fakes; fake_open->filename; fake_open++) { @@ -7728,8 +7696,19 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, return ret; #endif case TARGET_NR_close: - fd_trans_unregister(arg1); - return get_errno(close(arg1)); + { + int fd = arg1; + if (fd == execfd) { + /* + * We don't need to close execfd. + * It will be closed on QEMU exit. + */ + return 0; + } + + fd_trans_unregister(fd); + return get_errno(close(fd)); + } case TARGET_NR_brk: return do_brk(arg1); @@ -9031,7 +9010,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, } else if (!arg3) { /* Short circuit this for the magic exe check. */ ret = -TARGET_EINVAL; - } else if (is_proc_myself((const char *)p, "exe")) { + } else if (is_proc_myself_exe((const char *)p)) { char real[PATH_MAX], *temp; temp = realpath(exec_path, real); /* Return value is # of bytes that we wrote to the buffer. */ @@ -9060,7 +9039,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0); if (!p || !p2) { ret = -TARGET_EFAULT; - } else if (is_proc_myself((const char *)p, "exe")) { + } else if (is_proc_myself_exe((const char *)p)) { char real[PATH_MAX], *temp; temp = realpath(exec_path, real); ret = temp == NULL ? get_errno(-1) : strlen(real) ; diff --git a/linux-user/syscall_proc.c b/linux-user/syscall_proc.c new file mode 100644 index 0000000000..8688459c7d --- /dev/null +++ b/linux-user/syscall_proc.c @@ -0,0 +1,102 @@ +#include "qemu/osdep.h" +#include "elf.h" + +#include "syscall_proc.h" +#include "qemu.h" + +#define PROC "/proc/" +#define SELF "self/" + +#define STARTS_WITH(path, CONSTANT) ( \ + strlen(path) >= strlen(CONSTANT) && \ + strncmp(path, CONSTANT, strlen(CONSTANT)) == 0 \ +) + +static inline char *scope_to_proc(const char *path) +{ + if (STARTS_WITH(path, PROC)) { + return (char *)path + strlen(PROC); + } + + return NULL; +} + +static inline char *scope_to_proc_myself(const char *path) +{ + char *scope_path = scope_to_proc(path); + if (scope_path == NULL) { + return NULL; + } + + if (STARTS_WITH(scope_path, SELF)) { + return scope_path + strlen(SELF); + } + + if (strlen(scope_path) >= 1 && + *scope_path >= '1' && *scope_path <= '9') { + char pid_path[80]; + snprintf(pid_path, sizeof(pid_path), "%d/", getpid()); + if (STARTS_WITH(scope_path, pid_path)) { + return scope_path + strlen(pid_path); + } + } + + return NULL; +} + +int is_proc(const char *path, const char *entry) +{ + char *scope_path = scope_to_proc(path); + if (scope_path == NULL) { + return 0; + } + + return strcmp(scope_path, entry) == 0; +} + +int is_proc_myself(const char *path, const char *entry) +{ + char *scope_path = scope_to_proc_myself(path); + if (scope_path == NULL) { + return 0; + } + + return strcmp(scope_path, entry) == 0; +} + +/* + * Kernel creates "fd/#{number}" link after opening "exe" link. + * Both "exe" and "fd/#{number}" can be used by application. + * + * Kernel can provide infinite amount of fd numbers. + * QEMU is going to always return single global execfd. + * + * So we need to check "exe" and "fd/#{execfd}" only. + */ + +int is_proc_myself_exe(const char *path) +{ + char *scope_path = scope_to_proc_myself(path); + if (scope_path == NULL) { + return 0; + } + + if (strcmp(scope_path, "exe") == 0) { + return 1; + } + + if (STARTS_WITH(scope_path, "fd/")) { + scope_path += strlen("fd/"); + + if (strlen(scope_path) >= 1 && + *scope_path >= '1' && *scope_path <= '9') { + char execfd_path[80]; + snprintf(execfd_path, sizeof(execfd_path), "%d", execfd); + if (strcmp(scope_path, execfd_path) == 0) { + return 1; + } + } + } + + return 0; +} diff --git a/linux-user/syscall_proc.h b/linux-user/syscall_proc.h new file mode 100644 index 0000000000..f0e59c0e96 --- /dev/null +++ b/linux-user/syscall_proc.h @@ -0,0 +1,8 @@ +#ifndef SYSCALL_PROC_H +#define SYSCALL_PROC_H + +int is_proc(const char *path, const char *entry); +int is_proc_myself(const char *path, const char *entry); +int is_proc_myself_exe(const char *path); + +#endif -- 2.26.2 --0000000000001651fc05ad06148b Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
From 738f6ec4598b4618acd7ecbd11e5d250a82f28b7 Mon Sep 17 0= 0:00:00 2001
From: Andrew Aladjev <aladjev.andrew@gmail.com>
Date: Mon, 17 Aug 2020 01:20:= 03 +0300
Subject: [PATCH] fixed proc myself (linux user) for musl
Signed-off-by: Andrew Aladjev <aladjev.andrew@gmail.com>
---
=C2=A0linux-user/Makefile.ob= js =C2=A0| =C2=A0 5 +-
=C2=A0linux-user/elfload.c =C2=A0 =C2=A0 =C2=A0| = =C2=A0 7 ++-
=C2=A0linux-user/exit.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2= =A0 7 ++-
=C2=A0linux-user/main.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0 2= +-
=C2=A0linux-user/qemu.h =C2=A0 =C2=A0 =C2=A0 =C2=A0 | =C2=A0 1 +
= =C2=A0linux-user/syscall.c =C2=A0 =C2=A0 =C2=A0| =C2=A063 ++++++++---------= ------
=C2=A0linux-user/syscall_proc.c | 102 +++++++++++++++++++++++++++= +++++++++++
=C2=A0linux-user/syscall_proc.h | =C2=A0 8 +++
=C2=A08 fi= les changed, 146 insertions(+), 49 deletions(-)
=C2=A0create mode 100644= linux-user/syscall_proc.c
=C2=A0create mode 100644 linux-user/syscall_p= roc.h

diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.ob= js
index 1940910a73..ad84380738 100644
--- a/linux-user/Makefile.objs=
+++ b/linux-user/Makefile.objs
@@ -1,7 +1,8 @@
=C2=A0obj-y =3D ma= in.o syscall.o strace.o mmap.o signal.o \
=C2=A0 elfload.o linuxload.o u= access.o uname.o \
- safe-syscall.o $(TARGET_ABI_DIR)/signal.o \
- = =C2=A0 =C2=A0 =C2=A0 =C2=A0$(TARGET_ABI_DIR)/cpu_loop.o exit.o fd-trans.o+ safe-syscall.o syscall_proc.o \
+ $(TARGET_ABI_DIR)/cpu_loop.o $(TAR= GET_ABI_DIR)/signal.o \
+ exit.o fd-trans.o
=C2=A0
=C2=A0obj-$(TAR= GET_HAS_BFLT) +=3D flatload.o
=C2=A0obj-$(TARGET_I386) +=3D vm86.o
di= ff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 619c054cc4.= .201db61d91 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfloa= d.c
@@ -2319,7 +2319,10 @@ exit_errmsg:
=C2=A0 =C2=A0 buffer is suffi= ciently aligned to present no problems to the host
=C2=A0 =C2=A0 in acce= ssing data at aligned offsets within the buffer.
=C2=A0
- =C2=A0 On r= eturn: INFO values will be filled in, as necessary or available. =C2=A0*/+ =C2=A0 On return: INFO values will be filled in, as necessary or availa= ble.
+
+ =C2=A0 WARNING: this function won't close "image_fd= ".
+*/
=C2=A0
=C2=A0static void load_elf_image(const char *im= age_name, int image_fd,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 struct image_info *info, = char **pinterp_name,
@@ -2576,7 +2579,6 @@ static void load_elf_image(co= nst char *image_name, int image_fd,
=C2=A0
=C2=A0 =C2=A0 =C2=A0mmap_u= nlock();
=C2=A0
- =C2=A0 =C2=A0close(image_fd);
=C2=A0 =C2=A0 =C2= =A0return;
=C2=A0
=C2=A0 exit_read:
@@ -2610,6 +2612,7 @@ static v= oid load_elf_interp(const char *filename, struct image_info *info,
=C2= =A0 =C2=A0 =C2=A0}
=C2=A0
=C2=A0 =C2=A0 =C2=A0load_elf_image(filename= , fd, info, NULL, bprm_buf);
+ =C2=A0 =C2=A0close(fd);
=C2=A0 =C2=A0 = =C2=A0return;
=C2=A0
=C2=A0 exit_perror:
diff --git a/linux-user/e= xit.c b/linux-user/exit.c
index 1594015444..f0626fc432 100644
--- a/l= inux-user/exit.c
+++ b/linux-user/exit.c
@@ -28,12 +28,15 @@ extern v= oid __gcov_dump(void);
=C2=A0
=C2=A0void preexit_cleanup(CPUArchState= *env, int code)
=C2=A0{
+ =C2=A0 =C2=A0close(execfd);
+
=C2=A0= #ifdef CONFIG_GPROF
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0_mcleanup();
= =C2=A0#endif
=C2=A0#ifdef CONFIG_GCOV
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0__gcov_dump();
=C2=A0#endif
- =C2=A0 =C2=A0 =C2=A0 =C2=A0gdb_exit(= env, code);
- =C2=A0 =C2=A0 =C2=A0 =C2=A0qemu_plugin_atexit_cb();
++ =C2=A0 =C2=A0gdb_exit(env, code);
+ =C2=A0 =C2=A0qemu_plugin_atexit_= cb();
=C2=A0}
diff --git a/linux-user/main.c b/linux-user/main.c
i= ndex 22578b1633..9cc6c1e6da 100644
--- a/linux-user/main.c
+++ b/linu= x-user/main.c
@@ -48,6 +48,7 @@
=C2=A0#include "crypto/init.h&qu= ot;
=C2=A0
=C2=A0char *exec_path;
+int execfd;
=C2=A0
=C2=A0= int singlestep;
=C2=A0static const char *argv0;
@@ -628,7 +629,6 @@ i= nt main(int argc, char **argv, char **envp)
=C2=A0 =C2=A0 =C2=A0int targ= et_argc;
=C2=A0 =C2=A0 =C2=A0int i;
=C2=A0 =C2=A0 =C2=A0int ret;
-= =C2=A0 =C2=A0int execfd;
=C2=A0 =C2=A0 =C2=A0int log_mask;
=C2=A0 = =C2=A0 =C2=A0unsigned long max_reserved_va;
=C2=A0
diff --git a/linux= -user/qemu.h b/linux-user/qemu.h
index 792c74290f..d822f2b9df 100644
= --- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -156,6 +156,7 @@ t= ypedef struct TaskState {
=C2=A0} __attribute__((aligned(16))) TaskState= ;
=C2=A0
=C2=A0extern char *exec_path;
+extern int execfd;
=C2= =A0void init_task_state(TaskState *ts);
=C2=A0void task_settid(TaskState= *);
=C2=A0void stop_all_tasks(void);
diff --git a/linux-user/syscall= .c b/linux-user/syscall.c
index 05f03919ff..af86385281 100644
--- a/l= inux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -122,6 +122,7 @@=C2=A0#include "qapi/error.h"
=C2=A0#include "fd-trans.h= "
=C2=A0#include "tcg/tcg.h"
+#include "syscall_p= roc.h"
=C2=A0
=C2=A0#ifndef CLONE_IO
=C2=A0#define CLONE_IO = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x80000000 =C2=A0 = =C2=A0 =C2=A0/* Clone io context */
@@ -7353,38 +7354,6 @@ static int op= en_self_auxv(void *cpu_env, int fd)
=C2=A0 =C2=A0 =C2=A0return 0;
=C2= =A0}
=C2=A0
-static int is_proc_myself(const char *filename, const ch= ar *entry)
-{
- =C2=A0 =C2=A0if (!strncmp(filename, "/proc/"= ;, strlen("/proc/"))) {
- =C2=A0 =C2=A0 =C2=A0 =C2=A0filename = +=3D strlen("/proc/");
- =C2=A0 =C2=A0 =C2=A0 =C2=A0if (!strnc= mp(filename, "self/", strlen("self/"))) {
- =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0filename +=3D strlen("self/");<= br>- =C2=A0 =C2=A0 =C2=A0 =C2=A0} else if (*filename >=3D '1' &a= mp;& *filename <=3D '9') {
- =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0char myself[80];
- =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0snprintf(myself, sizeof(myself), "%d/", getpid());
- =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (!strncmp(filename, myself, strlen(my= self))) {
- =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0filen= ame +=3D strlen(myself);
- =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} el= se {
- =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;<= br>- =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
- =C2=A0 =C2=A0 =C2=A0 = =C2=A0} else {
- =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
-= =C2=A0 =C2=A0 =C2=A0 =C2=A0}
- =C2=A0 =C2=A0 =C2=A0 =C2=A0if (!strcmp(f= ilename, entry)) {
- =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return 1;<= br>- =C2=A0 =C2=A0 =C2=A0 =C2=A0}
- =C2=A0 =C2=A0}
- =C2=A0 =C2=A0ret= urn 0;
-}
-
-#if defined(HOST_WORDS_BIGENDIAN) !=3D defined(TARGET= _WORDS_BIGENDIAN) || \
- =C2=A0 =C2=A0defined(TARGET_SPARC) || defined(T= ARGET_M68K)
-static int is_proc(const char *filename, const char *entry)=
-{
- =C2=A0 =C2=A0return strcmp(filename, entry) =3D=3D 0;
-}
= -#endif
-
=C2=A0#if defined(HOST_WORDS_BIGENDIAN) !=3D defined(TARGET= _WORDS_BIGENDIAN)
=C2=A0static int open_net_route(void *cpu_env, int fd)=
=C2=A0{
@@ -7460,20 +7429,19 @@ static int do_openat(void *cpu_env, = int dirfd, const char *pathname, int flags,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0{ "auxv", open_self_auxv, is_proc_myself },
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0{ "cmdline", open_self_cmdline, is_proc_m= yself },
=C2=A0#if defined(HOST_WORDS_BIGENDIAN) !=3D defined(TARGET_WOR= DS_BIGENDIAN)
- =C2=A0 =C2=A0 =C2=A0 =C2=A0{ "/proc/net/route"= , open_net_route, is_proc },
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0{ "net/ro= ute", open_net_route, is_proc },
=C2=A0#endif
=C2=A0#if defined(= TARGET_SPARC)
- =C2=A0 =C2=A0 =C2=A0 =C2=A0{ "/proc/cpuinfo", = open_cpuinfo, is_proc },
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0{ "cpuinfo&qu= ot;, open_cpuinfo, is_proc },
=C2=A0#endif
=C2=A0#if defined(TARGET_M= 68K)
- =C2=A0 =C2=A0 =C2=A0 =C2=A0{ "/proc/hardware", open_har= dware, is_proc },
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0{ "hardware", o= pen_hardware, is_proc },
=C2=A0#endif
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0{ NULL, NULL, NULL }
=C2=A0 =C2=A0 =C2=A0};
=C2=A0
- =C2=A0 =C2= =A0if (is_proc_myself(pathname, "exe")) {
- =C2=A0 =C2=A0 =C2= =A0 =C2=A0int execfd =3D qemu_getauxval(AT_EXECFD);
- =C2=A0 =C2=A0 =C2= =A0 =C2=A0return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mod= e);
+ =C2=A0 =C2=A0if (is_proc_myself_exe(pathname)) {
+ =C2=A0 =C2= =A0 =C2=A0 =C2=A0return execfd;
=C2=A0 =C2=A0 =C2=A0}
=C2=A0
=C2= =A0 =C2=A0 =C2=A0for (fake_open =3D fakes; fake_open->filename; fake_ope= n++) {
@@ -7728,8 +7696,19 @@ static abi_long do_syscall1(void *cpu_env,= int num, abi_long arg1,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return ret;=C2=A0#endif
=C2=A0 =C2=A0 =C2=A0case TARGET_NR_close:
- =C2=A0 =C2= =A0 =C2=A0 =C2=A0fd_trans_unregister(arg1);
- =C2=A0 =C2=A0 =C2=A0 =C2= =A0return get_errno(close(arg1));
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0{
+ = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0int fd =3D arg1;
+ =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (fd =3D=3D execfd) {
+ =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/*
+ =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 * We don't need to close execfd.
+ = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 * It will be closed= on QEMU exit.
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= */
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
+
+ =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0fd_trans_unregister(fd);
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0return get_errno(close(fd));
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0}
=C2=A0
=C2=A0 =C2=A0 =C2=A0case TARGET_NR_brk:
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0return do_brk(arg1);
@@ -9031,7 +9010,7 @@ stati= c abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} else if (!arg3) {
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Short circuit this for t= he magic exe check. */
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0ret =3D -TARGET_EINVAL;
- =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0} else if (is_proc_myself((const char *)p, "exe")) {+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} else if (is_proc_myself_exe((= const char *)p)) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0char real[PATH_MAX], *temp;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0temp =3D realpath(exec_path, real);
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Return value is #= of bytes that we wrote to the buffer. */
@@ -9060,7 +9039,7 @@ static a= bi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
=C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0p2 =3D lock_user(VERIFY_WRITE, arg3, arg= 4, 0);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (!p || !p2) {<= br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ret =3D -T= ARGET_EFAULT;
- =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0} else if (is_p= roc_myself((const char *)p, "exe")) {
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0} else if (is_proc_myself_exe((const char *)p)) {
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0char real[PAT= H_MAX], *temp;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0temp =3D realpath(exec_path, real);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ret =3D temp =3D=3D NULL ? get_errno(-1) = : strlen(real) ;
diff --git a/linux-user/syscall_proc.c b/linux-user/sys= call_proc.c
new file mode 100644
index 0000000000..8688459c7d
--- = /dev/null
+++ b/linux-user/syscall_proc.c
@@ -0,0 +1,102 @@
+#incl= ude "qemu/osdep.h"
+#include "elf.h"
+
+#inclu= de "syscall_proc.h"
+#include "qemu.h"
+
+#def= ine PROC "/proc/"
+#define SELF "self/"
+
+#de= fine STARTS_WITH(path, CONSTANT) ( =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0\
+ =C2=A0 =C2=A0strlen(path) >=3D strlen(CONSTANT) &&a= mp; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0\
+ =C2=A0 =C2=A0strncmp(pa= th, CONSTANT, strlen(CONSTANT)) =3D=3D 0 \
+)
+
+static inline cha= r *scope_to_proc(const char *path)
+{
+ =C2=A0 =C2=A0if (STARTS_WITH(= path, PROC)) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0return (char *)path + strlen= (PROC);
+ =C2=A0 =C2=A0}
+
+ =C2=A0 =C2=A0return NULL;
+}
+<= br>+static inline char *scope_to_proc_myself(const char *path)
+{
+ = =C2=A0 =C2=A0char *scope_path =3D scope_to_proc(path);
+ =C2=A0 =C2=A0if= (scope_path =3D=3D NULL) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0return NULL;+ =C2=A0 =C2=A0}
+
+ =C2=A0 =C2=A0if (STARTS_WITH(scope_path, SELF))= {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0return scope_path + strlen(SELF);
+ = =C2=A0 =C2=A0}
+
+ =C2=A0 =C2=A0if (strlen(scope_path) >=3D 1 &= ;&
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0*scope_path >=3D '1' &= ;& *scope_path <=3D '9') {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0c= har pid_path[80];
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0snprintf(pid_path, sizeof= (pid_path), "%d/", getpid());
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0if = (STARTS_WITH(scope_path, pid_path)) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0return scope_path + strlen(pid_path);
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0}
+ =C2=A0 =C2=A0}
+
+ =C2=A0 =C2=A0return NULL;
+}
+<= br>+int is_proc(const char *path, const char *entry)
+{
+ =C2=A0 =C2= =A0char *scope_path =3D scope_to_proc(path);
+ =C2=A0 =C2=A0if (scope_pa= th =3D=3D NULL) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
+ =C2=A0 =C2= =A0}
+
+ =C2=A0 =C2=A0return strcmp(scope_path, entry) =3D=3D 0;
+= }
+
+int is_proc_myself(const char *path, const char *entry)
+{+ =C2=A0 =C2=A0char *scope_path =3D scope_to_proc_myself(path);
+ =C2= =A0 =C2=A0if (scope_path =3D=3D NULL) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0ret= urn 0;
+ =C2=A0 =C2=A0}
+
+ =C2=A0 =C2=A0return strcmp(scope_path,= entry) =3D=3D 0;
+}
+
+/*
+ * Kernel creates "fd/#{number= }" link after opening "exe" link.
+ * Both "exe"= ; and "fd/#{number}" can be used by application.
+ *
+ * Ke= rnel can provide infinite amount of fd numbers.
+ * QEMU is going to alw= ays return single global execfd.
+ *
+ * So we need to check "ex= e" and "fd/#{execfd}" only.
+ */
+
+int is_proc_mys= elf_exe(const char *path)
+{
+ =C2=A0 =C2=A0char *scope_path =3D scop= e_to_proc_myself(path);
+ =C2=A0 =C2=A0if (scope_path =3D=3D NULL) {
= + =C2=A0 =C2=A0 =C2=A0 =C2=A0return 0;
+ =C2=A0 =C2=A0}
+
+ =C2=A0= =C2=A0if (strcmp(scope_path, "exe") =3D=3D 0) {
+ =C2=A0 =C2= =A0 =C2=A0 =C2=A0return 1;
+ =C2=A0 =C2=A0}
+
+ =C2=A0 =C2=A0if (S= TARTS_WITH(scope_path, "fd/")) {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0= scope_path +=3D strlen("fd/");
+
+ =C2=A0 =C2=A0 =C2=A0 =C2= =A0if (strlen(scope_path) >=3D 1 &&
+ =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0*scope_path >=3D '1' && *scope_path = <=3D '9') {
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0char e= xecfd_path[80];
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0snprintf(exec= fd_path, sizeof(execfd_path), "%d", execfd);
+ =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0if (strcmp(scope_path, execfd_path) =3D=3D 0) {<= br>+ =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return 1;
+ = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0}
+ =C2=A0 =C2=A0 =C2=A0 =C2=A0= }
+ =C2=A0 =C2=A0}
+
+ =C2=A0 =C2=A0return 0;
+}
diff --git = a/linux-user/syscall_proc.h b/linux-user/syscall_proc.h
new file mode 10= 0644
index 0000000000..f0e59c0e96
--- /dev/null
+++ b/linux-user/s= yscall_proc.h
@@ -0,0 +1,8 @@
+#ifndef SYSCALL_PROC_H
+#define SYS= CALL_PROC_H
+
+int is_proc(const char *path, const char *entry);
+= int is_proc_myself(const char *path, const char *entry);
+int is_proc_my= self_exe(const char *path);
+
+#endif
--
2.26.2

--0000000000001651fc05ad06148b--