drivers/fpga/dfl-afu-region.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
From: Hongyu Xie <xiehongyu1@kylinos.cn>
Overflow Scenarios:
1, region->offset + region->size Overflow:
When region->offset is close to U64_MAX and region->size is
sufficiently large, the addition result may wrap around to a
very small value (e.g., 0 or near 0).
In this case, even if the target range [offset, offset+size)
falls within the region, the condition region->offset +
region->size >= offset + size will fail due to the wrapped
value being small. This causes the function to erroneously
return -EINVAL.
2, offset + size Overflow:
When offset is close to U64_MAX and size is large, offset +
size wraps around to a small value.
Here, region->offset + region->size (which would be a large
value if not overflowing) might incorrectly satisfy
region->offset + region->size >= offset + size due to the
wrapped small value. This leads to a false match, even though
the actual range [offset, offset+size) spans the wrap-around
boundary and does not belong to this region.
So fix these two scenarios.
Signed-off-by: Hongyu Xie <xiehongyu1@kylinos.cn>
---
drivers/fpga/dfl-afu-region.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/fpga/dfl-afu-region.c b/drivers/fpga/dfl-afu-region.c
index b11a5b21e666..449c2ae809bd 100644
--- a/drivers/fpga/dfl-afu-region.c
+++ b/drivers/fpga/dfl-afu-region.c
@@ -157,7 +157,8 @@ int afu_mmio_region_get_by_offset(struct dfl_feature_dev_data *fdata,
afu = dfl_fpga_fdata_get_private(fdata);
for_each_region(region, afu)
if (region->offset <= offset &&
- region->offset + region->size >= offset + size) {
+ region->size >= size &&
+ (offset - region->offset) <= (region->size - size)) {
*pregion = *region;
goto exit;
}
--
2.25.1
On Mon, Aug 04, 2025 at 04:25:23PM +0800, xiehongyu1@kylinos.cn wrote: > From: Hongyu Xie <xiehongyu1@kylinos.cn> > > Overflow Scenarios: > 1, region->offset + region->size Overflow: > When region->offset is close to U64_MAX and region->size is > sufficiently large, the addition result may wrap around to a > very small value (e.g., 0 or near 0). > In this case, even if the target range [offset, offset+size) > falls within the region, the condition region->offset + > region->size >= offset + size will fail due to the wrapped > value being small. This causes the function to erroneously > return -EINVAL. > > 2, offset + size Overflow: > When offset is close to U64_MAX and size is large, offset + > size wraps around to a small value. > > Here, region->offset + region->size (which would be a large > value if not overflowing) might incorrectly satisfy > region->offset + region->size >= offset + size due to the > wrapped small value. This leads to a false match, even though > the actual range [offset, offset+size) spans the wrap-around > boundary and does not belong to this region. > > So fix these two scenarios. > > Signed-off-by: Hongyu Xie <xiehongyu1@kylinos.cn> > --- > drivers/fpga/dfl-afu-region.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/drivers/fpga/dfl-afu-region.c b/drivers/fpga/dfl-afu-region.c > index b11a5b21e666..449c2ae809bd 100644 > --- a/drivers/fpga/dfl-afu-region.c > +++ b/drivers/fpga/dfl-afu-region.c > @@ -157,7 +157,8 @@ int afu_mmio_region_get_by_offset(struct dfl_feature_dev_data *fdata, > afu = dfl_fpga_fdata_get_private(fdata); > for_each_region(region, afu) > if (region->offset <= offset && > - region->offset + region->size >= offset + size) { > + region->size >= size && > + (offset - region->offset) <= (region->size - size)) { You don't have to use these tricks, they make the code hard to understand. If you care about the overflow, just pick some helpers from overflow.h And don't check region->offset + region->size for every get, they should be properly initialized at the very beginning. Thanks, Yilun > *pregion = *region; > goto exit; > } > -- > 2.25.1 > >
© 2016 - 2025 Red Hat, Inc.