[PATCH] fs: Fix signed integer overflow for vfs_setpos

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The undefined behaviour sanatizer detected an signed integer overflow like this:

r0 = memfd_create(&(0x7f0000002000-0x12)="2e726571756573745f6b65795f6175746800",0x0)
lseek(r0, 0x4040000000000000, 0x1)
setsockopt$inet6_IPV6_FLOWLABEL_MGR(r0, 0x29, 0x20,
&(0x7f000000b000-0xd)={@empty={[0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]}, 0x9, 0x1, 0xff, 0x2, 0x6, 0x1,0xd27}, 0x20)
mmap(&(0x7f000000e000/0x1000)=nil, 0x1000, 0x3, 0x32,0xffffffffffffffff, 0x0)
ioctl$sock_SIOCGSKNS(r0, 0x894c, &(0x7f000000f000-0x4)=0x10000)
---------------------------------------------------------------------------------
UBSAN: Undefined behaviour in fs/read_write.c:107:12
signed integer overflow:
4629700416936869888 + 4629700416936869888 cannot be represented in type
'long long int'
CPU: 0 PID: 11653 Comm: syz-executor0 Not tainted 4.x.xx+ #2
Hardware name: linux,dummy-virt (DT)
Call trace:
[<ffffffc00008f4d0>] dump_backtrace+0x0/0x2a0
[<ffffffc00008f790>] show_stack+0x20/0x30
[<ffffffc000ec3b5c>] dump_stack+0x11c/0x16c
[<ffffffc000ec3e80>] ubsan_epilogue+0x18/0x70
[<ffffffc000ec4ca0>] handle_overflow+0x14c/0x188
[<ffffffc000ec4d10>] __ubsan_handle_add_overflow+0x34/0x44
[<ffffffc000327740>] generic_file_llseek_size+0x1f8/0x2a0
[<ffffffc0002826fc>] shmem_file_llseek+0x7c/0x1f8
[<ffffffc000327b88>] SyS_lseek+0xc0/0x118
--------------------------------------------------------------------------------

The problem happened because the calculation of signed integer resulted
an overflow for the signed integer, so use the unsigned integer to avoid
undefined behaviour when it does overflow.

Signed-off-by: Ding Tianhong <dingtianhong@xxxxxxxxxx>
---
 fs/read_write.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/read_write.c b/fs/read_write.c
index f8547b8..2c377fc 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -105,7 +105,7 @@ loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize)
 		 * like SEEK_SET.
 		 */
 		spin_lock(&file->f_lock);
-		offset = vfs_setpos(file, file->f_pos + offset, maxsize);
+		offset = vfs_setpos(file, (u64)file->f_pos + offset, maxsize);
 		spin_unlock(&file->f_lock);
 		return offset;
 	case SEEK_DATA:
-- 
1.8.3.1





[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux