Re: Re: Re: Re: Re: [PATCH] usb: core: fix a double free in the usb driver
>On Tue, 7 Jun 2016, Chung-Geol Kim wrote: > >> = >> At *remove USB(3.0) Storage >> sequence <1> --> <5> ((Problem Case)) >> = >> VOLD >> | >> (uevent) >> |_ >>|<1> | >>|dwc3_otg_sm_work | >>|usb_put_hcd | >>|shared_hcd(kref=2)| >>|__| >> |_ >>|<2> | >>|New USB BUS #2| >>| | >>|shared_hcd(kref=1)| >>| | >> --(Link)-bandXX_mutex| >> | |__| >> | >> ___ | >>|<3>| | >>|dwc3_otg_sm_work | | >>|usb_put_hcd| | >>|primary_hcd(kref=1)| | >>|___| | >> _|_ | >>|<4>| | >>|New USB BUS #1 | | >>|hcd_release| | >>|primary_hcd(kref=0)| | >>| | | >>|bandXX_mutex(free) |<- >>|___| >>(( VOLD )) >> __|___ >>|<5> | >>| SCSI| >>|usb_put_hcd | >>|shared_hcd(kref=0)| >>|*hcd_release | >>|bandXX_mutex(free*)|<- double free >>|__| >> >> = > >Okay, now I understand the problem you want to solve. What we need to >do is make sure the mutex is deallocated when the _last_ hcd is >released, which is not necessarily the same as when the _primary_ hcd >is released. > >Can you please test the patch below? > >By the way, a good change (if you want to do it) would be to rename the >"shared_hcd" field to "other_hcd" or "peer_hcd". This is because it >always points to the other hcd in the peer set: In the primary >structure it points to the secondary, and in the secondary structure it >points to the primary. > >Alan Stern > Thank you for clear understanding the problem that I faced. When I tested with your below patch, it also works well. The description has been modified as follows as you suggested. = At *remove USB(3.0) Storage sequence <1> --> <5> ((Problem Case)) = VOLD | (uevent) |_ |<1> | |dwc3_otg_sm_work | |usb_put_hcd | |peer_hcd(kref=2)| |__| |_ |<2> | |New USB BUS #2| | | |peer_hcd(kref=1)| | | --(Link)-bandXX_mutex| | |__| | ___ | |<3>| | |dwc3_otg_sm_work | | |usb_put_hcd| | |primary_hcd(kref=1)| | |___| | _|_ | |<4>| | |New USB BUS #1 | | |hcd_release| | |primary_hcd(kref=0)| | | | | |bandXX_mutex(free) |<- |___| (( VOLD )) __|___ |<5> | | SCSI| |usb_put_hcd | |peer_hcd(kref=0)| |*hcd_release | |bandXX_mutex(free*)|<- double free |__| = > > >Index: usb-4.x/drivers/usb/core/hcd.c >=== >--- usb-4.x.orig/drivers/usb/core/hcd.c >+++ usb-4.x/drivers/usb/core/hcd.c >@@ -2588,24 +2588,22 @@ EXPORT_SYMBOL_GPL(usb_create_hcd); > * Don't deallocate the bandwidth_mutex until the last
Re: Re: Re: Re: Re: [PATCH] usb: core: fix a double free in the usb driver
>On Tue, 7 Jun 2016, Chung-Geol Kim wrote: > >> = >> At *remove USB(3.0) Storage >> sequence <1> --> <5> ((Problem Case)) >> = >> VOLD >> | >> (uevent) >> |_ >>|<1> | >>|dwc3_otg_sm_work | >>|usb_put_hcd | >>|shared_hcd(kref=2)| >>|__| >> |_ >>|<2> | >>|New USB BUS #2| >>| | >>|shared_hcd(kref=1)| >>| | >> --(Link)-bandXX_mutex| >> | |__| >> | >> ___ | >>|<3>| | >>|dwc3_otg_sm_work | | >>|usb_put_hcd| | >>|primary_hcd(kref=1)| | >>|___| | >> _|_ | >>|<4>| | >>|New USB BUS #1 | | >>|hcd_release| | >>|primary_hcd(kref=0)| | >>| | | >>|bandXX_mutex(free) |<- >>|___| >>(( VOLD )) >> __|___ >>|<5> | >>| SCSI| >>|usb_put_hcd | >>|shared_hcd(kref=0)| >>|*hcd_release | >>|bandXX_mutex(free*)|<- double free >>|__| >> >> = > >Okay, now I understand the problem you want to solve. What we need to >do is make sure the mutex is deallocated when the _last_ hcd is >released, which is not necessarily the same as when the _primary_ hcd >is released. > >Can you please test the patch below? > >By the way, a good change (if you want to do it) would be to rename the >"shared_hcd" field to "other_hcd" or "peer_hcd". This is because it >always points to the other hcd in the peer set: In the primary >structure it points to the secondary, and in the secondary structure it >points to the primary. > >Alan Stern > Thank you for clear understanding the problem that I faced. When I tested with your below patch, it also works well. The description has been modified as follows as you suggested. = At *remove USB(3.0) Storage sequence <1> --> <5> ((Problem Case)) = VOLD | (uevent) |_ |<1> | |dwc3_otg_sm_work | |usb_put_hcd | |peer_hcd(kref=2)| |__| |_ |<2> | |New USB BUS #2| | | |peer_hcd(kref=1)| | | --(Link)-bandXX_mutex| | |__| | ___ | |<3>| | |dwc3_otg_sm_work | | |usb_put_hcd| | |primary_hcd(kref=1)| | |___| | _|_ | |<4>| | |New USB BUS #1 | | |hcd_release| | |primary_hcd(kref=0)| | | | | |bandXX_mutex(free) |<- |___| (( VOLD )) __|___ |<5> | | SCSI| |usb_put_hcd | |peer_hcd(kref=0)| |*hcd_release | |bandXX_mutex(free*)|<- double free |__| = > > >Index: usb-4.x/drivers/usb/core/hcd.c >=== >--- usb-4.x.orig/drivers/usb/core/hcd.c >+++ usb-4.x/drivers/usb/core/hcd.c >@@ -2588,24 +2588,22 @@ EXPORT_SYMBOL_GPL(usb_create_hcd); > * Don't deallocate the bandwidth_mutex until the last
RE: Re: Re: Re: [PATCH] usb: core: fix a double free in the usb driver
On Tue, 7 Jun 2016, Chung-Geol Kim wrote: > = > At *remove USB(3.0) Storage > sequence <1> --> <5> ((Problem Case)) > = > VOLD > | > (uevent) > |_ >|<1> | >|dwc3_otg_sm_work | >|usb_put_hcd | >|shared_hcd(kref=2)| >|__| > |_ >|<2> | >|New USB BUS #2| >| | >|shared_hcd(kref=1)| >| | > --(Link)-bandXX_mutex| > | |__| > | > ___ | >|<3>| | >|dwc3_otg_sm_work | | >|usb_put_hcd| | >|primary_hcd(kref=1)| | >|___| | > _|_ | >|<4>| | >|New USB BUS #1 | | >|hcd_release| | >|primary_hcd(kref=0)| | >| | | >|bandXX_mutex(free) |<- >|___| >(( VOLD )) > __|___ >|<5> | >| SCSI| >|usb_put_hcd | >|shared_hcd(kref=0)| >|*hcd_release | >|bandXX_mutex(free*)|<- double free >|__| > > = Okay, now I understand the problem you want to solve. What we need to do is make sure the mutex is deallocated when the _last_ hcd is released, which is not necessarily the same as when the _primary_ hcd is released. Can you please test the patch below? By the way, a good change (if you want to do it) would be to rename the "shared_hcd" field to "other_hcd" or "peer_hcd". This is because it always points to the other hcd in the peer set: In the primary structure it points to the secondary, and in the secondary structure it points to the primary. Alan Stern Index: usb-4.x/drivers/usb/core/hcd.c === --- usb-4.x.orig/drivers/usb/core/hcd.c +++ usb-4.x/drivers/usb/core/hcd.c @@ -2588,24 +2588,22 @@ EXPORT_SYMBOL_GPL(usb_create_hcd); * Don't deallocate the bandwidth_mutex until the last shared usb_hcd is * deallocated. * - * Make sure to only deallocate the bandwidth_mutex when the primary HCD is - * freed. When hcd_release() is called for either hcd in a peer set - * invalidate the peer's ->shared_hcd and ->primary_hcd pointers to - * block new peering attempts + * Make sure to deallocate the bandwidth_mutex only when the last HCD is + * freed. When hcd_release() is called for either hcd in a peer set, + * invalidate the peer's ->shared_hcd and ->primary_hcd pointers. */ static void hcd_release(struct kref *kref) { struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); mutex_lock(_port_peer_mutex); - if (usb_hcd_is_primary_hcd(hcd)) - kfree(hcd->bandwidth_mutex); if (hcd->shared_hcd) { struct usb_hcd *peer = hcd->shared_hcd; peer->shared_hcd = NULL; - if (peer->primary_hcd == hcd) - peer->primary_hcd = NULL; + peer->primary_hcd = NULL; + } else { + kfree(hcd->bandwidth_mutex); } mutex_unlock(_port_peer_mutex); kfree(hcd);
RE: Re: Re: Re: [PATCH] usb: core: fix a double free in the usb driver
On Tue, 7 Jun 2016, Chung-Geol Kim wrote: > = > At *remove USB(3.0) Storage > sequence <1> --> <5> ((Problem Case)) > = > VOLD > | > (uevent) > |_ >|<1> | >|dwc3_otg_sm_work | >|usb_put_hcd | >|shared_hcd(kref=2)| >|__| > |_ >|<2> | >|New USB BUS #2| >| | >|shared_hcd(kref=1)| >| | > --(Link)-bandXX_mutex| > | |__| > | > ___ | >|<3>| | >|dwc3_otg_sm_work | | >|usb_put_hcd| | >|primary_hcd(kref=1)| | >|___| | > _|_ | >|<4>| | >|New USB BUS #1 | | >|hcd_release| | >|primary_hcd(kref=0)| | >| | | >|bandXX_mutex(free) |<- >|___| >(( VOLD )) > __|___ >|<5> | >| SCSI| >|usb_put_hcd | >|shared_hcd(kref=0)| >|*hcd_release | >|bandXX_mutex(free*)|<- double free >|__| > > = Okay, now I understand the problem you want to solve. What we need to do is make sure the mutex is deallocated when the _last_ hcd is released, which is not necessarily the same as when the _primary_ hcd is released. Can you please test the patch below? By the way, a good change (if you want to do it) would be to rename the "shared_hcd" field to "other_hcd" or "peer_hcd". This is because it always points to the other hcd in the peer set: In the primary structure it points to the secondary, and in the secondary structure it points to the primary. Alan Stern Index: usb-4.x/drivers/usb/core/hcd.c === --- usb-4.x.orig/drivers/usb/core/hcd.c +++ usb-4.x/drivers/usb/core/hcd.c @@ -2588,24 +2588,22 @@ EXPORT_SYMBOL_GPL(usb_create_hcd); * Don't deallocate the bandwidth_mutex until the last shared usb_hcd is * deallocated. * - * Make sure to only deallocate the bandwidth_mutex when the primary HCD is - * freed. When hcd_release() is called for either hcd in a peer set - * invalidate the peer's ->shared_hcd and ->primary_hcd pointers to - * block new peering attempts + * Make sure to deallocate the bandwidth_mutex only when the last HCD is + * freed. When hcd_release() is called for either hcd in a peer set, + * invalidate the peer's ->shared_hcd and ->primary_hcd pointers. */ static void hcd_release(struct kref *kref) { struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); mutex_lock(_port_peer_mutex); - if (usb_hcd_is_primary_hcd(hcd)) - kfree(hcd->bandwidth_mutex); if (hcd->shared_hcd) { struct usb_hcd *peer = hcd->shared_hcd; peer->shared_hcd = NULL; - if (peer->primary_hcd == hcd) - peer->primary_hcd = NULL; + peer->primary_hcd = NULL; + } else { + kfree(hcd->bandwidth_mutex); } mutex_unlock(_port_peer_mutex); kfree(hcd);
RE: Re: Re: Re: [PATCH] usb: core: fix a double free in the usb driver
>On Fri, 3 Jun 2016, Chung-Geol Kim wrote: > >> Yes, you are right, The presentational errors in order to obtain an >> understanding of the process. >> Therefore, I will be happy to explain again the diagrammatic representation >> as shown below. >> If using usb 3.0 storage(OTG), you can see as below. >> >> == >> At *Insert USB(3.0) Storage >> sequence <1> --> <5> >> == >> VOLD >> =| >> (uevent) >>__|___ >> |<5> | >> | SCSI| >> |usb_get_hcd | >> |shared_hcd(kref=3)| >> |__| >>___ |_ >> |<2>| |<4> | >> |dwc3_otg_sm_work | |dwc3_otg_sm_work | >> |usb_get_hcd| |usb_get_hcd | >> |primary_hcd(kref=2)| |shared_hcd(kref=2)| >> |___| |__| >>_|_ |_ >> |<1>| |<3> | >> |New USB BUS #1 | |New USB BUS #2| >> |usb_create_hcd | |usb_create_hcd| >> |primary_hcd(kref=1)| |shared_hcd(kref=1)| >> | | | | >> |bandXX_mutex(alloc)|<-(Link)-bandXX_mutex | >> |___| |__| >> > >When people present diagrams like this, the universal convention is to >show earlier times at the top and later times at the bottom. That way >the order in which you read the diagram is the same as the order in >which the events are supposed to occur. > >Also, the convention is to put events next to each other if they happen >at the same time. In your diagram, <1> and <3> are next to each other >but they don't happen at the same time. Thank you for your kind explanation. It has been modified as shown below. = At *Insert USB(3.0) Storage sequence <1> --> <5> = ___ |<1>| |New USB BUS #1 | |usb_create_hcd | |primary_hcd(kref=1)| | | |bandXX_mutex(alloc)|<-- |___| | _|_ | |<2>| | |dwc3_otg_sm_work | | |usb_get_hcd| | |primary_hcd(kref=2)| | |___| | | __ | |<3> | | |New USB BUS #2| | |usb_create_hcd| | |shared_hcd(kref=1)| | | | --(Link)-bandXX_mutex| |__| |_ |<4> | |dwc3_otg_sm_work | |usb_get_hcd | |shared_hcd(kref=2)| |__| ___|__ |<5> | | SCSI| |usb_get_hcd | |shared_hcd(kref=3)| |__| | (uevent) ---| VOLD = = At *remove USB(3.0) Storage sequence <1> --> <5> ((Normal Case)) = VOLD | (uevent) __|___ |<1> | | SCSI| |usb_put_hcd | |shared_hcd(kref=2)| |__| |_ |<2> | |dwc3_otg_sm_work | |usb_put_hcd | |shared_hcd(kref=1)| |__| |_ |<3> | |New USB BUS #2| |hcd_release | |shared_hcd(kref=0)|
RE: Re: Re: Re: [PATCH] usb: core: fix a double free in the usb driver
>On Fri, 3 Jun 2016, Chung-Geol Kim wrote: > >> Yes, you are right, The presentational errors in order to obtain an >> understanding of the process. >> Therefore, I will be happy to explain again the diagrammatic representation >> as shown below. >> If using usb 3.0 storage(OTG), you can see as below. >> >> == >> At *Insert USB(3.0) Storage >> sequence <1> --> <5> >> == >> VOLD >> =| >> (uevent) >>__|___ >> |<5> | >> | SCSI| >> |usb_get_hcd | >> |shared_hcd(kref=3)| >> |__| >>___ |_ >> |<2>| |<4> | >> |dwc3_otg_sm_work | |dwc3_otg_sm_work | >> |usb_get_hcd| |usb_get_hcd | >> |primary_hcd(kref=2)| |shared_hcd(kref=2)| >> |___| |__| >>_|_ |_ >> |<1>| |<3> | >> |New USB BUS #1 | |New USB BUS #2| >> |usb_create_hcd | |usb_create_hcd| >> |primary_hcd(kref=1)| |shared_hcd(kref=1)| >> | | | | >> |bandXX_mutex(alloc)|<-(Link)-bandXX_mutex | >> |___| |__| >> > >When people present diagrams like this, the universal convention is to >show earlier times at the top and later times at the bottom. That way >the order in which you read the diagram is the same as the order in >which the events are supposed to occur. > >Also, the convention is to put events next to each other if they happen >at the same time. In your diagram, <1> and <3> are next to each other >but they don't happen at the same time. Thank you for your kind explanation. It has been modified as shown below. = At *Insert USB(3.0) Storage sequence <1> --> <5> = ___ |<1>| |New USB BUS #1 | |usb_create_hcd | |primary_hcd(kref=1)| | | |bandXX_mutex(alloc)|<-- |___| | _|_ | |<2>| | |dwc3_otg_sm_work | | |usb_get_hcd| | |primary_hcd(kref=2)| | |___| | | __ | |<3> | | |New USB BUS #2| | |usb_create_hcd| | |shared_hcd(kref=1)| | | | --(Link)-bandXX_mutex| |__| |_ |<4> | |dwc3_otg_sm_work | |usb_get_hcd | |shared_hcd(kref=2)| |__| ___|__ |<5> | | SCSI| |usb_get_hcd | |shared_hcd(kref=3)| |__| | (uevent) ---| VOLD = = At *remove USB(3.0) Storage sequence <1> --> <5> ((Normal Case)) = VOLD | (uevent) __|___ |<1> | | SCSI| |usb_put_hcd | |shared_hcd(kref=2)| |__| |_ |<2> | |dwc3_otg_sm_work | |usb_put_hcd | |shared_hcd(kref=1)| |__| |_ |<3> | |New USB BUS #2| |hcd_release | |shared_hcd(kref=0)|
Re: Re: Re: [PATCH] usb: core: fix a double free in the usb driver
On Fri, 3 Jun 2016, Chung-Geol Kim wrote: > Yes, you are right, The presentational errors in order to obtain an > understanding of the process. > Therefore, I will be happy to explain again the diagrammatic representation > as shown below. > If using usb 3.0 storage(OTG), you can see as below. > > == > At *Insert USB(3.0) Storage > sequence <1> --> <5> > == > VOLD > =| > (uevent) >__|___ > |<5> | > | SCSI| > |usb_get_hcd | > |shared_hcd(kref=3)| > |__| >___ |_ > |<2>| |<4> | > |dwc3_otg_sm_work | |dwc3_otg_sm_work | > |usb_get_hcd| |usb_get_hcd | > |primary_hcd(kref=2)| |shared_hcd(kref=2)| > |___| |__| >_|_ |_ > |<1>| |<3> | > |New USB BUS #1 | |New USB BUS #2| > |usb_create_hcd | |usb_create_hcd| > |primary_hcd(kref=1)| |shared_hcd(kref=1)| > | | | | > |bandXX_mutex(alloc)|<-(Link)-bandXX_mutex | > |___| |__| > When people present diagrams like this, the universal convention is to show earlier times at the top and later times at the bottom. That way the order in which you read the diagram is the same as the order in which the events are supposed to occur. Also, the convention is to put events next to each other if they happen at the same time. In your diagram, <1> and <3> are next to each other but they don't happen at the same time. > == > At *remove USB(3.0) Storage > sequence <1> --> <5> ((Normal Case)) > == > VOLD > =| > (uevent) >__|___ > |<1> | > | SCSI| > |usb_put_hcd | > |shared_hcd(kref=2)| > |__| >___ |_ > |<4>| |<2> | > |dwc3_otg_sm_work | |dwc3_otg_sm_work | > |usb_put_hcd| |usb_put_hcd | > |primary_hcd(kref=1)| |shared_hcd(kref=1)| > |___| |__| >_|_ |_ > |<5>| |<3> | > |New USB BUS #1 | |New USB BUS #2| > |hcd_release| |hcd_release | > |primary_hcd(kref=0)| |shared_hcd(kref=0)| > | | | | > |bandXX_mutex(free) | -X-cut off)-bandXX_mutex| > |___| |__| > > -- > >The real bug here is that the shared_hcd is released after the > >primary_hcd. That's what you need to fix. > > NO, It 's only depend on vold(scsi) release time. > If the vold later released and is being released first hcd, > Double free happened at <5> as below. > > == > At *remove USB(3.0) Storage > sequence <1> --> <5> ((Problem Case)) > == > VOLD > =| > (uevent) >__|___ > |<5> | > | SCSI| > |usb_put_hcd | > |shared_hcd(kref=0)| > |*hcd_release | > |bandXX_mutex(free*)|<- double free > |__| >___ |_ > |<3>| |<1> | > |dwc3_otg_sm_work | |dwc3_otg_sm_work | > |usb_put_hcd| |usb_put_hcd | > |primary_hcd(kref=1)| |shared_hcd(kref=2)| > |___| |__| >_|_ |_ > |<4>| |<2> | > |New USB BUS #1 | |New USB BUS #2| > |hcd_release| | | > |primary_hcd(kref=0)| |shared_hcd(kref=1)| > | | | | > |bandXX_mutex(free) |<-(Link)-bandXX_mutex | >
Re: Re: Re: [PATCH] usb: core: fix a double free in the usb driver
On Fri, 3 Jun 2016, Chung-Geol Kim wrote: > Yes, you are right, The presentational errors in order to obtain an > understanding of the process. > Therefore, I will be happy to explain again the diagrammatic representation > as shown below. > If using usb 3.0 storage(OTG), you can see as below. > > == > At *Insert USB(3.0) Storage > sequence <1> --> <5> > == > VOLD > =| > (uevent) >__|___ > |<5> | > | SCSI| > |usb_get_hcd | > |shared_hcd(kref=3)| > |__| >___ |_ > |<2>| |<4> | > |dwc3_otg_sm_work | |dwc3_otg_sm_work | > |usb_get_hcd| |usb_get_hcd | > |primary_hcd(kref=2)| |shared_hcd(kref=2)| > |___| |__| >_|_ |_ > |<1>| |<3> | > |New USB BUS #1 | |New USB BUS #2| > |usb_create_hcd | |usb_create_hcd| > |primary_hcd(kref=1)| |shared_hcd(kref=1)| > | | | | > |bandXX_mutex(alloc)|<-(Link)-bandXX_mutex | > |___| |__| > When people present diagrams like this, the universal convention is to show earlier times at the top and later times at the bottom. That way the order in which you read the diagram is the same as the order in which the events are supposed to occur. Also, the convention is to put events next to each other if they happen at the same time. In your diagram, <1> and <3> are next to each other but they don't happen at the same time. > == > At *remove USB(3.0) Storage > sequence <1> --> <5> ((Normal Case)) > == > VOLD > =| > (uevent) >__|___ > |<1> | > | SCSI| > |usb_put_hcd | > |shared_hcd(kref=2)| > |__| >___ |_ > |<4>| |<2> | > |dwc3_otg_sm_work | |dwc3_otg_sm_work | > |usb_put_hcd| |usb_put_hcd | > |primary_hcd(kref=1)| |shared_hcd(kref=1)| > |___| |__| >_|_ |_ > |<5>| |<3> | > |New USB BUS #1 | |New USB BUS #2| > |hcd_release| |hcd_release | > |primary_hcd(kref=0)| |shared_hcd(kref=0)| > | | | | > |bandXX_mutex(free) | -X-cut off)-bandXX_mutex| > |___| |__| > > -- > >The real bug here is that the shared_hcd is released after the > >primary_hcd. That's what you need to fix. > > NO, It 's only depend on vold(scsi) release time. > If the vold later released and is being released first hcd, > Double free happened at <5> as below. > > == > At *remove USB(3.0) Storage > sequence <1> --> <5> ((Problem Case)) > == > VOLD > =| > (uevent) >__|___ > |<5> | > | SCSI| > |usb_put_hcd | > |shared_hcd(kref=0)| > |*hcd_release | > |bandXX_mutex(free*)|<- double free > |__| >___ |_ > |<3>| |<1> | > |dwc3_otg_sm_work | |dwc3_otg_sm_work | > |usb_put_hcd| |usb_put_hcd | > |primary_hcd(kref=1)| |shared_hcd(kref=2)| > |___| |__| >_|_ |_ > |<4>| |<2> | > |New USB BUS #1 | |New USB BUS #2| > |hcd_release| | | > |primary_hcd(kref=0)| |shared_hcd(kref=1)| > | | | | > |bandXX_mutex(free) |<-(Link)-bandXX_mutex | >
Re: Re: Re: [PATCH] usb: core: fix a double free in the usb driver
>On Fri, 27 May 2016, Chung-Geol Kim wrote: > >> >On Fri, May 27, 2016 at 01:38:17AM +, Chung-Geol Kim wrote: >> >> There is a double free problem in the usb driver. >> > >> >Which driver? >> When I using the USB OTG Storage, this issue happened. >> When remove the OTG Storage, it reproduced sometimes. > >> cpu 0 cpu 1 >> >> >> (*Insert USB Storage) >> usb_create_shared_hcd() >> kmalloc(primary_hcd) >> kmalloc(primary_hcd->bandwidth_mutex) >> ->(primary_hcd->kref==1) >> usb_get_hcd() >> ->(primary_hcd->kref==2) >> usb_create_shared_hcd() >> kmalloc(hcd->shared_hcd) >> >> ->hcd->shared_hcd->bandwidth_mutex=primary->bandwidth_mutex >> >> ->primary_hcd->primary_hcd = primary_hcd >> >> ->hcd->shared_hcd->primary_hcd = primary_hcd >> >> ->(hcd->shared_hcd->kref==1) >> usb_get_hcd() >> >> ->(hcd->shared_hcd->kref==2) >> >> usb_get_hcd() >> >> ->(hcd->shared_hcd->kref==3) > >I don't understand. Why do these actions take place on two different >CPUs? Aren't the primary_hcd and the shared_hcd structures allocated >by the same thread, on the same CPU? Yes, you are right, The presentational errors in order to obtain an understanding of the process. Therefore, I will be happy to explain again the diagrammatic representation as shown below. If using usb 3.0 storage(OTG), you can see as below. == At *Insert USB(3.0) Storage sequence <1> --> <5> == VOLD =| (uevent) __|___ |<5> | | SCSI| |usb_get_hcd | |shared_hcd(kref=3)| |__| ___ |_ |<2>| |<4> | |dwc3_otg_sm_work | |dwc3_otg_sm_work | |usb_get_hcd| |usb_get_hcd | |primary_hcd(kref=2)| |shared_hcd(kref=2)| |___| |__| _|_ |_ |<1>| |<3> | |New USB BUS #1 | |New USB BUS #2| |usb_create_hcd | |usb_create_hcd| |primary_hcd(kref=1)| |shared_hcd(kref=1)| | | | | |bandXX_mutex(alloc)|<-(Link)-bandXX_mutex | |___| |__| == At *remove USB(3.0) Storage sequence <1> --> <5> ((Normal Case)) == VOLD =| (uevent) __|___ |<1> | | SCSI| |usb_put_hcd | |shared_hcd(kref=2)| |__| ___ |_ |<4>| |<2> | |dwc3_otg_sm_work | |dwc3_otg_sm_work | |usb_put_hcd| |usb_put_hcd | |primary_hcd(kref=1)| |shared_hcd(kref=1)| |___| |__| _|_ |_ |<5>| |<3> | |New USB BUS #1 | |New USB BUS #2| |hcd_release| |hcd_release | |primary_hcd(kref=0)| |shared_hcd(kref=0)| | | | | |bandXX_mutex(free) | -X-cut off)-bandXX_mutex| |___| |__| -- > >> >> --- >> (*remove USB Storage) >> usb_release_dev() >> >> ->(hcd->shared_hcd-kref==2) >> usb_release_dev() >> >>
Re: Re: Re: [PATCH] usb: core: fix a double free in the usb driver
>On Fri, 27 May 2016, Chung-Geol Kim wrote: > >> >On Fri, May 27, 2016 at 01:38:17AM +, Chung-Geol Kim wrote: >> >> There is a double free problem in the usb driver. >> > >> >Which driver? >> When I using the USB OTG Storage, this issue happened. >> When remove the OTG Storage, it reproduced sometimes. > >> cpu 0 cpu 1 >> >> >> (*Insert USB Storage) >> usb_create_shared_hcd() >> kmalloc(primary_hcd) >> kmalloc(primary_hcd->bandwidth_mutex) >> ->(primary_hcd->kref==1) >> usb_get_hcd() >> ->(primary_hcd->kref==2) >> usb_create_shared_hcd() >> kmalloc(hcd->shared_hcd) >> >> ->hcd->shared_hcd->bandwidth_mutex=primary->bandwidth_mutex >> >> ->primary_hcd->primary_hcd = primary_hcd >> >> ->hcd->shared_hcd->primary_hcd = primary_hcd >> >> ->(hcd->shared_hcd->kref==1) >> usb_get_hcd() >> >> ->(hcd->shared_hcd->kref==2) >> >> usb_get_hcd() >> >> ->(hcd->shared_hcd->kref==3) > >I don't understand. Why do these actions take place on two different >CPUs? Aren't the primary_hcd and the shared_hcd structures allocated >by the same thread, on the same CPU? Yes, you are right, The presentational errors in order to obtain an understanding of the process. Therefore, I will be happy to explain again the diagrammatic representation as shown below. If using usb 3.0 storage(OTG), you can see as below. == At *Insert USB(3.0) Storage sequence <1> --> <5> == VOLD =| (uevent) __|___ |<5> | | SCSI| |usb_get_hcd | |shared_hcd(kref=3)| |__| ___ |_ |<2>| |<4> | |dwc3_otg_sm_work | |dwc3_otg_sm_work | |usb_get_hcd| |usb_get_hcd | |primary_hcd(kref=2)| |shared_hcd(kref=2)| |___| |__| _|_ |_ |<1>| |<3> | |New USB BUS #1 | |New USB BUS #2| |usb_create_hcd | |usb_create_hcd| |primary_hcd(kref=1)| |shared_hcd(kref=1)| | | | | |bandXX_mutex(alloc)|<-(Link)-bandXX_mutex | |___| |__| == At *remove USB(3.0) Storage sequence <1> --> <5> ((Normal Case)) == VOLD =| (uevent) __|___ |<1> | | SCSI| |usb_put_hcd | |shared_hcd(kref=2)| |__| ___ |_ |<4>| |<2> | |dwc3_otg_sm_work | |dwc3_otg_sm_work | |usb_put_hcd| |usb_put_hcd | |primary_hcd(kref=1)| |shared_hcd(kref=1)| |___| |__| _|_ |_ |<5>| |<3> | |New USB BUS #1 | |New USB BUS #2| |hcd_release| |hcd_release | |primary_hcd(kref=0)| |shared_hcd(kref=0)| | | | | |bandXX_mutex(free) | -X-cut off)-bandXX_mutex| |___| |__| -- > >> >> --- >> (*remove USB Storage) >> usb_release_dev() >> >> ->(hcd->shared_hcd-kref==2) >> usb_release_dev() >> >>
Re: Re: [PATCH] usb: core: fix a double free in the usb driver
On Fri, 27 May 2016, Chung-Geol Kim wrote: > >On Fri, May 27, 2016 at 01:38:17AM +, Chung-Geol Kim wrote: > >> There is a double free problem in the usb driver. > > > >Which driver? > When I using the USB OTG Storage, this issue happened. > When remove the OTG Storage, it reproduced sometimes. > cpu 0 cpu 1 > > > (*Insert USB Storage) > usb_create_shared_hcd() > kmalloc(primary_hcd) > kmalloc(primary_hcd->bandwidth_mutex) > ->(primary_hcd->kref==1) > usb_get_hcd() > ->(primary_hcd->kref==2) > usb_create_shared_hcd() > kmalloc(hcd->shared_hcd) > > ->hcd->shared_hcd->bandwidth_mutex=primary->bandwidth_mutex > > ->primary_hcd->primary_hcd = primary_hcd > > ->hcd->shared_hcd->primary_hcd = primary_hcd > > ->(hcd->shared_hcd->kref==1) > usb_get_hcd() > > ->(hcd->shared_hcd->kref==2) > > usb_get_hcd() > > ->(hcd->shared_hcd->kref==3) I don't understand. Why do these actions take place on two different CPUs? Aren't the primary_hcd and the shared_hcd structures allocated by the same thread, on the same CPU? > > --- > (*remove USB Storage) > usb_release_dev() > > ->(hcd->shared_hcd-kref==2) > usb_release_dev() > > ->(hcd->shared_hcd-kref==1) > usb_release_dev() > -> (primary_hcd-kref==1) > usb_release_dev() > -> (primary_hcd-kref==0) > hcd_release() > -> kfree(primary_hcd->bandwidth_mutex) > -> hcd->shared_hcd->primary_hcd = NULL > -> kfree(primary_hcd) > usb_release_dev() > -> > (hcd->shared_hcd-kref==0) > hcd_release() > -> > usb_hcd_is_primary_hcd(hcd->shared_hcd) > -> > hcd->shared_hcd->primary_hcd already NULL, return 1 > -> try to double > kfree(primary_hcd->bandwidth_mutex) The same question applies here. Aren't the shared_hcd and primary_hcd structures released by the same thread, on the same CPU? The real bug here is that the shared_hcd is released after the primary_hcd. That's what you need to fix. > Since hcd->shared_hcd->priary_hcd was Null it didn't reach (hcd == > hcd->primary_hcd) in usb_hcd_is_primary_hcd(). > It returned 1 at since condition !hcd->primary_hcd is met. > >> --- a/drivers/usb/core/hcd.c > >> +++ b/drivers/usb/core/hcd.c > >> @@ -2608,7 +2608,7 @@ static void hcd_release(struct kref *kref) > >> struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); > >> > >> mutex_lock(_port_peer_mutex); > >> - if (usb_hcd_is_primary_hcd(hcd)) { > >> + if (hcd == hcd->primary_hcd) { > > > >That doesn't make sense, usb_hcd_is_primary_hcd() is the same as this > >check, what are you changing here? > > Since hcd->priary_hcd was Null it didn't reach (hcd == hcd->primary_hcd). > It returned 1 at since condition !hcd->primary_hcd is met. > > int usb_hcd_is_primary_hcd(struct usb_hcd *hcd) > { > if (!hcd->primary_hcd) > return 1; > return hcd == hcd->primary_hcd; > } That's just a symptom, not the real cause of the bug. You need to fix the real cause: the shared_hcd has to be released _before_ the primary_hcd. The right way to do this is to make the shared_hcd take a reference to the primary_hcd. This reference should be dropped when hcd_release() is called for the shared_hcd. Alan Stern
Re: Re: [PATCH] usb: core: fix a double free in the usb driver
On Fri, 27 May 2016, Chung-Geol Kim wrote: > >On Fri, May 27, 2016 at 01:38:17AM +, Chung-Geol Kim wrote: > >> There is a double free problem in the usb driver. > > > >Which driver? > When I using the USB OTG Storage, this issue happened. > When remove the OTG Storage, it reproduced sometimes. > cpu 0 cpu 1 > > > (*Insert USB Storage) > usb_create_shared_hcd() > kmalloc(primary_hcd) > kmalloc(primary_hcd->bandwidth_mutex) > ->(primary_hcd->kref==1) > usb_get_hcd() > ->(primary_hcd->kref==2) > usb_create_shared_hcd() > kmalloc(hcd->shared_hcd) > > ->hcd->shared_hcd->bandwidth_mutex=primary->bandwidth_mutex > > ->primary_hcd->primary_hcd = primary_hcd > > ->hcd->shared_hcd->primary_hcd = primary_hcd > > ->(hcd->shared_hcd->kref==1) > usb_get_hcd() > > ->(hcd->shared_hcd->kref==2) > > usb_get_hcd() > > ->(hcd->shared_hcd->kref==3) I don't understand. Why do these actions take place on two different CPUs? Aren't the primary_hcd and the shared_hcd structures allocated by the same thread, on the same CPU? > > --- > (*remove USB Storage) > usb_release_dev() > > ->(hcd->shared_hcd-kref==2) > usb_release_dev() > > ->(hcd->shared_hcd-kref==1) > usb_release_dev() > -> (primary_hcd-kref==1) > usb_release_dev() > -> (primary_hcd-kref==0) > hcd_release() > -> kfree(primary_hcd->bandwidth_mutex) > -> hcd->shared_hcd->primary_hcd = NULL > -> kfree(primary_hcd) > usb_release_dev() > -> > (hcd->shared_hcd-kref==0) > hcd_release() > -> > usb_hcd_is_primary_hcd(hcd->shared_hcd) > -> > hcd->shared_hcd->primary_hcd already NULL, return 1 > -> try to double > kfree(primary_hcd->bandwidth_mutex) The same question applies here. Aren't the shared_hcd and primary_hcd structures released by the same thread, on the same CPU? The real bug here is that the shared_hcd is released after the primary_hcd. That's what you need to fix. > Since hcd->shared_hcd->priary_hcd was Null it didn't reach (hcd == > hcd->primary_hcd) in usb_hcd_is_primary_hcd(). > It returned 1 at since condition !hcd->primary_hcd is met. > >> --- a/drivers/usb/core/hcd.c > >> +++ b/drivers/usb/core/hcd.c > >> @@ -2608,7 +2608,7 @@ static void hcd_release(struct kref *kref) > >> struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); > >> > >> mutex_lock(_port_peer_mutex); > >> - if (usb_hcd_is_primary_hcd(hcd)) { > >> + if (hcd == hcd->primary_hcd) { > > > >That doesn't make sense, usb_hcd_is_primary_hcd() is the same as this > >check, what are you changing here? > > Since hcd->priary_hcd was Null it didn't reach (hcd == hcd->primary_hcd). > It returned 1 at since condition !hcd->primary_hcd is met. > > int usb_hcd_is_primary_hcd(struct usb_hcd *hcd) > { > if (!hcd->primary_hcd) > return 1; > return hcd == hcd->primary_hcd; > } That's just a symptom, not the real cause of the bug. You need to fix the real cause: the shared_hcd has to be released _before_ the primary_hcd. The right way to do this is to make the shared_hcd take a reference to the primary_hcd. This reference should be dropped when hcd_release() is called for the shared_hcd. Alan Stern
Re: Re: [PATCH] usb: core: fix a double free in the usb driver
>On Fri, May 27, 2016 at 01:38:17AM +, Chung-Geol Kim wrote: >> There is a double free problem in the usb driver. > >Which driver? When I using the USB OTG Storage, this issue happened. When remove the OTG Storage, it reproduced sometimes. > >> This is caused by delayed deregister for scsi device. >> <*> at Insert USB Storage >> - USB bus #1 register >> usb_create_hcd (primary-kref==1) >> * primary-bandwidth_mutex(alloc)) >> usb_get_hcd(primary-kref==2) >> - USB bus #2 register >> usb_create_hcd (second-kref==1) >> * second-bandwidth_mutex==primary-bandwidth_mutex >> usb_get_hcd(second-kref==2) >> - scsi_device_get >> usb_get_hcd(second-kref==3) >> >> <*> at remove USB Storage (Normal) >> - scsi_device_put >> usb_put_hcd(second-kref==2) >> - USB bus #2 deregister >> usb_release_dev(second-kref==1) >> usb_release_dev(second-kref==0) -> hcd_release() >> - USB bus #1 deregister >> usb_release_dev(primary-kref==1) >> usb_release_dev(primary-kref==0) -> hcd_release() >> *(primary-bandwidth_mutex free) >> >> at remove USB Storage >> - USB bus #2 deregister >> usb_release_dev(second-kref==2) >> usb_release_dev(second-kref==1) >> - USB bus #1 deregister >> usb_release_dev(primary-kref==1) >> usb_release_dev(primary-kref==0) -> hcd_release() >> *(primary-bandwidth_mutex free) >> - scsi_device_put >> usb_put_hcd(second-kref==0) -> hcd_release(*) >> * at this, second->primary==0 therefore try to >> free the primary-bandwidth_mutex.(already freed) > >The formatting for this is all confused, can you fix it up? Sorry to confuse you, Let me change as below. cpu 0 cpu 1 (*Insert USB Storage) usb_create_shared_hcd() kmalloc(primary_hcd) kmalloc(primary_hcd->bandwidth_mutex) ->(primary_hcd->kref==1) usb_get_hcd() ->(primary_hcd->kref==2) usb_create_shared_hcd() kmalloc(hcd->shared_hcd) ->hcd->shared_hcd->bandwidth_mutex=primary->bandwidth_mutex ->primary_hcd->primary_hcd = primary_hcd ->hcd->shared_hcd->primary_hcd = primary_hcd ->(hcd->shared_hcd->kref==1) usb_get_hcd() ->(hcd->shared_hcd->kref==2) usb_get_hcd() ->(hcd->shared_hcd->kref==3) --- (*remove USB Storage) usb_release_dev() ->(hcd->shared_hcd-kref==2) usb_release_dev() ->(hcd->shared_hcd-kref==1) usb_release_dev() -> (primary_hcd-kref==1) usb_release_dev() -> (primary_hcd-kref==0) hcd_release() -> kfree(primary_hcd->bandwidth_mutex) -> hcd->shared_hcd->primary_hcd = NULL -> kfree(primary_hcd) usb_release_dev() -> (hcd->shared_hcd-kref==0) hcd_release() -> usb_hcd_is_primary_hcd(hcd->shared_hcd) -> hcd->shared_hcd->primary_hcd already NULL, return 1 -> try to double kfree(primary_hcd->bandwidth_mutex) Since hcd->shared_hcd->priary_hcd was Null it didn't reach (hcd == hcd->primary_hcd) in usb_hcd_is_primary_hcd(). It returned 1 at since condition !hcd->primary_hcd is met. > >> >> To fix this problem kfree(hcd->bandwidth_mutex); >> should be executed at only (hcd->primary_hcd==hcd). >> >> Signed-off-by: Chunggeol Kim > >We need an email address at the end of this line, look at how the >commits in the kernel git history look like for examples. sorry, maybe deleted during transfer the patch. Signed-off-by: Chunggeol Kim> >> --- >> drivers/usb/core/hcd.c |2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c >> index 34b837a..60077f3 100644 >> --- a/drivers/usb/core/hcd.c >> +++ b/drivers/usb/core/hcd.c >> @@ -2608,7
Re: Re: [PATCH] usb: core: fix a double free in the usb driver
>On Fri, May 27, 2016 at 01:38:17AM +, Chung-Geol Kim wrote: >> There is a double free problem in the usb driver. > >Which driver? When I using the USB OTG Storage, this issue happened. When remove the OTG Storage, it reproduced sometimes. > >> This is caused by delayed deregister for scsi device. >> <*> at Insert USB Storage >> - USB bus #1 register >> usb_create_hcd (primary-kref==1) >> * primary-bandwidth_mutex(alloc)) >> usb_get_hcd(primary-kref==2) >> - USB bus #2 register >> usb_create_hcd (second-kref==1) >> * second-bandwidth_mutex==primary-bandwidth_mutex >> usb_get_hcd(second-kref==2) >> - scsi_device_get >> usb_get_hcd(second-kref==3) >> >> <*> at remove USB Storage (Normal) >> - scsi_device_put >> usb_put_hcd(second-kref==2) >> - USB bus #2 deregister >> usb_release_dev(second-kref==1) >> usb_release_dev(second-kref==0) -> hcd_release() >> - USB bus #1 deregister >> usb_release_dev(primary-kref==1) >> usb_release_dev(primary-kref==0) -> hcd_release() >> *(primary-bandwidth_mutex free) >> >> at remove USB Storage >> - USB bus #2 deregister >> usb_release_dev(second-kref==2) >> usb_release_dev(second-kref==1) >> - USB bus #1 deregister >> usb_release_dev(primary-kref==1) >> usb_release_dev(primary-kref==0) -> hcd_release() >> *(primary-bandwidth_mutex free) >> - scsi_device_put >> usb_put_hcd(second-kref==0) -> hcd_release(*) >> * at this, second->primary==0 therefore try to >> free the primary-bandwidth_mutex.(already freed) > >The formatting for this is all confused, can you fix it up? Sorry to confuse you, Let me change as below. cpu 0 cpu 1 (*Insert USB Storage) usb_create_shared_hcd() kmalloc(primary_hcd) kmalloc(primary_hcd->bandwidth_mutex) ->(primary_hcd->kref==1) usb_get_hcd() ->(primary_hcd->kref==2) usb_create_shared_hcd() kmalloc(hcd->shared_hcd) ->hcd->shared_hcd->bandwidth_mutex=primary->bandwidth_mutex ->primary_hcd->primary_hcd = primary_hcd ->hcd->shared_hcd->primary_hcd = primary_hcd ->(hcd->shared_hcd->kref==1) usb_get_hcd() ->(hcd->shared_hcd->kref==2) usb_get_hcd() ->(hcd->shared_hcd->kref==3) --- (*remove USB Storage) usb_release_dev() ->(hcd->shared_hcd-kref==2) usb_release_dev() ->(hcd->shared_hcd-kref==1) usb_release_dev() -> (primary_hcd-kref==1) usb_release_dev() -> (primary_hcd-kref==0) hcd_release() -> kfree(primary_hcd->bandwidth_mutex) -> hcd->shared_hcd->primary_hcd = NULL -> kfree(primary_hcd) usb_release_dev() -> (hcd->shared_hcd-kref==0) hcd_release() -> usb_hcd_is_primary_hcd(hcd->shared_hcd) -> hcd->shared_hcd->primary_hcd already NULL, return 1 -> try to double kfree(primary_hcd->bandwidth_mutex) Since hcd->shared_hcd->priary_hcd was Null it didn't reach (hcd == hcd->primary_hcd) in usb_hcd_is_primary_hcd(). It returned 1 at since condition !hcd->primary_hcd is met. > >> >> To fix this problem kfree(hcd->bandwidth_mutex); >> should be executed at only (hcd->primary_hcd==hcd). >> >> Signed-off-by: Chunggeol Kim > >We need an email address at the end of this line, look at how the >commits in the kernel git history look like for examples. sorry, maybe deleted during transfer the patch. Signed-off-by: Chunggeol Kim > >> --- >> drivers/usb/core/hcd.c |2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c >> index 34b837a..60077f3 100644 >> --- a/drivers/usb/core/hcd.c >> +++ b/drivers/usb/core/hcd.c >> @@ -2608,7 +2608,7 @@ static void
Re: [PATCH] usb: core: fix a double free in the usb driver
On Fri, May 27, 2016 at 01:38:17AM +, Chung-Geol Kim wrote: > There is a double free problem in the usb driver. Which driver? > This is caused by delayed deregister for scsi device. > <*> at Insert USB Storage > - USB bus #1 register > usb_create_hcd (primary-kref==1) > * primary-bandwidth_mutex(alloc)) > usb_get_hcd(primary-kref==2) > - USB bus #2 register > usb_create_hcd (second-kref==1) > * second-bandwidth_mutex==primary-bandwidth_mutex > usb_get_hcd(second-kref==2) > - scsi_device_get > usb_get_hcd(second-kref==3) > > <*> at remove USB Storage (Normal) > - scsi_device_put > usb_put_hcd(second-kref==2) > - USB bus #2 deregister > usb_release_dev(second-kref==1) > usb_release_dev(second-kref==0) -> hcd_release() > - USB bus #1 deregister > usb_release_dev(primary-kref==1) > usb_release_dev(primary-kref==0) -> hcd_release() > *(primary-bandwidth_mutex free) > > at remove USB Storage > - USB bus #2 deregister > usb_release_dev(second-kref==2) > usb_release_dev(second-kref==1) > - USB bus #1 deregister > usb_release_dev(primary-kref==1) > usb_release_dev(primary-kref==0) -> hcd_release() > *(primary-bandwidth_mutex free) > - scsi_device_put > usb_put_hcd(second-kref==0) -> hcd_release(*) > * at this, second->primary==0 therefore try to > free the primary-bandwidth_mutex.(already freed) The formatting for this is all confused, can you fix it up? > > To fix this problem kfree(hcd->bandwidth_mutex); > should be executed at only (hcd->primary_hcd==hcd). > > Signed-off-by: Chunggeol Kim We need an email address at the end of this line, look at how the commits in the kernel git history look like for examples. > --- > drivers/usb/core/hcd.c |2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c > index 34b837a..60077f3 100644 > --- a/drivers/usb/core/hcd.c > +++ b/drivers/usb/core/hcd.c > @@ -2608,7 +2608,7 @@ static void hcd_release(struct kref *kref) > struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); > > mutex_lock(_port_peer_mutex); > - if (usb_hcd_is_primary_hcd(hcd)) { > + if (hcd == hcd->primary_hcd) { That doesn't make sense, usb_hcd_is_primary_hcd() is the same as this check, what are you changing here? > kfree(hcd->address0_mutex); > kfree(hcd->bandwidth_mutex); > } Your patch itself is also corrupted, and can't be applied, can you also resolve this and resend? thanks, greg k-h
Re: [PATCH] usb: core: fix a double free in the usb driver
On Fri, May 27, 2016 at 01:38:17AM +, Chung-Geol Kim wrote: > There is a double free problem in the usb driver. Which driver? > This is caused by delayed deregister for scsi device. > <*> at Insert USB Storage > - USB bus #1 register > usb_create_hcd (primary-kref==1) > * primary-bandwidth_mutex(alloc)) > usb_get_hcd(primary-kref==2) > - USB bus #2 register > usb_create_hcd (second-kref==1) > * second-bandwidth_mutex==primary-bandwidth_mutex > usb_get_hcd(second-kref==2) > - scsi_device_get > usb_get_hcd(second-kref==3) > > <*> at remove USB Storage (Normal) > - scsi_device_put > usb_put_hcd(second-kref==2) > - USB bus #2 deregister > usb_release_dev(second-kref==1) > usb_release_dev(second-kref==0) -> hcd_release() > - USB bus #1 deregister > usb_release_dev(primary-kref==1) > usb_release_dev(primary-kref==0) -> hcd_release() > *(primary-bandwidth_mutex free) > > at remove USB Storage > - USB bus #2 deregister > usb_release_dev(second-kref==2) > usb_release_dev(second-kref==1) > - USB bus #1 deregister > usb_release_dev(primary-kref==1) > usb_release_dev(primary-kref==0) -> hcd_release() > *(primary-bandwidth_mutex free) > - scsi_device_put > usb_put_hcd(second-kref==0) -> hcd_release(*) > * at this, second->primary==0 therefore try to > free the primary-bandwidth_mutex.(already freed) The formatting for this is all confused, can you fix it up? > > To fix this problem kfree(hcd->bandwidth_mutex); > should be executed at only (hcd->primary_hcd==hcd). > > Signed-off-by: Chunggeol Kim We need an email address at the end of this line, look at how the commits in the kernel git history look like for examples. > --- > drivers/usb/core/hcd.c |2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c > index 34b837a..60077f3 100644 > --- a/drivers/usb/core/hcd.c > +++ b/drivers/usb/core/hcd.c > @@ -2608,7 +2608,7 @@ static void hcd_release(struct kref *kref) > struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); > > mutex_lock(_port_peer_mutex); > - if (usb_hcd_is_primary_hcd(hcd)) { > + if (hcd == hcd->primary_hcd) { That doesn't make sense, usb_hcd_is_primary_hcd() is the same as this check, what are you changing here? > kfree(hcd->address0_mutex); > kfree(hcd->bandwidth_mutex); > } Your patch itself is also corrupted, and can't be applied, can you also resolve this and resend? thanks, greg k-h
[PATCH] usb: core: fix a double free in the usb driver
There is a double free problem in the usb driver. This is caused by delayed deregister for scsi device. <*> at Insert USB Storage - USB bus #1 register usb_create_hcd (primary-kref==1) * primary-bandwidth_mutex(alloc)) usb_get_hcd(primary-kref==2) - USB bus #2 register usb_create_hcd (second-kref==1) * second-bandwidth_mutex==primary-bandwidth_mutex usb_get_hcd(second-kref==2) - scsi_device_get usb_get_hcd(second-kref==3) <*> at remove USB Storage (Normal) - scsi_device_put usb_put_hcd(second-kref==2) - USB bus #2 deregister usb_release_dev(second-kref==1) usb_release_dev(second-kref==0) -> hcd_release() - USB bus #1 deregister usb_release_dev(primary-kref==1) usb_release_dev(primary-kref==0) -> hcd_release() *(primary-bandwidth_mutex free) at remove USB Storage - USB bus #2 deregister usb_release_dev(second-kref==2) usb_release_dev(second-kref==1) - USB bus #1 deregister usb_release_dev(primary-kref==1) usb_release_dev(primary-kref==0) -> hcd_release() *(primary-bandwidth_mutex free) - scsi_device_put usb_put_hcd(second-kref==0) -> hcd_release(*) * at this, second->primary==0 therefore try to free the primary-bandwidth_mutex.(already freed) To fix this problem kfree(hcd->bandwidth_mutex); should be executed at only (hcd->primary_hcd==hcd). Signed-off-by: Chunggeol Kim --- drivers/usb/core/hcd.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 34b837a..60077f3 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2608,7 +2608,7 @@ static void hcd_release(struct kref *kref) struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); mutex_lock(_port_peer_mutex); - if (usb_hcd_is_primary_hcd(hcd)) { + if (hcd == hcd->primary_hcd) { kfree(hcd->address0_mutex); kfree(hcd->bandwidth_mutex); } -- 1.7.9.5
[PATCH] usb: core: fix a double free in the usb driver
There is a double free problem in the usb driver. This is caused by delayed deregister for scsi device. <*> at Insert USB Storage - USB bus #1 register usb_create_hcd (primary-kref==1) * primary-bandwidth_mutex(alloc)) usb_get_hcd(primary-kref==2) - USB bus #2 register usb_create_hcd (second-kref==1) * second-bandwidth_mutex==primary-bandwidth_mutex usb_get_hcd(second-kref==2) - scsi_device_get usb_get_hcd(second-kref==3) <*> at remove USB Storage (Normal) - scsi_device_put usb_put_hcd(second-kref==2) - USB bus #2 deregister usb_release_dev(second-kref==1) usb_release_dev(second-kref==0) -> hcd_release() - USB bus #1 deregister usb_release_dev(primary-kref==1) usb_release_dev(primary-kref==0) -> hcd_release() *(primary-bandwidth_mutex free) at remove USB Storage - USB bus #2 deregister usb_release_dev(second-kref==2) usb_release_dev(second-kref==1) - USB bus #1 deregister usb_release_dev(primary-kref==1) usb_release_dev(primary-kref==0) -> hcd_release() *(primary-bandwidth_mutex free) - scsi_device_put usb_put_hcd(second-kref==0) -> hcd_release(*) * at this, second->primary==0 therefore try to free the primary-bandwidth_mutex.(already freed) To fix this problem kfree(hcd->bandwidth_mutex); should be executed at only (hcd->primary_hcd==hcd). Signed-off-by: Chunggeol Kim --- drivers/usb/core/hcd.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 34b837a..60077f3 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2608,7 +2608,7 @@ static void hcd_release(struct kref *kref) struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref); mutex_lock(_port_peer_mutex); - if (usb_hcd_is_primary_hcd(hcd)) { + if (hcd == hcd->primary_hcd) { kfree(hcd->address0_mutex); kfree(hcd->bandwidth_mutex); } -- 1.7.9.5