Potential Integer Overflow in video_splash_align_axis() Function
yb
ybdesire at 163.com
Tue May 27 13:12:32 CEST 2025
Dears,
Hello everyone, I have found a potential vulnerability. The specific description is as follows. Please help me check whether this is a real vulnerability.
1. Description
This code demonstrates the CWE-190 (Integer Overflow or Wraparound) vulnerability in the `video_splash_align_axis()` function, which fails to properly handle unsigned-to-signed integer conversions and arithmetic operations.
https://github.com/u-boot/u-boot/blob/70dfd674782adb47a641288925484d6edc8df963/drivers/video/video_bmp.c#L229\
The current main branch also has this vulnerability.
2. Vulnerability Details
Integer Overflow Mechanism:
The function subtracts two `unsigned long` values (`panel_size` and `picture_size`), storing the result in a `long` variable.
When `panel_size < picture_size`, the unsigned subtraction yields a large positive value (e.g., `ULONG_MAX - delta`), which converts to a **negative signed value** due to undefined behavior.
Subsequent division by 2 and casting to `int` can cause truncation or sign reversal, leading to unexpected coordinate values.
3. Exploit
An attacker could exploit this vulnerability by:
(1) Forcing `panel_size < picture_size`: Supply crafted values (e.g., `panel_size = 100`, `picture_size = ULONG_MAX - 100`) to trigger a large unsigned result.
(2) Triggering Signed Conversion: The unsigned result converts to a negative signed value, which is then divided and cast to `int`.
(3) Causing Unintended Behavior: The final `int` value (e.g., `-10` instead of the expected `1000000000`) can crash the application if the coordinate is used as a memory offset. Or bypass security checks by creating out-of-bounds conditions.
4. Proof of Concept (PoC)
The provided code demonstrates the vulnerability by:
- Setting `panel_size = ULONG_MAX - 10` and `picture_size = 10`.
- The subtraction results in `ULONG_MAX - 20`, which converts to `-21` when cast to `long`.
- Division by 2 yields `-10`, which is assigned to `axis`, causing unexpected alignment.
```c
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define BMP_ALIGN_CENTER 0x7fff
static void video_splash_align_axis(int *axis, unsigned long panel_size,
unsigned long picture_size)
{
unsigned long panel_picture_delta = panel_size - picture_size;
long axis_alignment;
printf("Before calculation: panel_size = %lu, picture_size = %lu\n", panel_size, picture_size);
printf("panel_size - picture_size = %lu (unsigned)\n", panel_picture_delta);
// Force conversion to signed long, may cause sign error
long signed_delta = (long)panel_picture_delta;
printf("Converted to signed: %ld\n", signed_delta);
if (*axis == BMP_ALIGN_CENTER)
axis_alignment = signed_delta / 2;
else if (*axis < 0)
axis_alignment = signed_delta + *axis + 1;
else
return;
printf("axis_alignment = %ld\n", axis_alignment);
printf("int range before conversion: INT_MIN=%d, INT_MAX=%d\n", INT_MIN, INT_MAX);
// Check for 64-bit overflow condition
if (axis_alignment > LONG_MAX || axis_alignment < LONG_MIN) {
printf("Warning: Calculation result exceeds long range! (%ld)\n", axis_alignment);
}
*axis = (int)axis_alignment;
printf("Converted to int: %d (binary: 0x%08x)\n", *axis, *axis);
}
int main() {
// Use values close to ULONG_MAX to ensure overflow
unsigned long panel_size = ULONG_MAX - 10; // 2^64 - 11
unsigned long picture_size = 10;
int axis = BMP_ALIGN_CENTER;
printf("Before call: axis = %d, panel_size = %lu, picture_size = %lu\n",
axis, panel_size, picture_size);
video_splash_align_axis(&axis, panel_size, picture_size);
printf("After call: axis = %d (Expected positive value, but overflowed to negative)\n", axis);
return 0;
}
```
output:
```
Before call: axis = 32767, panel_size = 18446744073709551605, picture_size = 10
Before calculation: panel_size = 18446744073709551605, picture_size = 10
panel_size - picture_size = 18446744073709551595 (unsigned)
Converted to signed: -21
axis_alignment = -10
int range before conversion: INT_MIN=-2147483648, INT_MAX=2147483647
Converted to int: -10 (binary: 0xfffffff6)
After call: axis = -10 (Expected positive value, but overflowed to negative)
```
Best Regards,
ybdesire
More information about the U-Boot
mailing list