From: Clayton Craft <[email protected]> Linux 6.12 added AT_HANDLE_MNT_ID_UNIQUE, which indicates that mount_id is 64-bits. If name_to_handle_at is called with this flag set then qemu passes a 4 byte int to the kernel, which then tries to store 8 bytes in a 4 byte variable, causing a SIGSEGV[1][2].
This stores mount_id in a 64-bit var if the flag is set. 1. https://gitlab.postmarketos.org/postmarketOS/pmaports/-/work_items/4431 2. https://github.com/systemd/systemd/issues/41279 Signed-off-by: Clayton Craft <[email protected]> Reviewed-by: Helge Deller <[email protected]> Message-id: [email protected] Signed-off-by: Peter Maydell <[email protected]> (cherry picked from commit 22966937f4130278259a79d6462d1a0887e22c6e) Signed-off-by: Michael Tokarev <[email protected]> diff --git a/linux-user/syscall.c b/linux-user/syscall.c index e6dd35d2a1..3f61dd732c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8040,6 +8040,9 @@ static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr, #endif #if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE) +#ifndef AT_HANDLE_MNT_ID_UNIQUE +#define AT_HANDLE_MNT_ID_UNIQUE 0x001 +#endif static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname, abi_long handle, abi_long mount_id, abi_long flags) @@ -8047,6 +8050,7 @@ static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname, struct file_handle *target_fh; struct file_handle *fh; int mid = 0; + uint64_t mid64 = 0; abi_long ret; char *name; unsigned int size, total_size; @@ -8070,7 +8074,12 @@ static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname, fh = g_malloc0(total_size); fh->handle_bytes = size; - ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags)); + if (flags & AT_HANDLE_MNT_ID_UNIQUE) { + ret = get_errno(name_to_handle_at(dirfd, path(name), fh, + (int *)&mid64, flags)); + } else { + ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags)); + } unlock_user(name, pathname, 0); /* man name_to_handle_at(2): @@ -8084,8 +8093,14 @@ static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname, g_free(fh); unlock_user(target_fh, handle, total_size); - if (put_user_s32(mid, mount_id)) { - return -TARGET_EFAULT; + if (flags & AT_HANDLE_MNT_ID_UNIQUE) { + if (put_user_u64(mid64, mount_id)) { + return -TARGET_EFAULT; + } + } else { + if (put_user_s32(mid, mount_id)) { + return -TARGET_EFAULT; + } } return ret; -- 2.47.3
