[RHEL7,COMMIT] fuse kio: Fix NULL pointer dereference in pcs_map_get_locked()

Submitted by Konstantin Khorenko on July 10, 2018, 4:16 p.m.

Details

Message ID 201807101616.w6AGGaGE029064@finist_ce7.work
State New
Series "fuse kio: Fix NULL pointer dereference in pcs_map_get_locked()"
Headers show

Commit Message

Konstantin Khorenko July 10, 2018, 4:16 p.m.
The commit is pushed to "branch-rh7-3.10.0-862.6.3.vz7.62.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-862.6.3.vz7.62.2
------>
commit 9b7aca26400412c1881ee3dab03c8abf554934e3
Author: Kirill Tkhai <ktkhai@virtuozzo.com>
Date:   Tue Jul 10 19:16:36 2018 +0300

    fuse kio: Fix NULL pointer dereference in pcs_map_get_locked()
    
    MAP_ARGS() contains reference to struct pcs_map_entry::mapping,
    which can be NULL in case of map dead. So, we must not access
    it in such situation. Otherwise, the following crash may occur:
    
    [ 2233.116831] BUG: unable to handle kernel paging request at ffffffffffffff80
    [ 2233.123903] IP: [<ffffffffc0c6a477>] pcs_find_get_map+0x97/0x330 [fuse_kio_pcs]
    [ 2233.131269] PGD 31b412067 PUD 31b414067 PMD 0
    [ 2233.283614] CPU: 1 PID: 82 Comm: kworker/1:1 ve: 0 Kdump: loaded Not tainted 3.10.0-862.3.2.vz7.61.12 #1 61.12
    [ 2233.303374] Workqueue: pcs_cluster cc_workqueue_handler [fuse_kio_pcs]
    [ 2233.309956] task: ffff9f3539c252d0 ti: ffff9f37d65ec000 task.ti: ffff9f37d65ec000
    [ 2233.317478] RIP: 0010:[<ffffffffc0c6a477>]  [<ffffffffc0c6a477>] pcs_find_get_map+0x97/0x330 [fuse_kio_pcs]
    [ 2233.327281] RSP: 0018:ffff9f37d65efce8  EFLAGS: 00010246
    [ 2233.332645] RAX: 0000000000000000 RBX: ffff9f36b5791228 RCX: 0000000000000001
    [ 2233.339813] RDX: 0000000000000101 RSI: ffff9f37d8985d80 RDI: 0000000000000000
    [ 2233.346987] RBP: ffff9f37d65efd58 R08: 0000000000000002 R09: 0000000000000030
    [ 2233.354136] R10: 00000207f02219e5 R11: ffff9f37d567ddb0 R12: 0000000000000002
    [ 2233.361304] R13: ffff9f36b57934a0 R14: ffff9f3758300000 R15: ffff9f36b5791200
    [ 2233.368463] FS:  00007f7fd9e4a700(0000) GS:ffff9f37eec40000(0000) knlGS:0000000000000000
    [ 2233.376564] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
    [ 2233.382328] CR2: ffffffffffffff80 CR3: 00000003f17ea000 CR4: 00000000000407e0
    [ 2233.389530] Call Trace:
    [ 2233.391996]  [<ffffffffabd79b7c>] ? __trace_bprintk+0x5c/0x80
    [ 2233.397767]  [<ffffffffc0c6f84c>] pcs_cc_process_ireq_chunk+0x5c/0xf0 [fuse_kio_pcs]
    [ 2233.405542]  [<ffffffffc0c70318>] ireq_process_+0x1e8/0x2a0 [fuse_kio_pcs]
    [ 2233.412464]  [<ffffffffc0c7070e>] cc_workqueue_handler+0xee/0x120 [fuse_kio_pcs]
    [ 2233.419898]  [<ffffffffabcb65b2>] process_one_work+0x182/0x440
    [ 2233.425782]  [<ffffffffabcb7766>] worker_thread+0x126/0x3c0
    [ 2233.431405]  [<ffffffffabcb7640>] ? manage_workers.isra.24+0x2a0/0x2a0
    [ 2233.437985]  [<ffffffffabcbe8f1>] kthread+0xd1/0xe0
    [ 2233.442862]  [<ffffffffabcbe820>] ? create_kthread+0x60/0x60
    [ 2233.448541]  [<ffffffffac3506e4>] ret_from_fork_nospec_begin+0xe/0x21
    [ 2233.455012]  [<ffffffffabcbe820>] ? create_kthread+0x60/0x60
    
    (We may meet more crashes like this in the situations, when map
     is truncated after successful pcs_find_get_map(), and they have
     to be fixed in the same way, i.e., check for PCS_MAP_DEAD under spinlock
     before dereference of other fields).
    
    https://jira.sw.ru/browse/PSBM-86458
    
    Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
    Reviewed-by: Pavel Butsykin <pbutsykin@virtuozzo.com>
---
 fs/fuse/kio/pcs/pcs_map.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/fuse/kio/pcs/pcs_map.h b/fs/fuse/kio/pcs/pcs_map.h
index 3eb380bd0b07..6a7535d8cbdb 100644
--- a/fs/fuse/kio/pcs/pcs_map.h
+++ b/fs/fuse/kio/pcs/pcs_map.h
@@ -237,12 +237,12 @@  static inline void pcs_map_put_locked(struct pcs_map_entry *m)
 
 static inline bool pcs_map_get_locked(struct pcs_map_entry *m)
 {
-	TRACE( MAP_FMT " refcnt:%d\n", MAP_ARGS(m), atomic_read(&m->__refcnt));
 	BUG_ON(atomic_read(&m->__refcnt) < 0);
 
-	if (m->state & PCS_MAP_DEAD) {
+	if (m->state & PCS_MAP_DEAD)
 		return 0;
-	}
+
+	TRACE( MAP_FMT " refcnt:%d\n", MAP_ARGS(m), atomic_read(&m->__refcnt));
 
 	if (atomic_inc_return(&m->__refcnt) == 1)
 		map_del_lru(m);