From 6a3e132a1be8c9e649967a4eb341d00731be7f51 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 10 Jul 2025 12:31:23 +0100 Subject: linux-user: Implement fchmodat2 syscall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fchmodat2 syscall is new from Linux 6.6; it is like the existing fchmodat syscall except that it takes a flags parameter. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3019 Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Signed-off-by: Richard Henderson Message-ID: <20250710113123.1109461-1-peter.maydell@linaro.org> --- linux-user/syscall.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'linux-user/syscall.c') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index fc37028..e1b1476 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -790,6 +790,10 @@ safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff, int, outfd, loff_t *, poutoff, size_t, length, unsigned int, flags) #endif +#if defined(TARGET_NR_fchmodat2) && defined(__NR_fchmodat2) +safe_syscall4(int, fchmodat2, int, dfd, const char *, filename, + unsigned short, mode, unsigned int, flags) +#endif /* We do ioctl like this rather than via safe_syscall3 to preserve the * "third argument might be integer or pointer or not present" behaviour of @@ -10714,6 +10718,15 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, unlock_user(p, arg2, 0); return ret; #endif +#if defined(TARGET_NR_fchmodat2) && defined(__NR_fchmodat2) + case TARGET_NR_fchmodat2: + if (!(p = lock_user_string(arg2))) { + return -TARGET_EFAULT; + } + ret = get_errno(safe_fchmodat2(arg1, p, arg3, arg4)); + unlock_user(p, arg2, 0); + return ret; +#endif case TARGET_NR_getpriority: /* Note that negative values are valid for getpriority, so we must differentiate based on errno settings. */ -- cgit v1.1 From c4828cb8502d0b2adc39b9cde93df7d2886df897 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 10 Jul 2025 17:43:54 +0100 Subject: linux-user: Check for EFAULT failure in nanosleep target_to_host_timespec() returns an error if the memory the guest passed us isn't actually readable. We check for this everywhere except the callsite in the TARGET_NR_nanosleep case, so this mistake was caught by a Coverity heuristic. Add the missing error checks to the calls that convert between the host and target timespec structs. Coverity: CID 1507104 Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Signed-off-by: Richard Henderson Message-ID: <20250710164355.1296648-1-peter.maydell@linaro.org> --- linux-user/syscall.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'linux-user/syscall.c') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index e1b1476..38dd563 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -11643,10 +11643,14 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, case TARGET_NR_nanosleep: { struct timespec req, rem; - target_to_host_timespec(&req, arg1); + if (target_to_host_timespec(&req, arg1)) { + return -TARGET_EFAULT; + } ret = get_errno(safe_nanosleep(&req, &rem)); if (is_error(ret) && arg2) { - host_to_target_timespec(arg2, &rem); + if (host_to_target_timespec(arg2, &rem)) { + return -TARGET_EFAULT; + } } } return ret; -- cgit v1.1 From d6390204c61e148488f034d1f79be35cd3318d93 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 11 Jul 2025 15:12:17 +0100 Subject: linux-user: Use qemu_set_cloexec() to mark pidfd as FD_CLOEXEC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the linux-user do_fork() function we try to set the FD_CLOEXEC flag on a pidfd like this: fcntl(pid_fd, F_SETFD, fcntl(pid_fd, F_GETFL) | FD_CLOEXEC); This has two problems: (1) it doesn't check errors, which Coverity complains about (2) we use F_GETFL when we mean F_GETFD Deal with both of these problems by using qemu_set_cloexec() instead. That function will assert() if the fcntls fail, which is fine (we are inside fork_start()/fork_end() so we know nothing can mess around with our file descriptors here, and we just got this one from pidfd_open()). (As we are touching the if() statement here, we correct the indentation.) Coverity: CID 1508111 Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Daniel P. Berrangé Signed-off-by: Richard Henderson Message-ID: <20250711141217.1429412-1-peter.maydell@linaro.org> --- linux-user/syscall.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'linux-user/syscall.c') diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 38dd563..91360a0 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -6747,10 +6747,9 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, int pid_child = ret; pid_fd = pidfd_open(pid_child, 0); if (pid_fd >= 0) { - fcntl(pid_fd, F_SETFD, fcntl(pid_fd, F_GETFL) - | FD_CLOEXEC); + qemu_set_cloexec(pid_fd); } else { - pid_fd = 0; + pid_fd = 0; } #endif put_user_u32(pid_fd, parent_tidptr); -- cgit v1.1