From patchwork Tue Jul 25 13:44:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Tokarev X-Patchwork-Id: 706142 Delivered-To: patch@linaro.org Received: by 2002:a5d:464f:0:b0:317:2194:b2bc with SMTP id j15csp195580wrs; Tue, 25 Jul 2023 06:52:19 -0700 (PDT) X-Google-Smtp-Source: APBJJlHYWQZFc6lTkavG/cg8QcDT9Sd/ct1l3Y+orUIGFdhrXD+jYIcUFSCjuczUI4EXHQxrzRWt X-Received: by 2002:ac8:59d3:0:b0:405:3a8b:d753 with SMTP id f19-20020ac859d3000000b004053a8bd753mr3406645qtf.47.1690293139632; Tue, 25 Jul 2023 06:52:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1690293139; cv=none; d=google.com; s=arc-20160816; b=R7CTQv3Z8mtXHIGcthx9Uv5/xV3zp5tYz9YXRAI3mCpc80XKQNt32JM47q4T9UKPD9 Ow033KCNEfra38x5lrkKBBdDEzziDj8r+RP+F59KkCO13jS74wQxi7lMuqGDeEn2Zzit 826uWP9zEhFT55KDYVo7Rw3yCxhGcjGrIaDM7UFWPHTja9RvHC+Lzjjf+7GnURBny8pn BUjG3EExlPWVf8e+Qa6xCzIM2F7Yd4U2GyOa45TPV0tfYhIb1B/3A/Jt+ds4VYWFmke0 63xglT0DDSgpULUrkJa2jQWjOqpoI//n7znkEN61gfftx68fZ6zt9EUanIuFmbFFvkFf 5kNw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from; bh=JAagleDxxN9hC3CBJXDpuUZu61qYtSfnart72cbu6bg=; fh=fE54LLX1ksKgAWqXP2sVbot0faJG0Jr+3uWME2EBXXU=; b=pG8NryD1KtFBXHHfwdUz6D6O1q/MhfXjZo248mrqF6QHCoUHUdTBxrXXURGn6E6OCM PRhK8O5lU2BT/AKW0LGkRN9f+AVlSZtDorzhKW44N6IcC88MuXA7xqyxr9kQBm9KCVWv exc0+iQN2My1Zm8GxyNYgg+mIzki65Jlu5ZH0FckWfionzFzF3+c7cKpIXPh5mSf5Cco 8N91TZu8k0sIp4hdDaDV59QBXWOqCKoWUCnJGDSZw+/44MoWQaX5aXr+1t46hHyUt/jn XQXOMsQ708dxukQGpsWzTQ4E0AFddZtTb+dlyCQu8ynrQiAi7N6pLMVOQrwGkd9cwlky AF6w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org" Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id d7-20020a05622a15c700b00403bfdaa607si6625272qty.777.2023.07.25.06.52.19 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Tue, 25 Jul 2023 06:52:19 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org" Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qOINb-0007KV-7B; Tue, 25 Jul 2023 09:47:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qOIMo-0005l7-6f; Tue, 25 Jul 2023 09:46:32 -0400 Received: from isrv.corpit.ru ([86.62.121.231]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qOIMm-0001U7-AI; Tue, 25 Jul 2023 09:46:21 -0400 Received: from tsrv.corpit.ru (tsrv.tls.msk.ru [192.168.177.2]) by isrv.corpit.ru (Postfix) with ESMTP id D72EF160F5; Tue, 25 Jul 2023 16:45:34 +0300 (MSK) Received: from tls.msk.ru (mjt.wg.tls.msk.ru [192.168.177.130]) by tsrv.corpit.ru (Postfix) with SMTP id 77C7B194B8; Tue, 25 Jul 2023 16:45:32 +0300 (MSK) Received: (nullmailer pid 3370822 invoked by uid 1000); Tue, 25 Jul 2023 13:45:29 -0000 From: Michael Tokarev To: qemu-devel@nongnu.org Cc: qemu-stable@nongnu.org, Pierrick Bouvier , Richard Henderson , Michael Tokarev Subject: [Stable-8.0.4 13/31] linux-user/syscall: Implement execve without execveat Date: Tue, 25 Jul 2023 16:44:58 +0300 Message-Id: <20230725134517.3370706-13-mjt@tls.msk.ru> X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=86.62.121.231; envelope-from=mjt@tls.msk.ru; helo=isrv.corpit.ru X-Spam_score_int: -68 X-Spam_score: -6.9 X-Spam_bar: ------ X-Spam_report: (-6.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_HI=-5, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org From: Pierrick Bouvier Support for execveat syscall was implemented in 55bbe4 and is available since QEMU 8.0.0. It relies on host execveat, which is widely available on most of Linux kernels today. However, this change breaks qemu-user self emulation, if "host" qemu version is less than 8.0.0. Indeed, it does not implement yet execveat. This strange use case happens with most of distribution today having binfmt support. With a concrete failing example: $ qemu-x86_64-7.2 qemu-x86_64-8.0 /bin/bash -c /bin/ls /bin/bash: line 1: /bin/ls: Function not implemented -> not implemented means execve returned ENOSYS qemu-user-static 7.2 and 8.0 can be conveniently grabbed from debian packages qemu-user-static* [1]. One usage of this is running wine-arm64 from linux-x64 (details [2]). This is by updating qemu embedded in docker image that we ran into this issue. The solution to update host qemu is not always possible. Either it's complicated or ask you to recompile it, or simply is not accessible (GitLab CI, GitHub Actions). Thus, it could be worth to implement execve without relying on execveat, which is the goal of this patch. This patch was tested with example presented in this commit message. [1] http://ftp.us.debian.org/debian/pool/main/q/qemu/ [1] https://www.linaro.org/blog/emulate-windows-on-arm/ Signed-off-by: Pierrick Bouvier Reviewed-by: Richard Henderson Reviewed-by: Michael Tokarev Message-Id: <20230705121023.973284-1-pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson (cherry picked from commit 7a8d9f3a0e882df50681e40f09c29cfb4966ea2d) Signed-off-by: Michael Tokarev diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 0901884495..150d70633e 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -659,6 +659,7 @@ safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \ #endif safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \ int, options, struct rusage *, rusage) +safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp) safe_syscall5(int, execveat, int, dirfd, const char *, filename, char **, argv, char **, envp, int, flags) #if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \ @@ -8398,9 +8399,9 @@ static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int return safe_openat(dirfd, path(pathname), flags, mode); } -static int do_execveat(CPUArchState *cpu_env, int dirfd, - abi_long pathname, abi_long guest_argp, - abi_long guest_envp, int flags) +static int do_execv(CPUArchState *cpu_env, int dirfd, + abi_long pathname, abi_long guest_argp, + abi_long guest_envp, int flags, bool is_execveat) { int ret; char **argp, **envp; @@ -8479,11 +8480,14 @@ static int do_execveat(CPUArchState *cpu_env, int dirfd, goto execve_efault; } + const char *exe = p; if (is_proc_myself(p, "exe")) { - ret = get_errno(safe_execveat(dirfd, exec_path, argp, envp, flags)); - } else { - ret = get_errno(safe_execveat(dirfd, p, argp, envp, flags)); + exe = exec_path; } + ret = is_execveat + ? safe_execveat(dirfd, exe, argp, envp, flags) + : safe_execve(exe, argp, envp); + ret = get_errno(ret); unlock_user(p, pathname, 0); @@ -9022,9 +9026,9 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, return ret; #endif case TARGET_NR_execveat: - return do_execveat(cpu_env, arg1, arg2, arg3, arg4, arg5); + return do_execv(cpu_env, arg1, arg2, arg3, arg4, arg5, true); case TARGET_NR_execve: - return do_execveat(cpu_env, AT_FDCWD, arg1, arg2, arg3, 0); + return do_execv(cpu_env, AT_FDCWD, arg1, arg2, arg3, 0, false); case TARGET_NR_chdir: if (!(p = lock_user_string(arg1))) return -TARGET_EFAULT;