All of lore.kernel.org
 help / color / mirror / Atom feed
* [v1,1/1] drivers/usb/storage: NULL pointer dereference [null-pointer-deref] (CWE 476) problem
@ 2018-02-27 14:59 Joe Moriarty
  0 siblings, 0 replies; 10+ messages in thread
From: Joe Moriarty @ 2018-02-27 14:59 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-usb

On 2/26/2018 2:35 PM, Greg KH wrote:
> On Mon, Feb 26, 2018 at 02:08:08PM -0500, Joe Moriarty wrote:
>> On 2/26/2018 1:12 PM, Greg KH wrote:
>>> On Mon, Feb 26, 2018 at 12:10:02PM -0500, Joe Moriarty wrote:
>>>> The Parfait (version 2.1.0) static code analysis tool found the
>>>> following NULL pointer dereference problem.
>>>
>>> What is the "CWE 476" thing in the subject line for?
>>>
>> [JDM]
>> (CWE 476) stands for Common Weakness Enumeration.
>> https://secur1ty.com/cwe/CWE-476/
>>
>> It is the type of security flaw related to a NULL pointer dereference
> 
> Ok, why put that in the subject line and not just the body of the
> changelog if you really want to call something out like this?
> 
>>>> dev_to_shost() in include/scsi/scsi_host.h has the ability to return
>>>> NULL if the scsi host device does not have the Scsi_host->parent
>>>> field set.  With the possibilty of a NULL pointer being set for
>>>> the Scsi_Host->parent field, calls to host_to_us() have to make
>>>> sure the return pointer is not null.  Changes were made to check
>>>> for a return value of NULL on calls to host_to_us().
>>>>
>>>> Signed-off-by: Joe Moriarty <joe.moriarty@oracle.com>
>>>> Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
>>>> Acked-by: Hakon Bugge <hakon.bugge@oracle.com>
>>>> ---
>>>>    drivers/usb/storage/scsiglue.c | 53 ++++++++++++++++++++++++++++++++++++------
>>>>    1 file changed, 46 insertions(+), 7 deletions(-)
>>>>
>>>> diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
>>>> index c267f2812a04..94af609d49bf 100644
>>>> --- a/drivers/usb/storage/scsiglue.c
>>>> +++ b/drivers/usb/storage/scsiglue.c
>>>> @@ -66,6 +66,9 @@ static int slave_alloc (struct scsi_device *sdev)
>>>>    {
>>>>    	struct us_data *us = host_to_us(sdev->host);
>>>> +	if (!us)
>>>> +		pr_warn("Error in %s: us = NULL\n", __func__);
>>>
>>> It is a driver, you should never use pr_* calls, but rather dev_* calls.
>>>
>>> Also, you don't exit, are you sure the code keeps working after this
>>> happens?
>>>
>>> And what is a user supposed to do with this warning message?
>>
>> [JDM]
> 
> ???  You need a better email client, inline comments are the norm.
> 
>> - The messages are targeted for a developer and not the end user. I can
>> change it to dev_ calls.
> 
> But an end user sees "KERN_WARNING" messages, right?  If this is a
> debugging-only thing, then make it as such, and properly recover from it
> as it could be hit during normal operation.
> 
>>>> +
>>>>    	/*
>>>>    	 * Set the INQUIRY transfer length to 36.  We don't use any of
>>>>    	 * the extra data and many devices choke if asked for more or
>>>> @@ -102,6 +105,11 @@ static int slave_configure(struct scsi_device *sdev)
>>>>    {
>>>>    	struct us_data *us = host_to_us(sdev->host);
>>>> +	if (!us) {
>>>> +		pr_warn("Error in %s: us = NULL\n", __func__);
>>>> +		return 0;
>>>
>>> Why are you returning a success?
>> [JDM]
>> - Yes, I need to return -ENXIO for the slave_alloc routine.
>>
>>>
>>>> +	}
>>>> +
>>>>    	/*
>>>>    	 * Many devices have trouble transferring more than 32KB at a time,
>>>>    	 * while others have trouble with more than 64K. At this time we
>>>> @@ -331,6 +339,11 @@ static int target_alloc(struct scsi_target *starget)
>>>>    {
>>>>    	struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
>>>
>>> Can host_to_us() handle NULL?
>>>
>>> Nope, just looked at it, this will never cause the return value to be
>>> NULL, your checker needs some more work :(
>> [JDM]
>> This what the static code checker is catching.  host_to_us will return NULL
>> if the following occurs.
>>
>> 'dev_to_shost()' in include/scsi/scsi_host.h line 757.
>>
>> This is done everytime a slave device is created at the following code
>> 'target_alloc()' in drivers/usb/storage/scsiglue.c  linue 340.
>>
>> This means that any call to host_to_us in the scsiglue module will have the
>> possibility of setting the return value of NULL.  In fact, I would need to
>> split out the following embedded call in 'target_alloc()' to avoid a
>> possible NULL pointer dereference.
>>
>> struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
> 
> Exactly, your change did nothing, and us is probably not NULL here.
> 
>> The question becomes, Can a slave device ever have it's parent field set to
>> NULL (ie: dev->parent).
> 
> I don't think it can, do you see how?
> 
Ok,  I believe we went off the original problem this patch solves. 
Since you and I both agree that a slave device can never have it's 
parent field set to NULL (ie:  dev->parent) then this patch boils down 
to the following one change.

include/scsi/scsi_host.h
static inline struct Scsi_Host *dev_to_shost(struct device *dev)
{
	while (!scsi_is_host_device(dev)) {
		if (!dev->parent)
-			return NULL;
+			BUG();
		dev = dev->parent;
	}
	return container_of(dev, struct Scsi_Host, shost_gendev);
}

If you agree, then I can revert all the other changes and resubmit a 
version 2 of this patch with this change.  If you do not agree, then I 
will mark it as a false positive and move on, or we can continue to work 
on the initial patch to get it to your satisfaction.  Let me know how 
you would like to proceed here.

Joe

>> Can it?  If not, this becomes a false positive that needs to be
>> ignored and the entire patch is not needed.  I would tend to believe a
>> slave device will always be enumerated by the parent (host) device.
>> Correct?
> 
> How else can it be created?
> 
>>>> +	if (!us) {
>>>> +		pr_warn("Error in %s: us = NULL\n", __func__);
>>>> +		return 0;
>>>> +	}
>>>> +
>>>>    	/*
>>>>    	 * Some USB drives don't support REPORT LUNS, even though they
>>>>    	 * report a SCSI revision level above 2.  Tell the SCSI layer
>>>> @@ -361,6 +374,11 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
>>>>    {
>>>>    	struct us_data *us = host_to_us(srb->device->host);
>>>> +	if (!us) {
>>>
>>> How is that possible?  This doesn't have anything to do with your
>>> subject line, right?
>>>
>>>> +		pr_warn("Error in %s: us = NULL\n", __func__);
>>>> +		return 0;
>>>
>>> success?
>>
>> [JDM] I need to return -ENXIO here.
> 
> -ENODEV?
> 
> But again, how can this happen?
> 
> thanks,
> 
> greg k-h
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
---
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [v1,1/1] drivers/usb/storage: NULL pointer dereference [null-pointer-deref] (CWE 476) problem
@ 2018-02-27 19:49 Joe Moriarty
  0 siblings, 0 replies; 10+ messages in thread
From: Joe Moriarty @ 2018-02-27 19:49 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-usb

On 2/27/2018 2:05 PM, Greg KH wrote:
> On Tue, Feb 27, 2018 at 01:22:24PM -0500, Joe Moriarty wrote:
>> On 2/27/2018 1:14 PM, Greg KH wrote:
>>> On Tue, Feb 27, 2018 at 09:59:40AM -0500, Joe Moriarty wrote:
>>>> On 2/26/2018 2:35 PM, Greg KH wrote:
>>>>> On Mon, Feb 26, 2018 at 02:08:08PM -0500, Joe Moriarty wrote:
>>>>>> On 2/26/2018 1:12 PM, Greg KH wrote:
>>>>>>> On Mon, Feb 26, 2018 at 12:10:02PM -0500, Joe Moriarty wrote:
>>>>>>>> The Parfait (version 2.1.0) static code analysis tool found the
>>>>>>>> following NULL pointer dereference problem.
>>>>>>>
>>>>>>> What is the "CWE 476" thing in the subject line for?
>>>>>>>
>>>>>> [JDM]
>>>>>> (CWE 476) stands for Common Weakness Enumeration.
>>>>>> https://secur1ty.com/cwe/CWE-476/
>>>>>>
>>>>>> It is the type of security flaw related to a NULL pointer dereference
>>>>>
>>>>> Ok, why put that in the subject line and not just the body of the
>>>>> changelog if you really want to call something out like this?
>>>>>
>>>>>>>> dev_to_shost() in include/scsi/scsi_host.h has the ability to return
>>>>>>>> NULL if the scsi host device does not have the Scsi_host->parent
>>>>>>>> field set.  With the possibilty of a NULL pointer being set for
>>>>>>>> the Scsi_Host->parent field, calls to host_to_us() have to make
>>>>>>>> sure the return pointer is not null.  Changes were made to check
>>>>>>>> for a return value of NULL on calls to host_to_us().
>>>>>>>>
>>>>>>>> Signed-off-by: Joe Moriarty <joe.moriarty@oracle.com>
>>>>>>>> Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
>>>>>>>> Acked-by: Hakon Bugge <hakon.bugge@oracle.com>
>>>>>>>> ---
>>>>>>>>      drivers/usb/storage/scsiglue.c | 53 ++++++++++++++++++++++++++++++++++++------
>>>>>>>>      1 file changed, 46 insertions(+), 7 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
>>>>>>>> index c267f2812a04..94af609d49bf 100644
>>>>>>>> --- a/drivers/usb/storage/scsiglue.c
>>>>>>>> +++ b/drivers/usb/storage/scsiglue.c
>>>>>>>> @@ -66,6 +66,9 @@ static int slave_alloc (struct scsi_device *sdev)
>>>>>>>>      {
>>>>>>>>      	struct us_data *us = host_to_us(sdev->host);
>>>>>>>> +	if (!us)
>>>>>>>> +		pr_warn("Error in %s: us = NULL\n", __func__);
>>>>>>>
>>>>>>> It is a driver, you should never use pr_* calls, but rather dev_* calls.
>>>>>>>
>>>>>>> Also, you don't exit, are you sure the code keeps working after this
>>>>>>> happens?
>>>>>>>
>>>>>>> And what is a user supposed to do with this warning message?
>>>>>>
>>>>>> [JDM]
>>>>>
>>>>> ???  You need a better email client, inline comments are the norm.
>>>>>
>>>>>> - The messages are targeted for a developer and not the end user. I can
>>>>>> change it to dev_ calls.
>>>>>
>>>>> But an end user sees "KERN_WARNING" messages, right?  If this is a
>>>>> debugging-only thing, then make it as such, and properly recover from it
>>>>> as it could be hit during normal operation.
>>>>>
>>>>>>>> +
>>>>>>>>      	/*
>>>>>>>>      	 * Set the INQUIRY transfer length to 36.  We don't use any of
>>>>>>>>      	 * the extra data and many devices choke if asked for more or
>>>>>>>> @@ -102,6 +105,11 @@ static int slave_configure(struct scsi_device *sdev)
>>>>>>>>      {
>>>>>>>>      	struct us_data *us = host_to_us(sdev->host);
>>>>>>>> +	if (!us) {
>>>>>>>> +		pr_warn("Error in %s: us = NULL\n", __func__);
>>>>>>>> +		return 0;
>>>>>>>
>>>>>>> Why are you returning a success?
>>>>>> [JDM]
>>>>>> - Yes, I need to return -ENXIO for the slave_alloc routine.
>>>>>>
>>>>>>>
>>>>>>>> +	}
>>>>>>>> +
>>>>>>>>      	/*
>>>>>>>>      	 * Many devices have trouble transferring more than 32KB at a time,
>>>>>>>>      	 * while others have trouble with more than 64K. At this time we
>>>>>>>> @@ -331,6 +339,11 @@ static int target_alloc(struct scsi_target *starget)
>>>>>>>>      {
>>>>>>>>      	struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
>>>>>>>
>>>>>>> Can host_to_us() handle NULL?
>>>>>>>
>>>>>>> Nope, just looked at it, this will never cause the return value to be
>>>>>>> NULL, your checker needs some more work :(
>>>>>> [JDM]
>>>>>> This what the static code checker is catching.  host_to_us will return NULL
>>>>>> if the following occurs.
>>>>>>
>>>>>> 'dev_to_shost()' in include/scsi/scsi_host.h line 757.
>>>>>>
>>>>>> This is done everytime a slave device is created at the following code
>>>>>> 'target_alloc()' in drivers/usb/storage/scsiglue.c  linue 340.
>>>>>>
>>>>>> This means that any call to host_to_us in the scsiglue module will have the
>>>>>> possibility of setting the return value of NULL.  In fact, I would need to
>>>>>> split out the following embedded call in 'target_alloc()' to avoid a
>>>>>> possible NULL pointer dereference.
>>>>>>
>>>>>> struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
>>>>>
>>>>> Exactly, your change did nothing, and us is probably not NULL here.
>>>>>
>>>>>> The question becomes, Can a slave device ever have it's parent field set to
>>>>>> NULL (ie: dev->parent).
>>>>>
>>>>> I don't think it can, do you see how?
>>>>>
>>>> Ok,  I believe we went off the original problem this patch solves. Since you
>>>> and I both agree that a slave device can never have it's parent field set to
>>>> NULL (ie:  dev->parent) then this patch boils down to the following one
>>>> change.
>>>>
>>>> include/scsi/scsi_host.h
>>>> static inline struct Scsi_Host *dev_to_shost(struct device *dev)
>>>> {
>>>> 	while (!scsi_is_host_device(dev)) {
>>>> 		if (!dev->parent)
>>>> -			return NULL;
>>>> +			BUG();
>>>
>>> No, never crash the kernel.
>> There is Bug() throughout the kernel.  So that is invalid.
> 
> Nope, we are trying to get rid of them.  If you see new ones being
> added, please point it out.
> 
>> Kernel Developers will put in Bug() statements anywhere the code is
>> not suppose to go.  It is easier to debug and then trying to backtrace
>> from a side effect issue.
> 
> Not at all, it causes the machine to crash and make it harder to debug.
> Or it causes a reboot.  Even WARN_ON() should not be used for debugging
> as we are seeing tools hit those and reboot and complain (see the
> syzkaller threads about this.)
> 
> If you want a debugging message, make it a debugging message using
> dev_dbg().  That's all that is needed.
> 
>>> Why not ask the scsi developers about this?  They put that line there
>>> for a good reason, right?
>> I submitted the original patch here because the original patch was in the
>> drivers/usb/storage directory of which you are the maintainer.
> 
> But this is a scsi core api call, I know nothing about that :)
> 
>>> And if NULL is valid to return, then your patch still does not fix the
>>> issue at all, which was my main point.
>> Yes it does.  A NULL return from dev_to_shost will kernel panic the machine
>> in multiple places in the SCSI kernel modules.  Swapping out the NULL with a
>> BUG() will do that.
> 
> Neither is good to have, they should all be fixed.
> 
> thanks,
> 
> greg k-h
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
Ok, Then I will need to stay in the linux-usb group to fix the NULL 
pointer dereference problem.  The fix will need to be applied to 
drivers/usb/storage/scsiglue.c and *NOT* include/scsi/scsi_host.h with 
the call to BUG().  You can't get rid of me that easily :-).  I'll send 
a new version out in the next few days for review.

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [v1,1/1] drivers/usb/storage: NULL pointer dereference [null-pointer-deref] (CWE 476) problem
@ 2018-02-27 19:05 Greg Kroah-Hartman
  0 siblings, 0 replies; 10+ messages in thread
From: Greg Kroah-Hartman @ 2018-02-27 19:05 UTC (permalink / raw)
  To: Joe Moriarty; +Cc: linux-usb

On Tue, Feb 27, 2018 at 01:22:24PM -0500, Joe Moriarty wrote:
> On 2/27/2018 1:14 PM, Greg KH wrote:
> > On Tue, Feb 27, 2018 at 09:59:40AM -0500, Joe Moriarty wrote:
> > > On 2/26/2018 2:35 PM, Greg KH wrote:
> > > > On Mon, Feb 26, 2018 at 02:08:08PM -0500, Joe Moriarty wrote:
> > > > > On 2/26/2018 1:12 PM, Greg KH wrote:
> > > > > > On Mon, Feb 26, 2018 at 12:10:02PM -0500, Joe Moriarty wrote:
> > > > > > > The Parfait (version 2.1.0) static code analysis tool found the
> > > > > > > following NULL pointer dereference problem.
> > > > > > 
> > > > > > What is the "CWE 476" thing in the subject line for?
> > > > > > 
> > > > > [JDM]
> > > > > (CWE 476) stands for Common Weakness Enumeration.
> > > > > https://secur1ty.com/cwe/CWE-476/
> > > > > 
> > > > > It is the type of security flaw related to a NULL pointer dereference
> > > > 
> > > > Ok, why put that in the subject line and not just the body of the
> > > > changelog if you really want to call something out like this?
> > > > 
> > > > > > > dev_to_shost() in include/scsi/scsi_host.h has the ability to return
> > > > > > > NULL if the scsi host device does not have the Scsi_host->parent
> > > > > > > field set.  With the possibilty of a NULL pointer being set for
> > > > > > > the Scsi_Host->parent field, calls to host_to_us() have to make
> > > > > > > sure the return pointer is not null.  Changes were made to check
> > > > > > > for a return value of NULL on calls to host_to_us().
> > > > > > > 
> > > > > > > Signed-off-by: Joe Moriarty <joe.moriarty@oracle.com>
> > > > > > > Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
> > > > > > > Acked-by: Hakon Bugge <hakon.bugge@oracle.com>
> > > > > > > ---
> > > > > > >     drivers/usb/storage/scsiglue.c | 53 ++++++++++++++++++++++++++++++++++++------
> > > > > > >     1 file changed, 46 insertions(+), 7 deletions(-)
> > > > > > > 
> > > > > > > diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
> > > > > > > index c267f2812a04..94af609d49bf 100644
> > > > > > > --- a/drivers/usb/storage/scsiglue.c
> > > > > > > +++ b/drivers/usb/storage/scsiglue.c
> > > > > > > @@ -66,6 +66,9 @@ static int slave_alloc (struct scsi_device *sdev)
> > > > > > >     {
> > > > > > >     	struct us_data *us = host_to_us(sdev->host);
> > > > > > > +	if (!us)
> > > > > > > +		pr_warn("Error in %s: us = NULL\n", __func__);
> > > > > > 
> > > > > > It is a driver, you should never use pr_* calls, but rather dev_* calls.
> > > > > > 
> > > > > > Also, you don't exit, are you sure the code keeps working after this
> > > > > > happens?
> > > > > > 
> > > > > > And what is a user supposed to do with this warning message?
> > > > > 
> > > > > [JDM]
> > > > 
> > > > ???  You need a better email client, inline comments are the norm.
> > > > 
> > > > > - The messages are targeted for a developer and not the end user. I can
> > > > > change it to dev_ calls.
> > > > 
> > > > But an end user sees "KERN_WARNING" messages, right?  If this is a
> > > > debugging-only thing, then make it as such, and properly recover from it
> > > > as it could be hit during normal operation.
> > > > 
> > > > > > > +
> > > > > > >     	/*
> > > > > > >     	 * Set the INQUIRY transfer length to 36.  We don't use any of
> > > > > > >     	 * the extra data and many devices choke if asked for more or
> > > > > > > @@ -102,6 +105,11 @@ static int slave_configure(struct scsi_device *sdev)
> > > > > > >     {
> > > > > > >     	struct us_data *us = host_to_us(sdev->host);
> > > > > > > +	if (!us) {
> > > > > > > +		pr_warn("Error in %s: us = NULL\n", __func__);
> > > > > > > +		return 0;
> > > > > > 
> > > > > > Why are you returning a success?
> > > > > [JDM]
> > > > > - Yes, I need to return -ENXIO for the slave_alloc routine.
> > > > > 
> > > > > > 
> > > > > > > +	}
> > > > > > > +
> > > > > > >     	/*
> > > > > > >     	 * Many devices have trouble transferring more than 32KB at a time,
> > > > > > >     	 * while others have trouble with more than 64K. At this time we
> > > > > > > @@ -331,6 +339,11 @@ static int target_alloc(struct scsi_target *starget)
> > > > > > >     {
> > > > > > >     	struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
> > > > > > 
> > > > > > Can host_to_us() handle NULL?
> > > > > > 
> > > > > > Nope, just looked at it, this will never cause the return value to be
> > > > > > NULL, your checker needs some more work :(
> > > > > [JDM]
> > > > > This what the static code checker is catching.  host_to_us will return NULL
> > > > > if the following occurs.
> > > > > 
> > > > > 'dev_to_shost()' in include/scsi/scsi_host.h line 757.
> > > > > 
> > > > > This is done everytime a slave device is created at the following code
> > > > > 'target_alloc()' in drivers/usb/storage/scsiglue.c  linue 340.
> > > > > 
> > > > > This means that any call to host_to_us in the scsiglue module will have the
> > > > > possibility of setting the return value of NULL.  In fact, I would need to
> > > > > split out the following embedded call in 'target_alloc()' to avoid a
> > > > > possible NULL pointer dereference.
> > > > > 
> > > > > struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
> > > > 
> > > > Exactly, your change did nothing, and us is probably not NULL here.
> > > > 
> > > > > The question becomes, Can a slave device ever have it's parent field set to
> > > > > NULL (ie: dev->parent).
> > > > 
> > > > I don't think it can, do you see how?
> > > > 
> > > Ok,  I believe we went off the original problem this patch solves. Since you
> > > and I both agree that a slave device can never have it's parent field set to
> > > NULL (ie:  dev->parent) then this patch boils down to the following one
> > > change.
> > > 
> > > include/scsi/scsi_host.h
> > > static inline struct Scsi_Host *dev_to_shost(struct device *dev)
> > > {
> > > 	while (!scsi_is_host_device(dev)) {
> > > 		if (!dev->parent)
> > > -			return NULL;
> > > +			BUG();
> > 
> > No, never crash the kernel.
> There is Bug() throughout the kernel.  So that is invalid.

Nope, we are trying to get rid of them.  If you see new ones being
added, please point it out.

> Kernel Developers will put in Bug() statements anywhere the code is
> not suppose to go.  It is easier to debug and then trying to backtrace
> from a side effect issue.

Not at all, it causes the machine to crash and make it harder to debug.
Or it causes a reboot.  Even WARN_ON() should not be used for debugging
as we are seeing tools hit those and reboot and complain (see the
syzkaller threads about this.)

If you want a debugging message, make it a debugging message using
dev_dbg().  That's all that is needed.

> > Why not ask the scsi developers about this?  They put that line there
> > for a good reason, right?
> I submitted the original patch here because the original patch was in the
> drivers/usb/storage directory of which you are the maintainer.

But this is a scsi core api call, I know nothing about that :)

> > And if NULL is valid to return, then your patch still does not fix the
> > issue at all, which was my main point.
> Yes it does.  A NULL return from dev_to_shost will kernel panic the machine
> in multiple places in the SCSI kernel modules.  Swapping out the NULL with a
> BUG() will do that.

Neither is good to have, they should all be fixed.

thanks,

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [v1,1/1] drivers/usb/storage: NULL pointer dereference [null-pointer-deref] (CWE 476) problem
@ 2018-02-27 18:22 Joe Moriarty
  0 siblings, 0 replies; 10+ messages in thread
From: Joe Moriarty @ 2018-02-27 18:22 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-usb

On 2/27/2018 1:14 PM, Greg KH wrote:
> On Tue, Feb 27, 2018 at 09:59:40AM -0500, Joe Moriarty wrote:
>> On 2/26/2018 2:35 PM, Greg KH wrote:
>>> On Mon, Feb 26, 2018 at 02:08:08PM -0500, Joe Moriarty wrote:
>>>> On 2/26/2018 1:12 PM, Greg KH wrote:
>>>>> On Mon, Feb 26, 2018 at 12:10:02PM -0500, Joe Moriarty wrote:
>>>>>> The Parfait (version 2.1.0) static code analysis tool found the
>>>>>> following NULL pointer dereference problem.
>>>>>
>>>>> What is the "CWE 476" thing in the subject line for?
>>>>>
>>>> [JDM]
>>>> (CWE 476) stands for Common Weakness Enumeration.
>>>> https://secur1ty.com/cwe/CWE-476/
>>>>
>>>> It is the type of security flaw related to a NULL pointer dereference
>>>
>>> Ok, why put that in the subject line and not just the body of the
>>> changelog if you really want to call something out like this?
>>>
>>>>>> dev_to_shost() in include/scsi/scsi_host.h has the ability to return
>>>>>> NULL if the scsi host device does not have the Scsi_host->parent
>>>>>> field set.  With the possibilty of a NULL pointer being set for
>>>>>> the Scsi_Host->parent field, calls to host_to_us() have to make
>>>>>> sure the return pointer is not null.  Changes were made to check
>>>>>> for a return value of NULL on calls to host_to_us().
>>>>>>
>>>>>> Signed-off-by: Joe Moriarty <joe.moriarty@oracle.com>
>>>>>> Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
>>>>>> Acked-by: Hakon Bugge <hakon.bugge@oracle.com>
>>>>>> ---
>>>>>>     drivers/usb/storage/scsiglue.c | 53 ++++++++++++++++++++++++++++++++++++------
>>>>>>     1 file changed, 46 insertions(+), 7 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
>>>>>> index c267f2812a04..94af609d49bf 100644
>>>>>> --- a/drivers/usb/storage/scsiglue.c
>>>>>> +++ b/drivers/usb/storage/scsiglue.c
>>>>>> @@ -66,6 +66,9 @@ static int slave_alloc (struct scsi_device *sdev)
>>>>>>     {
>>>>>>     	struct us_data *us = host_to_us(sdev->host);
>>>>>> +	if (!us)
>>>>>> +		pr_warn("Error in %s: us = NULL\n", __func__);
>>>>>
>>>>> It is a driver, you should never use pr_* calls, but rather dev_* calls.
>>>>>
>>>>> Also, you don't exit, are you sure the code keeps working after this
>>>>> happens?
>>>>>
>>>>> And what is a user supposed to do with this warning message?
>>>>
>>>> [JDM]
>>>
>>> ???  You need a better email client, inline comments are the norm.
>>>
>>>> - The messages are targeted for a developer and not the end user. I can
>>>> change it to dev_ calls.
>>>
>>> But an end user sees "KERN_WARNING" messages, right?  If this is a
>>> debugging-only thing, then make it as such, and properly recover from it
>>> as it could be hit during normal operation.
>>>
>>>>>> +
>>>>>>     	/*
>>>>>>     	 * Set the INQUIRY transfer length to 36.  We don't use any of
>>>>>>     	 * the extra data and many devices choke if asked for more or
>>>>>> @@ -102,6 +105,11 @@ static int slave_configure(struct scsi_device *sdev)
>>>>>>     {
>>>>>>     	struct us_data *us = host_to_us(sdev->host);
>>>>>> +	if (!us) {
>>>>>> +		pr_warn("Error in %s: us = NULL\n", __func__);
>>>>>> +		return 0;
>>>>>
>>>>> Why are you returning a success?
>>>> [JDM]
>>>> - Yes, I need to return -ENXIO for the slave_alloc routine.
>>>>
>>>>>
>>>>>> +	}
>>>>>> +
>>>>>>     	/*
>>>>>>     	 * Many devices have trouble transferring more than 32KB at a time,
>>>>>>     	 * while others have trouble with more than 64K. At this time we
>>>>>> @@ -331,6 +339,11 @@ static int target_alloc(struct scsi_target *starget)
>>>>>>     {
>>>>>>     	struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
>>>>>
>>>>> Can host_to_us() handle NULL?
>>>>>
>>>>> Nope, just looked at it, this will never cause the return value to be
>>>>> NULL, your checker needs some more work :(
>>>> [JDM]
>>>> This what the static code checker is catching.  host_to_us will return NULL
>>>> if the following occurs.
>>>>
>>>> 'dev_to_shost()' in include/scsi/scsi_host.h line 757.
>>>>
>>>> This is done everytime a slave device is created at the following code
>>>> 'target_alloc()' in drivers/usb/storage/scsiglue.c  linue 340.
>>>>
>>>> This means that any call to host_to_us in the scsiglue module will have the
>>>> possibility of setting the return value of NULL.  In fact, I would need to
>>>> split out the following embedded call in 'target_alloc()' to avoid a
>>>> possible NULL pointer dereference.
>>>>
>>>> struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
>>>
>>> Exactly, your change did nothing, and us is probably not NULL here.
>>>
>>>> The question becomes, Can a slave device ever have it's parent field set to
>>>> NULL (ie: dev->parent).
>>>
>>> I don't think it can, do you see how?
>>>
>> Ok,  I believe we went off the original problem this patch solves. Since you
>> and I both agree that a slave device can never have it's parent field set to
>> NULL (ie:  dev->parent) then this patch boils down to the following one
>> change.
>>
>> include/scsi/scsi_host.h
>> static inline struct Scsi_Host *dev_to_shost(struct device *dev)
>> {
>> 	while (!scsi_is_host_device(dev)) {
>> 		if (!dev->parent)
>> -			return NULL;
>> +			BUG();
> 
> No, never crash the kernel.
There is Bug() throughout the kernel.  So that is invalid.  Kernel 
Developers will put in Bug() statements anywhere the code is not suppose 
to go.  It is easier to debug and then trying to backtrace from a side 
effect issue.

> 
> Why not ask the scsi developers about this?  They put that line there
> for a good reason, right?
I submitted the original patch here because the original patch was in 
the drivers/usb/storage directory of which you are the maintainer.

> 
> And if NULL is valid to return, then your patch still does not fix the
> issue at all, which was my main point.
Yes it does.  A NULL return from dev_to_shost will kernel panic the 
machine in multiple places in the SCSI kernel modules.  Swapping out the 
NULL with a BUG() will do that.

> 
> So go ask the linux-scsi list about this either way.
Yep, I will do that.  Thanks for your review.

Joe

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [v1,1/1] drivers/usb/storage: NULL pointer dereference [null-pointer-deref] (CWE 476) problem
@ 2018-02-27 18:14 Greg Kroah-Hartman
  0 siblings, 0 replies; 10+ messages in thread
From: Greg Kroah-Hartman @ 2018-02-27 18:14 UTC (permalink / raw)
  To: Joe Moriarty; +Cc: linux-usb

On Tue, Feb 27, 2018 at 09:59:40AM -0500, Joe Moriarty wrote:
> On 2/26/2018 2:35 PM, Greg KH wrote:
> > On Mon, Feb 26, 2018 at 02:08:08PM -0500, Joe Moriarty wrote:
> > > On 2/26/2018 1:12 PM, Greg KH wrote:
> > > > On Mon, Feb 26, 2018 at 12:10:02PM -0500, Joe Moriarty wrote:
> > > > > The Parfait (version 2.1.0) static code analysis tool found the
> > > > > following NULL pointer dereference problem.
> > > > 
> > > > What is the "CWE 476" thing in the subject line for?
> > > > 
> > > [JDM]
> > > (CWE 476) stands for Common Weakness Enumeration.
> > > https://secur1ty.com/cwe/CWE-476/
> > > 
> > > It is the type of security flaw related to a NULL pointer dereference
> > 
> > Ok, why put that in the subject line and not just the body of the
> > changelog if you really want to call something out like this?
> > 
> > > > > dev_to_shost() in include/scsi/scsi_host.h has the ability to return
> > > > > NULL if the scsi host device does not have the Scsi_host->parent
> > > > > field set.  With the possibilty of a NULL pointer being set for
> > > > > the Scsi_Host->parent field, calls to host_to_us() have to make
> > > > > sure the return pointer is not null.  Changes were made to check
> > > > > for a return value of NULL on calls to host_to_us().
> > > > > 
> > > > > Signed-off-by: Joe Moriarty <joe.moriarty@oracle.com>
> > > > > Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
> > > > > Acked-by: Hakon Bugge <hakon.bugge@oracle.com>
> > > > > ---
> > > > >    drivers/usb/storage/scsiglue.c | 53 ++++++++++++++++++++++++++++++++++++------
> > > > >    1 file changed, 46 insertions(+), 7 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
> > > > > index c267f2812a04..94af609d49bf 100644
> > > > > --- a/drivers/usb/storage/scsiglue.c
> > > > > +++ b/drivers/usb/storage/scsiglue.c
> > > > > @@ -66,6 +66,9 @@ static int slave_alloc (struct scsi_device *sdev)
> > > > >    {
> > > > >    	struct us_data *us = host_to_us(sdev->host);
> > > > > +	if (!us)
> > > > > +		pr_warn("Error in %s: us = NULL\n", __func__);
> > > > 
> > > > It is a driver, you should never use pr_* calls, but rather dev_* calls.
> > > > 
> > > > Also, you don't exit, are you sure the code keeps working after this
> > > > happens?
> > > > 
> > > > And what is a user supposed to do with this warning message?
> > > 
> > > [JDM]
> > 
> > ???  You need a better email client, inline comments are the norm.
> > 
> > > - The messages are targeted for a developer and not the end user. I can
> > > change it to dev_ calls.
> > 
> > But an end user sees "KERN_WARNING" messages, right?  If this is a
> > debugging-only thing, then make it as such, and properly recover from it
> > as it could be hit during normal operation.
> > 
> > > > > +
> > > > >    	/*
> > > > >    	 * Set the INQUIRY transfer length to 36.  We don't use any of
> > > > >    	 * the extra data and many devices choke if asked for more or
> > > > > @@ -102,6 +105,11 @@ static int slave_configure(struct scsi_device *sdev)
> > > > >    {
> > > > >    	struct us_data *us = host_to_us(sdev->host);
> > > > > +	if (!us) {
> > > > > +		pr_warn("Error in %s: us = NULL\n", __func__);
> > > > > +		return 0;
> > > > 
> > > > Why are you returning a success?
> > > [JDM]
> > > - Yes, I need to return -ENXIO for the slave_alloc routine.
> > > 
> > > > 
> > > > > +	}
> > > > > +
> > > > >    	/*
> > > > >    	 * Many devices have trouble transferring more than 32KB at a time,
> > > > >    	 * while others have trouble with more than 64K. At this time we
> > > > > @@ -331,6 +339,11 @@ static int target_alloc(struct scsi_target *starget)
> > > > >    {
> > > > >    	struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
> > > > 
> > > > Can host_to_us() handle NULL?
> > > > 
> > > > Nope, just looked at it, this will never cause the return value to be
> > > > NULL, your checker needs some more work :(
> > > [JDM]
> > > This what the static code checker is catching.  host_to_us will return NULL
> > > if the following occurs.
> > > 
> > > 'dev_to_shost()' in include/scsi/scsi_host.h line 757.
> > > 
> > > This is done everytime a slave device is created at the following code
> > > 'target_alloc()' in drivers/usb/storage/scsiglue.c  linue 340.
> > > 
> > > This means that any call to host_to_us in the scsiglue module will have the
> > > possibility of setting the return value of NULL.  In fact, I would need to
> > > split out the following embedded call in 'target_alloc()' to avoid a
> > > possible NULL pointer dereference.
> > > 
> > > struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
> > 
> > Exactly, your change did nothing, and us is probably not NULL here.
> > 
> > > The question becomes, Can a slave device ever have it's parent field set to
> > > NULL (ie: dev->parent).
> > 
> > I don't think it can, do you see how?
> > 
> Ok,  I believe we went off the original problem this patch solves. Since you
> and I both agree that a slave device can never have it's parent field set to
> NULL (ie:  dev->parent) then this patch boils down to the following one
> change.
> 
> include/scsi/scsi_host.h
> static inline struct Scsi_Host *dev_to_shost(struct device *dev)
> {
> 	while (!scsi_is_host_device(dev)) {
> 		if (!dev->parent)
> -			return NULL;
> +			BUG();

No, never crash the kernel.

Why not ask the scsi developers about this?  They put that line there
for a good reason, right?

And if NULL is valid to return, then your patch still does not fix the
issue at all, which was my main point.

So go ask the linux-scsi list about this either way.

thanks,

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [v1,1/1] drivers/usb/storage: NULL pointer dereference [null-pointer-deref] (CWE 476) problem
@ 2018-02-27 16:56 Joe Moriarty
  0 siblings, 0 replies; 10+ messages in thread
From: Joe Moriarty @ 2018-02-27 16:56 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-usb

On 2/27/2018 9:59 AM, Joe Moriarty wrote:
> On 2/26/2018 2:35 PM, Greg KH wrote:
>> On Mon, Feb 26, 2018 at 02:08:08PM -0500, Joe Moriarty wrote:
>>> On 2/26/2018 1:12 PM, Greg KH wrote:
>>>> On Mon, Feb 26, 2018 at 12:10:02PM -0500, Joe Moriarty wrote:
>>>>> The Parfait (version 2.1.0) static code analysis tool found the
>>>>> following NULL pointer dereference problem.
>>>>
>>>> What is the "CWE 476" thing in the subject line for?
>>>>
>>> [JDM]
>>> (CWE 476) stands for Common Weakness Enumeration.
>>> https://secur1ty.com/cwe/CWE-476/
>>>
>>> It is the type of security flaw related to a NULL pointer dereference
>>
>> Ok, why put that in the subject line and not just the body of the
>> changelog if you really want to call something out like this?
>>
>>>>> dev_to_shost() in include/scsi/scsi_host.h has the ability to return
>>>>> NULL if the scsi host device does not have the Scsi_host->parent
>>>>> field set.  With the possibilty of a NULL pointer being set for
>>>>> the Scsi_Host->parent field, calls to host_to_us() have to make
>>>>> sure the return pointer is not null.  Changes were made to check
>>>>> for a return value of NULL on calls to host_to_us().
>>>>>
>>>>> Signed-off-by: Joe Moriarty <joe.moriarty@oracle.com>
>>>>> Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
>>>>> Acked-by: Hakon Bugge <hakon.bugge@oracle.com>
>>>>> ---
>>>>>    drivers/usb/storage/scsiglue.c | 53 
>>>>> ++++++++++++++++++++++++++++++++++++------
>>>>>    1 file changed, 46 insertions(+), 7 deletions(-)
>>>>>
>>>>> diff --git a/drivers/usb/storage/scsiglue.c 
>>>>> b/drivers/usb/storage/scsiglue.c
>>>>> index c267f2812a04..94af609d49bf 100644
>>>>> --- a/drivers/usb/storage/scsiglue.c
>>>>> +++ b/drivers/usb/storage/scsiglue.c
>>>>> @@ -66,6 +66,9 @@ static int slave_alloc (struct scsi_device *sdev)
>>>>>    {
>>>>>        struct us_data *us = host_to_us(sdev->host);
>>>>> +    if (!us)
>>>>> +        pr_warn("Error in %s: us = NULL\n", __func__);
>>>>
>>>> It is a driver, you should never use pr_* calls, but rather dev_* 
>>>> calls.
>>>>
>>>> Also, you don't exit, are you sure the code keeps working after this
>>>> happens?
>>>>
>>>> And what is a user supposed to do with this warning message?
>>>
>>> [JDM]
>>
>> ???  You need a better email client, inline comments are the norm.
>>
>>> - The messages are targeted for a developer and not the end user. I can
>>> change it to dev_ calls.
>>
>> But an end user sees "KERN_WARNING" messages, right?  If this is a
>> debugging-only thing, then make it as such, and properly recover from it
>> as it could be hit during normal operation.
>>
>>>>> +
>>>>>        /*
>>>>>         * Set the INQUIRY transfer length to 36.  We don't use any of
>>>>>         * the extra data and many devices choke if asked for more or
>>>>> @@ -102,6 +105,11 @@ static int slave_configure(struct scsi_device 
>>>>> *sdev)
>>>>>    {
>>>>>        struct us_data *us = host_to_us(sdev->host);
>>>>> +    if (!us) {
>>>>> +        pr_warn("Error in %s: us = NULL\n", __func__);
>>>>> +        return 0;
>>>>
>>>> Why are you returning a success?
>>> [JDM]
>>> - Yes, I need to return -ENXIO for the slave_alloc routine.
>>>
>>>>
>>>>> +    }
>>>>> +
>>>>>        /*
>>>>>         * Many devices have trouble transferring more than 32KB at 
>>>>> a time,
>>>>>         * while others have trouble with more than 64K. At this 
>>>>> time we
>>>>> @@ -331,6 +339,11 @@ static int target_alloc(struct scsi_target 
>>>>> *starget)
>>>>>    {
>>>>>        struct us_data *us = 
>>>>> host_to_us(dev_to_shost(starget->dev.parent));
>>>>
>>>> Can host_to_us() handle NULL?
>>>>
>>>> Nope, just looked at it, this will never cause the return value to be
>>>> NULL, your checker needs some more work :(
>>> [JDM]
>>> This what the static code checker is catching.  host_to_us will 
>>> return NULL
>>> if the following occurs.
>>>
>>> 'dev_to_shost()' in include/scsi/scsi_host.h line 757.
>>>
>>> This is done everytime a slave device is created at the following code
>>> 'target_alloc()' in drivers/usb/storage/scsiglue.c  linue 340.
>>>
>>> This means that any call to host_to_us in the scsiglue module will 
>>> have the
>>> possibility of setting the return value of NULL.  In fact, I would 
>>> need to
>>> split out the following embedded call in 'target_alloc()' to avoid a
>>> possible NULL pointer dereference.
>>>
>>> struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
>>
>> Exactly, your change did nothing, and us is probably not NULL here.
>>
>>> The question becomes, Can a slave device ever have it's parent field 
>>> set to
>>> NULL (ie: dev->parent).
>>
>> I don't think it can, do you see how?
>>
> Ok,  I believe we went off the original problem this patch solves. Since 
> you and I both agree that a slave device can never have it's parent 
> field set to NULL (ie:  dev->parent) then this patch boils down to the 
> following one change.
> 
> include/scsi/scsi_host.h
> static inline struct Scsi_Host *dev_to_shost(struct device *dev)
> {
>      while (!scsi_is_host_device(dev)) {
>          if (!dev->parent)
> -            return NULL;
> +            BUG();
>          dev = dev->parent;
>      }
>      return container_of(dev, struct Scsi_Host, shost_gendev);
> }
>
The above code change cleared up an additional 49 NULL pointer 
dereference instances found from the parfait static analysis.  I checked 
a few of them out and notices that none of them were checking for a NULL 
pointer being returned from dev_to_shost().  This looks very much like a 
code path that is never taken and is never believe to occur.  In fact, 
if the code path was taken then an immediate kernel panic would occur.

> If you agree, then I can revert all the other changes and resubmit a 
> version 2 of this patch with this change.  If you do not agree, then I 
> will mark it as a false positive and move on, or we can continue to work 
> on the initial patch to get it to your satisfaction.  Let me know how 
> you would like to proceed here.
> 
> Joe
> 
>>> Can it?  If not, this becomes a false positive that needs to be
>>> ignored and the entire patch is not needed.  I would tend to believe a
>>> slave device will always be enumerated by the parent (host) device.
>>> Correct?
>>
>> How else can it be created?
>>
>>>>> +    if (!us) {
>>>>> +        pr_warn("Error in %s: us = NULL\n", __func__);
>>>>> +        return 0;
>>>>> +    }
>>>>> +
>>>>>        /*
>>>>>         * Some USB drives don't support REPORT LUNS, even though they
>>>>>         * report a SCSI revision level above 2.  Tell the SCSI layer
>>>>> @@ -361,6 +374,11 @@ static int queuecommand_lck(struct scsi_cmnd 
>>>>> *srb,
>>>>>    {
>>>>>        struct us_data *us = host_to_us(srb->device->host);
>>>>> +    if (!us) {
>>>>
>>>> How is that possible?  This doesn't have anything to do with your
>>>> subject line, right?
>>>>
>>>>> +        pr_warn("Error in %s: us = NULL\n", __func__);
>>>>> +        return 0;
>>>>
>>>> success?
>>>
>>> [JDM] I need to return -ENXIO here.
>>
>> -ENODEV?
>>
>> But again, how can this happen?
>>
>> thanks,
>>
>> greg k-h
>> -- 
>> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 
> -- 
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
---
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [v1,1/1] drivers/usb/storage: NULL pointer dereference [null-pointer-deref] (CWE 476) problem
@ 2018-02-26 19:35 Greg Kroah-Hartman
  0 siblings, 0 replies; 10+ messages in thread
From: Greg Kroah-Hartman @ 2018-02-26 19:35 UTC (permalink / raw)
  To: Joe Moriarty; +Cc: linux-usb

On Mon, Feb 26, 2018 at 02:08:08PM -0500, Joe Moriarty wrote:
> On 2/26/2018 1:12 PM, Greg KH wrote:
> > On Mon, Feb 26, 2018 at 12:10:02PM -0500, Joe Moriarty wrote:
> > > The Parfait (version 2.1.0) static code analysis tool found the
> > > following NULL pointer dereference problem.
> > 
> > What is the "CWE 476" thing in the subject line for?
> > 
> [JDM]
> (CWE 476) stands for Common Weakness Enumeration.
> https://secur1ty.com/cwe/CWE-476/
> 
> It is the type of security flaw related to a NULL pointer dereference

Ok, why put that in the subject line and not just the body of the
changelog if you really want to call something out like this?

> > > dev_to_shost() in include/scsi/scsi_host.h has the ability to return
> > > NULL if the scsi host device does not have the Scsi_host->parent
> > > field set.  With the possibilty of a NULL pointer being set for
> > > the Scsi_Host->parent field, calls to host_to_us() have to make
> > > sure the return pointer is not null.  Changes were made to check
> > > for a return value of NULL on calls to host_to_us().
> > > 
> > > Signed-off-by: Joe Moriarty <joe.moriarty@oracle.com>
> > > Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
> > > Acked-by: Hakon Bugge <hakon.bugge@oracle.com>
> > > ---
> > >   drivers/usb/storage/scsiglue.c | 53 ++++++++++++++++++++++++++++++++++++------
> > >   1 file changed, 46 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
> > > index c267f2812a04..94af609d49bf 100644
> > > --- a/drivers/usb/storage/scsiglue.c
> > > +++ b/drivers/usb/storage/scsiglue.c
> > > @@ -66,6 +66,9 @@ static int slave_alloc (struct scsi_device *sdev)
> > >   {
> > >   	struct us_data *us = host_to_us(sdev->host);
> > > +	if (!us)
> > > +		pr_warn("Error in %s: us = NULL\n", __func__);
> > 
> > It is a driver, you should never use pr_* calls, but rather dev_* calls.
> > 
> > Also, you don't exit, are you sure the code keeps working after this
> > happens?
> > 
> > And what is a user supposed to do with this warning message?
> 
> [JDM]

???  You need a better email client, inline comments are the norm.

> - The messages are targeted for a developer and not the end user. I can
> change it to dev_ calls.

But an end user sees "KERN_WARNING" messages, right?  If this is a
debugging-only thing, then make it as such, and properly recover from it
as it could be hit during normal operation.

> > > +
> > >   	/*
> > >   	 * Set the INQUIRY transfer length to 36.  We don't use any of
> > >   	 * the extra data and many devices choke if asked for more or
> > > @@ -102,6 +105,11 @@ static int slave_configure(struct scsi_device *sdev)
> > >   {
> > >   	struct us_data *us = host_to_us(sdev->host);
> > > +	if (!us) {
> > > +		pr_warn("Error in %s: us = NULL\n", __func__);
> > > +		return 0;
> > 
> > Why are you returning a success?
> [JDM]
> - Yes, I need to return -ENXIO for the slave_alloc routine.
> 
> > 
> > > +	}
> > > +
> > >   	/*
> > >   	 * Many devices have trouble transferring more than 32KB at a time,
> > >   	 * while others have trouble with more than 64K. At this time we
> > > @@ -331,6 +339,11 @@ static int target_alloc(struct scsi_target *starget)
> > >   {
> > >   	struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
> > 
> > Can host_to_us() handle NULL?
> > 
> > Nope, just looked at it, this will never cause the return value to be
> > NULL, your checker needs some more work :(
> [JDM]
> This what the static code checker is catching.  host_to_us will return NULL
> if the following occurs.
> 
> 'dev_to_shost()' in include/scsi/scsi_host.h line 757.
> 
> This is done everytime a slave device is created at the following code
> 'target_alloc()' in drivers/usb/storage/scsiglue.c  linue 340.
> 
> This means that any call to host_to_us in the scsiglue module will have the
> possibility of setting the return value of NULL.  In fact, I would need to
> split out the following embedded call in 'target_alloc()' to avoid a
> possible NULL pointer dereference.
> 
> struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));

Exactly, your change did nothing, and us is probably not NULL here.

> The question becomes, Can a slave device ever have it's parent field set to
> NULL (ie: dev->parent).

I don't think it can, do you see how?

> Can it?  If not, this becomes a false positive that needs to be
> ignored and the entire patch is not needed.  I would tend to believe a
> slave device will always be enumerated by the parent (host) device.
> Correct?

How else can it be created?

> > > +	if (!us) {
> > > +		pr_warn("Error in %s: us = NULL\n", __func__);
> > > +		return 0;
> > > +	}
> > > +
> > >   	/*
> > >   	 * Some USB drives don't support REPORT LUNS, even though they
> > >   	 * report a SCSI revision level above 2.  Tell the SCSI layer
> > > @@ -361,6 +374,11 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
> > >   {
> > >   	struct us_data *us = host_to_us(srb->device->host);
> > > +	if (!us) {
> > 
> > How is that possible?  This doesn't have anything to do with your
> > subject line, right?
> > 
> > > +		pr_warn("Error in %s: us = NULL\n", __func__);
> > > +		return 0;
> > 
> > success?
> 
> [JDM] I need to return -ENXIO here.

-ENODEV?

But again, how can this happen?

thanks,

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [v1,1/1] drivers/usb/storage: NULL pointer dereference [null-pointer-deref] (CWE 476) problem
@ 2018-02-26 19:08 Joe Moriarty
  0 siblings, 0 replies; 10+ messages in thread
From: Joe Moriarty @ 2018-02-26 19:08 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-usb

On 2/26/2018 1:12 PM, Greg KH wrote:
> On Mon, Feb 26, 2018 at 12:10:02PM -0500, Joe Moriarty wrote:
>> The Parfait (version 2.1.0) static code analysis tool found the
>> following NULL pointer dereference problem.
> 
> What is the "CWE 476" thing in the subject line for?
>
[JDM]
(CWE 476) stands for Common Weakness Enumeration.
https://secur1ty.com/cwe/CWE-476/

It is the type of security flaw related to a NULL pointer dereference

>>
>> dev_to_shost() in include/scsi/scsi_host.h has the ability to return
>> NULL if the scsi host device does not have the Scsi_host->parent
>> field set.  With the possibilty of a NULL pointer being set for
>> the Scsi_Host->parent field, calls to host_to_us() have to make
>> sure the return pointer is not null.  Changes were made to check
>> for a return value of NULL on calls to host_to_us().
>>
>> Signed-off-by: Joe Moriarty <joe.moriarty@oracle.com>
>> Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
>> Acked-by: Hakon Bugge <hakon.bugge@oracle.com>
>> ---
>>   drivers/usb/storage/scsiglue.c | 53 ++++++++++++++++++++++++++++++++++++------
>>   1 file changed, 46 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
>> index c267f2812a04..94af609d49bf 100644
>> --- a/drivers/usb/storage/scsiglue.c
>> +++ b/drivers/usb/storage/scsiglue.c
>> @@ -66,6 +66,9 @@ static int slave_alloc (struct scsi_device *sdev)
>>   {
>>   	struct us_data *us = host_to_us(sdev->host);
>>   
>> +	if (!us)
>> +		pr_warn("Error in %s: us = NULL\n", __func__);
> 
> It is a driver, you should never use pr_* calls, but rather dev_* calls.
> 
> Also, you don't exit, are you sure the code keeps working after this
> happens?
> 
> And what is a user supposed to do with this warning message?

[JDM]
- The messages are targeted for a developer and not the end user. I can 
change it to dev_ calls.

> 
>> +
>>   	/*
>>   	 * Set the INQUIRY transfer length to 36.  We don't use any of
>>   	 * the extra data and many devices choke if asked for more or
>> @@ -102,6 +105,11 @@ static int slave_configure(struct scsi_device *sdev)
>>   {
>>   	struct us_data *us = host_to_us(sdev->host);
>>   
>> +	if (!us) {
>> +		pr_warn("Error in %s: us = NULL\n", __func__);
>> +		return 0;
> 
> Why are you returning a success?
[JDM]
- Yes, I need to return -ENXIO for the slave_alloc routine.

> 
>> +	}
>> +
>>   	/*
>>   	 * Many devices have trouble transferring more than 32KB at a time,
>>   	 * while others have trouble with more than 64K. At this time we
>> @@ -331,6 +339,11 @@ static int target_alloc(struct scsi_target *starget)
>>   {
>>   	struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
> 
> Can host_to_us() handle NULL?
> 
> Nope, just looked at it, this will never cause the return value to be
> NULL, your checker needs some more work :(
[JDM]
This what the static code checker is catching.  host_to_us will return 
NULL if the following occurs.

'dev_to_shost()' in include/scsi/scsi_host.h line 757.

This is done everytime a slave device is created at the following code
'target_alloc()' in drivers/usb/storage/scsiglue.c  linue 340.

This means that any call to host_to_us in the scsiglue module will have 
the possibility of setting the return value of NULL.  In fact, I would 
need to split out the following embedded call in 'target_alloc()' to 
avoid a possible NULL pointer dereference.

struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));

The question becomes, Can a slave device ever have it's parent field set 
to NULL (ie: dev->parent).  Can it?  If not, this becomes a false 
positive that needs to be ignored and the entire patch is not needed.  I 
would tend to believe a slave device will always be enumerated by the 
parent (host) device.  Correct?

> 
>>   
>> +	if (!us) {
>> +		pr_warn("Error in %s: us = NULL\n", __func__);
>> +		return 0;
>> +	}
>> +
>>   	/*
>>   	 * Some USB drives don't support REPORT LUNS, even though they
>>   	 * report a SCSI revision level above 2.  Tell the SCSI layer
>> @@ -361,6 +374,11 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
>>   {
>>   	struct us_data *us = host_to_us(srb->device->host);
>>   
>> +	if (!us) {
> 
> How is that possible?  This doesn't have anything to do with your
> subject line, right?
> 
>> +		pr_warn("Error in %s: us = NULL\n", __func__);
>> +		return 0;
> 
> success?

[JDM] I need to return -ENXIO here.

> 
> I stopped reviewing here, sorry :(
> 
> greg k-h

[JDM] My bad on the return values.  I will fix them accordingly and 
resubmit.

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

Thanks for your review.  I've added some comments inline above for you 
to respond to.


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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [v1,1/1] drivers/usb/storage: NULL pointer dereference [null-pointer-deref] (CWE 476) problem
@ 2018-02-26 18:12 Greg Kroah-Hartman
  0 siblings, 0 replies; 10+ messages in thread
From: Greg Kroah-Hartman @ 2018-02-26 18:12 UTC (permalink / raw)
  To: Joe Moriarty; +Cc: linux-usb

On Mon, Feb 26, 2018 at 12:10:02PM -0500, Joe Moriarty wrote:
> The Parfait (version 2.1.0) static code analysis tool found the
> following NULL pointer dereference problem.

What is the "CWE 476" thing in the subject line for?

> 
> dev_to_shost() in include/scsi/scsi_host.h has the ability to return
> NULL if the scsi host device does not have the Scsi_host->parent
> field set.  With the possibilty of a NULL pointer being set for
> the Scsi_Host->parent field, calls to host_to_us() have to make
> sure the return pointer is not null.  Changes were made to check
> for a return value of NULL on calls to host_to_us().
> 
> Signed-off-by: Joe Moriarty <joe.moriarty@oracle.com>
> Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
> Acked-by: Hakon Bugge <hakon.bugge@oracle.com>
> ---
>  drivers/usb/storage/scsiglue.c | 53 ++++++++++++++++++++++++++++++++++++------
>  1 file changed, 46 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
> index c267f2812a04..94af609d49bf 100644
> --- a/drivers/usb/storage/scsiglue.c
> +++ b/drivers/usb/storage/scsiglue.c
> @@ -66,6 +66,9 @@ static int slave_alloc (struct scsi_device *sdev)
>  {
>  	struct us_data *us = host_to_us(sdev->host);
>  
> +	if (!us)
> +		pr_warn("Error in %s: us = NULL\n", __func__);

It is a driver, you should never use pr_* calls, but rather dev_* calls.

Also, you don't exit, are you sure the code keeps working after this
happens?

And what is a user supposed to do with this warning message?

> +
>  	/*
>  	 * Set the INQUIRY transfer length to 36.  We don't use any of
>  	 * the extra data and many devices choke if asked for more or
> @@ -102,6 +105,11 @@ static int slave_configure(struct scsi_device *sdev)
>  {
>  	struct us_data *us = host_to_us(sdev->host);
>  
> +	if (!us) {
> +		pr_warn("Error in %s: us = NULL\n", __func__);
> +		return 0;

Why are you returning a success?

> +	}
> +
>  	/*
>  	 * Many devices have trouble transferring more than 32KB at a time,
>  	 * while others have trouble with more than 64K. At this time we
> @@ -331,6 +339,11 @@ static int target_alloc(struct scsi_target *starget)
>  {
>  	struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));

Can host_to_us() handle NULL?

Nope, just looked at it, this will never cause the return value to be
NULL, your checker needs some more work :(

>  
> +	if (!us) {
> +		pr_warn("Error in %s: us = NULL\n", __func__);
> +		return 0;
> +	}
> +
>  	/*
>  	 * Some USB drives don't support REPORT LUNS, even though they
>  	 * report a SCSI revision level above 2.  Tell the SCSI layer
> @@ -361,6 +374,11 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
>  {
>  	struct us_data *us = host_to_us(srb->device->host);
>  
> +	if (!us) {

How is that possible?  This doesn't have anything to do with your
subject line, right?

> +		pr_warn("Error in %s: us = NULL\n", __func__);
> +		return 0;

success?

I stopped reviewing here, sorry :(

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [v1,1/1] drivers/usb/storage: NULL pointer dereference [null-pointer-deref] (CWE 476) problem
@ 2018-02-26 17:10 Joe Moriarty
  0 siblings, 0 replies; 10+ messages in thread
From: Joe Moriarty @ 2018-02-26 17:10 UTC (permalink / raw)
  To: gregkh; +Cc: linux-usb

The Parfait (version 2.1.0) static code analysis tool found the
following NULL pointer dereference problem.

dev_to_shost() in include/scsi/scsi_host.h has the ability to return
NULL if the scsi host device does not have the Scsi_host->parent
field set.  With the possibilty of a NULL pointer being set for
the Scsi_Host->parent field, calls to host_to_us() have to make
sure the return pointer is not null.  Changes were made to check
for a return value of NULL on calls to host_to_us().

Signed-off-by: Joe Moriarty <joe.moriarty@oracle.com>
Reviewed-by: Steven Sistare <steven.sistare@oracle.com>
Acked-by: Hakon Bugge <hakon.bugge@oracle.com>
---
 drivers/usb/storage/scsiglue.c | 53 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index c267f2812a04..94af609d49bf 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -66,6 +66,9 @@ static int slave_alloc (struct scsi_device *sdev)
 {
 	struct us_data *us = host_to_us(sdev->host);
 
+	if (!us)
+		pr_warn("Error in %s: us = NULL\n", __func__);
+
 	/*
 	 * Set the INQUIRY transfer length to 36.  We don't use any of
 	 * the extra data and many devices choke if asked for more or
@@ -102,6 +105,11 @@ static int slave_configure(struct scsi_device *sdev)
 {
 	struct us_data *us = host_to_us(sdev->host);
 
+	if (!us) {
+		pr_warn("Error in %s: us = NULL\n", __func__);
+		return 0;
+	}
+
 	/*
 	 * Many devices have trouble transferring more than 32KB at a time,
 	 * while others have trouble with more than 64K. At this time we
@@ -331,6 +339,11 @@ static int target_alloc(struct scsi_target *starget)
 {
 	struct us_data *us = host_to_us(dev_to_shost(starget->dev.parent));
 
+	if (!us) {
+		pr_warn("Error in %s: us = NULL\n", __func__);
+		return 0;
+	}
+
 	/*
 	 * Some USB drives don't support REPORT LUNS, even though they
 	 * report a SCSI revision level above 2.  Tell the SCSI layer
@@ -361,6 +374,11 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
 {
 	struct us_data *us = host_to_us(srb->device->host);
 
+	if (!us) {
+		pr_warn("Error in %s: us = NULL\n", __func__);
+		return 0;
+	}
+
 	/* check for state-transition errors */
 	if (us->srb != NULL) {
 		printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n",
@@ -395,6 +413,11 @@ static int command_abort(struct scsi_cmnd *srb)
 {
 	struct us_data *us = host_to_us(srb->device->host);
 
+	if (!us) {
+		pr_warn("Error in %s: us = NULL\n", __func__);
+		return FAILED;
+	}
+
 	usb_stor_dbg(us, "%s called\n", __func__);
 
 	/*
@@ -438,12 +461,17 @@ static int device_reset(struct scsi_cmnd *srb)
 	struct us_data *us = host_to_us(srb->device->host);
 	int result;
 
-	usb_stor_dbg(us, "%s called\n", __func__);
+	if (us) {
+		usb_stor_dbg(us, "%s called\n", __func__);
 
-	/* lock the device pointers and do the reset */
-	mutex_lock(&(us->dev_mutex));
-	result = us->transport_reset(us);
-	mutex_unlock(&us->dev_mutex);
+		/* lock the device pointers and do the reset */
+		mutex_lock(&(us->dev_mutex));
+		result = us->transport_reset(us);
+		mutex_unlock(&us->dev_mutex);
+	} else {
+		pr_warn("Error in %s: us = NULL\n", __func__);
+		result = -ENXIO;
+	}
 
 	return result < 0 ? FAILED : SUCCESS;
 }
@@ -454,9 +482,15 @@ static int bus_reset(struct scsi_cmnd *srb)
 	struct us_data *us = host_to_us(srb->device->host);
 	int result;
 
-	usb_stor_dbg(us, "%s called\n", __func__);
+	if (us) {
+		usb_stor_dbg(us, "%s called\n", __func__);
+
+		result = usb_stor_port_reset(us);
+	} else {
+		pr_warn("Error in %s: us = NULL\n", __func__);
+		result = -ENXIO;
+	}
 
-	result = usb_stor_port_reset(us);
 	return result < 0 ? FAILED : SUCCESS;
 }
 
@@ -506,6 +540,11 @@ static int show_info (struct seq_file *m, struct Scsi_Host *host)
 	struct us_data *us = host_to_us(host);
 	const char *string;
 
+	if (!us) {
+		pr_warn("Error in %s: us = NULL\n", __func__);
+		return 0;
+	}
+
 	/* print the controller name */
 	seq_printf(m, "   Host scsi%d: usb-storage\n", host->host_no);
 

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-02-27 19:49 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-27 14:59 [v1,1/1] drivers/usb/storage: NULL pointer dereference [null-pointer-deref] (CWE 476) problem Joe Moriarty
  -- strict thread matches above, loose matches on Subject: below --
2018-02-27 19:49 Joe Moriarty
2018-02-27 19:05 Greg Kroah-Hartman
2018-02-27 18:22 Joe Moriarty
2018-02-27 18:14 Greg Kroah-Hartman
2018-02-27 16:56 Joe Moriarty
2018-02-26 19:35 Greg Kroah-Hartman
2018-02-26 19:08 Joe Moriarty
2018-02-26 18:12 Greg Kroah-Hartman
2018-02-26 17:10 Joe Moriarty

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.