Messages in this thread Patches in this message | | | From | Steve French <> | Date | Thu, 12 Aug 2021 10:55:56 -0500 | Subject | Re: signed integer overflow in atomic.h |
| |
If the "signed integer overflow" is a compiler bug fixed in last couple of years - do we even need these two patches that we were seeing to fix this issue in a few places in cifs.ko (which we noted on 5.11 regression test runs, but not 5.14-rc)
On Thu, Aug 12, 2021 at 10:43 AM Steve French <smfrench@gmail.com> wrote: > > Ronnie, > The guest irunning the tests is Fedora (although the host where the > compile is done is RHEL7.9 IIRC) ... do we need to update the compiler > on it - we do hit some of these with UBSAN enabled on 5.11 tests > (strangely I don't see them on 5.14-rc) > > ---------- Forwarded message --------- > From: Randy Dunlap <rdunlap@infradead.org> > Date: Thu, Aug 12, 2021 at 10:07 AM > Subject: Re: signed integer overflow in atomic.h > To: Steve French <smfrench@gmail.com>, LKML > <linux-kernel@vger.kernel.org>, Netdev <netdev@vger.kernel.org> > > > On 8/11/21 10:41 PM, Steve French wrote: > > =============== > > [ 28.345189] UBSAN: signed-integer-overflow in > > ./arch/x86/include/asm/atomic.h:165:11 > > [ 28.345196] 484501395 + 2024361625 cannot be represented in type 'int' > > [ 28.345202] CPU: 6 PID: 987 Comm: nmbd Not tainted 5.11.22 #1 > > [ 28.345208] Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 > > [ 28.345212] Call Trace: > > [ 28.345218] dump_stack+0x8d/0xb5 > > [ 28.345233] ubsan_epilogue+0x5/0x50 > > [ 28.345242] handle_overflow+0xa3/0xb0 > > [ 28.345257] ? rcu_read_lock_sched_held+0x39/0x80 > > [ 28.345270] ip_idents_reserve+0x8d/0xb0 > > [ 28.345283] __ip_select_ident+0x3f/0x70 > > [ 28.345292] __ip_make_skb+0x279/0x450 > > [ 28.345302] ? ip_reply_glue_bits+0x40/0x40 > > [ 28.345314] ip_make_skb+0x10d/0x130 > > [ 28.345326] ? ip_route_output_key_hash+0xee/0x190 > > [ 28.345344] udp_sendmsg+0x79b/0x13b0 > > [ 28.345365] ? ip_reply_glue_bits+0x40/0x40 > > [ 28.345403] ? find_held_lock+0x29/0xb0 > > [ 28.345420] ? sock_sendmsg+0x54/0x60 > > [ 28.345426] sock_sendmsg+0x54/0x60 > > from net/ipv4/route.c: > > /* If UBSAN reports an error there, please make sure your compiler > * supports -fno-strict-overflow before reporting it that was a bug > * in UBSAN, and it has been fixed in GCC-8. > */ > return atomic_add_return(segs + delta, p_id) - segs; > > > -- > ~Randy > > > > -- > Thanks, > > Steve
-- Thanks,
Steve From 84fca254fde6100c25689038f91e64e16161ec51 Mon Sep 17 00:00:00 2001 From: Steve French <stfrench@microsoft.com> Date: Wed, 11 Aug 2021 23:23:02 -0500 Subject: [PATCH 4/4] cifs: avoid signed integer overflow in calculating blocks
xfstest generic/525 can generate the following warning:
UBSAN: signed-integer-overflow in fs/cifs/file.c:2644:31 9223372036854775807 + 511 cannot be represented in type 'long long int'
Call Trace: dump_stack+0x8d/0xb5 ubsan_epilogue+0x5/0x50 handle_overflow+0xa3/0xb0 cifs_write_end+0x424/0x440 [cifs] generic_perform_write+0xef/0x190
due to overflowing loff_t (a signed 64 bit) when it is rounded up to calculate number of 512 byte blocks in a file in two places.
Signed-off-by: Steve French <stfrench@microsoft.com> --- fs/cifs/file.c | 3 ++- fs/cifs/inode.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 0166f39f1888..3cc17871471a 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2641,7 +2641,8 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, spin_lock(&inode->i_lock); if (pos > inode->i_size) { i_size_write(inode, pos); - inode->i_blocks = (512 - 1 + pos) >> 9; + /* round up to block boundary, avoid overflow loff_t */ + inode->i_blocks = ((__u64)pos + (512 - 1)) >> 9; } spin_unlock(&inode->i_lock); } diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 65f8a70cece3..f1dbcbc79abb 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -2631,7 +2631,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, * this is best estimate we have for blocks allocated for a file * Number of blocks must be rounded up so size 1 is not 0 blocks */ - inode->i_blocks = (512 - 1 + attrs->ia_size) >> 9; + inode->i_blocks = ((__u64)attrs->ia_size + (512 - 1)) >> 9; /* * The man page of truncate says if the size changed, -- 2.30.2 From accb6de3f9c9583cf916b681f5cecb01a9490c2b Mon Sep 17 00:00:00 2001 From: Paulo Alcantara <pc@cjr.nz> Date: Tue, 10 Aug 2021 13:10:44 -0300 Subject: [PATCH 1/4] cifs: fix signed integer overflow when fl_end is OFFSET_MAX
This fixes the following when running xfstests generic/504:
[ 134.394698] CIFS: Attempting to mount \\win16.vm.test\Share [ 134.420905] CIFS: VFS: generate_smb3signingkey: dumping generated AES session keys [ 134.420911] CIFS: VFS: Session Id 05 00 00 00 00 c4 00 00 [ 134.420914] CIFS: VFS: Cipher type 1 [ 134.420917] CIFS: VFS: Session Key ea 0b d9 22 2e af 01 69 30 1b 15 74 bf 87 41 11 [ 134.420920] CIFS: VFS: Signing Key 59 28 43 5c f0 b6 b1 6f f5 7b 65 f2 9f 9e 58 7d [ 134.420923] CIFS: VFS: ServerIn Key eb aa 58 c8 95 01 9a f7 91 98 e4 fa bc d8 74 f1 [ 134.420926] CIFS: VFS: ServerOut Key 08 5b 21 e5 2e 4e 86 f6 05 c2 58 e0 af 53 83 e7 [ 134.771946] ================================================================================ [ 134.771953] UBSAN: signed-integer-overflow in fs/cifs/file.c:1706:19 [ 134.771957] 9223372036854775807 + 1 cannot be represented in type 'long long int' [ 134.771960] CPU: 4 PID: 2773 Comm: flock Not tainted 5.11.22 #1 [ 134.771964] Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 [ 134.771966] Call Trace: [ 134.771970] dump_stack+0x8d/0xb5 [ 134.771981] ubsan_epilogue+0x5/0x50 [ 134.771988] handle_overflow+0xa3/0xb0 [ 134.771997] ? lockdep_hardirqs_on_prepare+0xe8/0x1b0 [ 134.772006] cifs_setlk+0x63c/0x680 [cifs] [ 134.772085] ? _get_xid+0x5f/0xa0 [cifs] [ 134.772085] cifs_flock+0x131/0x400 [cifs] [ 134.772085] __x64_sys_flock+0xfc/0x120 [ 134.772085] do_syscall_64+0x33/0x40 [ 134.772085] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 134.772085] RIP: 0033:0x7fea4f83b3fb [ 134.772085] Code: ff 48 8b 15 8f 1a 0d 00 f7 d8 64 89 02 b8 ff ff ff ff eb da e8 16 0b 02 00 66 0f 1f 44 00 00 f3 0f 1e fa b8 49 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 5d 1a 0d 00 f7 d8 64 89 01 48
And fixes a similar loff_t overflow problem in smb2_unlock_range
Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz> Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com> --- fs/cifs/cifsglob.h | 5 +++++ fs/cifs/cifssmb.c | 3 ++- fs/cifs/file.c | 8 ++++---- fs/cifs/smb2file.c | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index c0bfc2f01030..2d6178df426f 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1964,4 +1964,9 @@ static inline bool is_tcon_dfs(struct cifs_tcon *tcon) tcon->share_flags & (SHI1005_FLAGS_DFS | SHI1005_FLAGS_DFS_ROOT); } +static inline u64 cifs_flock_len(struct file_lock *fl) +{ + return fl->fl_end == OFFSET_MAX ? fl->fl_end - fl->fl_start : fl->fl_end - fl->fl_start + 1; +} + #endif /* _CIFS_GLOB_H */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 65d1a65bfc37..6ab6cf669438 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2607,7 +2607,8 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon, pLockData->fl_start = le64_to_cpu(parm_data->start); pLockData->fl_end = pLockData->fl_start + - le64_to_cpu(parm_data->length) - 1; + (le64_to_cpu(parm_data->length) ? + le64_to_cpu(parm_data->length) - 1 : 0); pLockData->fl_pid = -le32_to_cpu(parm_data->pid); } } diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 0a72840a88f1..e1cfd50996a0 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1385,7 +1385,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) cifs_dbg(VFS, "Can't push all brlocks!\n"); break; } - length = 1 + flock->fl_end - flock->fl_start; + length = cifs_flock_len(flock); if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK) type = CIFS_RDLCK; else @@ -1501,7 +1501,7 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, bool wait_flag, bool posix_lck, unsigned int xid) { int rc = 0; - __u64 length = 1 + flock->fl_end - flock->fl_start; + __u64 length = cifs_flock_len(flock); struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); struct TCP_Server_Info *server = tcon->ses->server; @@ -1599,7 +1599,7 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); struct cifsLockInfo *li, *tmp; - __u64 length = 1 + flock->fl_end - flock->fl_start; + __u64 length = cifs_flock_len(flock); struct list_head tmp_llist; INIT_LIST_HEAD(&tmp_llist); @@ -1703,7 +1703,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, unsigned int xid) { int rc = 0; - __u64 length = 1 + flock->fl_end - flock->fl_start; + __u64 length = cifs_flock_len(flock); struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); struct TCP_Server_Info *server = tcon->ses->server; diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c index c9d8a50062b8..7932354bf90c 100644 --- a/fs/cifs/smb2file.c +++ b/fs/cifs/smb2file.c @@ -111,7 +111,7 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); struct cifsLockInfo *li, *tmp; - __u64 length = 1 + flock->fl_end - flock->fl_start; + __u64 length = cifs_flock_len(flock); struct list_head tmp_llist; INIT_LIST_HEAD(&tmp_llist); -- 2.30.2
| |