Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: g_file_storage: fix use-after-free bug when closing files

This patch (as1231) fixes a use-after-free bug in g_file_storage. A
device's name may not be available after the device is unregistered,
even if the device structure itself is still allocated. Since
close_backing_file() prints a LUN's name for debugging, it shouldn't
be called after the LUN has been unregistered.

That whole area needed to be cleaned up; the backing files were
getting closed in a couple of different places. The patch fixes
things so that they get closed in just one place, as part of the
unbind procedure, immediately before the LUN is unregistered.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Alan Stern and committed by
Greg Kroah-Hartman
82a10a81 c065c60e

+4 -16
+4 -16
drivers/usb/gadget/file_storage.c
··· 738 738 static struct usb_gadget_driver fsg_driver; 739 739 740 740 static void close_backing_file(struct lun *curlun); 741 - static void close_all_backing_files(struct fsg_dev *fsg); 742 741 743 742 744 743 /*-------------------------------------------------------------------------*/ ··· 3592 3593 fsg->thread_task = NULL; 3593 3594 spin_unlock_irq(&fsg->lock); 3594 3595 3595 - /* In case we are exiting because of a signal, unregister the 3596 - * gadget driver and close the backing file. */ 3597 - if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) { 3596 + /* If we are exiting because of a signal, unregister the 3597 + * gadget driver. */ 3598 + if (test_and_clear_bit(REGISTERED, &fsg->atomic_bitflags)) 3598 3599 usb_gadget_unregister_driver(&fsg_driver); 3599 - close_all_backing_files(fsg); 3600 - } 3601 3600 3602 3601 /* Let the unbind and cleanup routines know the thread has exited */ 3603 3602 complete_and_exit(&fsg->thread_notifier, 0); ··· 3698 3701 fput(curlun->filp); 3699 3702 curlun->filp = NULL; 3700 3703 } 3701 - } 3702 - 3703 - static void close_all_backing_files(struct fsg_dev *fsg) 3704 - { 3705 - int i; 3706 - 3707 - for (i = 0; i < fsg->nluns; ++i) 3708 - close_backing_file(&fsg->luns[i]); 3709 3704 } 3710 3705 3711 3706 ··· 3834 3845 if (curlun->registered) { 3835 3846 device_remove_file(&curlun->dev, &dev_attr_ro); 3836 3847 device_remove_file(&curlun->dev, &dev_attr_file); 3848 + close_backing_file(curlun); 3837 3849 device_unregister(&curlun->dev); 3838 3850 curlun->registered = 0; 3839 3851 } ··· 4180 4190 out: 4181 4191 fsg->state = FSG_STATE_TERMINATED; // The thread is dead 4182 4192 fsg_unbind(gadget); 4183 - close_all_backing_files(fsg); 4184 4193 complete(&fsg->thread_notifier); 4185 4194 return rc; 4186 4195 } ··· 4273 4284 /* Wait for the thread to finish up */ 4274 4285 wait_for_completion(&fsg->thread_notifier); 4275 4286 4276 - close_all_backing_files(fsg); 4277 4287 kref_put(&fsg->ref, fsg_release); 4278 4288 } 4279 4289 module_exit(fsg_cleanup);