• Hou Tao's avatar
    bpf: Enable IRQ after irq_work_raise() completes in unit_free{_rcu}() · 62cf51cb
    Hou Tao authored
    Both unit_free() and unit_free_rcu() invoke irq_work_raise() to free
    freed objects back to slab and the invocation may also be preempted by
    unit_alloc() and unit_alloc() may return NULL unexpectedly as shown in
    the following case:
    
    task A         task B
    
    unit_free()
      // high_watermark = 48
      // free_cnt = 49 after free
      irq_work_raise()
        // mark irq work as IRQ_WORK_PENDING
        irq_work_claim()
    
                   // task B preempts task A
                   unit_alloc()
                     // free_cnt = 48 after alloc
    
                   // does unit_alloc() 32-times
    	       ......
    	       // free_cnt = 16
    
    	       unit_alloc()
    	         // free_cnt = 15 after alloc
                     // irq work is already PENDING,
                     // so just return
                     irq_work_raise()
    
    	       // does unit_alloc() 15-times
                   ......
    	       // free_cnt = 0
    
                   unit_alloc()
                     // free_cnt = 0 before alloc
                     return NULL
    
    Fix it by enabling IRQ after irq_work_raise() completes.
    Signed-off-by: default avatarHou Tao <houtao1@huawei.com>
    Link: https://lore.kernel.org/r/20230901111954.1804721-3-houtao@huaweicloud.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    62cf51cb
memalloc.c 24.5 KB