lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20150430151202.GE1515@saruman.tx.rr.com>
Date:	Thu, 30 Apr 2015 10:12:02 -0500
From:	Felipe Balbi <balbi@...com>
To:	Robert Baldyga <r.baldyga@...sung.com>
CC:	<balbi@...com>, <gregkh@...uxfoundation.org>,
	<linux-usb@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
	<m.szyprowski@...sung.com>, <andrzej.p@...sung.com>
Subject: Re: [PATCH 1/2] usb: gadget: add usb_gadget_activate/deactivate
 functions

On Thu, Apr 30, 2015 at 11:08:27AM +0200, Robert Baldyga wrote:
> On 04/29/2015 05:30 PM, Felipe Balbi wrote:
> > On Wed, Apr 29, 2015 at 11:08:06AM +0200, Robert Baldyga wrote:
> >> Hi Felipe,
> >>
> >> On 04/28/2015 06:40 PM, Felipe Balbi wrote:
> >>> On Tue, Apr 07, 2015 at 10:31:52AM +0200, Robert Baldyga wrote:
> >>>> These functions allows to deactivate gadget to make it not visible to
> >>>> host and make it active again when gadget driver is finally ready.
> >>>>
> >>>> They are needed to fix usb_function_activate() and usb_function_deactivate()
> >>>> functions which currently are not working as usb_gadget_connect() is
> >>>> called immediately after function bind regardless to previous calls of
> >>>> usb_gadget_disconnect() function.
> >>>
> >>> and that's what needs to be fixed, a long time ago I wrote the patch
> >>> below which I never got to finishing:
> >>>
> >>> commit a23800e2463ae1f4eafa7c0a15bb44afee75994f
> >>> Author: Felipe Balbi <balbi@...com>
> >>> Date:   Thu Jul 26 14:23:44 2012 +0300
> >>>
> >>>     usb: gadget: let gadgets control pullup on their own
> >>>     
> >>>     This is useful on gadgets that depend on userland
> >>>     daemons to function properly. We can delay connection
> >>>     to the host until userland is ready.
> >>>     
> >>>     Signed-off-by: Felipe Balbi <balbi@...com>
> >>>
> >>> diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
> >>> index 7c821de8ce3d..790ccf29f2ee 100644
> >>> --- a/drivers/usb/gadget/composite.c
> >>> +++ b/drivers/usb/gadget/composite.c
> >>> @@ -1784,8 +1784,9 @@ int usb_composite_probe(struct usb_composite_driver *driver)
> >>>  		driver->name = "composite";
> >>>  
> >>>  	driver->gadget_driver = composite_driver_template;
> >>> -	gadget_driver = &driver->gadget_driver;
> >>>  
> >>> +	gadget_driver = &driver->gadget_driver;
> >>> +	gadget_driver->controls_pullups = driver->controls_pullups;
> >>>  	gadget_driver->function =  (char *) driver->name;
> >>>  	gadget_driver->driver.name = driver->name;
> >>>  	gadget_driver->max_speed = driver->max_speed;
> >>> diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
> >>> index 8a1eeb24ae6a..c0f4fca9384b 100644
> >>> --- a/drivers/usb/gadget/udc-core.c
> >>> +++ b/drivers/usb/gadget/udc-core.c
> >>> @@ -235,7 +235,18 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
> >>>  
> >>>  	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
> >>>  
> >>> -	usb_gadget_disconnect(udc->gadget);
> >>> +	/*
> >>> +	 * NOTICE: if gadget driver wants to control
> >>> +	 * pullup, it needs to make sure that when
> >>> +	 * user tries to rmmod the gadget driver, it
> >>> +	 * will disconnect the pullups before returning
> >>> +	 * from its ->unbind() method.
> >>> +	 *
> >>> +	 * We are truly trusting the gadget driver here.
> >>> +	 */
> >>> +	if (!udc->driver->controls_pullups)
> >>> +		usb_gadget_disconnect(udc->gadget);
> >>> +
> >>>  	udc->driver->disconnect(udc->gadget);
> >>>  	udc->driver->unbind(udc->gadget);
> >>>  	usb_gadget_udc_stop(udc->gadget, udc->driver);
> >>> @@ -300,7 +311,18 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
> >>>  		driver->unbind(udc->gadget);
> >>>  		goto err1;
> >>>  	}
> >>> -	usb_gadget_connect(udc->gadget);
> >>> +
> >>> +	/*
> >>> +	 * NOTICE: if gadget driver wants to control
> >>> +	 * pullups, it needs to make sure its calls
> >>> +	 * to usb_function_activate() and
> >>> +	 * usb_function_deactivate() are balanced,
> >>> +	 * otherwise gadget_driver will never enumerate.
> >>> +	 *
> >>> +	 * We are truly trusting the gadget driver here.
> >>> +	 */
> >>> +	if (!driver->controls_pullups)
> >>> +		usb_gadget_connect(udc->gadget);
> >>>  
> >>>  	kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
> >>>  	return 0;
> >>> diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
> >>> index 3c671c1b37f6..7ae797c85cb9 100644
> >>> --- a/include/linux/usb/composite.h
> >>> +++ b/include/linux/usb/composite.h
> >>> @@ -157,6 +157,7 @@ struct usb_function {
> >>>  	int			(*get_status)(struct usb_function *);
> >>>  	int			(*func_suspend)(struct usb_function *,
> >>>  						u8 suspend_opt);
> >>> +
> >>>  	/* private: */
> >>>  	/* internals */
> >>>  	struct list_head		list;
> >>> @@ -279,6 +280,8 @@ enum {
> >>>   * @max_speed: Highest speed the driver supports.
> >>>   * @needs_serial: set to 1 if the gadget needs userspace to provide
> >>>   * 	a serial number.  If one is not provided, warning will be printed.
> >>> + * @controls_pullups: this driver will control pullup and udc-core shouldn't
> >>> + *	enable it by default
> >>>   * @bind: (REQUIRED) Used to allocate resources that are shared across the
> >>>   *	whole device, such as string IDs, and add its configurations using
> >>>   *	@usb_add_config(). This may fail by returning a negative errno
> >>> @@ -308,6 +311,7 @@ struct usb_composite_driver {
> >>>  	struct usb_gadget_strings		**strings;
> >>>  	enum usb_device_speed			max_speed;
> >>>  	unsigned		needs_serial:1;
> >>> +	unsigned		controls_pullups:1;
> >>>  
> >>>  	int			(*bind)(struct usb_composite_dev *cdev);
> >>>  	int			(*unbind)(struct usb_composite_dev *);
> >>> diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
> >>> index 32b734d88d6b..87971fa38f08 100644
> >>> --- a/include/linux/usb/gadget.h
> >>> +++ b/include/linux/usb/gadget.h
> >>> @@ -774,6 +774,7 @@ static inline int usb_gadget_disconnect(struct usb_gadget *gadget)
> >>>   * @suspend: Invoked on USB suspend.  May be called in_interrupt.
> >>>   * @resume: Invoked on USB resume.  May be called in_interrupt.
> >>>   * @driver: Driver model state for this driver.
> >>> + * @controls_pullups: tells udc-core to not enable pullups by default
> >>>   *
> >>>   * Devices are disabled till a gadget driver successfully bind()s, which
> >>>   * means the driver will handle setup() requests needed to enumerate (and
> >>> @@ -833,6 +834,8 @@ struct usb_gadget_driver {
> >>>  
> >>>  	/* FIXME support safe rmmod */
> >>>  	struct device_driver	driver;
> >>> +
> >>> +	unsigned		controls_pullups:1;
> >>>  };
> >>>  
> >>>  
> >>>
> >>> Together with that, I wrote:
> >>>
> >>> commit 0b733885e276a38cc9fa415c0977f063f9ce4d9d
> >>> Author: Felipe Balbi <balbi@...com>
> >>> Date:   Wed Feb 6 12:34:33 2013 +0200
> >>>
> >>>     usb: gadget: webcam: let it control pullups
> >>>     
> >>>     this gadget driver needs to make sure that
> >>>     we will only enumerate after its userland
> >>>     counterpart is up and running.
> >>>     
> >>>     Signed-off-by: Felipe Balbi <balbi@...com>
> >>>
> >>> diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c
> >>> index 8cef1e658c29..41a4d03715bc 100644
> >>> --- a/drivers/usb/gadget/webcam.c
> >>> +++ b/drivers/usb/gadget/webcam.c
> >>> @@ -388,6 +388,7 @@ static __refdata struct usb_composite_driver webcam_driver = {
> >>>  	.max_speed	= USB_SPEED_SUPER,
> >>>  	.bind		= webcam_bind,
> >>>  	.unbind		= webcam_unbind,
> >>> +	.controls_pullups = true,
> >>>  };
> >>>  
> >>>  static int __init
> >>>
> >>> This makes it really simple, either a gadget driver wants to control
> >>> pullups, or it doesn't. For those who wish to control pullups (for
> >>> whatever reason) we rely completely on the gadget telling us it's ok to
> >>> connect pullups by means of usb_function_activate()/deactivate(), for
> >>> all others, we just connect straight away.
> >>>
> >>
> >> It looks like your patch fixes problem at gadget level, but in case of
> >> gadgets composed using ConfigFS we don't know if any function will want
> >> to deactivate gadget. We would need to supply mechanism which functions
> >> could use to tell composite that they want to control pullups by
> >> themselves. That's why I made it a little more complicated, but in
> >> result we have no need to modify function drivers.
> > 
> > I really prefer functions to tell us that they can control pullups; much
> > like Host stack requires a "supports_autosuspend" flag if your driver
> > supports runtime PM.
> > 
> > I see that your patch is much more granular, but then, we need a
> > per-function flag then we could:
> > 
> > for_each_function(config)
> > 	if (fuction->controls_pullup)
> > 		usb_function_deactivate(function);
> > 
> > (well, just illustrating)
> > 
> > Then, usb_function_deactivate() is initially called by the framework so
> > that deactivate counter already has the correct initial value and gadget
> > will only connect after all functions in a particular configuration have
> > called usb_function_activate(). How do you feel about that ?
> 
> Looks good to me, makes things more clear. I will update my patches.

Cool, thanks

Let's see what you come up with for configuration changes, I didn't
think too much about it, but we need to consider that possibility too.

-- 
balbi

Download attachment "signature.asc" of type "application/pgp-signature" (820 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ