Skip to content

Commit 65100f7

Browse files
keesUlrich Hecht
authored andcommitted
randstruct: gcc-plugin: Remove bogus void member
[ Upstream commit e136a4062174a9a8d1c1447ca040ea81accfa6a8 ] When building the randomized replacement tree of struct members, the randstruct GCC plugin would insert, as the first member, a 0-sized void member. This appears as though it was done to catch non-designated ("unnamed") static initializers, which wouldn't be stable since they depend on the original struct layout order. This was accomplished by having the side-effect of the "void member" tripping an assert in GCC internals (count_type_elements) if the member list ever needed to be counted (e.g. for figuring out the order of members during a non-designated initialization), which would catch impossible type (void) in the struct: security/landlock/fs.c: In function ‘hook_file_ioctl_common’: security/landlock/fs.c:1745:61: internal compiler error: in count_type_elements, at expr.cc:7075 1745 | .u.op = &(struct lsm_ioctlop_audit) { | ^ static HOST_WIDE_INT count_type_elements (const_tree type, bool for_ctor_p) { switch (TREE_CODE (type)) ... case VOID_TYPE: default: gcc_unreachable (); } } However this is a redundant safety measure since randstruct uses the __designated_initializer attribute both internally and within the __randomized_layout attribute macro so that this would be enforced by the compiler directly even when randstruct was not enabled (via -Wdesignated-init). A recent change in Landlock ended up tripping the same member counting routine when using a full-struct copy initializer as part of an anonymous initializer. This, however, is a false positive as the initializer is copying between identical structs (and hence identical layouts). The "path" member is "struct path", a randomized struct, and is being copied to from another "struct path", the "f_path" member: landlock_log_denial(landlock_cred(file->f_cred), &(struct landlock_request) { .type = LANDLOCK_REQUEST_FS_ACCESS, .audit = { .type = LSM_AUDIT_DATA_IOCTL_OP, .u.op = &(struct lsm_ioctlop_audit) { .path = file->f_path, .cmd = cmd, }, }, ... As can be seen with the coming randstruct KUnit test, there appears to be no behavioral problems with this kind of initialization when the void member is removed from the randstruct GCC plugin, so remove it. Reported-by: "Dr. David Alan Gilbert" <linux@treblig.org> Closes: https://lore.kernel.org/lkml/Z_PRaKx7q70MKgCA@gallifrey/ Reported-by: Mark Brown <broonie@kernel.org> Closes: https://lore.kernel.org/lkml/20250407-kbuild-disable-gcc-plugins-v1-1-5d46ae583f5e@kernel.org/ Reported-by: WangYuli <wangyuli@uniontech.com> Closes: https://lore.kernel.org/lkml/337D5D4887277B27+3c677db3-a8b9-47f0-93a4-7809355f1381@uniontech.com/ Fixes: 313dd1b ("gcc-plugins: Add the randstruct plugin") Signed-off-by: Kees Cook <kees@kernel.org> Stable-dep-of: f39f18f3c353 ("randstruct: gcc-plugin: Fix attribute addition") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Ulrich Hecht <uli@kernel.org>
1 parent f615da5 commit 65100f7

1 file changed

Lines changed: 1 addition & 17 deletions

File tree

scripts/gcc-plugins/randomize_layout_plugin.c

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -377,29 +377,13 @@ static int relayout_struct(tree type)
377377

378378
shuffle(type, (tree *)newtree, shuffle_length);
379379

380-
/*
381-
* set up a bogus anonymous struct field designed to error out on unnamed struct initializers
382-
* as gcc provides no other way to detect such code
383-
*/
384-
list = make_node(FIELD_DECL);
385-
TREE_CHAIN(list) = newtree[0];
386-
TREE_TYPE(list) = void_type_node;
387-
DECL_SIZE(list) = bitsize_zero_node;
388-
DECL_NONADDRESSABLE_P(list) = 1;
389-
DECL_FIELD_BIT_OFFSET(list) = bitsize_zero_node;
390-
DECL_SIZE_UNIT(list) = size_zero_node;
391-
DECL_FIELD_OFFSET(list) = size_zero_node;
392-
DECL_CONTEXT(list) = type;
393-
// to satisfy the constify plugin
394-
TREE_READONLY(list) = 1;
395-
396380
for (i = 0; i < num_fields - 1; i++)
397381
TREE_CHAIN(newtree[i]) = newtree[i+1];
398382
TREE_CHAIN(newtree[num_fields - 1]) = NULL_TREE;
399383

400384
main_variant = TYPE_MAIN_VARIANT(type);
401385
for (variant = main_variant; variant; variant = TYPE_NEXT_VARIANT(variant)) {
402-
TYPE_FIELDS(variant) = list;
386+
TYPE_FIELDS(variant) = newtree[0];
403387
TYPE_ATTRIBUTES(variant) = copy_list(TYPE_ATTRIBUTES(variant));
404388
TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("randomize_performed"), NULL_TREE, TYPE_ATTRIBUTES(variant));
405389
TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("designated_init"), NULL_TREE, TYPE_ATTRIBUTES(variant));

0 commit comments

Comments
 (0)