diff mbox series

firmware: xilinx: fix out-of-bounds access

Message ID 20201026155449.3703142-1-arnd@kernel.org (mailing list archive)
State New, archived
Headers show
Series firmware: xilinx: fix out-of-bounds access | expand

Commit Message

Arnd Bergmann Oct. 26, 2020, 3:54 p.m. UTC
From: Arnd Bergmann <arnd@arndb.de>

The zynqmp_pm_set_suspend_mode() and zynqmp_pm_get_trustzone_version()
functions pass values as api_id into zynqmp_pm_invoke_fn
that are beyond PM_API_MAX, resulting in an out-of-bounds access:

drivers/firmware/xilinx/zynqmp.c: In function 'zynqmp_pm_set_suspend_mode':
drivers/firmware/xilinx/zynqmp.c:150:24: warning: array subscript 2562 is above array bounds of 'u32[64]' {aka 'unsigned int[64]'} [-Warray-bounds]
  150 |  if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
      |      ~~~~~~~~~~~~~~~~~~^~~~~~~~
drivers/firmware/xilinx/zynqmp.c:28:12: note: while referencing 'zynqmp_pm_features'
   28 | static u32 zynqmp_pm_features[PM_API_MAX];
      |            ^~~~~~~~~~~~~~~~~~

Replace the resulting undefined behavior with an error return.
This may break some things that happen to work at the moment
but seems better than randomly overwriting kernel data.

I assume we need additional fixes for the two functions that now
return an error.

Fixes: 76582671eb5d ("firmware: xilinx: Add Zynqmp firmware driver")
Fixes: e178df31cf41 ("firmware: xilinx: Implement ZynqMP power management APIs")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 drivers/firmware/xilinx/zynqmp.c | 3 +++
 1 file changed, 3 insertions(+)

Comments

Michal Simek Oct. 27, 2020, 9:53 a.m. UTC | #1
On 26. 10. 20 16:54, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
> 
> The zynqmp_pm_set_suspend_mode() and zynqmp_pm_get_trustzone_version()
> functions pass values as api_id into zynqmp_pm_invoke_fn
> that are beyond PM_API_MAX, resulting in an out-of-bounds access:
> 
> drivers/firmware/xilinx/zynqmp.c: In function 'zynqmp_pm_set_suspend_mode':
> drivers/firmware/xilinx/zynqmp.c:150:24: warning: array subscript 2562 is above array bounds of 'u32[64]' {aka 'unsigned int[64]'} [-Warray-bounds]
>   150 |  if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
>       |      ~~~~~~~~~~~~~~~~~~^~~~~~~~
> drivers/firmware/xilinx/zynqmp.c:28:12: note: while referencing 'zynqmp_pm_features'
>    28 | static u32 zynqmp_pm_features[PM_API_MAX];
>       |            ^~~~~~~~~~~~~~~~~~

Which CONFIG option/tool is reporting this issue?

> 
> Replace the resulting undefined behavior with an error return.
> This may break some things that happen to work at the moment
> but seems better than randomly overwriting kernel data.
> 
> I assume we need additional fixes for the two functions that now
> return an error.
> 
> Fixes: 76582671eb5d ("firmware: xilinx: Add Zynqmp firmware driver")
> Fixes: e178df31cf41 ("firmware: xilinx: Implement ZynqMP power management APIs")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
>  drivers/firmware/xilinx/zynqmp.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
> index 8d1ff2454e2e..efb8a66efc68 100644
> --- a/drivers/firmware/xilinx/zynqmp.c
> +++ b/drivers/firmware/xilinx/zynqmp.c
> @@ -147,6 +147,9 @@ static int zynqmp_pm_feature(u32 api_id)
>  		return 0;
>  
>  	/* Return value if feature is already checked */
> +	if (api_id > ARRAY_SIZE(zynqmp_pm_features))
> +		return PM_FEATURE_INVALID;
> +
>  	if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
>  		return zynqmp_pm_features[api_id];
>  
> 

Definitely good catch but not quite sure what should be correct reaction.
Rajan: Can you please take a look at it with priority?

Thanks,
Michal
Rajan Vaja Oct. 27, 2020, 12:23 p.m. UTC | #2
Hi Michal,

> -----Original Message-----
> From: Michal Simek <michal.simek@xilinx.com>
> Sent: 27 October 2020 02:53
> To: Arnd Bergmann <arnd@kernel.org>; Michal Simek <michals@xilinx.com>;
> Rajan Vaja <RAJANV@xilinx.com>
> Cc: Arnd Bergmann <arnd@arndb.de>; Rajan Vaja <RAJANV@xilinx.com>; Greg
> Kroah-Hartman <gregkh@linuxfoundation.org>; Tejas Patel
> <TEJASP@xilinx.com>; linux-arm-kernel@lists.infradead.org; linux-
> kernel@vger.kernel.org; git <git@xilinx.com>
> Subject: Re: [PATCH] firmware: xilinx: fix out-of-bounds access
> 
> 
> 
> On 26. 10. 20 16:54, Arnd Bergmann wrote:
> > From: Arnd Bergmann <arnd@arndb.de>
> >
> > The zynqmp_pm_set_suspend_mode() and
> zynqmp_pm_get_trustzone_version()
> > functions pass values as api_id into zynqmp_pm_invoke_fn
> > that are beyond PM_API_MAX, resulting in an out-of-bounds access:
> >
> > drivers/firmware/xilinx/zynqmp.c: In function
> 'zynqmp_pm_set_suspend_mode':
> > drivers/firmware/xilinx/zynqmp.c:150:24: warning: array subscript 2562 is above
> array bounds of 'u32[64]' {aka 'unsigned int[64]'} [-Warray-bounds]
> >   150 |  if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
> >       |      ~~~~~~~~~~~~~~~~~~^~~~~~~~
> > drivers/firmware/xilinx/zynqmp.c:28:12: note: while referencing
> 'zynqmp_pm_features'
> >    28 | static u32 zynqmp_pm_features[PM_API_MAX];
> >       |            ^~~~~~~~~~~~~~~~~~
> 
> Which CONFIG option/tool is reporting this issue?
> 
> >
> > Replace the resulting undefined behavior with an error return.
> > This may break some things that happen to work at the moment
> > but seems better than randomly overwriting kernel data.
> >
> > I assume we need additional fixes for the two functions that now
> > return an error.
> >
> > Fixes: 76582671eb5d ("firmware: xilinx: Add Zynqmp firmware driver")
> > Fixes: e178df31cf41 ("firmware: xilinx: Implement ZynqMP power management
> APIs")
> > Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> > ---
> >  drivers/firmware/xilinx/zynqmp.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/drivers/firmware/xilinx/zynqmp.c
> b/drivers/firmware/xilinx/zynqmp.c
> > index 8d1ff2454e2e..efb8a66efc68 100644
> > --- a/drivers/firmware/xilinx/zynqmp.c
> > +++ b/drivers/firmware/xilinx/zynqmp.c
> > @@ -147,6 +147,9 @@ static int zynqmp_pm_feature(u32 api_id)
> >  		return 0;
> >
> >  	/* Return value if feature is already checked */
> > +	if (api_id > ARRAY_SIZE(zynqmp_pm_features))
> > +		return PM_FEATURE_INVALID;
> > +
> >  	if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
> >  		return zynqmp_pm_features[api_id];
> >
> >
> 
> Definitely good catch but not quite sure what should be correct reaction.
> Rajan: Can you please take a look at it with priority?
[Rajan] Change looks fine to me.

Thanks,
Rajan
> 
> Thanks,
> Michal
Michal Simek Oct. 27, 2020, 12:27 p.m. UTC | #3
On 27. 10. 20 13:23, Rajan Vaja wrote:
> Hi Michal,
> 
>> -----Original Message-----
>> From: Michal Simek <michal.simek@xilinx.com>
>> Sent: 27 October 2020 02:53
>> To: Arnd Bergmann <arnd@kernel.org>; Michal Simek <michals@xilinx.com>;
>> Rajan Vaja <RAJANV@xilinx.com>
>> Cc: Arnd Bergmann <arnd@arndb.de>; Rajan Vaja <RAJANV@xilinx.com>; Greg
>> Kroah-Hartman <gregkh@linuxfoundation.org>; Tejas Patel
>> <TEJASP@xilinx.com>; linux-arm-kernel@lists.infradead.org; linux-
>> kernel@vger.kernel.org; git <git@xilinx.com>
>> Subject: Re: [PATCH] firmware: xilinx: fix out-of-bounds access
>>
>>
>>
>> On 26. 10. 20 16:54, Arnd Bergmann wrote:
>>> From: Arnd Bergmann <arnd@arndb.de>
>>>
>>> The zynqmp_pm_set_suspend_mode() and
>> zynqmp_pm_get_trustzone_version()
>>> functions pass values as api_id into zynqmp_pm_invoke_fn
>>> that are beyond PM_API_MAX, resulting in an out-of-bounds access:
>>>
>>> drivers/firmware/xilinx/zynqmp.c: In function
>> 'zynqmp_pm_set_suspend_mode':
>>> drivers/firmware/xilinx/zynqmp.c:150:24: warning: array subscript 2562 is above
>> array bounds of 'u32[64]' {aka 'unsigned int[64]'} [-Warray-bounds]
>>>   150 |  if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
>>>       |      ~~~~~~~~~~~~~~~~~~^~~~~~~~
>>> drivers/firmware/xilinx/zynqmp.c:28:12: note: while referencing
>> 'zynqmp_pm_features'
>>>    28 | static u32 zynqmp_pm_features[PM_API_MAX];
>>>       |            ^~~~~~~~~~~~~~~~~~
>>
>> Which CONFIG option/tool is reporting this issue?
>>
>>>
>>> Replace the resulting undefined behavior with an error return.
>>> This may break some things that happen to work at the moment
>>> but seems better than randomly overwriting kernel data.
>>>
>>> I assume we need additional fixes for the two functions that now
>>> return an error.
>>>
>>> Fixes: 76582671eb5d ("firmware: xilinx: Add Zynqmp firmware driver")
>>> Fixes: e178df31cf41 ("firmware: xilinx: Implement ZynqMP power management
>> APIs")
>>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>>> ---
>>>  drivers/firmware/xilinx/zynqmp.c | 3 +++
>>>  1 file changed, 3 insertions(+)
>>>
>>> diff --git a/drivers/firmware/xilinx/zynqmp.c
>> b/drivers/firmware/xilinx/zynqmp.c
>>> index 8d1ff2454e2e..efb8a66efc68 100644
>>> --- a/drivers/firmware/xilinx/zynqmp.c
>>> +++ b/drivers/firmware/xilinx/zynqmp.c
>>> @@ -147,6 +147,9 @@ static int zynqmp_pm_feature(u32 api_id)
>>>  		return 0;
>>>
>>>  	/* Return value if feature is already checked */
>>> +	if (api_id > ARRAY_SIZE(zynqmp_pm_features))
>>> +		return PM_FEATURE_INVALID;
>>> +
>>>  	if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
>>>  		return zynqmp_pm_features[api_id];
>>>
>>>
>>
>> Definitely good catch but not quite sure what should be correct reaction.
>> Rajan: Can you please take a look at it with priority?
> [Rajan] Change looks fine to me.

as is mentioned above that two functions now returns and error
PM_FEATURE_INVALID. Which means that zynqmp_pm_set_suspend_mode() and
zynqmp_pm_get_trustzone_version() fail all the time which doesn't look
correct.

M
Rajan Vaja Oct. 27, 2020, 12:38 p.m. UTC | #4
Hi Michal,


> -----Original Message-----
> From: Michal Simek <michal.simek@xilinx.com>
> Sent: 27 October 2020 05:27
> To: Rajan Vaja <RAJANV@xilinx.com>; Arnd Bergmann <arnd@kernel.org>
> Cc: Arnd Bergmann <arnd@arndb.de>; Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>; Tejas Patel <TEJASP@xilinx.com>; linux-arm-
> kernel@lists.infradead.org; linux-kernel@vger.kernel.org; git <git@xilinx.com>
> Subject: Re: [PATCH] firmware: xilinx: fix out-of-bounds access
> 
> 
> 
> On 27. 10. 20 13:23, Rajan Vaja wrote:
> > Hi Michal,
> >
> >> -----Original Message-----
> >> From: Michal Simek <michal.simek@xilinx.com>
> >> Sent: 27 October 2020 02:53
> >> To: Arnd Bergmann <arnd@kernel.org>; Michal Simek <michals@xilinx.com>;
> >> Rajan Vaja <RAJANV@xilinx.com>
> >> Cc: Arnd Bergmann <arnd@arndb.de>; Rajan Vaja <RAJANV@xilinx.com>;
> Greg
> >> Kroah-Hartman <gregkh@linuxfoundation.org>; Tejas Patel
> >> <TEJASP@xilinx.com>; linux-arm-kernel@lists.infradead.org; linux-
> >> kernel@vger.kernel.org; git <git@xilinx.com>
> >> Subject: Re: [PATCH] firmware: xilinx: fix out-of-bounds access
> >>
> >>
> >>
> >> On 26. 10. 20 16:54, Arnd Bergmann wrote:
> >>> From: Arnd Bergmann <arnd@arndb.de>
> >>>
> >>> The zynqmp_pm_set_suspend_mode() and
> >> zynqmp_pm_get_trustzone_version()
> >>> functions pass values as api_id into zynqmp_pm_invoke_fn
> >>> that are beyond PM_API_MAX, resulting in an out-of-bounds access:
> >>>
> >>> drivers/firmware/xilinx/zynqmp.c: In function
> >> 'zynqmp_pm_set_suspend_mode':
> >>> drivers/firmware/xilinx/zynqmp.c:150:24: warning: array subscript 2562 is
> above
> >> array bounds of 'u32[64]' {aka 'unsigned int[64]'} [-Warray-bounds]
> >>>   150 |  if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
> >>>       |      ~~~~~~~~~~~~~~~~~~^~~~~~~~
> >>> drivers/firmware/xilinx/zynqmp.c:28:12: note: while referencing
> >> 'zynqmp_pm_features'
> >>>    28 | static u32 zynqmp_pm_features[PM_API_MAX];
> >>>       |            ^~~~~~~~~~~~~~~~~~
> >>
> >> Which CONFIG option/tool is reporting this issue?
> >>
> >>>
> >>> Replace the resulting undefined behavior with an error return.
> >>> This may break some things that happen to work at the moment
> >>> but seems better than randomly overwriting kernel data.
> >>>
> >>> I assume we need additional fixes for the two functions that now
> >>> return an error.
> >>>
> >>> Fixes: 76582671eb5d ("firmware: xilinx: Add Zynqmp firmware driver")
> >>> Fixes: e178df31cf41 ("firmware: xilinx: Implement ZynqMP power
> management
> >> APIs")
> >>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> >>> ---
> >>>  drivers/firmware/xilinx/zynqmp.c | 3 +++
> >>>  1 file changed, 3 insertions(+)
> >>>
> >>> diff --git a/drivers/firmware/xilinx/zynqmp.c
> >> b/drivers/firmware/xilinx/zynqmp.c
> >>> index 8d1ff2454e2e..efb8a66efc68 100644
> >>> --- a/drivers/firmware/xilinx/zynqmp.c
> >>> +++ b/drivers/firmware/xilinx/zynqmp.c
> >>> @@ -147,6 +147,9 @@ static int zynqmp_pm_feature(u32 api_id)
> >>>  		return 0;
> >>>
> >>>  	/* Return value if feature is already checked */
> >>> +	if (api_id > ARRAY_SIZE(zynqmp_pm_features))
> >>> +		return PM_FEATURE_INVALID;
> >>> +
> >>>  	if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
> >>>  		return zynqmp_pm_features[api_id];
> >>>
> >>>
> >>
> >> Definitely good catch but not quite sure what should be correct reaction.
> >> Rajan: Can you please take a look at it with priority?
> > [Rajan] Change looks fine to me.
> 
> as is mentioned above that two functions now returns and error
> PM_FEATURE_INVALID. Which means that zynqmp_pm_set_suspend_mode()
> and
> zynqmp_pm_get_trustzone_version() fail all the time which doesn't look
> correct.
[Rajan] Right Michal, I completely missed API which are not in pmufw ,  API IDs from ATF are different and it doesn't fit in PM_API_MAX range, so I think instead of just single array with PM_API_MAX size, implementation can be updated having, hash table kind of implementation and not directly in array index which is same as API ID.

Thanks,
Rajan 
> 
> M
Arnd Bergmann Oct. 27, 2020, 1:32 p.m. UTC | #5
On Tue, Oct 27, 2020 at 10:53 AM Michal Simek <michal.simek@xilinx.com> wrote:
> On 26. 10. 20 16:54, Arnd Bergmann wrote:
> > From: Arnd Bergmann <arnd@arndb.de>
> >
> > The zynqmp_pm_set_suspend_mode() and zynqmp_pm_get_trustzone_version()
> > functions pass values as api_id into zynqmp_pm_invoke_fn
> > that are beyond PM_API_MAX, resulting in an out-of-bounds access:
> >
> > drivers/firmware/xilinx/zynqmp.c: In function 'zynqmp_pm_set_suspend_mode':
> > drivers/firmware/xilinx/zynqmp.c:150:24: warning: array subscript 2562 is above array bounds of 'u32[64]' {aka 'unsigned int[64]'} [-Warray-bounds]
> >   150 |  if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
> >       |      ~~~~~~~~~~~~~~~~~~^~~~~~~~
> > drivers/firmware/xilinx/zynqmp.c:28:12: note: while referencing 'zynqmp_pm_features'
> >    28 | static u32 zynqmp_pm_features[PM_API_MAX];
> >       |            ^~~~~~~~~~~~~~~~~~
>
> Which CONFIG option/tool is reporting this issue?

This is with gcc-10. Commit 44720996e2d7 ("gcc-10: disable
'array-bounds' warning for
now") turned off this warning globally, but most of the reported warnings got
fixed in the meantime. I'm trying to take care of the rest so we can enabled it
again.

You should be able to reproduce the problem by removing the cc-disable-warning
line from the top-level Makefile.

        Arnd
diff mbox series

Patch

diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index 8d1ff2454e2e..efb8a66efc68 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -147,6 +147,9 @@  static int zynqmp_pm_feature(u32 api_id)
 		return 0;
 
 	/* Return value if feature is already checked */
+	if (api_id > ARRAY_SIZE(zynqmp_pm_features))
+		return PM_FEATURE_INVALID;
+
 	if (zynqmp_pm_features[api_id] != PM_FEATURE_UNCHECKED)
 		return zynqmp_pm_features[api_id];