pytorch / pytorch/cpuinfo

CFI Type Mismatch (Function Pointer Cast) in ARM Linux Parser

Open Beginner friendly
#402 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
1.2k
Forks
409
PR merge metrics
No merged PRs in 30d

Description

Hi, I spotted this when trying to run an Android application under UBSan. Upon digging, I found this issue:

A Clang Control Flow Integrity (CFI) type mismatch occurs in src/arm/linux/cpuinfo.c when invoking the parse_line callback through the cpuinfo_line_callback function pointer. This triggers a runtime SIGTRAP when CFI is enabled.

The issue is that parse_line is defined with a specific structure pointer as its third argument, but it is cast to cpuinfo_line_callback which expects void* for that argument.

In src/arm/linux/cpuinfo.c we have parse_line which takes a proc_cpuinfo_parser_state argument

https://github.com/pytorch/cpuinfo/blob/ae5443646e5092d42d2a5b6e202b548169bc023e/src/arm/linux/cpuinfo.c#L726-L730

In cpuinfo_arm_linux_parse_proc_cpuinfo:

https://github.com/pytorch/cpuinfo/blob/ae5443646e5092d42d2a5b6e202b548169bc023e/src/arm/linux/api.h#L297-L301

The callback type is defined in src/linux/api.h as:

https://github.com/pytorch/cpuinfo/blob/ae5443646e5092d42d2a5b6e202b548169bc023e/src/linux/api.h#L37

The problem is specifically here, where we cast parse_line to cpuinfo_line_callback. These functions have different signatures:

https://github.com/pytorch/cpuinfo/blob/ae5443646e5092d42d2a5b6e202b548169bc023e/src/arm/linux/cpuinfo.c#L1021-L1023

Calling a function through a pointer of a different type (even if they are pointer-compatible in some ABIs) is Undefined Behavior in C and is flagged by Clang's -fsanitize=cfi-icall.

Suggested fix: Change parse_line to accept void* for the context argument, and cast it inside the function. Remove the cast when passing it to cpuinfo_linux_parse_multiline_file.

--- a/src/arm/linux/cpuinfo.c
+++ b/src/arm/linux/cpuinfo.c
@@ -726,8 +726,9 @@
 static bool parse_line(
 	const char* line_start,
 	const char* line_end,
-	struct proc_cpuinfo_parser_state state[restrict static 1],
+	void* context,
 	uint64_t line_number) {
+	struct proc_cpuinfo_parser_state* restrict state = (struct proc_cpuinfo_parser_state*)context;
 	/* Empty line. Skip. */
 	if (line_start == line_end) {
 		return true;
@@ -1019,5 +1018,5 @@
 		.processors = processors,
 	};
 	return cpuinfo_linux_parse_multiline_file(
-		"/proc/cpuinfo", BUFFER_SIZE, (cpuinfo_line_callback)parse_line, &state);
+		"/proc/cpuinfo", BUFFER_SIZE, parse_line, &state);
 }

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/arm/linux/cpuinfo.c at parse_line and cpuinfo_arm_linux_parse_proc_cpuinfo, then compare the callback declaration in src/linux/api.h. Make the callback signatures agree without a function-pointer cast, and verify the ARM Linux parser under Clang CFI/UBSan so the SIGTRAP no longer occurs.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
operating-systems
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.