[prev in list] [next in list] [prev in thread] [next in thread]
List: linuxbios
Subject: [coreboot] [coreboot - Bug #522] `region_overlap()` function might not work as expected due to an in
From: Nico Huber <coreboot () fe80 ! eu>
Date: 2024-02-10 20:31:52
Message-ID: redmine.journal-1753.20240210203152.700 () fe80 ! eu
[Download RAW message or body]
Issue #522 has been updated by Nico Huber.
Valerii Huhnin wrote in #note-14:
> * What are well-formed regions?
> * The last address of the region should be representable as a `size_t` value?
Definitely yes.
> * The last address of the region +1 should be representable as a `size_t` value?
This won't be necessary and would only complicate the implementation. Everybody seems \
to agree that we don't want this.
> * Regions should not have size 0 ?
There seems to be consensus that we don't need it (and it would also minimally \
complicate the implementation). Though, we should do some testing because it is hard \
to assess if any part of the code expects this to work.
> * What functions can assume that regions are well-formed?
> * region API functions?
> * SMRAM overlap check functions?
> * But for sure not the SMI handlers themselves?
We should check well-formedness before a `struct region` gets filled. Then any \
function using a struct region can assume that it's well formed.
> * Where should we check if a region is well-formed?
> * Create a dedicated function to check well-formdness of regions?
> * Create a dedicated constructor function and check it there?
We should explicitly check for invalid regions whenever data comes from outside of \
coreboot. We still need to decide on one of these two options. In any case, invalid \
external data should be handled gracefully.
> * Check it directly in region API functions?
We wouldn't want to do explicit error handling in every level of the API. IMO, an \
assert() in every public API function should suffice.
> * What should we do if we encounter a non-well-formed region?
> * Stop the execution?
> * Try to treat it as well-formed (e.g. by ignoring addresses outside of `SIZE_MAX`) \
> ?
> * Other context-dependent handling?
I'd say depending on the context as described above.
> Note: I also have a concern of the usage of the `size_t` type there. Shouldn't we \
> actually use `uintptr_t`? Might there be problems when converting between this two?
They should be the same anyway. A `struct region` only sometimes describes a region \
in memory, so `uintptr_t` wouldn't always be right.
> After looking at the `mainboard_smi_brigthness_down()` function I think that \
> regions whose last address is non-representable as `size_t` is a problem on its own \
> (independently from whether or not `region_overlap()` correctly detects overlap), \
> as having such regions would later lead to an attempt of constructing a pointer \
> that points outside of the address space.
This is true, but in this particular case, with the particular hardware, not a \
problem. The register should report 0 in the lower bits (except for the masked ones). \
This is also why the original overflow is hard to exploit with PCI BARs.
Maximilian Brune wrote in #note-15:
> > 2) Implement a specialized function that checks if the region is well-formed and \
> > returns a boolean value. I prefer this approach over ensuring well-formdness of \
> > regions in the constructor function because this would allow us to separate the \
> > well-formdness check itself from the handling of non-well-formed regions, which \
> > would also allow us to handle non-well-formed regions differently in different \
> > contexts if needed;
>
> I agree. The constructor should be separate from the check of itself. That gives us \
> the ability to check for sane values where it makes sense (SMM) and leave them out \
> for the rest (we can't check for overflows everywhere in the code base).
I proposed two different constructors in [1]. One that asserts and one that checks \
and allows to handle an error. I would prefer this over a separate function as it \
would make it clear when the check needs to be performed. If every API user with \
untrusted input would have to do the same `if (check(base, size)) ...`, I don't see \
what we win. I don't mind if somebody wants to implement it like that though. The \
callers that use region_create_unstrusted() in [1] are those that I identified as \
needing a check.
[1] https://review.coreboot.org/c/coreboot/+/79905/
> > 4) Call the region well-formdness check function directly inside the SMI handlers \
> > before the smm_points_to_smram() check function;
>
> Sounds good.
If they all go through smm_points_to_smram(), I would check there. Otherwise, the \
check could be missed on any new, future callers. That the region API is used that \
can overflow is also an implementation detail of smm_points_to_smram().
----------------------------------------
Bug #522: `region_overlap()` function might not work as expected due to an integer \
overflow in `region_end()` function.
https://ticket.coreboot.org/issues/522#change-1753
* Author: Vadim Zaliva
* Status: New
* Priority: Normal
* Category: coreboot common code
* Target version: none
* Start date: 2023-12-27
* Affected versions: master
* Related links: https://review.coreboot.org/q/topic:enforce_region_api
----------------------------------------
`region_overlap()` function checks whether or not two memory regions overlap. Memory \
regions are represented as a region struct that contains the region's offset and \
size. This function then relies on `region_end()` function to compute the end of the \
region. `region_end()` function is susceptible to an integer overflow, which might \
result in the incorrect behaviour of `region_overlap()` function.
An example of inputs that lead to wrong behaviour:
```
struct region r1 = {SIZE_MAX - 10, 20};
struct region r2 = {SIZE_MAX - 20, 15};
```
It returns 0, but since the regions actually overlap, it should return 1.
`region_overlap()` function is used in `smm_region_overlaps_handler()` function, \
which is itself used in SMI handlers to validate address values that come from an \
untrusted environment. This is necessary to prevent security vulnerabilities such as \
described in [BARing the System by Yuriy Bulygin, Oleksandr Bazhaniuk et \
al.](https://www.c7zero.info/stuff/REConBrussels2017_BARing_the_system.pdf)
We do not have an example of an exploit based on this incorrect behaviour and are \
aware of the existence of one. However, theoretically, this could lead to security \
vulnerabilities.
This bug was found during an ongoing [Coreboot Formal Verification \
Project](https://zaliva.org/UCSC-Twisted-Presentation-20231211.pdf), which aims to \
prove some important security properties of the coreboot's SMI handler for the Gemini \
Lake/Octopus platform using Coq proof assistant and Verified Software Toolchain \
framework.
---Files--------------------------------
diff.txt (930 Bytes)
--
You have received this notification because you have either subscribed to it, or are \
involved in it.
To change your notification preferences, please click here: \
https://ticket.coreboot.org/my/account
_______________________________________________
coreboot mailing list -- coreboot@coreboot.org
To unsubscribe send an email to coreboot-leave@coreboot.org
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic