Re: [PATCH] u_serial.c - Force destroy tty_port in gserial_free_port

2014-10-10 Thread Peter Hurley
On 10/10/2014 12:05 AM, Andre Wolokita wrote:
 
 
 On 10/10/14 00:47, Peter Hurley wrote:
 Hi Andre,

 On 10/08/2014 11:54 PM, Andre Wolokita wrote:
 On 09/10/14 14:38, Greg KH wrote:
 On Thu, Oct 09, 2014 at 02:08:04PM +1100, Andre Wolokita wrote:
 On 09/10/14 13:56, Greg KH wrote:
 On Thu, Oct 09, 2014 at 11:23:59AM +1100, Andre Wolokita wrote:
 Issuing a modprobe -r g_serial command to the target
 over the gadget serial communications line causes
 modprobe to enter uninterruptable sleep, leaving the
 system in an unstable state.

 The associated tty_port.count won't drop to 0 because
 the command is issued over the very line being removed.

 Destroying the tty_port will ensure that resources are
 freed and modprobe will not hang.

 Signed-off-by: Andre Wolokita andre.wolok...@analog.com
 ---
  drivers/usb/gadget/function/u_serial.c |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/drivers/usb/gadget/function/u_serial.c 
 b/drivers/usb/gadget/function/u_serial.c
 index ad0aca8..db631c4 100644
 --- a/drivers/usb/gadget/function/u_serial.c
 +++ b/drivers/usb/gadget/function/u_serial.c
 @@ -1074,10 +1074,10 @@ static int gs_closed(struct gs_port *port)
  static void gserial_free_port(struct gs_port *port)
  {
 tasklet_kill(port-push);
 +   tty_port_destroy(port-port);
 /* wait for old opens to finish */
 wait_event(port-port.close_wait, gs_closed(port));

 Isn't this now a use-after-free issue?


 Are you referring to the subsequent call to wait event() on gs_closed()?

 Yes.

 Testing the use-case with this patch applied seemed to work without any 
 issues. The ttyGS0 reference in /dev/ is gone after running modprobe -r
 but I'm just a newbie, so I could be doing sometime horrible here.

 Hm, I dug into the tty core, it should be ok, but it just seems really
 odd, and bad-form to be doing something with port-port after calling a
 destroy function with it, don't you agree?

 I do. The call to wait_event() can be removed as we no longer care whether
 gs_closed(port) is returning true - if it even can, having destroyed the
 tty_port.

 Neither the patch nor the idea that this wait_event() is unnecessary is
 correct (within the current design of u_serial).

 tty_port_destroy() frees the input processing buffers, which may be in use
 right at this moment, if a port is still in use by its tty. Since whatever
 was using those buffers doesn't know this has happened, it may still be 
 writing
 to that memory, which may now be reallocated to some other kernel subsystem, 
 like
 file cache buffers.

 The wait_event() tries to ensure that the port destruction can't take place
 while the port is still in use, so when it's hung there, it's preventing bad
 things from happening.

 There is no way to simply 'force' the port to no longer be in use, since a
 userspace process can maintain an open file indefinitely.

 There are a couple of possible solutions though:

 In gserial_free_line(), hangup the tty associated with the port. You can
 look at usb_serial_disconnect() for how to do that properly. This doesn't
 guarantee that the userspace process will close the tty, but most programs
 will close the file on end-of-file read (which is what hangup will cause).
 
 I tried adding the adding the same tty_vhangup(tty) and tty_kref_put(tty) 
 logic that usb serial has
 but the problem still occurs.

That's because g_serial has no hangup() method; ports aren't going to
close themselves.

 It doesn't look like making the wait_event() interruptible is possible
 (or desirable).

 The ideal solution would be for u_serial to reference count its gs_ports;
 that's what usb serial does for its usb_serial_port. Then gserial_free_line()
 becomes a 'disconnect', and the actual cleanup happens later. The key
 implementation details are:
 1. The tty core helps keep reference counting simple by calling the tty
 driver's install() and cleanup() methods; install() for the first open() and
 cleanup() when the tty is being released. usb serial does this with
 usb_serial_port_get_by_minor() from serial_install() and usb_serial_put() in
 serial_cleanup() and usb_serial_disconnect().
 2. a flag (like usb serial's '-disconnected') to prevent continued port
 allocation after 'disconnect'.

 The key concept is that although the tty and port still exist, neither
 does anything useful after the disconnect.

 And u_serial.c should really be ported to using tty_port which takes care of
 stuff like parallel opens and closes without looping and other stuff like
 the port-openclose flag.

 FWIW, the tty_unregister_device() does not need to be after 
 gserial_free_port()
 because existing ttys maintain a device reference count which prevents the
 underlying tty device from being released.
 
 To be honest with you, I am in way over my head at the moment. I'll continue
 working on this problem but I can't guarantee it'll be fixed any time soon.

Maybe you should reconsider if this use-case is really worth 

Re: [PATCH] u_serial.c - Force destroy tty_port in gserial_free_port

2014-10-09 Thread Alan Stern
On Thu, 9 Oct 2014, Andre Wolokita wrote:

 Issuing a modprobe -r g_serial command to the target
 over the gadget serial communications line causes
 modprobe to enter uninterruptable sleep, leaving the
 system in an unstable state.
 
 The associated tty_port.count won't drop to 0 because
 the command is issued over the very line being removed.
 
 Destroying the tty_port will ensure that resources are
 freed and modprobe will not hang.

You know, this last paragraph doesn't explain anything.  The existing 
code already calls tty_port_destroy; all you did was move that call 
down a couple of lines.  You need to explain why _moving_ the function 
call is important, not why _calling_ the function is important.

Alan Stern

 --- a/drivers/usb/gadget/function/u_serial.c
 +++ b/drivers/usb/gadget/function/u_serial.c
 @@ -1074,10 +1074,10 @@ static int gs_closed(struct gs_port *port)
  static void gserial_free_port(struct gs_port *port)
  {
 tasklet_kill(port-push);
 +   tty_port_destroy(port-port);
 /* wait for old opens to finish */
 wait_event(port-port.close_wait, gs_closed(port));
 WARN_ON(port-port_usb != NULL);
 -   tty_port_destroy(port-port);
 kfree(port);
  }

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] u_serial.c - Force destroy tty_port in gserial_free_port

2014-10-09 Thread Alan Stern
On Thu, 9 Oct 2014, Andre Wolokita wrote:

  Isn't this now a use-after-free issue?
 
 
  Are you referring to the subsequent call to wait event() on gs_closed()?
  
  Yes.
  
  Testing the use-case with this patch applied seemed to work without any 
  issues. The ttyGS0 reference in /dev/ is gone after running modprobe -r
  but I'm just a newbie, so I could be doing sometime horrible here.
  
  Hm, I dug into the tty core, it should be ok, but it just seems really
  odd, and bad-form to be doing something with port-port after calling a
  destroy function with it, don't you agree?
 
 I do. The call to wait_event() can be removed as we no longer care whether
 gs_closed(port) is returning true - if it even can, having destroyed the
 tty_port.

Maybe you don't care whether gs_closed(port) returns true, but you 
should care about whether gs_closed() crashes -- which it might well do 
if it tries to access deallocated memory.

Did you test your patch by unloading the module while there were
pending opens?

Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] u_serial.c - Force destroy tty_port in gserial_free_port

2014-10-09 Thread Peter Hurley
Hi Andre,

On 10/08/2014 11:54 PM, Andre Wolokita wrote:
 On 09/10/14 14:38, Greg KH wrote:
 On Thu, Oct 09, 2014 at 02:08:04PM +1100, Andre Wolokita wrote:
 On 09/10/14 13:56, Greg KH wrote:
 On Thu, Oct 09, 2014 at 11:23:59AM +1100, Andre Wolokita wrote:
 Issuing a modprobe -r g_serial command to the target
 over the gadget serial communications line causes
 modprobe to enter uninterruptable sleep, leaving the
 system in an unstable state.

 The associated tty_port.count won't drop to 0 because
 the command is issued over the very line being removed.

 Destroying the tty_port will ensure that resources are
 freed and modprobe will not hang.

 Signed-off-by: Andre Wolokita andre.wolok...@analog.com
 ---
  drivers/usb/gadget/function/u_serial.c |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/drivers/usb/gadget/function/u_serial.c 
 b/drivers/usb/gadget/function/u_serial.c
 index ad0aca8..db631c4 100644
 --- a/drivers/usb/gadget/function/u_serial.c
 +++ b/drivers/usb/gadget/function/u_serial.c
 @@ -1074,10 +1074,10 @@ static int gs_closed(struct gs_port *port)
  static void gserial_free_port(struct gs_port *port)
  {
 tasklet_kill(port-push);
 +   tty_port_destroy(port-port);
 /* wait for old opens to finish */
 wait_event(port-port.close_wait, gs_closed(port));

 Isn't this now a use-after-free issue?


 Are you referring to the subsequent call to wait event() on gs_closed()?

 Yes.

 Testing the use-case with this patch applied seemed to work without any 
 issues. The ttyGS0 reference in /dev/ is gone after running modprobe -r
 but I'm just a newbie, so I could be doing sometime horrible here.

 Hm, I dug into the tty core, it should be ok, but it just seems really
 odd, and bad-form to be doing something with port-port after calling a
 destroy function with it, don't you agree?
 
 I do. The call to wait_event() can be removed as we no longer care whether
 gs_closed(port) is returning true - if it even can, having destroyed the
 tty_port.

Neither the patch nor the idea that this wait_event() is unnecessary is
correct (within the current design of u_serial).

tty_port_destroy() frees the input processing buffers, which may be in use
right at this moment, if a port is still in use by its tty. Since whatever
was using those buffers doesn't know this has happened, it may still be writing
to that memory, which may now be reallocated to some other kernel subsystem, 
like
file cache buffers.

The wait_event() tries to ensure that the port destruction can't take place
while the port is still in use, so when it's hung there, it's preventing bad
things from happening.

There is no way to simply 'force' the port to no longer be in use, since a
userspace process can maintain an open file indefinitely.

There are a couple of possible solutions though:

In gserial_free_line(), hangup the tty associated with the port. You can
look at usb_serial_disconnect() for how to do that properly. This doesn't
guarantee that the userspace process will close the tty, but most programs
will close the file on end-of-file read (which is what hangup will cause).

It doesn't look like making the wait_event() interruptible is possible
(or desirable).

The ideal solution would be for u_serial to reference count its gs_ports;
that's what usb serial does for its usb_serial_port. Then gserial_free_line()
becomes a 'disconnect', and the actual cleanup happens later. The key
implementation details are:
1. The tty core helps keep reference counting simple by calling the tty
driver's install() and cleanup() methods; install() for the first open() and
cleanup() when the tty is being released. usb serial does this with
usb_serial_port_get_by_minor() from serial_install() and usb_serial_put() in
serial_cleanup() and usb_serial_disconnect().
2. a flag (like usb serial's '-disconnected') to prevent continued port
allocation after 'disconnect'.

The key concept is that although the tty and port still exist, neither
does anything useful after the disconnect.

And u_serial.c should really be ported to using tty_port which takes care of
stuff like parallel opens and closes without looping and other stuff like
the port-openclose flag.

FWIW, the tty_unregister_device() does not need to be after gserial_free_port()
because existing ttys maintain a device reference count which prevents the
underlying tty device from being released.

Regards,
Peter Hurley

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] u_serial.c - Force destroy tty_port in gserial_free_port

2014-10-09 Thread Peter Hurley
On 10/09/2014 10:26 AM, Alan Stern wrote:
 On Thu, 9 Oct 2014, Andre Wolokita wrote:
 
 Isn't this now a use-after-free issue?


 Are you referring to the subsequent call to wait event() on gs_closed()?

 Yes.

 Testing the use-case with this patch applied seemed to work without any 
 issues. The ttyGS0 reference in /dev/ is gone after running modprobe -r
 but I'm just a newbie, so I could be doing sometime horrible here.

 Hm, I dug into the tty core, it should be ok, but it just seems really
 odd, and bad-form to be doing something with port-port after calling a
 destroy function with it, don't you agree?

 I do. The call to wait_event() can be removed as we no longer care whether
 gs_closed(port) is returning true - if it even can, having destroyed the
 tty_port.
 
 Maybe you don't care whether gs_closed(port) returns true, but you 
 should care about whether gs_closed() crashes -- which it might well do 
 if it tries to access deallocated memory.
 
 Did you test your patch by unloading the module while there were
 pending opens?

gs_closed() won't crash because that's not the memory being deallocated.
tty_port_destroy() is somewhat misnamed; should be more like tty_port_cleanup(),
as it doesn't actually deallocate the port (because tty_port could be an
embedded structure in a larger 'port' which is the most common usage).

I've been struggling to understand how this patch could even cause the
wait_event() to complete and the only thing I can hypothesize is that
the deallocation in tty_port_destroy() somehow causes the process with
the open tty to crash but I don't see how.

Regards,
Peter Hurley

PS - My earlier email was greylisted so that's why I appeared to reply
well after your answer :)

X-Greylist: delayed 4693 seconds by postgrey-1.27 at vger.kernel.org; Thu, 09 
Oct 2014 11:06:05 EDT
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] u_serial.c - Force destroy tty_port in gserial_free_port

2014-10-09 Thread Andre Wolokita


On 10/10/14 00:47, Peter Hurley wrote:
 Hi Andre,
 
 On 10/08/2014 11:54 PM, Andre Wolokita wrote:
 On 09/10/14 14:38, Greg KH wrote:
 On Thu, Oct 09, 2014 at 02:08:04PM +1100, Andre Wolokita wrote:
 On 09/10/14 13:56, Greg KH wrote:
 On Thu, Oct 09, 2014 at 11:23:59AM +1100, Andre Wolokita wrote:
 Issuing a modprobe -r g_serial command to the target
 over the gadget serial communications line causes
 modprobe to enter uninterruptable sleep, leaving the
 system in an unstable state.

 The associated tty_port.count won't drop to 0 because
 the command is issued over the very line being removed.

 Destroying the tty_port will ensure that resources are
 freed and modprobe will not hang.

 Signed-off-by: Andre Wolokita andre.wolok...@analog.com
 ---
  drivers/usb/gadget/function/u_serial.c |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/drivers/usb/gadget/function/u_serial.c 
 b/drivers/usb/gadget/function/u_serial.c
 index ad0aca8..db631c4 100644
 --- a/drivers/usb/gadget/function/u_serial.c
 +++ b/drivers/usb/gadget/function/u_serial.c
 @@ -1074,10 +1074,10 @@ static int gs_closed(struct gs_port *port)
  static void gserial_free_port(struct gs_port *port)
  {
 tasklet_kill(port-push);
 +   tty_port_destroy(port-port);
 /* wait for old opens to finish */
 wait_event(port-port.close_wait, gs_closed(port));

 Isn't this now a use-after-free issue?


 Are you referring to the subsequent call to wait event() on gs_closed()?

 Yes.

 Testing the use-case with this patch applied seemed to work without any 
 issues. The ttyGS0 reference in /dev/ is gone after running modprobe -r
 but I'm just a newbie, so I could be doing sometime horrible here.

 Hm, I dug into the tty core, it should be ok, but it just seems really
 odd, and bad-form to be doing something with port-port after calling a
 destroy function with it, don't you agree?

 I do. The call to wait_event() can be removed as we no longer care whether
 gs_closed(port) is returning true - if it even can, having destroyed the
 tty_port.
 
 Neither the patch nor the idea that this wait_event() is unnecessary is
 correct (within the current design of u_serial).
 
 tty_port_destroy() frees the input processing buffers, which may be in use
 right at this moment, if a port is still in use by its tty. Since whatever
 was using those buffers doesn't know this has happened, it may still be 
 writing
 to that memory, which may now be reallocated to some other kernel subsystem, 
 like
 file cache buffers.
 
 The wait_event() tries to ensure that the port destruction can't take place
 while the port is still in use, so when it's hung there, it's preventing bad
 things from happening.
 
 There is no way to simply 'force' the port to no longer be in use, since a
 userspace process can maintain an open file indefinitely.
 
 There are a couple of possible solutions though:
 
 In gserial_free_line(), hangup the tty associated with the port. You can
 look at usb_serial_disconnect() for how to do that properly. This doesn't
 guarantee that the userspace process will close the tty, but most programs
 will close the file on end-of-file read (which is what hangup will cause).

I tried adding the adding the same tty_vhangup(tty) and tty_kref_put(tty) logic 
that usb serial has
but the problem still occurs.

 It doesn't look like making the wait_event() interruptible is possible
 (or desirable).
 
 The ideal solution would be for u_serial to reference count its gs_ports;
 that's what usb serial does for its usb_serial_port. Then gserial_free_line()
 becomes a 'disconnect', and the actual cleanup happens later. The key
 implementation details are:
 1. The tty core helps keep reference counting simple by calling the tty
 driver's install() and cleanup() methods; install() for the first open() and
 cleanup() when the tty is being released. usb serial does this with
 usb_serial_port_get_by_minor() from serial_install() and usb_serial_put() in
 serial_cleanup() and usb_serial_disconnect().
 2. a flag (like usb serial's '-disconnected') to prevent continued port
 allocation after 'disconnect'.
 
 The key concept is that although the tty and port still exist, neither
 does anything useful after the disconnect.
 
 And u_serial.c should really be ported to using tty_port which takes care of
 stuff like parallel opens and closes without looping and other stuff like
 the port-openclose flag.
 
 FWIW, the tty_unregister_device() does not need to be after 
 gserial_free_port()
 because existing ttys maintain a device reference count which prevents the
 underlying tty device from being released.

To be honest with you, I am in way over my head at the moment. I'll continue
working on this problem but I can't guarantee it'll be fixed any time soon.

Regards,

Andre.
 
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  

Re: [PATCH] u_serial.c - Force destroy tty_port in gserial_free_port

2014-10-08 Thread Felipe Balbi
Hi,

On Thu, Oct 09, 2014 at 11:23:59AM +1100, Andre Wolokita wrote:
 Issuing a modprobe -r g_serial command to the target
 over the gadget serial communications line causes
 modprobe to enter uninterruptable sleep, leaving the
 system in an unstable state.

does anybody know if this is a valid usecase ? I'd expect us to return
-EBUSY in such a case, no ? In any case, using g_serial to rmmod
g_serial is, from what I can tell, not supported.

Let's wait to hear from Alan Cox or somebody else.

 The associated tty_port.count won't drop to 0 because
 the command is issued over the very line being removed.
 
 Destroying the tty_port will ensure that resources are
 freed and modprobe will not hang.
 
 Signed-off-by: Andre Wolokita andre.wolok...@analog.com
 ---
  drivers/usb/gadget/function/u_serial.c |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/drivers/usb/gadget/function/u_serial.c 
 b/drivers/usb/gadget/function/u_serial.c
 index ad0aca8..db631c4 100644
 --- a/drivers/usb/gadget/function/u_serial.c
 +++ b/drivers/usb/gadget/function/u_serial.c
 @@ -1074,10 +1074,10 @@ static int gs_closed(struct gs_port *port)
  static void gserial_free_port(struct gs_port *port)
  {
 tasklet_kill(port-push);
 +   tty_port_destroy(port-port);
 /* wait for old opens to finish */
 wait_event(port-port.close_wait, gs_closed(port));
 WARN_ON(port-port_usb != NULL);
 -   tty_port_destroy(port-port);
 kfree(port);
  }
 
 -- 

-- 
balbi


signature.asc
Description: Digital signature


Re: [PATCH] u_serial.c - Force destroy tty_port in gserial_free_port

2014-10-08 Thread Greg KH
On Thu, Oct 09, 2014 at 11:23:59AM +1100, Andre Wolokita wrote:
 Issuing a modprobe -r g_serial command to the target
 over the gadget serial communications line causes
 modprobe to enter uninterruptable sleep, leaving the
 system in an unstable state.
 
 The associated tty_port.count won't drop to 0 because
 the command is issued over the very line being removed.
 
 Destroying the tty_port will ensure that resources are
 freed and modprobe will not hang.
 
 Signed-off-by: Andre Wolokita andre.wolok...@analog.com
 ---
  drivers/usb/gadget/function/u_serial.c |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/drivers/usb/gadget/function/u_serial.c 
 b/drivers/usb/gadget/function/u_serial.c
 index ad0aca8..db631c4 100644
 --- a/drivers/usb/gadget/function/u_serial.c
 +++ b/drivers/usb/gadget/function/u_serial.c
 @@ -1074,10 +1074,10 @@ static int gs_closed(struct gs_port *port)
  static void gserial_free_port(struct gs_port *port)
  {
 tasklet_kill(port-push);
 +   tty_port_destroy(port-port);
 /* wait for old opens to finish */
 wait_event(port-port.close_wait, gs_closed(port));

Isn't this now a use-after-free issue?

--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] u_serial.c - Force destroy tty_port in gserial_free_port

2014-10-08 Thread Andre Wolokita
On 09/10/14 13:56, Greg KH wrote:
 On Thu, Oct 09, 2014 at 11:23:59AM +1100, Andre Wolokita wrote:
 Issuing a modprobe -r g_serial command to the target
 over the gadget serial communications line causes
 modprobe to enter uninterruptable sleep, leaving the
 system in an unstable state.

 The associated tty_port.count won't drop to 0 because
 the command is issued over the very line being removed.

 Destroying the tty_port will ensure that resources are
 freed and modprobe will not hang.

 Signed-off-by: Andre Wolokita andre.wolok...@analog.com
 ---
  drivers/usb/gadget/function/u_serial.c |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/drivers/usb/gadget/function/u_serial.c 
 b/drivers/usb/gadget/function/u_serial.c
 index ad0aca8..db631c4 100644
 --- a/drivers/usb/gadget/function/u_serial.c
 +++ b/drivers/usb/gadget/function/u_serial.c
 @@ -1074,10 +1074,10 @@ static int gs_closed(struct gs_port *port)
  static void gserial_free_port(struct gs_port *port)
  {
 tasklet_kill(port-push);
 +   tty_port_destroy(port-port);
 /* wait for old opens to finish */
 wait_event(port-port.close_wait, gs_closed(port));
 
 Isn't this now a use-after-free issue?
 

Are you referring to the subsequent call to wait event() on gs_closed()?

Testing the use-case with this patch applied seemed to work without any 
issues. The ttyGS0 reference in /dev/ is gone after running modprobe -r
but I'm just a newbie, so I could be doing sometime horrible here.
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] u_serial.c - Force destroy tty_port in gserial_free_port

2014-10-08 Thread Greg KH
On Thu, Oct 09, 2014 at 02:08:04PM +1100, Andre Wolokita wrote:
 On 09/10/14 13:56, Greg KH wrote:
  On Thu, Oct 09, 2014 at 11:23:59AM +1100, Andre Wolokita wrote:
  Issuing a modprobe -r g_serial command to the target
  over the gadget serial communications line causes
  modprobe to enter uninterruptable sleep, leaving the
  system in an unstable state.
 
  The associated tty_port.count won't drop to 0 because
  the command is issued over the very line being removed.
 
  Destroying the tty_port will ensure that resources are
  freed and modprobe will not hang.
 
  Signed-off-by: Andre Wolokita andre.wolok...@analog.com
  ---
   drivers/usb/gadget/function/u_serial.c |2 +-
   1 file changed, 1 insertion(+), 1 deletion(-)
 
  diff --git a/drivers/usb/gadget/function/u_serial.c 
  b/drivers/usb/gadget/function/u_serial.c
  index ad0aca8..db631c4 100644
  --- a/drivers/usb/gadget/function/u_serial.c
  +++ b/drivers/usb/gadget/function/u_serial.c
  @@ -1074,10 +1074,10 @@ static int gs_closed(struct gs_port *port)
   static void gserial_free_port(struct gs_port *port)
   {
  tasklet_kill(port-push);
  +   tty_port_destroy(port-port);
  /* wait for old opens to finish */
  wait_event(port-port.close_wait, gs_closed(port));
  
  Isn't this now a use-after-free issue?
  
 
 Are you referring to the subsequent call to wait event() on gs_closed()?

Yes.

 Testing the use-case with this patch applied seemed to work without any 
 issues. The ttyGS0 reference in /dev/ is gone after running modprobe -r
 but I'm just a newbie, so I could be doing sometime horrible here.

Hm, I dug into the tty core, it should be ok, but it just seems really
odd, and bad-form to be doing something with port-port after calling a
destroy function with it, don't you agree?

thanks,

greg k-h
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] u_serial.c - Force destroy tty_port in gserial_free_port

2014-10-08 Thread Andre Wolokita


On 09/10/14 14:38, Greg KH wrote:
 On Thu, Oct 09, 2014 at 02:08:04PM +1100, Andre Wolokita wrote:
 On 09/10/14 13:56, Greg KH wrote:
 On Thu, Oct 09, 2014 at 11:23:59AM +1100, Andre Wolokita wrote:
 Issuing a modprobe -r g_serial command to the target
 over the gadget serial communications line causes
 modprobe to enter uninterruptable sleep, leaving the
 system in an unstable state.

 The associated tty_port.count won't drop to 0 because
 the command is issued over the very line being removed.

 Destroying the tty_port will ensure that resources are
 freed and modprobe will not hang.

 Signed-off-by: Andre Wolokita andre.wolok...@analog.com
 ---
  drivers/usb/gadget/function/u_serial.c |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/drivers/usb/gadget/function/u_serial.c 
 b/drivers/usb/gadget/function/u_serial.c
 index ad0aca8..db631c4 100644
 --- a/drivers/usb/gadget/function/u_serial.c
 +++ b/drivers/usb/gadget/function/u_serial.c
 @@ -1074,10 +1074,10 @@ static int gs_closed(struct gs_port *port)
  static void gserial_free_port(struct gs_port *port)
  {
 tasklet_kill(port-push);
 +   tty_port_destroy(port-port);
 /* wait for old opens to finish */
 wait_event(port-port.close_wait, gs_closed(port));

 Isn't this now a use-after-free issue?


 Are you referring to the subsequent call to wait event() on gs_closed()?
 
 Yes.
 
 Testing the use-case with this patch applied seemed to work without any 
 issues. The ttyGS0 reference in /dev/ is gone after running modprobe -r
 but I'm just a newbie, so I could be doing sometime horrible here.
 
 Hm, I dug into the tty core, it should be ok, but it just seems really
 odd, and bad-form to be doing something with port-port after calling a
 destroy function with it, don't you agree?

I do. The call to wait_event() can be removed as we no longer care whether
gs_closed(port) is returning true - if it even can, having destroyed the
tty_port.

cheers.
--
To unsubscribe from this list: send the line unsubscribe linux-usb in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html