All of lore.kernel.org
 help / color / mirror / Atom feed
* memory allocations dring device removal
@ 2020-09-16 14:26 Oliver Neukum
  2020-09-16 15:25 ` Greg KH
  0 siblings, 1 reply; 2+ messages in thread
From: Oliver Neukum @ 2020-09-16 14:26 UTC (permalink / raw)
  To: Alan Stern, gregKH; +Cc: linux-usb

Hi,

I am cleaning up house, electronically speaking.
Reading the thread about the keyboard with the storage device
reminded me about a potential issue. What happens if you
allocate memory during disconnect()?

If the storage device is second, the storage driver will
still be bound and the SCSI device will still exist. The
kernel may use it to launder pages. This will fail, as the
device is physically gone. So can we deadlock?

Is this patch necessary?

	Regards
		Oliver

From 97b7e91af588b7489795e3eaf773be032bc91b70 Mon Sep 17 00:00:00 2001
From: Oliver Neukum <oneukum@suse.com>
Date: Tue, 28 May 2019 11:43:02 +0200
Subject: [PATCH] base: force NOIO allocations during unplug

There is one overlooked situation under which a driver
must not do IO to allocate memory. You cannot do that
while disconnecting a device. A device being disconnected
is no longer functional in most cases, yet IO may fail
only when the handler runs.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
 drivers/base/core.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index bb5806a2bd4c..509306a4ea89 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -26,6 +26,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/netdevice.h>
 #include <linux/sched/signal.h>
+#include <linux/sched/mm.h>
 #include <linux/sysfs.h>
 
 #include "base.h"
@@ -3062,6 +3063,7 @@ void device_del(struct device *dev)
 	struct device *parent = dev->parent;
 	struct kobject *glue_dir = NULL;
 	struct class_interface *class_intf;
+	unsigned int noio_flag;
 
 	device_lock(dev);
 	kill_device(dev);
@@ -3073,6 +3075,7 @@ void device_del(struct device *dev)
 	/* Notify clients of device removal.  This call must come
 	 * before dpm_sysfs_remove().
 	 */
+	noio_flag = memalloc_noio_save();
 	if (dev->bus)
 		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 					     BUS_NOTIFY_DEL_DEVICE, dev);
@@ -3106,6 +3109,7 @@ void device_del(struct device *dev)
 	device_platform_notify(dev, KOBJ_REMOVE);
 	device_remove_properties(dev);
 	device_links_purge(dev);
+	memalloc_noio_restore(noio_flag);
 
 	if (dev->bus)
 		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: memory allocations dring device removal
  2020-09-16 14:26 memory allocations dring device removal Oliver Neukum
@ 2020-09-16 15:25 ` Greg KH
  0 siblings, 0 replies; 2+ messages in thread
From: Greg KH @ 2020-09-16 15:25 UTC (permalink / raw)
  To: Oliver Neukum; +Cc: Alan Stern, linux-usb

On Wed, Sep 16, 2020 at 04:26:51PM +0200, Oliver Neukum wrote:
> Hi,
> 
> I am cleaning up house, electronically speaking.
> Reading the thread about the keyboard with the storage device
> reminded me about a potential issue. What happens if you
> allocate memory during disconnect()?

Does any driver do that today?

If so, I think we might have seen issues there already, but perhaps not,
it's a tricky codepath...

> If the storage device is second, the storage driver will
> still be bound and the SCSI device will still exist. The
> kernel may use it to launder pages. This will fail, as the
> device is physically gone. So can we deadlock?

The notifier callback worries me, who knows what can happen on that code
path.  So yes, I think your patch might be needed :(


> 
> Is this patch necessary?
> 
> 	Regards
> 		Oliver
> 
> >From 97b7e91af588b7489795e3eaf773be032bc91b70 Mon Sep 17 00:00:00 2001
> From: Oliver Neukum <oneukum@suse.com>
> Date: Tue, 28 May 2019 11:43:02 +0200
> Subject: [PATCH] base: force NOIO allocations during unplug
> 
> There is one overlooked situation under which a driver
> must not do IO to allocate memory. You cannot do that
> while disconnecting a device. A device being disconnected
> is no longer functional in most cases, yet IO may fail
> only when the handler runs.
> 
> Signed-off-by: Oliver Neukum <oneukum@suse.com>
> ---
>  drivers/base/core.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/base/core.c b/drivers/base/core.c
> index bb5806a2bd4c..509306a4ea89 100644
> --- a/drivers/base/core.c
> +++ b/drivers/base/core.c
> @@ -26,6 +26,7 @@
>  #include <linux/pm_runtime.h>
>  #include <linux/netdevice.h>
>  #include <linux/sched/signal.h>
> +#include <linux/sched/mm.h>
>  #include <linux/sysfs.h>
>  
>  #include "base.h"
> @@ -3062,6 +3063,7 @@ void device_del(struct device *dev)
>  	struct device *parent = dev->parent;
>  	struct kobject *glue_dir = NULL;
>  	struct class_interface *class_intf;
> +	unsigned int noio_flag;
>  
>  	device_lock(dev);
>  	kill_device(dev);
> @@ -3073,6 +3075,7 @@ void device_del(struct device *dev)
>  	/* Notify clients of device removal.  This call must come
>  	 * before dpm_sysfs_remove().
>  	 */
> +	noio_flag = memalloc_noio_save();
>  	if (dev->bus)
>  		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
>  					     BUS_NOTIFY_DEL_DEVICE, dev);
> @@ -3106,6 +3109,7 @@ void device_del(struct device *dev)
>  	device_platform_notify(dev, KOBJ_REMOVE);
>  	device_remove_properties(dev);
>  	device_links_purge(dev);
> +	memalloc_noio_restore(noio_flag);
>  
>  	if (dev->bus)
>  		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,

Can you move memalloc_noio_restore() down below here, odds are it should
just go after the last put_device(parent) to be safe.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-09-16 20:53 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-16 14:26 memory allocations dring device removal Oliver Neukum
2020-09-16 15:25 ` Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.