From patchwork Mon Jul 3 15:48:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pierrick Bouvier X-Patchwork-Id: 698718 Delivered-To: patch@linaro.org Received: by 2002:adf:fcc5:0:0:0:0:0 with SMTP id f5csp1818146wrs; Mon, 3 Jul 2023 08:49:20 -0700 (PDT) X-Google-Smtp-Source: APBJJlHDoLVuluPUtkfjxqIiaZp3LSwt6Eu38+21DaMQSbM/8+VzAQQ6N4KcQ+wxGgitpUlZx87J X-Received: by 2002:a05:6214:d4a:b0:630:1faa:a404 with SMTP id 10-20020a0562140d4a00b006301faaa404mr16037119qvr.39.1688399359733; Mon, 03 Jul 2023 08:49:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1688399359; cv=none; d=google.com; s=arc-20160816; b=wP4crCvFoyLKVwMRtfs9beaCL9TjVUU9Phs7K1h3avusAh65qgMkczdV9CtigTVWJX DyrNAhcpYkN+SgqiAmTywo9Q1Z0outsj/ZEwiUnnA/3mne2qT5p96pdk4K0po7k8pdeC 9g9fDQIEyRhqceQDlv8+VZtcIMe6h8tv+EfO8g0OJv9A05kGl1gtNc8m0rTEp4YXKnbz 2uivmz7s7Mvv1itwfRmEv+qmGNYfCto9xwD3TBuIRoZnpEi/wEJ/FlFbod3D2K5upUce y2H9BYWsuGVEexvZSmDravNuJ07HpmNxOW2GXacPl6AgP5wQEYO51nDO0my8vVWRRPSv Gz/g== 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:message-id:date:subject:cc:to:from:dkim-signature; bh=K6nvw44qQqM9g5knmzRWwl/2devY8jYCycM1edBfsPA=; fh=JZRaBWzjyZBlzUJI92Y33XzUB/h47Xa0b34sgRRQ9MQ=; b=BGty1WSYHp1ASsAoVFIWrj4is76KWIUjTOl3y91v+bPVMeAGMcf8MqNvdPey45oN5/ L5LTo6mhLR3vJd1xKXXXnbIvKoFBTtIhqQAp4xUKbh6lgmRSPeOrSmQKSnvpwmfSwiG5 qB+bZ8y7aPOq6xUi3ZlkF29a9ofvH9mz5+d4JK8lpQj5m7zUdeYsWk37ygrhLXUca5SS /9PZBC/KoatLZF320gBicRCIWutZASefESAe27y4egLMk7/kk+D0xRSzAz94xvzE0I3B bBfeW4m5RXX6k+dustF820xi3Ckvl90aavKBOxEalOmj38WzcDga+V+gNcN4BQ84ro7O sZFQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=xYCGqR8f; 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"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id kk20-20020a056214509400b00636cec467casi1942814qvb.108.2023.07.03.08.49.19 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Mon, 03 Jul 2023 08:49: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; dkim=pass header.i=@linaro.org header.s=google header.b=xYCGqR8f; 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"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qGLnO-00062C-Pq; Mon, 03 Jul 2023 11:48:58 -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 1qGLnL-0005zc-Hi for qemu-devel@nongnu.org; Mon, 03 Jul 2023 11:48:55 -0400 Received: from mail-wr1-x434.google.com ([2a00:1450:4864:20::434]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qGLnJ-0001un-IQ for qemu-devel@nongnu.org; Mon, 03 Jul 2023 11:48:55 -0400 Received: by mail-wr1-x434.google.com with SMTP id ffacd0b85a97d-313f1085ac2so5131939f8f.1 for ; Mon, 03 Jul 2023 08:48:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1688399331; x=1690991331; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=K6nvw44qQqM9g5knmzRWwl/2devY8jYCycM1edBfsPA=; b=xYCGqR8fBLyDSP4nCE3vVLK+nYwIAvJGXqAKyEzKuaoZiwp7exRZFqki8E+7kV5tQd zfxrTGXqTE8PX8r8Bv+hGPjF6KjoG8dlv+ka+9M61LYX41dWh5KGmCjC4zsvf7pdXvhf 4I38ypnL0ZdrmtK/uBBiFu8iahdzqK1qrzY+fkr7KoiRCCad1aG4Mu+8brairUR1+8mx CdfqRRP+i66yMfhs4v07mRiPRd2G+MTdcx5gXdXx9dUZaEz9Xw4u5PabsBZnWogCNI7e GGOihEq5I0/GVdJ+3vWFGHp7EpKZxbZ56ZixhWXFa1RVDwcEiETrNW4acg5oR4nM7AvO QAoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1688399331; x=1690991331; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=K6nvw44qQqM9g5knmzRWwl/2devY8jYCycM1edBfsPA=; b=BrYaWma/k7zUPL/GDWYjYzfr78tu3BJ0qJrvs0sJKzCv6n7siub+WQaviVAtFljHqZ 6TmXylaMGx6z4jMhGzT1/QWFxnN0ZVx1mORpbEPCLF1HAyffmshz1LmNeQUatLmjV5Ok lKk69iECtHq0Mpr8god+FU4rIKGTaaWx05jhzxyUgEQamg462ZhZClU36nNDO1fOJRVN lRY9MJjrfOmgODGICF4Bg93EpB7NUW0PAafQZcPmz7FpAGfkHdYqCiIefxENKg8nfcHL K0L9UOU7I55S9NXjR60Zc5BXuM4P+6e9cUwOFgoENu0Ba9ncCNpl6Zjmj/wVFy0r6LSa Bepw== X-Gm-Message-State: ABy/qLZpYO8LqNbDkxlMFtbOh0ZHcuLY7e88KufeJsxEEb2qIFi1dvc0 HMV2RUSB0WhkvhwzoRJC/S4hGRL9Y9xEsJ8aVe8= X-Received: by 2002:adf:ee51:0:b0:314:2a9:1071 with SMTP id w17-20020adfee51000000b0031402a91071mr9711954wro.19.1688399331110; Mon, 03 Jul 2023 08:48:51 -0700 (PDT) Received: from localhost.localdomain ([2a01:e0a:5cc:caa0:6d79:3eab:6444:9cd4]) by smtp.gmail.com with ESMTPSA id h15-20020a05600004cf00b0030e52d4c1bcsm26154285wri.71.2023.07.03.08.48.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Jul 2023 08:48:50 -0700 (PDT) From: Pierrick Bouvier To: qemu-devel@nongnu.org Cc: laurent@vivier.eu, richard.henderson@linaro.org, sir@cmpwn.com, Pierrick Bouvier Subject: [PATCH] linux-user/syscall: Implement execve without execveat Date: Mon, 3 Jul 2023 17:48:31 +0200 Message-Id: <20230703154831.1136575-1-pierrick.bouvier@linaro.org> X-Mailer: git-send-email 2.40.1 MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::434; envelope-from=pierrick.bouvier@linaro.org; helo=mail-wr1-x434.google.com 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, RCVD_IN_DNSWL_NONE=-0.0001, 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 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 --- linux-user/syscall.c | 45 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f2cb101d83..b64ec3296a 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) || \ @@ -8520,9 +8521,12 @@ 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) +#define IS_EXECVEAT 0 +#define IS_EXECVE 1 + +static int do_execv(CPUArchState *cpu_env, int dirfd, + abi_long pathname, abi_long guest_argp, + abi_long guest_envp, int flags, bool is_execve) { int ret; char **argp, **envp; @@ -8601,10 +8605,18 @@ static int do_execveat(CPUArchState *cpu_env, int dirfd, goto execve_efault; } - if (is_proc_myself(p, "exe")) { - ret = get_errno(safe_execveat(dirfd, exec_path, argp, envp, flags)); + if (is_execve == IS_EXECVE) { + if (is_proc_myself(p, "exe")) { + ret = get_errno(safe_execve(exec_path, argp, envp)); + } else { + ret = get_errno(safe_execve(p, argp, envp)); + } } else { - ret = get_errno(safe_execveat(dirfd, p, argp, envp, flags)); + 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)); + } } unlock_user(p, pathname, 0); @@ -8633,6 +8645,25 @@ execve_end: return ret; } +static int do_execveat(CPUArchState *cpu_env, int dirfd, + abi_long pathname, abi_long guest_argp, + abi_long guest_envp, int flags) +{ + return do_execv(cpu_env, dirfd, + pathname, guest_argp, guest_envp, flags, + IS_EXECVEAT); +} + +static int do_execve(CPUArchState *cpu_env, + abi_long pathname, abi_long guest_argp, + abi_long guest_envp) +{ + return do_execv(cpu_env, AT_FDCWD, + pathname, guest_argp, guest_envp, 0, + IS_EXECVE); +} + + #define TIMER_MAGIC 0x0caf0000 #define TIMER_MAGIC_MASK 0xffff0000 @@ -9158,7 +9189,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, case TARGET_NR_execveat: return do_execveat(cpu_env, arg1, arg2, arg3, arg4, arg5); case TARGET_NR_execve: - return do_execveat(cpu_env, AT_FDCWD, arg1, arg2, arg3, 0); + return do_execve(cpu_env, arg1, arg2, arg3); case TARGET_NR_chdir: if (!(p = lock_user_string(arg1))) return -TARGET_EFAULT;