diff options
author | Christoph Probst <kernel@probst.it> | 2019-05-07 11:16:40 -0400 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2019-05-08 00:24:55 -0400 |
commit | 6a54b2e002c9d00b398d35724c79f9fe0d9b38fb (patch) | |
tree | 15337da48020ddeb9265edcad0abf0255895d881 | |
parent | 26ea888f6282b0f5c1977d8ddb2fff1ea0238bd7 (diff) |
cifs: fix strcat buffer overflow and reduce raciness in smb21_set_oplock_level()
Change strcat to strncpy in the "None" case to fix a buffer overflow
when cinode->oplock is reset to 0 by another thread accessing the same
cinode. It is never valid to append "None" to any other message.
Consolidate multiple writes to cinode->oplock to reduce raciness.
Signed-off-by: Christoph Probst <kernel@probst.it>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
CC: Stable <stable@vger.kernel.org>
-rw-r--r-- | fs/cifs/smb2ops.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 860dd1696830..4313cb04549e 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -2974,26 +2974,28 @@ smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, | |||
2974 | unsigned int epoch, bool *purge_cache) | 2974 | unsigned int epoch, bool *purge_cache) |
2975 | { | 2975 | { |
2976 | char message[5] = {0}; | 2976 | char message[5] = {0}; |
2977 | unsigned int new_oplock = 0; | ||
2977 | 2978 | ||
2978 | oplock &= 0xFF; | 2979 | oplock &= 0xFF; |
2979 | if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE) | 2980 | if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE) |
2980 | return; | 2981 | return; |
2981 | 2982 | ||
2982 | cinode->oplock = 0; | ||
2983 | if (oplock & SMB2_LEASE_READ_CACHING_HE) { | 2983 | if (oplock & SMB2_LEASE_READ_CACHING_HE) { |
2984 | cinode->oplock |= CIFS_CACHE_READ_FLG; | 2984 | new_oplock |= CIFS_CACHE_READ_FLG; |
2985 | strcat(message, "R"); | 2985 | strcat(message, "R"); |
2986 | } | 2986 | } |
2987 | if (oplock & SMB2_LEASE_HANDLE_CACHING_HE) { | 2987 | if (oplock & SMB2_LEASE_HANDLE_CACHING_HE) { |
2988 | cinode->oplock |= CIFS_CACHE_HANDLE_FLG; | 2988 | new_oplock |= CIFS_CACHE_HANDLE_FLG; |
2989 | strcat(message, "H"); | 2989 | strcat(message, "H"); |
2990 | } | 2990 | } |
2991 | if (oplock & SMB2_LEASE_WRITE_CACHING_HE) { | 2991 | if (oplock & SMB2_LEASE_WRITE_CACHING_HE) { |
2992 | cinode->oplock |= CIFS_CACHE_WRITE_FLG; | 2992 | new_oplock |= CIFS_CACHE_WRITE_FLG; |
2993 | strcat(message, "W"); | 2993 | strcat(message, "W"); |
2994 | } | 2994 | } |
2995 | if (!cinode->oplock) | 2995 | if (!new_oplock) |
2996 | strcat(message, "None"); | 2996 | strncpy(message, "None", sizeof(message)); |
2997 | |||
2998 | cinode->oplock = new_oplock; | ||
2997 | cifs_dbg(FYI, "%s Lease granted on inode %p\n", message, | 2999 | cifs_dbg(FYI, "%s Lease granted on inode %p\n", message, |
2998 | &cinode->vfs_inode); | 3000 | &cinode->vfs_inode); |
2999 | } | 3001 | } |