linux/drivers/usb/gadget
Al Viro 2606b28aab USB: Fix breakage in ffs_fs_mount()
There's a bunch of failure exits in ffs_fs_mount() with
seriously broken recovery logics.  Most of that appears to stem
from misunderstanding of the ->kill_sb() semantics; unlike
->put_super() it is called for *all* superblocks of given type,
no matter how (in)complete the setup had been.  ->put_super()
is called only if ->s_root is not NULL; any failure prior to
setting ->s_root will have the call of ->put_super() skipped.
->kill_sb(), OTOH, awaits every superblock that has come from
sget().

Current behaviour of ffs_fs_mount():

We have struct ffs_sb_fill_data data on stack there.  We do
	ffs_dev = functionfs_acquire_dev_callback(dev_name);
and store that in data.private_data.  Then we call mount_nodev(),
passing it ffs_sb_fill() as a callback.  That will either fail
outright, or manage to call ffs_sb_fill().  There we allocate an
instance of struct ffs_data, slap the value of ffs_dev (picked
from data.private_data) into ffs->private_data and overwrite
data.private_data by storing ffs into an overlapping member
(data.ffs_data).  Then we store ffs into sb->s_fs_info and attempt
to set the rest of the things up (root inode, root dentry, then
create /ep0 there).  Any of those might fail.  Should that
happen, we get ffs_fs_kill_sb() called before mount_nodev()
returns.  If mount_nodev() fails for any reason whatsoever,
we proceed to
	functionfs_release_dev_callback(data.ffs_data);

That's broken in a lot of ways.  Suppose the thing has failed in
allocation of e.g. root inode or dentry.  We have
	functionfs_release_dev_callback(ffs);
	ffs_data_put(ffs);
done by ffs_fs_kill_sb() (ffs accessed via sb->s_fs_info), followed by
	functionfs_release_dev_callback(ffs);
from ffs_fs_mount() (via data.ffs_data).  Note that the second
functionfs_release_dev_callback() has every chance to be done to freed memory.

Suppose we fail *before* root inode allocation.  What happens then?
ffs_fs_kill_sb() doesn't do anything to ffs (it's either not called at all,
or it doesn't have a pointer to ffs stored in sb->s_fs_info).  And
	functionfs_release_dev_callback(data.ffs_data);
is called by ffs_fs_mount(), but here we are in nasal daemon country - we
are reading from a member of union we'd never stored into.  In practice,
we'll get what we used to store into the overlapping field, i.e. ffs_dev.
And then we get screwed, since we treat it (struct gfs_ffs_obj * in
disguise, returned by functionfs_acquire_dev_callback()) as struct
ffs_data *, pick what would've been ffs_data ->private_data from it
(*well* past the actual end of the struct gfs_ffs_obj - struct ffs_data
is much bigger) and poke in whatever it points to.

FWIW, there's a minor leak on top of all that in case if ffs_sb_fill()
fails on kstrdup() - ffs is obviously forgotten.

The thing is, there is no point in playing all those games with union.
Just allocate and initialize ffs_data *before* calling mount_nodev() and
pass a pointer to it via data.ffs_data.  And once it's stored in
sb->s_fs_info, clear data.ffs_data, so that ffs_fs_mount() knows that
it doesn't need to kill the sucker manually - from that point on
we'll have it done by ->kill_sb().

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Michal Nazarewicz <mina86@mina86.com>
Cc: stable <stable@vger.kernel.org> # 3.3+
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-09-26 16:22:29 -07:00
..
acm_ms.c
amd5536udc.c usb: gadget: amd5536udc: unconditionally use GFP_ATOMIC in udc_queue() 2013-08-09 16:33:31 +03:00
amd5536udc.h
at91_udc.c usb: gadget: at91_udc: add usb_clk for transition to common clk framework 2013-08-02 15:17:03 +03:00
at91_udc.h usb: gadget: at91_udc: add usb_clk for transition to common clk framework 2013-08-02 15:17:03 +03:00
atmel_usba_udc.c usb: gadget: double unlocks on error in atmel_usba_start() 2013-08-27 15:05:35 -05:00
atmel_usba_udc.h USB: gadget: atmel_usba: add DT support 2013-05-24 07:14:45 +08:00
audio.c
bcm63xx_udc.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
cdc2.c usb: gadget: cdc2: fix conversion to new interface of f_ecm 2013-09-17 10:38:52 -05:00
composite.c USB: gadget: audit sysfs attribute permissions 2013-08-27 12:50:53 -07:00
config.c
configfs.c usb: gadget: configfs: keep a function if it is not successfully added 2013-08-27 14:06:08 -05:00
dbgp.c
dummy_hcd.c usb: gadget: fix a bug and a WARN_ON in dummy-hcd 2013-09-17 10:38:51 -05:00
epautoconf.c
ether.c usb: gadget: ether: put_usb_function on unbind 2013-07-25 20:35:23 +03:00
f_acm.c usb: acm gadget: Null termintate strings table 2013-08-30 11:10:36 -07:00
f_ecm.c usb: gadget: f_ecm: Staticize ecm_alloc 2013-09-17 11:06:44 -05:00
f_eem.c usb: gadget: f_eem: Staticize eem_alloc 2013-09-17 11:06:50 -05:00
f_fs.c USB: Fix breakage in ffs_fs_mount() 2013-09-26 16:22:29 -07:00
f_hid.c
f_loopback.c
f_mass_storage.c usb: gadget: f_mass_storage: reset endpoint driver data when disabled 2013-09-17 11:07:14 -05:00
f_midi.c
f_ncm.c usb/gadget: free opts struct on error recovery 2013-07-25 11:32:15 -07:00
f_obex.c usb: gadget: f_obex: remove compatibility layer 2013-06-10 17:29:08 +03:00
f_phonet.c usb: gadget: f_phonet: remove unused preprocessor conditional 2013-07-29 14:15:23 +03:00
f_rndis.c usb/gadget: free opts struct on error recovery 2013-07-25 11:32:15 -07:00
f_serial.c
f_sourcesink.c usb: gadget: f_sourcesink.c: correct a copy-paste misnomer 2013-04-23 14:12:02 +03:00
f_subset.c usb/gadget: free opts struct on error recovery 2013-07-25 11:32:15 -07:00
f_uac1.c usb: gadget: f_uac1: Staticize local functions 2013-08-09 16:34:19 +03:00
f_uac2.c USB: gadget: f_uac2: Fix broken prm to uac2 mapping 2013-06-10 17:10:23 +03:00
f_uvc.c Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media 2013-07-13 12:09:57 -07:00
f_uvc.h
fotg210-udc.c USB: Faraday fotg210: fix email addresses 2013-09-17 09:36:10 -07:00
fotg210.h usb: gadget: add Faraday fotg210_udc driver 2013-06-10 17:58:11 +03:00
fsl_mxc_udc.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
fsl_qe_udc.c usb: gadget: use platform_{get,set}_drvdata() 2013-05-28 20:16:56 +03:00
fsl_qe_udc.h
fsl_udc_core.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
fsl_usb2_udc.h
functions.c
fusb300_udc.c USB: Faraday fotg210: fix email addresses 2013-09-17 09:36:10 -07:00
fusb300_udc.h
g_ffs.c usb: gadget: f_rndis: convert to new function interface with backward compatibility 2013-06-10 17:58:08 +03:00
g_zero.h
gadget_chips.h
gmidi.c
goku_udc.c usb: gadget: goku_udc: use NULL instead of 0 2013-08-02 11:19:51 +03:00
goku_udc.h
hid.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
inode.c Merge git://git.kvack.org/~bcrl/aio-next 2013-09-13 10:55:58 -07:00
Kconfig Remove GENERIC_HARDIRQ config option 2013-09-13 15:09:52 +02:00
lpc32xx_udc.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2013-05-01 17:51:54 -07:00
m66592-udc.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
m66592-udc.h
Makefile usb: gadget: remove imx_udc 2013-07-29 13:53:25 +03:00
mass_storage.c
multi.c usb: gadget: add '__ref' for rndis_config_register() and cdc_config_register() 2013-09-17 10:59:19 -05:00
mv_u3d_core.c usb: gadget: mv_u3d_core: fix violation of locking discipline in mv_u3d_ep_disable() 2013-09-17 10:38:48 -05:00
mv_u3d.h
mv_udc_core.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
mv_udc.h
ncm.c usb: gadget: ncm: convert to new function interface 2013-06-10 17:12:52 +03:00
ndis.h
net2272.c USB: gadget: audit sysfs attribute permissions 2013-08-27 12:50:53 -07:00
net2272.h
net2280.c USB: gadget: audit sysfs attribute permissions 2013-08-27 12:50:53 -07:00
net2280.h
nokia.c usb: gadget: nokia: convert to new interface of f_ecm 2013-06-10 17:32:23 +03:00
omap_udc.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
omap_udc.h
pch_udc.c
printer.c
pxa25x_udc.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
pxa25x_udc.h
pxa27x_udc.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
pxa27x_udc.h
r8a66597-udc.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
r8a66597-udc.h
rndis.c usb: gadget: rndis: Staticize rndis_init()/rndis_exit() 2013-08-09 16:33:36 +03:00
rndis.h usb: gadget: rndis: init & exit rndis at module load/unload 2013-06-10 17:58:09 +03:00
s3c2410_udc.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
s3c2410_udc.h
s3c-hsotg.c usb: s3c-hsotg: do not disconnect gadget when receiving ErlySusp intr 2013-09-17 11:08:46 -05:00
s3c-hsotg.h
s3c-hsudc.c usb: gadget: use dev_get_platdata() 2013-07-30 11:18:46 +03:00
serial.c
storage_common.c USB: gadget: audit sysfs attribute permissions 2013-08-27 12:50:53 -07:00
tcm_usb_gadget.c target: make queue_tm_rsp() return void 2013-07-07 18:36:53 -07:00
tcm_usb_gadget.h
u_ecm.h usb: gadget: f_ecm: add configfs support 2013-06-10 17:27:54 +03:00
u_eem.h usb: gadget: f_eem: add configfs support 2013-06-10 17:58:00 +03:00
u_ether_configfs.h usb: gadget: add helpers for configfs support for USB Ethernet 2013-06-10 17:15:43 +03:00
u_ether.c usb: gadget: u_ether: allow getting binary-form host address 2013-06-10 17:57:45 +03:00
u_ether.h usb: gadget: f_eem: remove compatibility layer 2013-06-10 17:57:47 +03:00
u_gether.h usb: gadget: f_subset: add configfs support 2013-06-10 17:58:08 +03:00
u_ncm.h usb: gadget: f_ncm: add configfs support 2013-06-10 17:15:02 +03:00
u_phonet.h usb: gadget: f_phonet: remove compatibility layer 2013-06-10 17:31:55 +03:00
u_rndis.h usb: gadget: f_rndis: add configfs support 2013-06-10 17:58:10 +03:00
u_serial.c
u_serial.h
u_uac1.c usb: gadget: u_uac1: add __user annotation 2013-08-09 16:34:13 +03:00
u_uac1.h
udc-core.c USB: gadget: audit sysfs attribute permissions 2013-08-27 12:50:53 -07:00
usbstring.c
uvc_queue.c usb: gadget: uvc: Fix error handling in uvc_queue_buffer() 2013-08-09 17:40:54 +03:00
uvc_queue.h
uvc_v4l2.c
uvc_video.c
uvc.h [media] f_uvc: add v4l2_device and replace parent with v4l2_dev 2013-06-21 11:04:47 -03:00
webcam.c
zero.c usb: gadget: zero: fix error return code in zero_bind() 2013-05-15 17:15:57 +03:00