[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <bug-205957-13602@https.bugzilla.kernel.org/>
Date: Tue, 24 Dec 2019 14:07:36 +0000
From: bugzilla-daemon@...zilla.kernel.org
To: linux-ext4@...r.kernel.org
Subject: [Bug 205957] New: Ext4 64 bit hash breaks 32 bit glibc 2.28+
https://bugzilla.kernel.org/show_bug.cgi?id=205957
Bug ID: 205957
Summary: Ext4 64 bit hash breaks 32 bit glibc 2.28+
Product: File System
Version: 2.5
Kernel Version: 5.3.16 (any version)
Hardware: ARM
OS: Linux
Tree: Mainline
Status: NEW
Severity: normal
Priority: P1
Component: ext4
Assignee: fs_ext4@...nel-bugs.osdl.org
Reporter: aladjev.andrew@...il.com
Regression: No
Hello. Please see the following glibc issue:
https://sourceware.org/bugzilla/show_bug.cgi?id=23960.
I am running arm system using qemu on host system with x86_64 kernel. I've
received 64 bits value for "d_off" instead of 32 bits from "getdents64".
Than I've tried i386 instead of arm and it works fine. I've received 32 bits
value for "d_off" from "getdents64".
I think that the problem is here
arch/x86/include/generated/uapi/asm/unistd_x32.h:
#define __NR_getdents64 (__X32_SYSCALL_BIT + 217)
arch/x86/include/asm/compat.h:
static inline bool in_x32_syscall(void)
{
#ifdef CONFIG_X86_X32_ABI
if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT)
return true;
#endif
return false;
}
fs/ext4/dir.c:
static inline int is_32bit_api(void)
{
#ifdef CONFIG_COMPAT
return in_compat_syscall();
#else
return (BITS_PER_LONG == 32);
#endif
}
static inline loff_t hash2pos(struct file *filp, __u32 major, __u32 minor)
{
if ((filp->f_mode & FMODE_32BITHASH) ||
(!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api()))
return major >> 1;
else
return ((__u64)(major >> 1) << 32) | (__u64)minor;
}
I think that i386 makes a special syscall with "__X32_SYSCALL_BIT" enabled.
This special bit makes "in_x32_syscall", "in_compat_syscall" and "is_32bit_api"
to return true. This thing affects "hash2pos" and it works like
"FMODE_32BITHASH" is enabled.
ARM has no such special system, it uses generic "in_compat_syscall".
include/linux/compat.h:
* For most but not all architectures, "am I in a compat syscall?" and
* "am I a compat task?" are the same question. For architectures on which
* they aren't the same question, arch code can override in_compat_syscall.
I don't know how to fix this issue.
1. Is it possible to implement special arm syscalls in the same way as x86?
2. Is it possible to add special compatibility syscall like
"__NR_compat_getdents64" that will make generic "in_compat_syscall" return
true?
3. Is it possible to force enable FMODE_32BITHASH for arm syscalls in runtime
in another way?
4. We can't shift "d_off >> 32" now, because we will have to restore "<< 32" in
all third party applications (not only glibc). Is it possible to replace
"((__u64)(major >> 1) << 32) | (__u64)minor" with "((__u64)minor << 32) |
(__u64)(major >> 1)"? So we will just ignore minor overflow.
5. Is it possible to refactor ext4 and remove hash from pos completely? It
provides so much pain.
--
You are receiving this mail because:
You are watching the assignee of the bug.
Powered by blists - more mailing lists