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;