]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fs: fix archiecture-specific compat_ftruncate64
authorChristoph Hellwig <hch@lst.de>
Mon, 23 Mar 2026 07:01:44 +0000 (08:01 +0100)
committerChristian Brauner <brauner@kernel.org>
Mon, 23 Mar 2026 11:41:57 +0000 (12:41 +0100)
The "small" argument to do_sys_ftruncate indicates if > 32-bit size
should be reject, but all the arch-specific compat ftruncate64
implementations get this wrong.  Merge do_sys_ftruncate and
ksys_ftruncate, replace the integer as boolean small flag with a
descriptive one about LFS semantics, and use it correctly in the
architecture-specific ftruncate64 implementations.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Fixes: 3dd681d944f6 ("arm64: 32-bit (compat) applications support")
Signed-off-by: Christoph Hellwig <hch@lst.de>
Link: https://patch.msgid.link/20260323070205.2939118-2-hch@lst.de
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christian Brauner <brauner@kernel.org>
arch/arm64/kernel/sys32.c
arch/mips/kernel/linux32.c
arch/parisc/kernel/sys_parisc.c
arch/powerpc/kernel/sys_ppc32.c
arch/sparc/kernel/sys_sparc32.c
arch/x86/kernel/sys_ia32.c
fs/internal.h
fs/open.c
include/linux/syscalls.h

index 96bcfb9074430b063b52cb531646725ca09d8a3c..12a948f3a5043775929c9511130a3c8ecd606e80 100644 (file)
@@ -89,7 +89,7 @@ COMPAT_SYSCALL_DEFINE4(aarch32_truncate64, const char __user *, pathname,
 COMPAT_SYSCALL_DEFINE4(aarch32_ftruncate64, unsigned int, fd, u32, __pad,
                       arg_u32p(length))
 {
-       return ksys_ftruncate(fd, arg_u64(length));
+       return ksys_ftruncate(fd, arg_u64(length), FTRUNCATE_LFS);
 }
 
 COMPAT_SYSCALL_DEFINE5(aarch32_readahead, int, fd, u32, __pad,
index a0c0a7a654e941958e84fd21a2c1320e39391a14..fe9a787db569417fce2ba6ce3851de61bc9726fe 100644 (file)
@@ -60,7 +60,7 @@ SYSCALL_DEFINE4(32_truncate64, const char __user *, path,
 SYSCALL_DEFINE4(32_ftruncate64, unsigned long, fd, unsigned long, __dummy,
        unsigned long, a2, unsigned long, a3)
 {
-       return ksys_ftruncate(fd, merge_64(a2, a3));
+       return ksys_ftruncate(fd, merge_64(a2, a3), FTRUNCATE_LFS);
 }
 
 SYSCALL_DEFINE5(32_llseek, unsigned int, fd, unsigned int, offset_high,
index b2cdbb8a12b16ec89f98cc59657213c67f0079e9..fcb0d806913925c4b814183e26a1498bffbf4886 100644 (file)
@@ -216,7 +216,7 @@ asmlinkage long parisc_truncate64(const char __user * path,
 asmlinkage long parisc_ftruncate64(unsigned int fd,
                                        unsigned int high, unsigned int low)
 {
-       return ksys_ftruncate(fd, (long)high << 32 | low);
+       return ksys_ftruncate(fd, (long)high << 32 | low, FTRUNCATE_LFS);
 }
 
 /* stubs for the benefit of the syscall_table since truncate64 and truncate 
@@ -227,7 +227,7 @@ asmlinkage long sys_truncate64(const char __user * path, unsigned long length)
 }
 asmlinkage long sys_ftruncate64(unsigned int fd, unsigned long length)
 {
-       return ksys_ftruncate(fd, length);
+       return ksys_ftruncate(fd, length, FTRUNCATE_LFS);
 }
 asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
index d451a8229223a3625d2d77886f036afc4c668acc..03fa487f26147c5a671334bfcffde7d837712211 100644 (file)
@@ -101,7 +101,7 @@ PPC32_SYSCALL_DEFINE4(ppc_ftruncate64,
                       unsigned int, fd, u32, reg4,
                       unsigned long, len1, unsigned long, len2)
 {
-       return ksys_ftruncate(fd, merge_64(len1, len2));
+       return ksys_ftruncate(fd, merge_64(len1, len2), FTRUNCATE_LFS);
 }
 
 PPC32_SYSCALL_DEFINE6(ppc32_fadvise64,
index f84a02ab6bf90f3ab6aabe3b93ae836a764c9c5d..04432b82b9e3efe8df934f0dbdb40891d3c5da7b 100644 (file)
@@ -58,7 +58,7 @@ COMPAT_SYSCALL_DEFINE3(truncate64, const char __user *, path, u32, high, u32, lo
 
 COMPAT_SYSCALL_DEFINE3(ftruncate64, unsigned int, fd, u32, high, u32, low)
 {
-       return ksys_ftruncate(fd, ((u64)high << 32) | low);
+       return ksys_ftruncate(fd, ((u64)high << 32) | low, FTRUNCATE_LFS);
 }
 
 static int cp_compat_stat64(struct kstat *stat,
index 6cf65397d2257a4b7f5bb13e9d6e66d24c50b92d..610a1c2f451919498280033c5d47baa0f965de69 100644 (file)
@@ -61,7 +61,8 @@ SYSCALL_DEFINE3(ia32_truncate64, const char __user *, filename,
 SYSCALL_DEFINE3(ia32_ftruncate64, unsigned int, fd,
                unsigned long, offset_low, unsigned long, offset_high)
 {
-       return ksys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low);
+       return ksys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low,
+                       FTRUNCATE_LFS);
 }
 
 /* warning: next two assume little endian */
index cbc384a1aa096ade4734f9c80ec978fd2ea6977f..2663823e273a1f032bc64a8a19ad51d0c445e543 100644 (file)
@@ -199,7 +199,6 @@ extern int build_open_flags(const struct open_how *how, struct open_flags *op);
 struct file *file_close_fd_locked(struct files_struct *files, unsigned fd);
 
 int do_ftruncate(struct file *file, loff_t length, int small);
-int do_sys_ftruncate(unsigned int fd, loff_t length, int small);
 int chmod_common(const struct path *path, umode_t mode);
 int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
                int flag);
index 91f1139591abed01d0242a8eafe9a9e00690e848..412d0d6fbaa7577de63fe4c8c6f2b96c0499d800 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -197,7 +197,7 @@ int do_ftruncate(struct file *file, loff_t length, int small)
                                   ATTR_MTIME | ATTR_CTIME, file);
 }
 
-int do_sys_ftruncate(unsigned int fd, loff_t length, int small)
+int ksys_ftruncate(unsigned int fd, loff_t length, unsigned int flags)
 {
        if (length < 0)
                return -EINVAL;
@@ -205,18 +205,18 @@ int do_sys_ftruncate(unsigned int fd, loff_t length, int small)
        if (fd_empty(f))
                return -EBADF;
 
-       return do_ftruncate(fd_file(f), length, small);
+       return do_ftruncate(fd_file(f), length, !(flags & FTRUNCATE_LFS));
 }
 
 SYSCALL_DEFINE2(ftruncate, unsigned int, fd, off_t, length)
 {
-       return do_sys_ftruncate(fd, length, 1);
+       return ksys_ftruncate(fd, length, 0);
 }
 
 #ifdef CONFIG_COMPAT
 COMPAT_SYSCALL_DEFINE2(ftruncate, unsigned int, fd, compat_off_t, length)
 {
-       return do_sys_ftruncate(fd, length, 1);
+       return ksys_ftruncate(fd, length, 0);
 }
 #endif
 
@@ -229,7 +229,7 @@ SYSCALL_DEFINE2(truncate64, const char __user *, path, loff_t, length)
 
 SYSCALL_DEFINE2(ftruncate64, unsigned int, fd, loff_t, length)
 {
-       return do_sys_ftruncate(fd, length, 0);
+       return ksys_ftruncate(fd, length, FTRUNCATE_LFS);
 }
 #endif /* BITS_PER_LONG == 32 */
 
@@ -245,7 +245,7 @@ COMPAT_SYSCALL_DEFINE3(truncate64, const char __user *, pathname,
 COMPAT_SYSCALL_DEFINE3(ftruncate64, unsigned int, fd,
                       compat_arg_u64_dual(length))
 {
-       return ksys_ftruncate(fd, compat_arg_u64_glue(length));
+       return ksys_ftruncate(fd, compat_arg_u64_glue(length), FTRUNCATE_LFS);
 }
 #endif
 
index 02bd6ddb627821aef22b2065066858b4b37bb177..8787b3511c86c2defb198ed21e51e5748e385026 100644 (file)
@@ -1283,12 +1283,8 @@ static inline long ksys_lchown(const char __user *filename, uid_t user,
                             AT_SYMLINK_NOFOLLOW);
 }
 
-int do_sys_ftruncate(unsigned int fd, loff_t length, int small);
-
-static inline long ksys_ftruncate(unsigned int fd, loff_t length)
-{
-       return do_sys_ftruncate(fd, length, 1);
-}
+#define FTRUNCATE_LFS  (1u << 0)       /* allow truncating > 32-bit */
+int ksys_ftruncate(unsigned int fd, loff_t length, unsigned int flags);
 
 int do_sys_truncate(const char __user *pathname, loff_t length);