KSPP / linux

Linux kernel source tree (Kernel Self Protection Project)
https://kernsec.org/wiki/index.php/Kernel_Self_Protection_Project
Other
80 stars 5 forks source link

Mitigate arithmetic wrap-around (overflow and underflow) #345

Open kees opened 9 months ago

kees commented 9 months ago

We must mitigate all arithmetic wrap-around (overflow and underflow). This requires solving it for each of the three variable types:

kees commented 9 months ago

One of the common "wrap" patterns is if (val + offset < val) { ... }. These can be found and replaced by Coccinelle:

@found@
unsigned long ULONG;
expression OFFSET;
@@

 {
+       unsigned long sum;
        ...
        (
-       ULONG + OFFSET < ULONG
+       check_add_overflow(ULONG, OFFSET, &sum)
        )
        ...
        (
-       ULONG + OFFSET
+       sum
        )
        ...
 }
kees commented 9 months ago

And to generally locate them:

@wrap_check@
void *PTR;
unsigned long ULONG;
unsigned int UINT;
expression OFFSET;
@@

        (
(
-       PTR + OFFSET < PTR
+       ULONG_MAX - OFFSET > PTR
|
-       ULONG + OFFSET < ULONG
+       ULONG_MAX - OFFSET > ULONG
|
-       UINT + OFFSET < UINT
+       UINT_MAX - OFFSET > UINT
)
        )

But this conversion results in worse code gen. It may be useful to add a wrapper macro:

#define would_add_overflow(a, b) ({ \
    typeof(a) __maybe_overflowed_sum; \
    check_add_overflow(a, b, &__maybe_overflowed_sum); \
})

See https://godbolt.org/z/Kc7vsMd9W