Hello Nguyen, > Date: 2026-10-10 23:44:49+0700 > From: Nguyen Ngoc Thang > > With clang 22 and CONFIG_FORTIFY_SOURCE, the second > landlock_restrict_self() call hits a bogus fortify report in > inherit_ruleset(): > > memcpy: detected buffer overflow: 16 byte read of buffer size 0 > Call Trace: > __fortify_panic > landlock_merge_ruleset+0xc46/0xc90 > __se_sys_landlock_restrict_self+0x2bc/0xd40 > > layers[] lives in an anonymous struct inside the anonymous union > that overlays work_free. For such a flexible array, clang computes the > address of the __counted_by counter as the start of the array instead of > &num_layers. The bound is then read from layers[0], i.e. from > the first layer's configuration, which is not a count. The same layout > crashes clang itself in a standalone test. > > The annotation was added as documentation, so drop it rather than > restructure the union. Keep the information in the member comment. > > Reported-by: syzbot+a0eecb22de4d821a9e5d@syzkaller.appspotmail.com > Closes: https://syzkaller.appspot.com/bug?extid=a0eecb22de4d821a9e5d > Fixes: bd3a19800dd1 ("landlock: Add counted_by in landlock_domain") > Signed-off-by: Nguyen Ngoc Thang > --- > Reproduced with clang 22.1.8 and FORTIFY_SOURCE on mic/next (64b9e6eff524): > the second landlock_restrict_self() hits the report, while 16 nested > restricts run clean with this patch. Mickaƫl, if you prefer to just drop > bd3a19800dd1 from next, that works as well. Is this reproducible with Clang 23 or later? Should __counted_by() expand to nothing for bogus versions of Clang? That would allow using it, and just ignore Clang when it's broken, rather than not using safety features. Have a lovely day! Alex > security/landlock/domain.h | 6 +++++- > 1 file changed, 5 insertions(+), 1 deletion(-) > > diff --git a/security/landlock/domain.h b/security/landlock/domain.h > index 60e8eb2d6ac2..4bf1555a4349 100644 > --- a/security/landlock/domain.h > +++ b/security/landlock/domain.h > @@ -246,8 +246,12 @@ struct landlock_domain { > * properly handle merged rulesets without overlapping > * access rights. These layers are set once and never > * changed for the lifetime of the domain. > + * > + * Not annotated with __counted_by(@num_layers): clang > + * miscomputes the counter address for a FAM nested in an > + * anonymous struct within a union, which trips FORTIFY. > */ > - struct layer_config layers[] __counted_by(num_layers); > + struct layer_config layers[]; > }; > }; > }; > -- > 2.43.0 > > --