Skip to content

Commit 4b8e88e

Browse files
committed
ftruncate: pass a signed offset
The old ftruncate() syscall, using the 32-bit off_t misses a sign extension when called in compat mode on 64-bit architectures. As a result, passing a negative length accidentally succeeds in truncating to file size between 2GiB and 4GiB. Changing the type of the compat syscall to the signed compat_off_t changes the behavior so it instead returns -EINVAL. The native entry point, the truncate() syscall and the corresponding loff_t based variants are all correct already and do not suffer from this mistake. Fixes: 3f6d078 ("fix compat truncate/ftruncate") Reviewed-by: Christian Brauner <brauner@kernel.org> Cc: stable@vger.kernel.org Signed-off-by: Arnd Bergmann <arnd@arndb.de>
1 parent f266106 commit 4b8e88e

File tree

3 files changed

+4
-4
lines changed

3 files changed

+4
-4
lines changed

fs/open.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,13 +202,13 @@ long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
202202
return error;
203203
}
204204

205-
SYSCALL_DEFINE2(ftruncate, unsigned int, fd, unsigned long, length)
205+
SYSCALL_DEFINE2(ftruncate, unsigned int, fd, off_t, length)
206206
{
207207
return do_sys_ftruncate(fd, length, 1);
208208
}
209209

210210
#ifdef CONFIG_COMPAT
211-
COMPAT_SYSCALL_DEFINE2(ftruncate, unsigned int, fd, compat_ulong_t, length)
211+
COMPAT_SYSCALL_DEFINE2(ftruncate, unsigned int, fd, compat_off_t, length)
212212
{
213213
return do_sys_ftruncate(fd, length, 1);
214214
}

include/linux/compat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd,
608608
asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz,
609609
struct compat_statfs64 __user *buf);
610610
asmlinkage long compat_sys_truncate(const char __user *, compat_off_t);
611-
asmlinkage long compat_sys_ftruncate(unsigned int, compat_ulong_t);
611+
asmlinkage long compat_sys_ftruncate(unsigned int, compat_off_t);
612612
/* No generic prototype for truncate64, ftruncate64, fallocate */
613613
asmlinkage long compat_sys_openat(int dfd, const char __user *filename,
614614
int flags, umode_t mode);

include/linux/syscalls.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ asmlinkage long sys_listmount(const struct mnt_id_req __user *req,
418418
u64 __user *mnt_ids, size_t nr_mnt_ids,
419419
unsigned int flags);
420420
asmlinkage long sys_truncate(const char __user *path, long length);
421-
asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
421+
asmlinkage long sys_ftruncate(unsigned int fd, off_t length);
422422
#if BITS_PER_LONG == 32
423423
asmlinkage long sys_truncate64(const char __user *path, loff_t length);
424424
asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length);

0 commit comments

Comments
 (0)