Skip to contentSkip to conversation

kernel.h: Retain constant expression output for max()/min()

PATCH In review Kees Cook 2 participants 8 messages Mar 31, 2018 – Apr 6, 2018 TPM device driver

lore
Share & tools
lore

Kees Cook

author
#0 lore raw

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
index d5c6a2e952b3..f6e1dbe212a7 100644
@@ -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
author
#1 lore raw
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
#2 lore raw
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

author
#3 lore raw
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
#4 lore raw
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

#5 lore raw
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

author
#6 lore raw
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_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.

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
author
#7 lore raw
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