Re: [PATCH v4 1/2] kernel.h: Introduce const_max() for VLA removal
From: Miguel Ojeda <hidden>
Date: 2018-03-15 22:58:10
Also in:
lkml, netdev
On Thu, Mar 15, 2018 at 11:46 PM, Kees Cook [off-list ref] wrote:
On Thu, Mar 15, 2018 at 3:23 PM, Linus Torvalds [off-list ref] wrote:quoted
On Thu, Mar 15, 2018 at 3:16 PM, Kees Cook [off-list ref] wrote:quoted
size_t __error_not_const_arg(void) \ __compiletime_error("const_max() used with non-compile-time constant arg"); #define const_max(x, y) \ __builtin_choose_expr(__builtin_constant_p(x) && \ __builtin_constant_p(y), \ (typeof(x))(x) > (typeof(y))(y) ? \ (x) : (y), \ __error_not_const_arg()) Is typeof() forcing enums to int? Regardless, I'll put this through larger testing. How does that look?Ok, that alleviates my worry about one class of insane behavior, but it does raise a few other questions: - what drugs is gcc on where (typeof(x)(x)) makes a difference? Funky.Yeah, that's why I didn't even try that originally. But in looking back at max() again, it seemed to be the only thing missing that would handle the enum evaluation, which turned out to be true.quoted
- this does have the usual "what happen if you do const_max(-1,sizeof(x)) where the comparison will now be done in 'size_t', and -1 ends up being a very very big unsigned integer. Is there no way to get that type checking inserted? Maybe now is a good point for that __builtin_types_compatible(), and add it to the constness checking (and change the name of that error case function)?So, AIUI, I can either get strict type checking, in which case, this is rejected (which I assume there is still a desire to have): int foo[const_max(6, sizeof(whatever))];
Is it that bad to just call it with (size_t)6?
due to __builtin_types_compatible_p() rejecting it, or I can construct a "positive arguments only" test, in which the above is accepted, but this is rejected: int foo[const_max(-1, sizeof(whatever))];
Do we need this case?
By using this eye-bleed:
size_t __error_not_const_arg(void) \
__compiletime_error("const_max() used with non-compile-time constant arg");
size_t __error_not_positive_arg(void) \
__compiletime_error("const_max() used with negative arg");
#define const_max(x, y) \
__builtin_choose_expr(__builtin_constant_p(x) && \
__builtin_constant_p(y), \
__builtin_choose_expr((x) >= 0 && (y) >= 0, \
(typeof(x))(x) > (typeof(y))(y) ? \
(x) : (y), \
__error_not_positive_arg()), \
__error_not_const_arg())
I was writing it like this:
#define const_max(a, b) \
({ \
if ((a) < 0) \
__const_max_called_with_negative_value(); \
if ((b) < 0) \
__const_max_called_with_negative_value(); \
if (!__builtin_types_compatible_p(typeof(a), typeof(b))) \
__const_max_called_with_incompatible_types(); \
__builtin_choose_expr((a) > (b), (a), (b)); \
})
Cheers,
Miguel
-Kees -- Kees Cook Pixel Security