[edk2-devel] [PATCH v3 01/12] MdeModulePkg/SmbiosDxe: Fix pointer and buffer overflow CodeQL alerts

Michael Kubacki posted 12 patches 2 years, 11 months ago
There is a newer version of this series
[edk2-devel] [PATCH v3 01/12] MdeModulePkg/SmbiosDxe: Fix pointer and buffer overflow CodeQL alerts
Posted by Michael Kubacki 2 years, 11 months ago
From: Erich McMillan <emcmillan@microsoft.com>

Details for these CodeQL alerts can be found here:

- Pointer overflow check (cpp/pointer-overflow-check):
  - https://cwe.mitre.org/data/definitions/758.html

- Potential buffer overflow check (cpp/potential-buffer-overflow):
  - https://cwe.mitre.org/data/definitions/676.html

CodeQL alert:

  - Line 1612 in MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
    - Type: Pointer overflow check
    - Severity: Low
    - Problem: Range check relying on pointer overflow

Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Erich McMillan <emcmillan@microsoft.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Michael Kubacki <mikuback@linux.microsoft.com>
Cc: Star Zeng <star.zeng@intel.com>
Cc: Zhichao Gao <zhichao.gao@intel.com>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Co-authored-by: Michael Kubacki <michael.kubacki@microsoft.com>
Signed-off-by: Erich McMillan <emcmillan@microsoft.com>
Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
---
 MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c   | 11 ++++++++---
 MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf |  1 +
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
index 1d43adc7662c..c1da2adc296b 100644
--- a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
+++ b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.c
@@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
 #include "SmbiosDxe.h"
+#include <Library/SafeIntLib.h>
 
 //
 // Module Global:
@@ -1594,6 +1595,7 @@ ParseAndAddExistingSmbiosTable (
   CHAR8                     *String;
   EFI_SMBIOS_HANDLE         SmbiosHandle;
   SMBIOS_STRUCTURE_POINTER  SmbiosEnd;
+  UINTN                     SafeIntResult;
 
   mPrivateData.Smbios.MajorVersion = MajorVersion;
   mPrivateData.Smbios.MinorVersion = MinorVersion;
@@ -1608,9 +1610,12 @@ ParseAndAddExistingSmbiosTable (
     //
     // Make sure not to access memory beyond SmbiosEnd
     //
-    if ((Smbios.Raw + sizeof (SMBIOS_STRUCTURE) > SmbiosEnd.Raw) ||
-        (Smbios.Raw + sizeof (SMBIOS_STRUCTURE) < Smbios.Raw))
-    {
+    Status = SafeUintnAdd ((UINTN)Smbios.Raw, sizeof (SMBIOS_STRUCTURE), &SafeIntResult);
+    if (EFI_ERROR (Status)) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    if ((SafeIntResult > (UINTN)SmbiosEnd.Raw) || (SafeIntResult < (UINTN)Smbios.Raw)) {
       return EFI_INVALID_PARAMETER;
     }
 
diff --git a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
index c03915a6921f..8b7c74694775 100644
--- a/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+++ b/MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
@@ -42,6 +42,7 @@ [LibraryClasses]
   DebugLib
   PcdLib
   HobLib
+  SafeIntLib
 
 [Protocols]
   gEfiSmbiosProtocolGuid                            ## PRODUCES
-- 
2.28.0.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#100102): https://edk2.groups.io/g/devel/message/100102
Mute This Topic: https://groups.io/mt/96938294/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH v3 01/12] MdeModulePkg/SmbiosDxe: Fix pointer and buffer overflow CodeQL alerts
Posted by Michael Brown 2 years, 11 months ago
On 13/02/2023 15:48, Michael Kubacki wrote:
> @@ -1608,9 +1610,12 @@ ParseAndAddExistingSmbiosTable (
>       //
>       // Make sure not to access memory beyond SmbiosEnd
>       //
> -    if ((Smbios.Raw + sizeof (SMBIOS_STRUCTURE) > SmbiosEnd.Raw) ||
> -        (Smbios.Raw + sizeof (SMBIOS_STRUCTURE) < Smbios.Raw))
> -    {
> +    Status = SafeUintnAdd ((UINTN)Smbios.Raw, sizeof (SMBIOS_STRUCTURE), &SafeIntResult);
> +    if (EFI_ERROR (Status)) {
> +      return EFI_INVALID_PARAMETER;
> +    }
> +
> +    if ((SafeIntResult > (UINTN)SmbiosEnd.Raw) || (SafeIntResult < (UINTN)Smbios.Raw)) {
>         return EFI_INVALID_PARAMETER;
>       }

Could this not be expressed much more cleanly as just:

   if ((UINTN)(SmbiosEnd.Raw - Smbios.Raw) < sizeof (SMBIOS_STRUCTURE)) {
     return EFI_INVALID_PARAMETER;
   }

without the need to hide a basic arithmetic operation behind an ugly 
wrapper function and drag in an external library?

The almost-identical check performed in the code immediately below (that 
takes Smbios.Hdr->Length into account) should also be updated to e.g.:

   if ((UINTN)(SmbiosEnd.Raw - Smbios.Raw) < (Smbios.Hdr->Length + 2)) {
     ...
   }

Thanks,

Michael



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#100116): https://edk2.groups.io/g/devel/message/100116
Mute This Topic: https://groups.io/mt/96938294/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH v3 01/12] MdeModulePkg/SmbiosDxe: Fix pointer and buffer overflow CodeQL alerts
Posted by Gerd Hoffmann 2 years, 11 months ago
On Mon, Feb 13, 2023 at 04:15:30PM +0000, Michael Brown wrote:
> On 13/02/2023 15:48, Michael Kubacki wrote:
> > @@ -1608,9 +1610,12 @@ ParseAndAddExistingSmbiosTable (
> >       //
> >       // Make sure not to access memory beyond SmbiosEnd
> >       //
> > -    if ((Smbios.Raw + sizeof (SMBIOS_STRUCTURE) > SmbiosEnd.Raw) ||
> > -        (Smbios.Raw + sizeof (SMBIOS_STRUCTURE) < Smbios.Raw))
> > -    {
> > +    Status = SafeUintnAdd ((UINTN)Smbios.Raw, sizeof (SMBIOS_STRUCTURE), &SafeIntResult);
> > +    if (EFI_ERROR (Status)) {
> > +      return EFI_INVALID_PARAMETER;
> > +    }
> > +
> > +    if ((SafeIntResult > (UINTN)SmbiosEnd.Raw) || (SafeIntResult < (UINTN)Smbios.Raw)) {
> >         return EFI_INVALID_PARAMETER;
> >       }
> 
> Could this not be expressed much more cleanly as just:
> 
>   if ((UINTN)(SmbiosEnd.Raw - Smbios.Raw) < sizeof (SMBIOS_STRUCTURE)) {
>     return EFI_INVALID_PARAMETER;
>   }
> 
> without the need to hide a basic arithmetic operation behind an ugly wrapper
> function and drag in an external library?

Well, the advantage of using SafeIntLib is that (a) it is obvious even
to untrained code readers what is going on here, and (b) it is hard to
get it wrong.

When looking at the quality some of the patches being posted to the list
have I'd say that is important to consider even if you personally have
no problems avoiding integer overflows without the help of SafeIntLib.

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#100174): https://edk2.groups.io/g/devel/message/100174
Mute This Topic: https://groups.io/mt/96938294/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH v3 01/12] MdeModulePkg/SmbiosDxe: Fix pointer and buffer overflow CodeQL alerts
Posted by Michael Kubacki 2 years, 11 months ago
Either approach works for me.

I understand the desire to avoid code bloat that comes with the library.

The most common classes of issues I see at the moment are asserts being 
misused for error handling (which is significant), general issues with 
integer conversion/evaluation, and unsafe arithmetic operations.

I suppose this is in the spirit of Gerd's comment as I thought 
additional library usage might increase awareness to help with the latter.

Do the MdeModulePkg / SMBIOS maintainers have a preference?

Thanks,
Michael

On 2/14/2023 8:01 AM, Gerd Hoffmann wrote:
> On Mon, Feb 13, 2023 at 04:15:30PM +0000, Michael Brown wrote:
>> On 13/02/2023 15:48, Michael Kubacki wrote:
>>> @@ -1608,9 +1610,12 @@ ParseAndAddExistingSmbiosTable (
>>>        //
>>>        // Make sure not to access memory beyond SmbiosEnd
>>>        //
>>> -    if ((Smbios.Raw + sizeof (SMBIOS_STRUCTURE) > SmbiosEnd.Raw) ||
>>> -        (Smbios.Raw + sizeof (SMBIOS_STRUCTURE) < Smbios.Raw))
>>> -    {
>>> +    Status = SafeUintnAdd ((UINTN)Smbios.Raw, sizeof (SMBIOS_STRUCTURE), &SafeIntResult);
>>> +    if (EFI_ERROR (Status)) {
>>> +      return EFI_INVALID_PARAMETER;
>>> +    }
>>> +
>>> +    if ((SafeIntResult > (UINTN)SmbiosEnd.Raw) || (SafeIntResult < (UINTN)Smbios.Raw)) {
>>>          return EFI_INVALID_PARAMETER;
>>>        }
>>
>> Could this not be expressed much more cleanly as just:
>>
>>    if ((UINTN)(SmbiosEnd.Raw - Smbios.Raw) < sizeof (SMBIOS_STRUCTURE)) {
>>      return EFI_INVALID_PARAMETER;
>>    }
>>
>> without the need to hide a basic arithmetic operation behind an ugly wrapper
>> function and drag in an external library?
> 
> Well, the advantage of using SafeIntLib is that (a) it is obvious even
> to untrained code readers what is going on here, and (b) it is hard to
> get it wrong.
> 
> When looking at the quality some of the patches being posted to the list
> have I'd say that is important to consider even if you personally have
> no problems avoiding integer overflows without the help of SafeIntLib.
> 
> take care,
>    Gerd


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#100178): https://edk2.groups.io/g/devel/message/100178
Mute This Topic: https://groups.io/mt/96938294/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH v3 01/12] MdeModulePkg/SmbiosDxe: Fix pointer and buffer overflow CodeQL alerts
Posted by Michael Brown 2 years, 11 months ago
On 14/02/2023 13:01, Gerd Hoffmann wrote:
> On Mon, Feb 13, 2023 at 04:15:30PM +0000, Michael Brown wrote:
>> On 13/02/2023 15:48, Michael Kubacki wrote:
>>> @@ -1608,9 +1610,12 @@ ParseAndAddExistingSmbiosTable (
>>>        //
>>>        // Make sure not to access memory beyond SmbiosEnd
>>>        //
>>> -    if ((Smbios.Raw + sizeof (SMBIOS_STRUCTURE) > SmbiosEnd.Raw) ||
>>> -        (Smbios.Raw + sizeof (SMBIOS_STRUCTURE) < Smbios.Raw))
>>> -    {
>>> +    Status = SafeUintnAdd ((UINTN)Smbios.Raw, sizeof (SMBIOS_STRUCTURE), &SafeIntResult);
>>> +    if (EFI_ERROR (Status)) {
>>> +      return EFI_INVALID_PARAMETER;
>>> +    }
>>> +
>>> +    if ((SafeIntResult > (UINTN)SmbiosEnd.Raw) || (SafeIntResult < (UINTN)Smbios.Raw)) {
>>>          return EFI_INVALID_PARAMETER;
>>>        }
>>
>> Could this not be expressed much more cleanly as just:
>>
>>    if ((UINTN)(SmbiosEnd.Raw - Smbios.Raw) < sizeof (SMBIOS_STRUCTURE)) {
>>      return EFI_INVALID_PARAMETER;
>>    }
>>
>> without the need to hide a basic arithmetic operation behind an ugly wrapper
>> function and drag in an external library?
> 
> Well, the advantage of using SafeIntLib is that (a) it is obvious even
> to untrained code readers what is going on here, and (b) it is hard to
> get it wrong.
> 
> When looking at the quality some of the patches being posted to the list
> have I'd say that is important to consider even if you personally have
> no problems avoiding integer overflows without the help of SafeIntLib.

Fair enough.  But in that case it should be used in a way that makes it 
clear what it's actually doing.  Specifically, the check for

   if (... || (SafeIntResult < (UINTN)Smbios.Raw)) {
     ...
   }

then becomes meaningless, since the whole point of SafeUintnAdd() is 
that it cannot result in this kind of unsigned integer wraparound.  The 
code as modified by this patch is *harder* to understand, because the 
reader has to dig through to figure out why this check still exists, 
look at the implementation of SafeUintnAdd() to see what is meant by 
"safe" in this context, and finally come to the conclusion that the 
remaining underflow check is redundant code that should have been removed.

The reader is also going to be confused by the fact that the code as 
modified by this patch then contains two separate methods for checking 
for integer overflows, since the patch does not similarly update the 
very similar code found almost immediately afterwards:

   if ((Smbios.Raw + Smbios.Hdr->Length + 2 * sizeof (UINT8) > 
SmbiosEnd.Raw) ||
         (Smbios.Raw + Smbios.Hdr->Length + 2 * sizeof (UINT8) < 
Smbios.Raw))
     {
       return EFI_INVALID_PARAMETER;
     }


Lastly: the actual operation being made safe here is "check that buffer 
contains at least this much data remaining".  This is most obviously 
done by calculating the remaining buffer space (i.e. 
(UINTN)(SmbiosEnd.Raw - Smbios.Raw)) and comparing against that.  That 
logic is clear, simple, and obviously correct at first glance.  Using 
the SafeUintnAdd() call does something that *is* mathematically 
equivalent to this check, but where the logic is much harder to parse.


I'd prefer it if the code were updated to avoid SafeUintnAdd() 
altogether.  But if not, then at a minimum the redundant check should be 
removed, and the calculation involving Smbios.Hdr->Length should also be 
updated to use SafeUintnAdd().

Thanks,

Michael



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#100177): https://edk2.groups.io/g/devel/message/100177
Mute This Topic: https://groups.io/mt/96938294/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH v3 01/12] MdeModulePkg/SmbiosDxe: Fix pointer and buffer overflow CodeQL alerts
Posted by Gerd Hoffmann 2 years, 11 months ago
  Hi,

> [ ... details snipped ... ]
> 
> I'd prefer it if the code were updated to avoid SafeUintnAdd() altogether.
> But if not, then at a minimum the redundant check should be removed, and the
> calculation involving Smbios.Hdr->Length should also be updated to use
> SafeUintnAdd().

Fully agreeing to that.

take care,
  Gerd



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#100180): https://edk2.groups.io/g/devel/message/100180
Mute This Topic: https://groups.io/mt/96938294/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [PATCH v3 01/12] MdeModulePkg/SmbiosDxe: Fix pointer and buffer overflow CodeQL alerts
Posted by Michael Kubacki 2 years, 11 months ago
I know the second case was missed, that will be updated.

I agree calculating the remaining buffer space is more straightforward 
here without the library so I'll go with that approach in a v4 of the 
series.

Thanks for the detailed feedback.

On 2/14/2023 9:11 AM, Gerd Hoffmann wrote:
>    Hi,
> 
>> [ ... details snipped ... ]
>>
>> I'd prefer it if the code were updated to avoid SafeUintnAdd() altogether.
>> But if not, then at a minimum the redundant check should be removed, and the
>> calculation involving Smbios.Hdr->Length should also be updated to use
>> SafeUintnAdd().
> 
> Fully agreeing to that.
> 
> take care,
>    Gerd
> 
> 
> 
> 
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#100182): https://edk2.groups.io/g/devel/message/100182
Mute This Topic: https://groups.io/mt/96938294/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-