Commit c77b30b
bpf: Fix undefined behavior in interpreter sdiv/smod for INT_MIN
The BPF interpreter's signed 32-bit division and modulo handlers use
the kernel abs() macro on s32 operands. The abs() macro documentation
(include/linux/math.h) explicitly states the result is undefined when
the input is the type minimum. When DST contains S32_MIN (0x80000000),
abs((s32)DST) triggers undefined behavior and returns S32_MIN unchanged
on arm64/x86. This value is then sign-extended to u64 as
0xFFFFFFFF80000000, causing do_div() to compute the wrong result.
The verifier's abstract interpretation (scalar32_min_max_sdiv) computes
the mathematically correct result for range tracking, creating a
verifier/interpreter mismatch that can be exploited for out-of-bounds
map value access.
Introduce abs_s32() which handles S32_MIN correctly by casting to u32
before negating, avoiding signed overflow entirely. Replace all 8
abs((s32)...) call sites in the interpreter's sdiv32/smod32 handlers.
s32 is the only affected case -- the s64 division/modulo handlers do
not use abs().
Fixes: ec0e2da ("bpf: Support new signed div/mod instructions.")
Acked-by: Yonghong Song <[email protected]>
Acked-by: Mykyta Yatsenko <[email protected]>
Signed-off-by: Jenny Guanni Qu <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Alexei Starovoitov <[email protected]>1 parent a1e5c46 commit c77b30b
1 file changed
Lines changed: 14 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1757 | 1757 | | |
1758 | 1758 | | |
1759 | 1759 | | |
| 1760 | + | |
| 1761 | + | |
| 1762 | + | |
| 1763 | + | |
| 1764 | + | |
| 1765 | + | |
1760 | 1766 | | |
1761 | 1767 | | |
1762 | 1768 | | |
| |||
1921 | 1927 | | |
1922 | 1928 | | |
1923 | 1929 | | |
1924 | | - | |
1925 | | - | |
| 1930 | + | |
| 1931 | + | |
1926 | 1932 | | |
1927 | 1933 | | |
1928 | 1934 | | |
| |||
1949 | 1955 | | |
1950 | 1956 | | |
1951 | 1957 | | |
1952 | | - | |
1953 | | - | |
| 1958 | + | |
| 1959 | + | |
1954 | 1960 | | |
1955 | 1961 | | |
1956 | 1962 | | |
| |||
1976 | 1982 | | |
1977 | 1983 | | |
1978 | 1984 | | |
1979 | | - | |
1980 | | - | |
| 1985 | + | |
| 1986 | + | |
1981 | 1987 | | |
1982 | 1988 | | |
1983 | 1989 | | |
| |||
2003 | 2009 | | |
2004 | 2010 | | |
2005 | 2011 | | |
2006 | | - | |
2007 | | - | |
| 2012 | + | |
| 2013 | + | |
2008 | 2014 | | |
2009 | 2015 | | |
2010 | 2016 | | |
| |||
0 commit comments