1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
From 29feced5e1e91c349718f36fe610142522263b61 Mon Sep 17 00:00:00 2001
From: Sasha Levin <sashal@kernel.org>
Date: Fri, 30 May 2025 15:18:28 -0700
Subject: randstruct: gcc-plugin: Fix attribute addition
From: Kees Cook <kees@kernel.org>
[ Upstream commit f39f18f3c3531aa802b58a20d39d96e82eb96c14 ]
Based on changes in the 2021 public version of the randstruct
out-of-tree GCC plugin[1], more carefully update the attributes on
resulting decls, to avoid tripping checks in GCC 15's
comptypes_check_enum_int() when it has been configured with
"--enable-checking=misc":
arch/arm64/kernel/kexec_image.c:132:14: internal compiler error: in comptypes_check_enum_int, at c/c-typeck.cc:1519
132 | const struct kexec_file_ops kexec_image_ops = {
| ^~~~~~~~~~~~~~
internal_error(char const*, ...), at gcc/gcc/diagnostic-global-context.cc:517
fancy_abort(char const*, int, char const*), at gcc/gcc/diagnostic.cc:1803
comptypes_check_enum_int(tree_node*, tree_node*, bool*), at gcc/gcc/c/c-typeck.cc:1519
...
Link: https://archive.org/download/grsecurity/grsecurity-3.1-5.10.41-202105280954.patch.gz [1]
Reported-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Closes: https://github.com/KSPP/linux/issues/367
Closes: https://lore.kernel.org/lkml/20250530000646.104457-1-thiago.bauermann@linaro.org/
Reported-by: Ingo Saitz <ingo@hannover.ccc.de>
Closes: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1104745
Fixes: 313dd1b62921 ("gcc-plugins: Add the randstruct plugin")
Tested-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
Link: https://lore.kernel.org/r/20250530221824.work.623-kees@kernel.org
Signed-off-by: Kees Cook <kees@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
scripts/gcc-plugins/gcc-common.h | 32 +++++++++++++++++++
scripts/gcc-plugins/randomize_layout_plugin.c | 22 ++++++-------
2 files changed, 43 insertions(+), 11 deletions(-)
diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h
index 1ae39b9f4a95e..90e83d62adb54 100644
--- a/scripts/gcc-plugins/gcc-common.h
+++ b/scripts/gcc-plugins/gcc-common.h
@@ -128,6 +128,38 @@ static inline tree build_const_char_string(int len, const char *str)
return cstr;
}
+static inline void __add_type_attr(tree type, const char *attr, tree args)
+{
+ tree oldattr;
+
+ if (type == NULL_TREE)
+ return;
+ oldattr = lookup_attribute(attr, TYPE_ATTRIBUTES(type));
+ if (oldattr != NULL_TREE) {
+ gcc_assert(TREE_VALUE(oldattr) == args || TREE_VALUE(TREE_VALUE(oldattr)) == TREE_VALUE(args));
+ return;
+ }
+
+ TYPE_ATTRIBUTES(type) = copy_list(TYPE_ATTRIBUTES(type));
+ TYPE_ATTRIBUTES(type) = tree_cons(get_identifier(attr), args, TYPE_ATTRIBUTES(type));
+}
+
+static inline void add_type_attr(tree type, const char *attr, tree args)
+{
+ tree main_variant = TYPE_MAIN_VARIANT(type);
+
+ __add_type_attr(TYPE_CANONICAL(type), attr, args);
+ __add_type_attr(TYPE_CANONICAL(main_variant), attr, args);
+ __add_type_attr(main_variant, attr, args);
+
+ for (type = TYPE_NEXT_VARIANT(main_variant); type; type = TYPE_NEXT_VARIANT(type)) {
+ if (!lookup_attribute(attr, TYPE_ATTRIBUTES(type)))
+ TYPE_ATTRIBUTES(type) = TYPE_ATTRIBUTES(main_variant);
+
+ __add_type_attr(TYPE_CANONICAL(type), attr, args);
+ }
+}
+
#define PASS_INFO(NAME, REF, ID, POS) \
struct register_pass_info NAME##_pass_info = { \
.pass = make_##NAME##_pass(), \
diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c
index 2b93dd14bd7b6..b00681ad3e383 100644
--- a/scripts/gcc-plugins/randomize_layout_plugin.c
+++ b/scripts/gcc-plugins/randomize_layout_plugin.c
@@ -77,6 +77,9 @@ static tree handle_randomize_layout_attr(tree *node, tree name, tree args, int f
if (TYPE_P(*node)) {
type = *node;
+ } else if (TREE_CODE(*node) == FIELD_DECL) {
+ *no_add_attrs = false;
+ return NULL_TREE;
} else {
gcc_assert(TREE_CODE(*node) == TYPE_DECL);
type = TREE_TYPE(*node);
@@ -363,15 +366,14 @@ static int relayout_struct(tree type)
TREE_CHAIN(newtree[i]) = newtree[i+1];
TREE_CHAIN(newtree[num_fields - 1]) = NULL_TREE;
+ add_type_attr(type, "randomize_performed", NULL_TREE);
+ add_type_attr(type, "designated_init", NULL_TREE);
+ if (has_flexarray)
+ add_type_attr(type, "has_flexarray", NULL_TREE);
+
main_variant = TYPE_MAIN_VARIANT(type);
- for (variant = main_variant; variant; variant = TYPE_NEXT_VARIANT(variant)) {
+ for (variant = main_variant; variant; variant = TYPE_NEXT_VARIANT(variant))
TYPE_FIELDS(variant) = newtree[0];
- TYPE_ATTRIBUTES(variant) = copy_list(TYPE_ATTRIBUTES(variant));
- TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("randomize_performed"), NULL_TREE, TYPE_ATTRIBUTES(variant));
- TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("designated_init"), NULL_TREE, TYPE_ATTRIBUTES(variant));
- if (has_flexarray)
- TYPE_ATTRIBUTES(type) = tree_cons(get_identifier("has_flexarray"), NULL_TREE, TYPE_ATTRIBUTES(type));
- }
/*
* force a re-layout of the main variant
@@ -439,10 +441,8 @@ static void randomize_type(tree type)
if (lookup_attribute("randomize_layout", TYPE_ATTRIBUTES(TYPE_MAIN_VARIANT(type))) || is_pure_ops_struct(type))
relayout_struct(type);
- for (variant = TYPE_MAIN_VARIANT(type); variant; variant = TYPE_NEXT_VARIANT(variant)) {
- TYPE_ATTRIBUTES(type) = copy_list(TYPE_ATTRIBUTES(type));
- TYPE_ATTRIBUTES(type) = tree_cons(get_identifier("randomize_considered"), NULL_TREE, TYPE_ATTRIBUTES(type));
- }
+ add_type_attr(type, "randomize_considered", NULL_TREE);
+
#ifdef __DEBUG_PLUGIN
fprintf(stderr, "Marking randomize_considered on struct %s\n", ORIG_TYPE_NAME(type));
#ifdef __DEBUG_VERBOSE
--
2.39.5
|