From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751176Ab3IIFMi (ORCPT ); Mon, 9 Sep 2013 01:12:38 -0400 Received: from szxga02-in.huawei.com ([119.145.14.65]:64705 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750769Ab3IIFMh (ORCPT ); Mon, 9 Sep 2013 01:12:37 -0400 From: Libin To: CC: , , , Subject: [PATCH] workqueue: fix potential reentrancy issue Date: Mon, 9 Sep 2013 13:12:14 +0800 Message-ID: <1378703534-4496-1-git-send-email-huawei.libin@huawei.com> X-Mailer: git-send-email 1.8.1.msysgit.1 MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.135.74.57] X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Li Bin 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 --- 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