From: Li Bin <huawei.li...@huawei.com> When one work starts execution, the high bits of work's data contain pool ID. It can represent a maximum of WORK_OFFQ_POOL_NONE. Pool ID is assigned WORK_OFFQ_POOL_NONE when the work being initialized indicating that no pool is associated and get_work_pool() uses it to check the associated pool. So if worker_pool_assign_id() assigns a ID greater than or equal WORK_OFFQ_POOL_NONE to a pool, it may break the non-reentrance guarantee.
This patch fix this issue by modifying the worker_pool_assign_id() function to add the WORK_OFFQ_POOL_NONE check condition. Signed-off-by: Li Bin <huawei.li...@huawei.com> --- kernel/workqueue.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 41019b1..97d9ff7 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -518,7 +518,14 @@ static inline void debug_work_activate(struct work_struct *work) { } static inline void debug_work_deactivate(struct work_struct *work) { } #endif -/* allocate ID and assign it to @pool */ +/** + * worker_pool_assign_id - allocate ID and assing it to @pool + * @pool: the pool pointer of interest + * + * Return 0 if ID assigned successful. + * Return non-zero if the allocation fails or the ID number out of + * %WORK_OFFQ_POOL_NONE range. + */ static int worker_pool_assign_id(struct worker_pool *pool) { int ret; @@ -526,6 +533,8 @@ static int worker_pool_assign_id(struct worker_pool *pool) lockdep_assert_held(&wq_pool_mutex); ret = idr_alloc(&worker_pool_idr, pool, 0, 0, GFP_KERNEL); + if (ret >= WORK_OFFQ_POOL_NONE) + return ret; if (ret >= 0) { pool->id = ret; return 0; -- 1.8.2.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/