Message ID | 4bca8ffa66fa094da37625e66f3a2681058531d6.1683043928.git.daniel@makrotopia.org |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp759481vqo; Tue, 2 May 2023 09:54:25 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ46AvuLjwmRLf/AlzHh5wmX2shOGzopm5byRH5bzHKr+VSRNkJWmP/c+UjNA0VmgJkBqGKB X-Received: by 2002:a17:90a:2e82:b0:24e:18e3:37ec with SMTP id r2-20020a17090a2e8200b0024e18e337ecmr4651471pjd.32.1683046465278; Tue, 02 May 2023 09:54:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1683046465; cv=none; d=google.com; s=arc-20160816; b=EHYj5KFaGlibKBBSQI01Cu52Pyi/KE24NWUePwEJ5pS2PQN5UqwX7RSILe4MPMGTq8 BPAo3mTvGmAUtkLxJCJlUQI9NKGXahXbpt2W/nA2oXDXX56v/Qk5q8pn71i8FCwbgOaN V15bGvRBbiaQn5AthFdCrL6dx54pbx/xTj+3C2yH/8beZzcRKjFX9zl8rLHPM8FcjFdy kMHwEWYjMpavSPQvZJRATpc/y7F7xvgkuo8rIT1x6vqI8Igaj2VWniR7zh6eUPfVX9Oq AfiWP/BO+Rol0iQSHBEHEmv9UlZjqhsHUiskZG9nK9CmKHlhQmorxbSvgeRe47LqQSyx GMdw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:to:from:date; bh=K5rQZzkpLFh12/Tkfwp5eyA1dz0oMZkvcSzICdsncNo=; b=JIzRvnXBLt3ves54wNJjN/A2XlHIgfRdD3KUGYjN+u43ueMTY33WLsA7DHLwKnNbcE B9it1DGpLVZKT5zCMJ9NmelHkwbYSe2ljVyNcp3eCo/OgXVxnOLQobu6DFwauGNB/M7M LnqNd2ndxZ4kjPItyC0NXMNs5Ox/yvGec82xfNeIRNvLfZrLIgUZekfFitpBGnsiCXKi p82BEJZmf6nBV1S6m8+8cM7KEkAmQBK0QuKg5UbdtqwROi77mJHq6/V9K+svpcAO5YzJ X/776rfARimMxfoR16q5Mk2dKy/+ZHWHKzMs1B0cepp38d/qMAqyTanq7ZBMhHriQLDk hldQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id bs188-20020a6328c5000000b00520b3928bebsi18027896pgb.7.2023.05.02.09.54.12; Tue, 02 May 2023 09:54:25 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234154AbjEBQsS (ORCPT <rfc822;rbbytesnap@gmail.com> + 99 others); Tue, 2 May 2023 12:48:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36392 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233478AbjEBQsP (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Tue, 2 May 2023 12:48:15 -0400 Received: from fudo.makrotopia.org (fudo.makrotopia.org [IPv6:2a07:2ec0:3002::71]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 132442118 for <linux-kernel@vger.kernel.org>; Tue, 2 May 2023 09:48:14 -0700 (PDT) Received: from local by fudo.makrotopia.org with esmtpsa (TLS1.3:TLS_AES_256_GCM_SHA384:256) (Exim 4.96) (envelope-from <daniel@makrotopia.org>) id 1pttAi-0000UW-1L; Tue, 02 May 2023 18:48:12 +0200 Date: Tue, 2 May 2023 17:48:07 +0100 From: Daniel Golle <daniel@makrotopia.org> To: linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org, Miquel Raynal <miquel.raynal@bootlin.com>, Richard Weinberger <richard@nod.at>, Vignesh Raghavendra <vigneshr@ti.com>, Zhihao Cheng <chengzhihao1@huawei.com> Subject: [PATCH 1/4] mtd: ubi: block: don't return on error when removing Message-ID: <4bca8ffa66fa094da37625e66f3a2681058531d6.1683043928.git.daniel@makrotopia.org> References: <cover.1683043928.git.daniel@makrotopia.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <cover.1683043928.git.daniel@makrotopia.org> X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1764802130413005014?= X-GMAIL-MSGID: =?utf-8?q?1764802130413005014?= |
Series |
mtd: ubi: behave like a good MTD citizen
|
|
Commit Message
Daniel Golle
May 2, 2023, 4:48 p.m. UTC
There is no point on returning the error from ubiblock_remove in case
it is being called due to a volume removal event -- the volume is gone,
we should destroy and remove the ubiblock device no matter what.
Introduce a new boolean parameter 'force' to tell ubiblock_remove to go
on even in case the ubiblock device is still busy. Use that new option
when calling ubiblock_remove due to a UBI_VOLUME_REMOVED event.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/mtd/ubi/block.c | 6 +++---
drivers/mtd/ubi/cdev.c | 2 +-
drivers/mtd/ubi/ubi.h | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
Comments
在 2023/5/3 0:48, Daniel Golle 写道: > There is no point on returning the error from ubiblock_remove in case > it is being called due to a volume removal event -- the volume is gone, > we should destroy and remove the ubiblock device no matter what. > > Introduce a new boolean parameter 'force' to tell ubiblock_remove to go > on even in case the ubiblock device is still busy. Use that new option > when calling ubiblock_remove due to a UBI_VOLUME_REMOVED event. > > Signed-off-by: Daniel Golle <daniel@makrotopia.org> > --- > drivers/mtd/ubi/block.c | 6 +++--- > drivers/mtd/ubi/cdev.c | 2 +- > drivers/mtd/ubi/ubi.h | 4 ++-- > 3 files changed, 6 insertions(+), 6 deletions(-) > > diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c > index 3711d7f746003..6f5804f4b8f55 100644 > --- a/drivers/mtd/ubi/block.c > +++ b/drivers/mtd/ubi/block.c > @@ -457,7 +457,7 @@ static void ubiblock_cleanup(struct ubiblock *dev) > idr_remove(&ubiblock_minor_idr, dev->gd->first_minor); > } > > -int ubiblock_remove(struct ubi_volume_info *vi) > +int ubiblock_remove(struct ubi_volume_info *vi, bool force) > { > struct ubiblock *dev; > int ret; > @@ -471,7 +471,7 @@ int ubiblock_remove(struct ubi_volume_info *vi) > > /* Found a device, let's lock it so we can check if it's busy */ > mutex_lock(&dev->dev_mutex); > - if (dev->refcnt > 0) { > + if (dev->refcnt > 0 && !force) { > ret = -EBUSY; > goto out_unlock_dev; > } After looking through this series, I think we should pay attention to one problem: The lifetime of mtd device and ubi things(ubi device/volume/block device). It's difficult to decide whether or not to destroy ubi things when mtd driver is removed. If we destroy ubi things, one application may have opened an ubi volume early, then ubi device and all its volumes are destroyed by ubi_notify_remove(), later volume accessing by the application will trigger an UAF problem in kernel. App driver_remove fd = ubi_open_volume ubi_notify_remove ubi_detach_mtd_dev vfree(ubi->vtbl) ioctl(fd, UBI_IOCVOLUP) ubi_start_update set_update_marker vtbl_rec = ubi->vtbl[vol->vol_id] // UAF! If we reserve ubi things even mtd driver is removed. There exists mtd drivers releasing mtd device (eg. phram_remove), then upper application could accessing released mtd device by the ubi device, which also triggers UAF in kernel. After looking at nvme_free_ctrl, I found that nvme_dev is released when device refcnt becomes zero, so block device and nvme_dev won't be freed immediately when pci driver removed if upper filesystem being mounted on nvme device. And the mtd device's refcnt is held by ubi too, we may follow this method, but investigating all mtd drivers looks like unrealistic. > @@ -546,7 +546,7 @@ static int ubiblock_notify(struct notifier_block *nb, > */ > break; > case UBI_VOLUME_REMOVED: > - ubiblock_remove(&nt->vi); > + ubiblock_remove(&nt->vi, true); > break; > case UBI_VOLUME_RESIZED: > ubiblock_resize(&nt->vi); > diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c > index f43430b9c1e65..bb55e863dd296 100644 > --- a/drivers/mtd/ubi/cdev.c > +++ b/drivers/mtd/ubi/cdev.c > @@ -572,7 +572,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, > struct ubi_volume_info vi; > > ubi_get_volume_info(desc, &vi); > - err = ubiblock_remove(&vi); > + err = ubiblock_remove(&vi, false); > break; > } > > diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h > index c8f1bd4fa1008..44c0eeaf1e1b0 100644 > --- a/drivers/mtd/ubi/ubi.h > +++ b/drivers/mtd/ubi/ubi.h > @@ -979,7 +979,7 @@ static inline void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol) {} > int ubiblock_init(void); > void ubiblock_exit(void); > int ubiblock_create(struct ubi_volume_info *vi); > -int ubiblock_remove(struct ubi_volume_info *vi); > +int ubiblock_remove(struct ubi_volume_info *vi, bool force); > #else > static inline int ubiblock_init(void) { return 0; } > static inline void ubiblock_exit(void) {} > @@ -987,7 +987,7 @@ static inline int ubiblock_create(struct ubi_volume_info *vi) > { > return -ENOSYS; > } > -static inline int ubiblock_remove(struct ubi_volume_info *vi) > +static inline int ubiblock_remove(struct ubi_volume_info *vi, bool force) > { > return -ENOSYS; > } >
On Wed, May 03, 2023 at 09:09:49PM +0800, Zhihao Cheng wrote: > 在 2023/5/3 0:48, Daniel Golle 写道: > > There is no point on returning the error from ubiblock_remove in case > > it is being called due to a volume removal event -- the volume is gone, > > we should destroy and remove the ubiblock device no matter what. > > > > Introduce a new boolean parameter 'force' to tell ubiblock_remove to go > > on even in case the ubiblock device is still busy. Use that new option > > when calling ubiblock_remove due to a UBI_VOLUME_REMOVED event. > > > > Signed-off-by: Daniel Golle <daniel@makrotopia.org> > > --- > > drivers/mtd/ubi/block.c | 6 +++--- > > drivers/mtd/ubi/cdev.c | 2 +- > > drivers/mtd/ubi/ubi.h | 4 ++-- > > 3 files changed, 6 insertions(+), 6 deletions(-) > > > > diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c > > index 3711d7f746003..6f5804f4b8f55 100644 > > --- a/drivers/mtd/ubi/block.c > > +++ b/drivers/mtd/ubi/block.c > > @@ -457,7 +457,7 @@ static void ubiblock_cleanup(struct ubiblock *dev) > > idr_remove(&ubiblock_minor_idr, dev->gd->first_minor); > > } > > -int ubiblock_remove(struct ubi_volume_info *vi) > > +int ubiblock_remove(struct ubi_volume_info *vi, bool force) > > { > > struct ubiblock *dev; > > int ret; > > @@ -471,7 +471,7 @@ int ubiblock_remove(struct ubi_volume_info *vi) > > /* Found a device, let's lock it so we can check if it's busy */ > > mutex_lock(&dev->dev_mutex); > > - if (dev->refcnt > 0) { > > + if (dev->refcnt > 0 && !force) { > > ret = -EBUSY; > > goto out_unlock_dev; > > } > > After looking through this series, I think we should pay attention to one > problem: The lifetime of mtd device and ubi things(ubi device/volume/block > device). It's difficult to decide whether or not to destroy ubi things when > mtd driver is removed. > If we destroy ubi things, one application may have opened an ubi volume > early, then ubi device and all its volumes are destroyed by > ubi_notify_remove(), later volume accessing by the application will trigger > an UAF problem in kernel. > App driver_remove > fd = ubi_open_volume > ubi_notify_remove > ubi_detach_mtd_dev > vfree(ubi->vtbl) > ioctl(fd, UBI_IOCVOLUP) > ubi_start_update > set_update_marker > vtbl_rec = ubi->vtbl[vol->vol_id] // UAF! > > If we reserve ubi things even mtd driver is removed. There exists mtd > drivers releasing mtd device (eg. phram_remove), then upper application > could accessing released mtd device by the ubi device, which also triggers > UAF in kernel. I agree this is a problem, and I also agree it is not a new problem introduced by this series, but rather already exists in the kernel for many years. An idea to get closer to a good state would be to try dropping the 'anyway' parameter from ubi_detach_mtd_dev which is currently only used in the module_exit. To avoid this, we should make sure the module's refcnt is increased/decreased together with ubi->ref_count. When it comes to the to-be-introduced ubi_notify_remove we still face another problem, see below... > > After looking at nvme_free_ctrl, I found that nvme_dev is released when > device refcnt becomes zero, so block device and nvme_dev won't be freed > immediately when pci driver removed if upper filesystem being mounted on > nvme device. And the mtd device's refcnt is held by ubi too, we may follow > this method, but investigating all mtd drivers looks like unrealistic. A good start would be deciding on and defining the way it should be. I agree with your suggestion above, however, also note that in case of MTD (in contrast to block devices) we have only a 'remove' notification call returning void, see include/linux/mtd/mtd.h struct mtd_notifier { void (*add)(struct mtd_info *mtd); void (*remove)(struct mtd_info *mtd); struct list_head list; }; Also see del_mtd_device in drivers/mtd/mtdcore.c: [...] /* No need to get a refcount on the module containing the notifier, since we hold the mtd_table_mutex */ list_for_each_entry(not, &mtd_notifiers, list) not->remove(mtd); if (mtd->usecount) { printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n", mtd->index, mtd->name, mtd->usecount); ret = -EBUSY; } else { [...] So remove is called despite usecount could still be > 0. Looks a bit like I've opened a can of worms... > > > @@ -546,7 +546,7 @@ static int ubiblock_notify(struct notifier_block *nb, > > */ > > break; > > case UBI_VOLUME_REMOVED: > > - ubiblock_remove(&nt->vi); > > + ubiblock_remove(&nt->vi, true); > > break; > > case UBI_VOLUME_RESIZED: > > ubiblock_resize(&nt->vi); > > diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c > > index f43430b9c1e65..bb55e863dd296 100644 > > --- a/drivers/mtd/ubi/cdev.c > > +++ b/drivers/mtd/ubi/cdev.c > > @@ -572,7 +572,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, > > struct ubi_volume_info vi; > > ubi_get_volume_info(desc, &vi); > > - err = ubiblock_remove(&vi); > > + err = ubiblock_remove(&vi, false); > > break; > > } > > diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h > > index c8f1bd4fa1008..44c0eeaf1e1b0 100644 > > --- a/drivers/mtd/ubi/ubi.h > > +++ b/drivers/mtd/ubi/ubi.h > > @@ -979,7 +979,7 @@ static inline void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol) {} > > int ubiblock_init(void); > > void ubiblock_exit(void); > > int ubiblock_create(struct ubi_volume_info *vi); > > -int ubiblock_remove(struct ubi_volume_info *vi); > > +int ubiblock_remove(struct ubi_volume_info *vi, bool force); > > #else > > static inline int ubiblock_init(void) { return 0; } > > static inline void ubiblock_exit(void) {} > > @@ -987,7 +987,7 @@ static inline int ubiblock_create(struct ubi_volume_info *vi) > > { > > return -ENOSYS; > > } > > -static inline int ubiblock_remove(struct ubi_volume_info *vi) > > +static inline int ubiblock_remove(struct ubi_volume_info *vi, bool force) > > { > > return -ENOSYS; > > } > > >
在 2023/5/24 17:41, Daniel Golle 写道: > On Wed, May 03, 2023 at 09:09:49PM +0800, Zhihao Cheng wrote: >> 在 2023/5/3 0:48, Daniel Golle 写道: >>> There is no point on returning the error from ubiblock_remove in case >>> it is being called due to a volume removal event -- the volume is gone, >>> we should destroy and remove the ubiblock device no matter what. >>> >>> Introduce a new boolean parameter 'force' to tell ubiblock_remove to go >>> on even in case the ubiblock device is still busy. Use that new option >>> when calling ubiblock_remove due to a UBI_VOLUME_REMOVED event. >>> >>> Signed-off-by: Daniel Golle <daniel@makrotopia.org> >>> --- >>> drivers/mtd/ubi/block.c | 6 +++--- >>> drivers/mtd/ubi/cdev.c | 2 +- >>> drivers/mtd/ubi/ubi.h | 4 ++-- >>> 3 files changed, 6 insertions(+), 6 deletions(-) >>> >>> diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c >>> index 3711d7f746003..6f5804f4b8f55 100644 >>> --- a/drivers/mtd/ubi/block.c >>> +++ b/drivers/mtd/ubi/block.c >>> @@ -457,7 +457,7 @@ static void ubiblock_cleanup(struct ubiblock *dev) >>> idr_remove(&ubiblock_minor_idr, dev->gd->first_minor); >>> } >>> -int ubiblock_remove(struct ubi_volume_info *vi) >>> +int ubiblock_remove(struct ubi_volume_info *vi, bool force) >>> { >>> struct ubiblock *dev; >>> int ret; >>> @@ -471,7 +471,7 @@ int ubiblock_remove(struct ubi_volume_info *vi) >>> /* Found a device, let's lock it so we can check if it's busy */ >>> mutex_lock(&dev->dev_mutex); >>> - if (dev->refcnt > 0) { >>> + if (dev->refcnt > 0 && !force) { >>> ret = -EBUSY; >>> goto out_unlock_dev; >>> } >> >> After looking through this series, I think we should pay attention to one >> problem: The lifetime of mtd device and ubi things(ubi device/volume/block >> device). It's difficult to decide whether or not to destroy ubi things when >> mtd driver is removed. >> If we destroy ubi things, one application may have opened an ubi volume >> early, then ubi device and all its volumes are destroyed by >> ubi_notify_remove(), later volume accessing by the application will trigger >> an UAF problem in kernel. >> App driver_remove >> fd = ubi_open_volume >> ubi_notify_remove >> ubi_detach_mtd_dev >> vfree(ubi->vtbl) >> ioctl(fd, UBI_IOCVOLUP) >> ubi_start_update >> set_update_marker >> vtbl_rec = ubi->vtbl[vol->vol_id] // UAF! >> >> If we reserve ubi things even mtd driver is removed. There exists mtd >> drivers releasing mtd device (eg. phram_remove), then upper application >> could accessing released mtd device by the ubi device, which also triggers >> UAF in kernel. > > I agree this is a problem, and I also agree it is not a new problem > introduced by this series, but rather already exists in the kernel for > many years. > Yes, the second UAF situation seems to exist a long time, maybe disabling ubi device in ubi_notify_remove is a temp solution? Importing new features based on the framework with known issues looks a little weird, I suggest to solve the problem of mtd lifetime management before applying this new feature. But I'm okay to this feature if maintainer doesn't care about this problem. > An idea to get closer to a good state would be to try dropping the > 'anyway' parameter from ubi_detach_mtd_dev which is currently only > used in the module_exit. To avoid this, we should make sure the > module's refcnt is increased/decreased together with ubi->ref_count. > Yes. Dropping 'anyway' param from ubi_detach_mtd_dev in ubi_notify_remove can avoid the first UAF problem happening. > When it comes to the to-be-introduced ubi_notify_remove we still > face another problem, see below... > >> >> After looking at nvme_free_ctrl, I found that nvme_dev is released when >> device refcnt becomes zero, so block device and nvme_dev won't be freed >> immediately when pci driver removed if upper filesystem being mounted on >> nvme device. And the mtd device's refcnt is held by ubi too, we may follow >> this method, but investigating all mtd drivers looks like unrealistic. > > A good start would be deciding on and defining the way it should be. > I agree with your suggestion above, however, also note that in case of > MTD (in contrast to block devices) we have only a 'remove' notification > call returning void, see include/linux/mtd/mtd.h > > struct mtd_notifier { > void (*add)(struct mtd_info *mtd); > void (*remove)(struct mtd_info *mtd); > struct list_head list; > }; > > Also see del_mtd_device in drivers/mtd/mtdcore.c: > [...] > /* No need to get a refcount on the module containing > the notifier, since we hold the mtd_table_mutex */ > list_for_each_entry(not, &mtd_notifiers, list) > not->remove(mtd); > > if (mtd->usecount) { > printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n", > mtd->index, mtd->name, mtd->usecount); > ret = -EBUSY; > } else { > [...] > > So remove is called despite usecount could still be > 0. > > Looks a bit like I've opened a can of worms... > > >> >>> @@ -546,7 +546,7 @@ static int ubiblock_notify(struct notifier_block *nb, >>> */ >>> break; >>> case UBI_VOLUME_REMOVED: >>> - ubiblock_remove(&nt->vi); >>> + ubiblock_remove(&nt->vi, true); >>> break; >>> case UBI_VOLUME_RESIZED: >>> ubiblock_resize(&nt->vi); >>> diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c >>> index f43430b9c1e65..bb55e863dd296 100644 >>> --- a/drivers/mtd/ubi/cdev.c >>> +++ b/drivers/mtd/ubi/cdev.c >>> @@ -572,7 +572,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, >>> struct ubi_volume_info vi; >>> ubi_get_volume_info(desc, &vi); >>> - err = ubiblock_remove(&vi); >>> + err = ubiblock_remove(&vi, false); >>> break; >>> } >>> diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h >>> index c8f1bd4fa1008..44c0eeaf1e1b0 100644 >>> --- a/drivers/mtd/ubi/ubi.h >>> +++ b/drivers/mtd/ubi/ubi.h >>> @@ -979,7 +979,7 @@ static inline void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol) {} >>> int ubiblock_init(void); >>> void ubiblock_exit(void); >>> int ubiblock_create(struct ubi_volume_info *vi); >>> -int ubiblock_remove(struct ubi_volume_info *vi); >>> +int ubiblock_remove(struct ubi_volume_info *vi, bool force); >>> #else >>> static inline int ubiblock_init(void) { return 0; } >>> static inline void ubiblock_exit(void) {} >>> @@ -987,7 +987,7 @@ static inline int ubiblock_create(struct ubi_volume_info *vi) >>> { >>> return -ENOSYS; >>> } >>> -static inline int ubiblock_remove(struct ubi_volume_info *vi) >>> +static inline int ubiblock_remove(struct ubi_volume_info *vi, bool force) >>> { >>> return -ENOSYS; >>> } >>> >> > > . >
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c index 3711d7f746003..6f5804f4b8f55 100644 --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c @@ -457,7 +457,7 @@ static void ubiblock_cleanup(struct ubiblock *dev) idr_remove(&ubiblock_minor_idr, dev->gd->first_minor); } -int ubiblock_remove(struct ubi_volume_info *vi) +int ubiblock_remove(struct ubi_volume_info *vi, bool force) { struct ubiblock *dev; int ret; @@ -471,7 +471,7 @@ int ubiblock_remove(struct ubi_volume_info *vi) /* Found a device, let's lock it so we can check if it's busy */ mutex_lock(&dev->dev_mutex); - if (dev->refcnt > 0) { + if (dev->refcnt > 0 && !force) { ret = -EBUSY; goto out_unlock_dev; } @@ -546,7 +546,7 @@ static int ubiblock_notify(struct notifier_block *nb, */ break; case UBI_VOLUME_REMOVED: - ubiblock_remove(&nt->vi); + ubiblock_remove(&nt->vi, true); break; case UBI_VOLUME_RESIZED: ubiblock_resize(&nt->vi); diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index f43430b9c1e65..bb55e863dd296 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -572,7 +572,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, struct ubi_volume_info vi; ubi_get_volume_info(desc, &vi); - err = ubiblock_remove(&vi); + err = ubiblock_remove(&vi, false); break; } diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index c8f1bd4fa1008..44c0eeaf1e1b0 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -979,7 +979,7 @@ static inline void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol) {} int ubiblock_init(void); void ubiblock_exit(void); int ubiblock_create(struct ubi_volume_info *vi); -int ubiblock_remove(struct ubi_volume_info *vi); +int ubiblock_remove(struct ubi_volume_info *vi, bool force); #else static inline int ubiblock_init(void) { return 0; } static inline void ubiblock_exit(void) {} @@ -987,7 +987,7 @@ static inline int ubiblock_create(struct ubi_volume_info *vi) { return -ENOSYS; } -static inline int ubiblock_remove(struct ubi_volume_info *vi) +static inline int ubiblock_remove(struct ubi_volume_info *vi, bool force) { return -ENOSYS; }