Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fs: fix archiecture-specific compat_ftruncate64

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>

authored by

Christoph Hellwig and committed by
Christian Brauner
e43dce8a 3d6bb84f

+16 -20
+1 -1
arch/arm64/kernel/sys32.c
··· 89 89 COMPAT_SYSCALL_DEFINE4(aarch32_ftruncate64, unsigned int, fd, u32, __pad, 90 90 arg_u32p(length)) 91 91 { 92 - return ksys_ftruncate(fd, arg_u64(length)); 92 + return ksys_ftruncate(fd, arg_u64(length), FTRUNCATE_LFS); 93 93 } 94 94 95 95 COMPAT_SYSCALL_DEFINE5(aarch32_readahead, int, fd, u32, __pad,
+1 -1
arch/mips/kernel/linux32.c
··· 60 60 SYSCALL_DEFINE4(32_ftruncate64, unsigned long, fd, unsigned long, __dummy, 61 61 unsigned long, a2, unsigned long, a3) 62 62 { 63 - return ksys_ftruncate(fd, merge_64(a2, a3)); 63 + return ksys_ftruncate(fd, merge_64(a2, a3), FTRUNCATE_LFS); 64 64 } 65 65 66 66 SYSCALL_DEFINE5(32_llseek, unsigned int, fd, unsigned int, offset_high,
+2 -2
arch/parisc/kernel/sys_parisc.c
··· 216 216 asmlinkage long parisc_ftruncate64(unsigned int fd, 217 217 unsigned int high, unsigned int low) 218 218 { 219 - return ksys_ftruncate(fd, (long)high << 32 | low); 219 + return ksys_ftruncate(fd, (long)high << 32 | low, FTRUNCATE_LFS); 220 220 } 221 221 222 222 /* stubs for the benefit of the syscall_table since truncate64 and truncate ··· 227 227 } 228 228 asmlinkage long sys_ftruncate64(unsigned int fd, unsigned long length) 229 229 { 230 - return ksys_ftruncate(fd, length); 230 + return ksys_ftruncate(fd, length, FTRUNCATE_LFS); 231 231 } 232 232 asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) 233 233 {
+1 -1
arch/powerpc/kernel/sys_ppc32.c
··· 101 101 unsigned int, fd, u32, reg4, 102 102 unsigned long, len1, unsigned long, len2) 103 103 { 104 - return ksys_ftruncate(fd, merge_64(len1, len2)); 104 + return ksys_ftruncate(fd, merge_64(len1, len2), FTRUNCATE_LFS); 105 105 } 106 106 107 107 PPC32_SYSCALL_DEFINE6(ppc32_fadvise64,
+1 -1
arch/sparc/kernel/sys_sparc32.c
··· 58 58 59 59 COMPAT_SYSCALL_DEFINE3(ftruncate64, unsigned int, fd, u32, high, u32, low) 60 60 { 61 - return ksys_ftruncate(fd, ((u64)high << 32) | low); 61 + return ksys_ftruncate(fd, ((u64)high << 32) | low, FTRUNCATE_LFS); 62 62 } 63 63 64 64 static int cp_compat_stat64(struct kstat *stat,
+2 -1
arch/x86/kernel/sys_ia32.c
··· 61 61 SYSCALL_DEFINE3(ia32_ftruncate64, unsigned int, fd, 62 62 unsigned long, offset_low, unsigned long, offset_high) 63 63 { 64 - return ksys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low); 64 + return ksys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low, 65 + FTRUNCATE_LFS); 65 66 } 66 67 67 68 /* warning: next two assume little endian */
-1
fs/internal.h
··· 199 199 struct file *file_close_fd_locked(struct files_struct *files, unsigned fd); 200 200 201 201 int do_ftruncate(struct file *file, loff_t length, int small); 202 - int do_sys_ftruncate(unsigned int fd, loff_t length, int small); 203 202 int chmod_common(const struct path *path, umode_t mode); 204 203 int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group, 205 204 int flag);
+6 -6
fs/open.c
··· 197 197 ATTR_MTIME | ATTR_CTIME, file); 198 198 } 199 199 200 - int do_sys_ftruncate(unsigned int fd, loff_t length, int small) 200 + int ksys_ftruncate(unsigned int fd, loff_t length, unsigned int flags) 201 201 { 202 202 if (length < 0) 203 203 return -EINVAL; ··· 205 205 if (fd_empty(f)) 206 206 return -EBADF; 207 207 208 - return do_ftruncate(fd_file(f), length, small); 208 + return do_ftruncate(fd_file(f), length, !(flags & FTRUNCATE_LFS)); 209 209 } 210 210 211 211 SYSCALL_DEFINE2(ftruncate, unsigned int, fd, off_t, length) 212 212 { 213 - return do_sys_ftruncate(fd, length, 1); 213 + return ksys_ftruncate(fd, length, 0); 214 214 } 215 215 216 216 #ifdef CONFIG_COMPAT 217 217 COMPAT_SYSCALL_DEFINE2(ftruncate, unsigned int, fd, compat_off_t, length) 218 218 { 219 - return do_sys_ftruncate(fd, length, 1); 219 + return ksys_ftruncate(fd, length, 0); 220 220 } 221 221 #endif 222 222 ··· 229 229 230 230 SYSCALL_DEFINE2(ftruncate64, unsigned int, fd, loff_t, length) 231 231 { 232 - return do_sys_ftruncate(fd, length, 0); 232 + return ksys_ftruncate(fd, length, FTRUNCATE_LFS); 233 233 } 234 234 #endif /* BITS_PER_LONG == 32 */ 235 235 ··· 245 245 COMPAT_SYSCALL_DEFINE3(ftruncate64, unsigned int, fd, 246 246 compat_arg_u64_dual(length)) 247 247 { 248 - return ksys_ftruncate(fd, compat_arg_u64_glue(length)); 248 + return ksys_ftruncate(fd, compat_arg_u64_glue(length), FTRUNCATE_LFS); 249 249 } 250 250 #endif 251 251
+2 -6
include/linux/syscalls.h
··· 1283 1283 AT_SYMLINK_NOFOLLOW); 1284 1284 } 1285 1285 1286 - int do_sys_ftruncate(unsigned int fd, loff_t length, int small); 1287 - 1288 - static inline long ksys_ftruncate(unsigned int fd, loff_t length) 1289 - { 1290 - return do_sys_ftruncate(fd, length, 1); 1291 - } 1286 + #define FTRUNCATE_LFS (1u << 0) /* allow truncating > 32-bit */ 1287 + int ksys_ftruncate(unsigned int fd, loff_t length, unsigned int flags); 1292 1288 1293 1289 int do_sys_truncate(const char __user *pathname, loff_t length); 1294 1290