OSDN Git Service

bpf: Check whether or not node is NULL before free it in free_bulk
authorHou Tao <houtao1@huawei.com>
Mon, 19 Sep 2022 14:48:11 +0000 (22:48 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 20 Sep 2022 15:06:27 +0000 (08:06 -0700)
llnode could be NULL if there are new allocations after the checking of
c-free_cnt > c->high_watermark in bpf_mem_refill() and before the
calling of __llist_del_first() in free_bulk (e.g. a PREEMPT_RT kernel
or allocation in NMI context). And it will incur oops as shown below:

 BUG: kernel NULL pointer dereference, address: 0000000000000000
 #PF: supervisor write access in kernel mode
 #PF: error_code(0x0002) - not-present page
 PGD 0 P4D 0
 Oops: 0002 [#1] PREEMPT_RT SMP
 CPU: 39 PID: 373 Comm: irq_work/39 Tainted: G        W          6.0.0-rc6-rt9+ #1
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996)
 RIP: 0010:bpf_mem_refill+0x66/0x130
 ......
 Call Trace:
  <TASK>
  irq_work_single+0x24/0x60
  irq_work_run_list+0x24/0x30
  run_irq_workd+0x18/0x20
  smpboot_thread_fn+0x13f/0x2c0
  kthread+0x121/0x140
  ? kthread_complete_and_exit+0x20/0x20
  ret_from_fork+0x1f/0x30
  </TASK>

Simply fixing it by checking whether or not llnode is NULL in free_bulk().

Fixes: 8d5a8011b35d ("bpf: Batch call_rcu callbacks instead of SLAB_TYPESAFE_BY_RCU.")
Signed-off-by: Hou Tao <houtao1@huawei.com>
Link: https://lore.kernel.org/r/20220919144811.3570825-1-houtao@huaweicloud.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/memalloc.c

index 20621f5..5f83be1 100644 (file)
@@ -277,7 +277,8 @@ static void free_bulk(struct bpf_mem_cache *c)
                local_dec(&c->active);
                if (IS_ENABLED(CONFIG_PREEMPT_RT))
                        local_irq_restore(flags);
-               enque_to_free(c, llnode);
+               if (llnode)
+                       enque_to_free(c, llnode);
        } while (cnt > (c->high_watermark + c->low_watermark) / 2);
 
        /* and drain free_llist_extra */