llvm / llvm/llvm-project

[cfi] CFI and KCFI reject indirect calls that are valid according to the C standard

Open
#192,388 6 comments 0 reactions 0 assignees View on GitHub
compiler-rt:cfi
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Consider the following C program ([Godbolt](https://godbolt.org/z/bsKfK9bfa)):

```c
// lib.c

#include

typedef struct {
char a;
} foo;

void fun(foo s) {
printf("Field a has value %d\n", s.a);
return;
}

void* fnptr = (void*)fun;
```

```c
// main.c (linked together with lib.c)

extern void* fnptr;

typedef struct {
char a;
} bar;

int main() {
bar s = {42};
void (*casted)(bar) = (void (*)(bar))fnptr;
casted(s);
return 0;
}
```

According to the C standard, the behavior should be [well-defined](https://open-std.org/JTC1/SC22/WG14/www/docs/n3220.pdf#subsubsection.6.5.3.3). `foo` and `bar` are [compatible types](https://open-std.org/JTC1/SC22/WG14/www/docs/n3220.pdf#subsection.6.2.7), as they are both completed `structs` with identical members in identical order declared without tags in separate translation units. However, with CFI or KCFI indirect call checking enabled, the program crashes.

The underlying issue is that CFI identifies the `typedef`ed no-tag structs based on the hash of the `typedef` name. This is incorrect; the CFI hash for these tag-less types should instead be based on the names and types of their fields.

Contributor guide

Open the contributing guide

Research direction

Reproduce the failure with the lib.c and main.c examples under CFI and KCFI, starting from the indirect-call type-hash generation path. Trace how the tag-less foo and bar structs are identified; done means compatible structs derive matching hashes from their fields and the call is no longer rejected.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
compilers, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.