@samitouri / QOSamiQemu / commits / 22966937f4

linux-user: fix name_to_handle_at when AT_HANDLE_MNT_ID_UNIQUE flag is set

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 <craftyguy@postmarketos.org> Reviewed-by: Helge Deller <deller@gmx.de> Message-id: 20260325-fix-name-to-handle-at-v1-1-49fb922e6fd3@craftyguy.net Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Clayton Craft committed Mar 25, 2026 at 22:59 UTC 22966937f4130278259a79d6462d1a0887e22c6e
1 file changed +18 -3
linux-user/syscall.c
+18 -3
@@ -8166,6 +8166,9 @@ static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr,
8166 #endif
8167
8168 #if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8169 +#ifndef AT_HANDLE_MNT_ID_UNIQUE
8170 +#define AT_HANDLE_MNT_ID_UNIQUE 0x001
8171 +#endif
8172 static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
8173 abi_long handle, abi_long mount_id,
8174 abi_long flags)
@@ -8173,6 +8176,7 @@ static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
8176 struct file_handle *target_fh;
8177 struct file_handle *fh;
8178 int mid = 0;
8179 + uint64_t mid64 = 0;
8180 abi_long ret;
8181 char *name;
8182 unsigned int size, total_size;
@@ -8196,7 +8200,12 @@ static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
8200 fh = g_malloc0(total_size);
8201 fh->handle_bytes = size;
8202
8199 - ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
8203 + if (flags & AT_HANDLE_MNT_ID_UNIQUE) {
8204 + ret = get_errno(name_to_handle_at(dirfd, path(name), fh,
8205 + (int *)&mid64, flags));
8206 + } else {
8207 + ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
8208 + }
8209 unlock_user(name, pathname, 0);
8210
8211 /* man name_to_handle_at(2):
@@ -8210,8 +8219,14 @@ static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
8219 g_free(fh);
8220 unlock_user(target_fh, handle, total_size);
8221
8213 - if (put_user_s32(mid, mount_id)) {
8214 - return -TARGET_EFAULT;
8222 + if (flags & AT_HANDLE_MNT_ID_UNIQUE) {
8223 + if (put_user_u64(mid64, mount_id)) {
8224 + return -TARGET_EFAULT;
8225 + }
8226 + } else {
8227 + if (put_user_s32(mid, mount_id)) {
8228 + return -TARGET_EFAULT;
8229 + }
8230 }
8231
8232 return ret;