[clang] [Clang] Fix __builtin_dynamic_object_size off by 4 (PR #111015)

Jan Hendrik Farr via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 3 14:54:53 PDT 2024


Cydox wrote:

After looking at the assembly produced by gcc more, it actually looks like it's using the allocation size if it's known in the current context (for example if the struct was just malloced in the same function) and otherwise returns INT_MAX for the __bdos of a struct containing a flexible array member. It's only returning the size based on the __counted_by attribute of you ask it for the __bdos of the flexible array member itself.

```C
int test(struct posix_acl *acl) {
    return __builtin_dynamic_object_size(acl, 0);
}
```
actually compiles to
```
test:
        mov     eax, -1
        ret
```
using gcc (trunk) on compiler explorer.

So the call to kmemdup in this function:
```C
struct posix_acl *
posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
{
	struct posix_acl *clone = NULL;

	if (acl) {
		int size = offsetof(struct posix_acl, a_entries) + acl->a_count *
		           sizeof(struct posix_acl_entry);
		clone = kmemdup(acl, size, flags);
		if (clone)
			refcount_set(&clone->a_refcount, 1);
	}
	return clone;
}
EXPORT_SYMBOL_GPL(posix_acl_clone);
```

won't actually be bounds-checked currently when compiling the kernel with gcc. Compiling with clang will make this bounds-checked using the lower bound of possible sizes (max(sizeof(struct s), offsetof(struct s, array) + p->count * sizeof(*p->array)))

https://github.com/llvm/llvm-project/pull/111015


More information about the cfe-commits mailing list