diff options
author | Stefano Brivio <sbrivio@redhat.com> | 2018-07-05 09:10:02 -0400 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2018-07-05 14:48:25 -0400 |
commit | 729c0c9dd55204f0c9a823ac8a7bfa83d36c7e78 (patch) | |
tree | e56c4645163b0b4b3bfbcdad619c44b4db6989cb /fs/cifs/smb2ops.c | |
parent | 7ffbe65578b44fafdef577a360eb0583929f7c6e (diff) |
cifs: Fix stack out-of-bounds in smb{2,3}_create_lease_buf()
smb{2,3}_create_lease_buf() store a lease key in the lease
context for later usage on a lease break.
In most paths, the key is currently sourced from data that
happens to be on the stack near local variables for oplock in
SMB2_open() callers, e.g. from open_shroot(), whereas
smb2_open_file() properly allocates space on its stack for it.
The address of those local variables holding the oplock is then
passed to create_lease_buf handlers via SMB2_open(), and 16
bytes near oplock are used. This causes a stack out-of-bounds
access as reported by KASAN on SMB2.1 and SMB3 mounts (first
out-of-bounds access is shown here):
[ 111.528823] BUG: KASAN: stack-out-of-bounds in smb3_create_lease_buf+0x399/0x3b0 [cifs]
[ 111.530815] Read of size 8 at addr ffff88010829f249 by task mount.cifs/985
[ 111.532838] CPU: 3 PID: 985 Comm: mount.cifs Not tainted 4.18.0-rc3+ #91
[ 111.534656] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014
[ 111.536838] Call Trace:
[ 111.537528] dump_stack+0xc2/0x16b
[ 111.540890] print_address_description+0x6a/0x270
[ 111.542185] kasan_report+0x258/0x380
[ 111.544701] smb3_create_lease_buf+0x399/0x3b0 [cifs]
[ 111.546134] SMB2_open+0x1ef8/0x4b70 [cifs]
[ 111.575883] open_shroot+0x339/0x550 [cifs]
[ 111.591969] smb3_qfs_tcon+0x32c/0x1e60 [cifs]
[ 111.617405] cifs_mount+0x4f3/0x2fc0 [cifs]
[ 111.674332] cifs_smb3_do_mount+0x263/0xf10 [cifs]
[ 111.677915] mount_fs+0x55/0x2b0
[ 111.679504] vfs_kern_mount.part.22+0xaa/0x430
[ 111.684511] do_mount+0xc40/0x2660
[ 111.698301] ksys_mount+0x80/0xd0
[ 111.701541] do_syscall_64+0x14e/0x4b0
[ 111.711807] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 111.713665] RIP: 0033:0x7f372385b5fa
[ 111.715311] Code: 48 8b 0d 99 78 2c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 66 78 2c 00 f7 d8 64 89 01 48
[ 111.720330] RSP: 002b:00007ffff27049d8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a5
[ 111.722601] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f372385b5fa
[ 111.724842] RDX: 000055c2ecdc73b2 RSI: 000055c2ecdc73f9 RDI: 00007ffff270580f
[ 111.727083] RBP: 00007ffff2705804 R08: 000055c2ee976060 R09: 0000000000001000
[ 111.729319] R10: 0000000000000000 R11: 0000000000000206 R12: 00007f3723f4d000
[ 111.731615] R13: 000055c2ee976060 R14: 00007f3723f4f90f R15: 0000000000000000
[ 111.735448] The buggy address belongs to the page:
[ 111.737420] page:ffffea000420a7c0 count:0 mapcount:0 mapping:0000000000000000 index:0x0
[ 111.739890] flags: 0x17ffffc0000000()
[ 111.741750] raw: 0017ffffc0000000 0000000000000000 dead000000000200 0000000000000000
[ 111.744216] raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000
[ 111.746679] page dumped because: kasan: bad access detected
[ 111.750482] Memory state around the buggy address:
[ 111.752562] ffff88010829f100: 00 f2 f2 f2 f2 f2 f2 f2 00 00 00 00 00 00 00 00
[ 111.754991] ffff88010829f180: 00 00 f2 f2 00 00 00 00 00 00 00 00 00 00 00 00
[ 111.757401] >ffff88010829f200: 00 00 00 00 00 f1 f1 f1 f1 01 f2 f2 f2 f2 f2 f2
[ 111.759801] ^
[ 111.762034] ffff88010829f280: f2 02 f2 f2 f2 f2 f2 f2 f2 00 00 00 00 00 00 00
[ 111.764486] ffff88010829f300: f2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 111.766913] ==================================================================
Lease keys are however already generated and stored in fid data
on open and create paths: pass them down to the lease context
creation handlers and use them.
Suggested-by: Aurélien Aptel <aaptel@suse.com>
Reviewed-by: Aurelien Aptel <aaptel@suse.com>
Fixes: b8c32dbb0deb ("CIFS: Request SMB2.1 leases")
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs/smb2ops.c')
-rw-r--r-- | fs/cifs/smb2ops.c | 9 |
1 files changed, 3 insertions, 6 deletions
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 1d5985bd760b..ea92a38b2f08 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -2222,8 +2222,7 @@ smb2_create_lease_buf(u8 *lease_key, u8 oplock) | |||
2222 | if (!buf) | 2222 | if (!buf) |
2223 | return NULL; | 2223 | return NULL; |
2224 | 2224 | ||
2225 | buf->lcontext.LeaseKeyLow = cpu_to_le64(*((u64 *)lease_key)); | 2225 | memcpy(&buf->lcontext.LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE); |
2226 | buf->lcontext.LeaseKeyHigh = cpu_to_le64(*((u64 *)(lease_key + 8))); | ||
2227 | buf->lcontext.LeaseState = map_oplock_to_lease(oplock); | 2226 | buf->lcontext.LeaseState = map_oplock_to_lease(oplock); |
2228 | 2227 | ||
2229 | buf->ccontext.DataOffset = cpu_to_le16(offsetof | 2228 | buf->ccontext.DataOffset = cpu_to_le16(offsetof |
@@ -2249,8 +2248,7 @@ smb3_create_lease_buf(u8 *lease_key, u8 oplock) | |||
2249 | if (!buf) | 2248 | if (!buf) |
2250 | return NULL; | 2249 | return NULL; |
2251 | 2250 | ||
2252 | buf->lcontext.LeaseKeyLow = cpu_to_le64(*((u64 *)lease_key)); | 2251 | memcpy(&buf->lcontext.LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE); |
2253 | buf->lcontext.LeaseKeyHigh = cpu_to_le64(*((u64 *)(lease_key + 8))); | ||
2254 | buf->lcontext.LeaseState = map_oplock_to_lease(oplock); | 2252 | buf->lcontext.LeaseState = map_oplock_to_lease(oplock); |
2255 | 2253 | ||
2256 | buf->ccontext.DataOffset = cpu_to_le16(offsetof | 2254 | buf->ccontext.DataOffset = cpu_to_le16(offsetof |
@@ -2287,8 +2285,7 @@ smb3_parse_lease_buf(void *buf, unsigned int *epoch, char *lease_key) | |||
2287 | if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS) | 2285 | if (lc->lcontext.LeaseFlags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS) |
2288 | return SMB2_OPLOCK_LEVEL_NOCHANGE; | 2286 | return SMB2_OPLOCK_LEVEL_NOCHANGE; |
2289 | if (lease_key) | 2287 | if (lease_key) |
2290 | memcpy(lease_key, &lc->lcontext.LeaseKeyLow, | 2288 | memcpy(lease_key, &lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); |
2291 | SMB2_LEASE_KEY_SIZE); | ||
2292 | return le32_to_cpu(lc->lcontext.LeaseState); | 2289 | return le32_to_cpu(lc->lcontext.LeaseState); |
2293 | } | 2290 | } |
2294 | 2291 | ||