mjbommar wrote:
Hi all,
Just following up from the lkml post below to say that I hit this on 7.3-rc5
through xz -> `landlock_merge_ruleset()` on 26.04.
https://lore.kernel.org/llvm/[email protected]/
My build is x86_64 clang 21.1.8.
In case it's helpful, here's some Claudeslop below from debugging the crash and
getting here:
<CLAUDE>
Reduced userspace reproducer:
```c
#include <stdio.h>
#include <stdlib.h>
struct m { unsigned int v; };
struct dom {
void *pad[4];
union {
long w[4]; /* largest member, like
work_struct */
struct {
unsigned int usage;
unsigned int num_layers;
struct m fam[] __attribute__((counted_by(num_layers)));
};
};
};
__attribute__((noinline)) static size_t bdos(struct dom *d)
{
return __builtin_dynamic_object_size(d->fam, 1);
}
int main(void)
{
struct dom *d = calloc(1, sizeof(*d) + 2 * sizeof(struct m));
d->num_layers = 2; /* expect 8 */
d->fam[0].v = 0x77; /* 476 if fam[0] is read as the count */
printf("%zu\n", bdos(d));
}
```
| compiler, `-O2` | result |
|---|---|
| clang 21.1.8 | **476** (0x77 × 4: the count is read from `fam[0]`) |
| gcc 15.2.0 | 8 (correct) |
Layout variants with clang 21.1.8:
| counter + FAM placed in | result |
|---|---|
| anonymous struct inside a union | 476 (wrong) |
| **named** struct inside a union (`d->s.fam`) | 476 (wrong) |
| anonymous struct, no union | 8 (correct) |
So the trigger is the union, not the anonymous struct. That fits the
description that `getGEPIndicesToField()` walks the union's IR type (its
largest member).
In the real kernel object, x86_64 `landlock_merge_ruleset()` loads the count
with `mov 0x28(%rbx),%esi`, which is `handled_masks[0]`, while `num_layers` is
at `0x24`. This matches the arm64 offsets in the PR description.
</CLAUDE>
https://github.com/llvm/llvm-project/pull/228309
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits