pytorch / pytorch/cpuinfo

Buffer Overflow (OOB Write/Read) in `Hardware` and `Revision` Parsing

Open Beginner friendly
#407 1 comment 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

I found this while trying to figure out why I was getting errors when running under strict checks (#402). While this wasn't the cause of my errors, I think it's a real (separate) bug.

The /proc/cpuinfo parser in src/arm/linux/cpuinfo.c has a logic error when handling Hardware and Revision values that are equal to or longer than the maximum buffer size (CPUINFO_HARDWARE_VALUE_MAX and CPUINFO_REVISION_VALUE_MAX, both 64).

This leads to:

  1. Out-of-bounds write of 1 byte (null terminator) if the value length is exactly 64.
  2. Lack of null-termination (potentially leading to out-of-bounds reads later) if the value length is greater than 64.
Affected Code

In src/arm/linux/cpuinfo.c:

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

Scenario 1: value_length == 64 (equal to CPUINFO_HARDWARE_VALUE_MAX)
  • The if condition value_length > 64 is false.
  • The else branch is executed: state->hardware[64] = '\0';.
  • Since state->hardware is char hardware[64], index 64 is out of bounds (valid indices are 0-63). This is a 1-byte OOB write.
Scenario 2: value_length > 64 (e.g., 70)
  • The if condition is true.
  • value_length is truncated to 64.
  • The else branch is skipped, so no null terminator is written.
  • memcpy copies 64 bytes to state->hardware.
  • state->hardware is left non-null-terminated. If it is later read as a C-string, it will cause an OOB read.

The same logic error exists for the Revision field.

Suggested Fix

Check for value_length >= LIMIT. If so, truncate to LIMIT - 1 and warn. Always write the null terminator at value_length after truncation/copying.

--- a/src/arm/linux/cpuinfo.c
+++ b/src/arm/linux/cpuinfo.c
@@ -872,31 +873,29 @@
 				/* BogoMIPS is useless, don't parse */
 			} else if (memcmp(line_start, "Hardware", key_length) == 0) {
 				size_t value_length = value_end - value_start;
-				if (value_length > CPUINFO_HARDWARE_VALUE_MAX) {
+				if (value_length >= CPUINFO_HARDWARE_VALUE_MAX) {
 					cpuinfo_log_warning(
 						"length of Hardware value \"%.*s\" in /proc/cpuinfo exceeds limit (%d): truncating to the limit",
 						(int)value_length,
 						value_start,
-						CPUINFO_HARDWARE_VALUE_MAX);
-					value_length = CPUINFO_HARDWARE_VALUE_MAX;
-				} else {
-					state->hardware[value_length] = '\0';
+						CPUINFO_HARDWARE_VALUE_MAX - 1);
+					value_length = CPUINFO_HARDWARE_VALUE_MAX - 1;
 				}
+				state->hardware[value_length] = '\0';
 				memcpy(state->hardware, value_start, value_length);
 				cpuinfo_log_debug(
 					"parsed /proc/cpuinfo Hardware = \"%.*s\"", (int)value_length, value_start);
 			} else if (memcmp(line_start, "Revision", key_length) == 0) {
 				size_t value_length = value_end - value_start;
-				if (value_length > CPUINFO_REVISION_VALUE_MAX) {
+				if (value_length >= CPUINFO_REVISION_VALUE_MAX) {
 					cpuinfo_log_warning(
 						"length of Revision value \"%.*s\" in /proc/cpuinfo exceeds limit (%d): truncating to the limit",
 						(int)value_length,
 						value_start,
-						CPUINFO_REVISION_VALUE_MAX);
-					value_length = CPUINFO_REVISION_VALUE_MAX;
-				} else {
-					state->revision[value_length] = '\0';
+						CPUINFO_REVISION_VALUE_MAX - 1);
+					value_length = CPUINFO_REVISION_VALUE_MAX - 1;
 				}
+				state->revision[value_length] = '\0';
 				memcpy(state->revision, value_start, value_length);

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 the linked Hardware and Revision parsing code, and inspect how value_length is handled against CPUINFO_HARDWARE_VALUE_MAX and CPUINFO_REVISION_VALUE_MAX. Exercise the parser with values of length 64 and greater than 64 for both fields; done means the buffers remain safely terminated without out-of-bounds access and the existing truncation warning behavior is preserved.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.