xdp_rxq_info_unreg() implicitly calls xdp_rxq_info_unreg_mem_model(). This may well be confusing to the driver authors, and lead to double free if they call xdp_rxq_info_unreg_mem_model() before xdp_rxq_info_unreg() (when mem model type == MEM_TYPE_PAGE_POOL). In fact error path of mvpp2_rxq_init() seems to currently do exactly that. The double free will result in refcount underflow in page_pool_destroy(). Make the interface a little more programmer friendly by clearing type and id so that xdp_rxq_info_unreg_mem_model() can be called multiple times.
Unified · Split
| @@ -113,8 +113,13 @@ static void mem_allocator_disconnect(void *allocator) · 112 unmodified lines | ||
| 113 | 113 | void xdp_rxq_info_unreg_mem_model(struct xdp_rxq_info *xdp_rxq) |
| 114 | 114 | { |
| 115 | 115 | struct xdp_mem_allocator *xa; |
| 116 | + int type = xdp_rxq->mem.type; | |
| 116 | 117 | int id = xdp_rxq->mem.id; |
| 117 | 118 | |
| 119 | + /* Reset mem info to defaults */ | |
| 120 | + xdp_rxq->mem.id = 0; | |
| 121 | + xdp_rxq->mem.type = 0; | |
| 122 | + | |
| 118 | 123 | if (xdp_rxq->reg_state != REG_STATE_REGISTERED) { |
| 119 | 124 | WARN(1, "Missing register, driver bug"); |
| 120 | 125 | return; |
| @@ -123,7 +128,7 @@ void xdp_rxq_info_unreg_mem_model(struct xdp_rxq_info *xdp_rxq) · 2 unmodified lines | ||
| 123 | 128 | if (id == 0) |
| 124 | 129 | return; |
| 125 | 130 | |
| 126 | − if (xdp_rxq->mem.type == MEM_TYPE_PAGE_POOL) { | |
| 131 | + if (type == MEM_TYPE_PAGE_POOL) { | |
| 127 | 132 | rcu_read_lock(); |
| 128 | 133 | xa = rhashtable_lookup(mem_id_ht, &id, mem_id_rht_params); |
| 129 | 134 | page_pool_destroy(xa->page_pool); |
| @@ -144,10 +149,6 @@ void xdp_rxq_info_unreg(struct xdp_rxq_info *xdp_rxq) · 14 unmodified lines | ||
| 144 | 149 | |
| 145 | 150 | xdp_rxq->reg_state = REG_STATE_UNREGISTERED; |
| 146 | 151 | xdp_rxq->dev = NULL; |
| 147 | − | |
| 148 | − /* Reset mem info to defaults */ | |
| 149 | − xdp_rxq->mem.id = 0; | |
| 150 | − xdp_rxq->mem.type = 0; | |
| 151 | 152 | } |
| 152 | 153 | EXPORT_SYMBOL_GPL(xdp_rxq_info_unreg); |
| 153 | 154 | |