From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753295AbbC3JKD (ORCPT ); Mon, 30 Mar 2015 05:10:03 -0400 Received: from mailout1.samsung.com ([203.254.224.24]:55094 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752866AbbC3JJl (ORCPT ); Mon, 30 Mar 2015 05:09:41 -0400 X-AuditID: cbfee68f-f791c6d000004834-85-551912d38927 Date: Mon, 30 Mar 2015 09:09:39 +0000 (GMT) From: EunTaik Lee Subject: Fwd: [PATCH] fix race condition between device_del and device_add To: "gregkh@linuxfoundation.org" Cc: "linux-kernel@vger.kernel.org" Reply-to: eun.taik.lee@samsung.com MIME-version: 1.0 X-MTR: 20150330090833218@eun.taik.lee Msgkey: 20150330090833218@eun.taik.lee X-EPLocale: ko_KR.utf-8 X-Priority: 3 X-EPWebmail-Msg-Type: personal X-EPWebmail-Reply-Demand: 0 X-EPApproval-Locale: X-EPHeader: ML X-MLAttribute: X-RootMTR: 20150330090525717@eun.taik.lee X-ParentMTR: 20150330090525717@eun.taik.lee X-ArchiveUser: EV X-CPGSPASS: N X-ConfirmMail: N,general Content-type: text/plain; charset=utf-8 MIME-version: 1.0 Message-id: <262914446.87761427706578969.JavaMail.weblogic@epmlwas08c> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprFJsWRmVeSWpSXmKPExsVy+t8zTd3LQpKhBuveqFhc3jWHzYHR4/Mm uQDGqAZGm8Si5IzMslSF1Lzk/JTMvHRbpdAQN10LJYWM/OISW6VoIwNjPSNTEz0jE3M9S4NY KyNTJYW8xNxUW6UKXaheJYWi5AKg2tzKYqABOal6UHG94tS8FIes/FKQS/SKE3OLS/PS9ZLz c5UUyhJzSoFGKOknTGXMOPD1P3PBEamKS1tXMzcwvpDsYuTkEBJQlzixew0LiC0hYCKx/UMf O4QtJnHh3nq2LkYuoJpljBKv39xkginauesrVGIOo8S6G1PBulkEVCW62z6B2WwCuhL/P3aB TRIW8JKYdvMHI4gtImArMXFZNzOIzSzgKPHo8h1miCuUJOYfbgDr5RUQlDg58wnURaoSs78+ YoWIq0lcXP6ZGSIuLnFh7iWoS3klZrQ/haqXk5j2dQ1UjbTE+VkbGGG+Wfz9MVScX+LY7R1Q zwhITD1zEKpGS2JSZzsbhK0jsev4JqgaQYnT17qZYXbd3zIXKi4hsbXlCSvEL4oSU7ofAt3D AWRrSqzfpY/uFV4BN4mGU8tZQOEmIdDLIdHw/zfLBEalWUjqZiEZNQthFLKSBYwsqxhFUwuS C4qT0ouMkWN7EyMkEfbvYLx7wPoQowAHoxIPr0O9RKgQa2JZcWXuIcZkYCxNZJYSTc4Hptu8 knhDYzMjC1MTU2Mjc0szDGETUwsLEyMcwkrivAulfgYLCaQnlqRmp6YWpBbFF5XmpBYfYmTi 4JRqYKx532bocvsbO+OpTolIK7e0pYklE/6m88e9XTFriTofT+olrl9rN5id52P9WX+qLd3x SY2Iv7253DEFhu+mWQndz3885pZ7JLjuyi8rG69bq3OTVTRrze9ank3Ldd/Gmbf1x/xte4ob FsxpKXdiOJoWG1X8wXmjXdrDtF9cMk/0DHjnsi+JU2Ipzkg01GIuKk4EAKIX+2GtAwAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrOKsWRmVeSWpSXmKPExsVy+t/tXt3LQpKhBkd3KVhc3jWHzYHR4/Mm uQDGqAybjNTElNQihdS85PyUzLx0WyXv4HjneFMzA0NdQ0sLcyWFvMTcVFslF58AXbfMHKCh SgpliTmlQKGAxOJiJX07m6L80pJUhYz84hJbpWgjA2M9I1MTPSNjAz0Tg1grQwMDI1OgqoSM jANf/zMXHJGquLR1NXMD4wvJLkZODiEBdYkTu9ewgNgSAiYSO3d9ZYOwxSQu3FsPZHMB1cxh lFh3YypYEYuAqkR32ycwm01AV+L/xy52EFtYwEti2s0fjCC2iICtxMRl3cwgNrOAo8Sjy3eY IZYpScw/3ADWyysgKHFy5hOoxaoSs78+YoWIq0lcXP6ZGSIuLnFh7iV2CJtXYkb7U6h6OYlp X9dA1UhLnJ+1gRHm6MXfH0PF+SWO3d7BBGELSEw9cxCqRktiUmc71JM6EruOb4KqEZQ4fa2b GWbX/S1zoeISEltbnrBC/KIoMaX7IdA9HEC2psT6XfroXuEVcJNoOLWcZQKj7CwkqVlIumch dCMrWcDIsopRNLUguaA4Kb3CSK84Mbe4NC9dLzk/dxMjOBE9W7SD8d9560OMAhyMSjy8DvUS oUKsiWXFlbmHGCU4mJVEeC15JUOFeFMSK6tSi/Lji0pzUosPMZoC42wis5Rocj4wSeaVxBsa GxgbGlqaG5gaGlkoifP+P5cbIiSQnliSmp2aWpBaBNPHxMEp1cB4e/qs97+zawykdBLnaqac urTxiVbTvskqprE1k4XyzrcZKD279CMyJOTm8ozr3sdCl3zYoWLV+COhPZelObzbPiLD6Pfb eUs/sj2sKPvRYdWZ4cgRMNvFNvJ/3UEt+aQPp2IkdIQv+R/7J1cXbW1VXCOk083Gq+jzIPld UVaCyr+4472sJ5RYijMSDbWYi4oTAftjptxaAwAA DLP-Filter: Pass X-CFilter-Loop: Reflected Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from base64 to 8bit by nfs id t2U9AB1O017247 There is a possible race condition when a device is added while another device with the same parent , with ref count of one, is deleted. CPU0 CPU1 device_add() device_del() get_device_parent() put_device(parent); kobj = kobject_get(k); kobject_put() kref_put() refcount=0 refcount is 0 WARNS it was 0 but return kobj frees kobj uses the freed parent kobj The race condition exists because kref_put() and the release function is not atomic. Using kobject_get_unless_zero() instead of kobject_get() in get_device_parent() will prevent this race condition. Signed-off-by: eun.taik.lee --- drivers/base/core.c | 2 +- include/linux/kobject.h | 2 ++ lib/kobject.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 07304a3..ec2f211 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -761,7 +761,7 @@ static struct kobject *get_device_parent(struct device *dev, spin_lock(&dev->class->p->glue_dirs.list_lock); list_for_each_entry(k, &dev->class->p->glue_dirs.list, entry) if (k->parent == parent_kobj) { - kobj = kobject_get(k); + kobj = kobject_get_unless_zero(k); break; } spin_unlock(&dev->class->p->glue_dirs.list_lock); diff --git a/include/linux/kobject.h b/include/linux/kobject.h index 2d61b90..3032744 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -107,6 +107,8 @@ extern int __must_check kobject_rename(struct kobject *, const char *new_name); extern int __must_check kobject_move(struct kobject *, struct kobject *); extern struct kobject *kobject_get(struct kobject *kobj); +extern struct kobject * __must_check kobject_get_unless_zero( + struct kobject *kobj); extern void kobject_put(struct kobject *kobj); extern const void *kobject_namespace(struct kobject *kobj); diff --git a/lib/kobject.c b/lib/kobject.c index 03d4ab3..ff0ce681 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -581,7 +581,7 @@ struct kobject *kobject_get(struct kobject *kobj) return kobj; } -static struct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj) +struct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj) { if (!kref_get_unless_zero(&kobj->kref)) kobj = NULL;{.n++%ݶw{.n+{G{ayʇڙ,jfhz_(階ݢj"mG?&~iOzv^m ?I