kernel.h: Retain constant expression output for max()/min()
PATCH v7 1/1 kernel.h: Retain constant expression output for max()/min()
In the effort to remove all VLAs from the kernel[1], it is desirable to build with -Wvla. However, this warning is overly pessimistic, in that it is only happy with stack array sizes that are declared as constant expressions, and not constant values. One case of this is the evaluation of the max() macro which, due to its construction, ends up converting constant expression arguments into a constant value result.
All attempts to rewrite this macro with __builtin_constant_p() failed with older compilers (e.g. gcc 4.4)[2]. However, Martin Uecker, constructed[3] a mind-shattering solution that works everywhere. Cthulhu fhtagn!
This patch updates the min()/max() macros to evaluate to a constant expression when called on constant expression arguments. This removes several false-positive stack VLA warnings from an x86 allmodconfig build when -Wvla is added:
$ diff -u before.txt after.txt | grep ^- -drivers/input/touchscreen/cyttsp4_core.c:871:2: warning: ISO C90 forbids variable length array ‘ids’ [-Wvla] -fs/btrfs/tree-checker.c:344:4: warning: ISO C90 forbids variable length array ‘namebuf’ [-Wvla] -lib/vsprintf.c:747:2: warning: ISO C90 forbids variable length array ‘sym’ [-Wvla] -net/ipv4/proc.c:403:2: warning: ISO C90 forbids variable length array ‘buff’ [-Wvla] -net/ipv6/proc.c:198:2: warning: ISO C90 forbids variable length array ‘buff’ [-Wvla] -net/ipv6/proc.c:218:2: warning: ISO C90 forbids variable length array ‘buff64’ [-Wvla]
This also updates the one case where different enums were being compared and explicitly casts them to int (which matches the old side-effect of the single-evaluation code).
[1] https://lkml.org/lkml/2018/3/7/621
[2] https://lkml.org/lkml/2018/3/10/170
[3] https://lkml.org/lkml/2018/3/20/845
---
v7:
- __is_constant() renamed to __is_constexpr() (Miguel Ojeda)
- adjust memory offset from 1 to 8 (David Laight)
- min_t()/max_t() "t" renamed back to "type" (0-day bot)
- add Acks
--- drivers/char/tpm/tpm_tis_core.h | 8 ++--- include/linux/kernel.h | 71 ++++++++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 34 deletions(-)
drivers/char/tpm/tpm_tis_core.h +4 -4
@@ -62,10 +62,10 @@ enum tis_defaults {/* Some timeout values are needed before it is known whether the chip is * TPM 1.0 or TPM 2.0. */ -#define TIS_TIMEOUT_A_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A) -#define TIS_TIMEOUT_B_MAX max(TIS_LONG_TIMEOUT, TPM2_TIMEOUT_B) -#define TIS_TIMEOUT_C_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_C) -#define TIS_TIMEOUT_D_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_D) +#define TIS_TIMEOUT_A_MAX max_t(int, TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A) +#define TIS_TIMEOUT_B_MAX max_t(int, TIS_LONG_TIMEOUT, TPM2_TIMEOUT_B) +#define TIS_TIMEOUT_C_MAX max_t(int, TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_C) +#define TIS_TIMEOUT_D_MAX max_t(int, TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_D)#define TPM_ACCESS (l) (0x0000 | ((l) << 12))#define TPM_INT_ENABLE (l) (0x0008 | ((l) << 12))
include/linux/kernel.h +41 -30
102 lines not on this page · raw message
Signature · 6 lines
2.7.4 -- Kees Cook Pixel Security
Quoted 2 lines · Kees Cook
This patch updates the min()/max() macros to evaluate to a constant expression when called on constant expression arguments. This removes
Hi Linus,
This patch seems finished (*knock on wood*). Do you want to take this directly for v4.17, should I send a single-patch pull-request, or should this go through -mm (for either 4.17 or 4.18)?
Thanks!
-Kees
Signature · 2 lines
Kees Cook Pixel Security
Quoted 4 lines · Kees Cook
This patch seems finished (*knock on wood*). Do you want to take this directly for v4.17, should I send a single-patch pull-request, or should this go through -mm (for either 4.17 or 4.18)?
I was actually expecting it to go with the other VLA removal patches, but if the plan is to try to just get them in individual maintainer trees, I guess I can just take this directly.
So if it would be a single-commit pull request, I'll just take it as a patch. I guess it could go through -mm, but since I was involved in the discussion anyway, I also don't mind just taking it directly. If it causes problems, I can curse at myself.
Linus
Quoted 9 lines · Linus Torvalds
Quoted 4 lines · Kees Cook
This patch seems finished (*knock on wood*). Do you want to take this directly for v4.17, should I send a single-patch pull-request, or should this go through -mm (for either 4.17 or 4.18)?
I was actually expecting it to go with the other VLA removal patches, but if the plan is to try to just get them in individual maintainer trees, I guess I can just take this directly.
Yeah, the VLA patches have been going through maintainer trees -- mostly due to needing specialized review, etc. While many are trivial, a fair number aren't (or at least the trade-offs aren't always obvious).
Quoted 4 lines
So if it would be a single-commit pull request, I'll just take it as a patch. I guess it could go through -mm, but since I was involved in the discussion anyway, I also don't mind just taking it directly. If it causes problems, I can curse at myself.
Yeah, I'm in no rush to collect the "unresponded" VLA patches into a tree, and we've still got more to go, so right now it'd just be a single-patch pull. If you can snag it now, that'd be great! :)
Thanks!
-Kees
Signature · 2 lines
Kees Cook Pixel Security
Quoted 4 lines · Kees Cook
Yeah, I'm in no rush to collect the "unresponded" VLA patches into a tree, and we've still got more to go, so right now it'd just be a single-patch pull. If you can snag it now, that'd be great! :)
Ok, applied.
Linus
Quoted 2 lines · Linus Torvalds
Ok, applied.
Ugh, during the merge window, we had actually grown a new example of that "different enum types" problem:
struct drm_prop_enum_list enum_list[max(DRM_COLOR_ENCODING_MAX,
DRM_COLOR_RANGE_MAX)];
in drm_plane_create_color_properties() in the drm drm_color_mgmt.c file.
I ended up just fixing it up manually and added it to the commit. You should double-check my change, I've pushed it out now that the build seems ok for me.
There may be others hiding that weren't caught by my limited build testing, trhough. So please keep an eye out for build warnings.
Linus
Quoted 8 lines · Linus Torvalds
Quoted 2 lines · Linus Torvalds
Ok, applied.
Ugh, during the merge window, we had actually grown a new example of that "different enum types" problem:
Quoted 8 lines
struct
drm_prop_enum_listenum_list[max(DRM_COLOR_ENCODING_MAX,
DRM_COLOR_RANGE_MAX)];in
drm_plane_create_color_properties()in the drmdrm_color_mgmt.cfile.I ended up just fixing it up manually and added it to the commit. You should double-check my change, I've pushed it out now that the build seems ok for me.
Looks good; thanks!
Quoted 2 lines
There may be others hiding that weren't caught by my limited build testing, trhough. So please keep an eye out for build warnings.
I'll spin up my full multi-arch allmodconfig builds and see if anything kicks out...
-Kees
Signature · 2 lines
Kees Cook Pixel Security
Quoted 7 lines · Kees Cook
Quoted 2 lines · Linus Torvalds
There may be others hiding that weren't caught by my limited build testing, trhough. So please keep an eye out for build warnings.
I'll spin up my full multi-arch allmodconfig builds and see if anything kicks out...
FWIW, nothing exploded on allmodconfig for x86_64, arm64, i386, arm, powerpc64, s390, powerpc, mips, nor sparc64...
-Kees
Signature · 2 lines
Kees Cook Pixel Security