https://bugzilla.kernel.org/show_bug.cgi?id=220884

            Bug ID: 220884
           Summary: Potential NULL pointer dereference in
                    hmat_get_extended_linear_cache_size due to
                    uninitialized memregions member
           Product: ACPI
           Version: 2.5
          Hardware: All
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P3
         Component: Other
          Assignee: [email protected]
          Reporter: [email protected]
        Regression: No

**Title**: Potential NULL pointer dereference in
`hmat_get_extended_linear_cache_size` due to uninitialized `memregions` member

**Bugzilla Entry ID**: (to be assigned)

**Product**: Linux Kernel

**Component**: ACPI / NUMA / HMAT

**Version**: upstream (torvalds/linux.git, master branch)

**Hardware**: x86_64, AArch64 (systems with HMAT support)

**Status**: NEW

**Severity**: medium

**Priority**: medium


**URL**: https://github.com/torvalds/linux/blob/master/drivers/acpi/numa/hmat.c

**CC**: [email protected], [email protected]

---

### **Description**

In function `hmat_get_extended_linear_cache_size()`, the code dereferences
`&target->memregions` without ensuring that the `memregions` structure member
has been properly initialized. While this is not a traditional NULL pointer
dereference (since `memregions` is a struct member, not a pointer), the
uninitialized `struct resource` can contain garbage values, leading to
unpredictable behavior in `resource_contains()`.

**Vulnerable Code Path**:
```c
res = &target->memregions;
if (!resource_contains(res, backing_res))
    continue;
```

The function `resource_contains()` directly accesses `res->start` and
`res->end`, which may be uninitialized stack or heap garbage. This can cause:
- Incorrect evaluation of the `if` condition
- Use of uninitialized values in comparisons
- Potential information leak (kernel memory disclosure)
- Kernel instability or oops if `resource_contains` traverses linked-list
pointers (parent/sibling/child) that are also uninitialized

**Impact**: A local user (with privileges to trigger HMAT operations) may cause
a kernel crash or obtain unintended memory information. The bug requires
HMAT-capable hardware (Intel Xeon Scalable, AMD EPYC with HMAT) and can be
triggered during memory hot-add or system boot with malformed/fuzzed ACPI
tables.

**Root Cause**: The `memory_target` structure's `memregions` member is not
guaranteed to be initialized before use in
`hmat_get_extended_linear_cache_size`. The initialization likely occurs in
`create_memory_target()` or similar, but there is no validation that this has
occurred before the cache query function runs.

---

### **Steps to Reproduce**

1. Boot a kernel with HMAT support on HMAT-capable hardware (or QEMU with HMAT
tables)
2. Use a kernel module or sysfs interface to trigger
`hmat_get_extended_linear_cache_size` before `memregions` is fully set up
   (or simulate by injecting an ACPI table with a memory target that has no
valid region described)
3. Observe kernel warning/oops if `resource_contains` hits an invalid pointer,
or note incorrect cache size returned due to uninitialized bounds.

Alternatively, with CONFIG_KASAN enabled, the kernel may report an
"uninitialized value" warning.

---

### **Proposed Fix**

Option 1 – Validate before use in `hmat_get_extended_linear_cache_size`:

```diff
--- a/drivers/acpi/numa/hmat.c
+++ b/drivers/acpi/numa/hmat.c
@@ -XXX, +XXX @@
+       /* Ensure memregions has been initialized */
+       if (resource_size(&target->memregions) == 0)
+               continue;
+
        res = &target->memregions;
        if (!resource_contains(res, backing_res))
                continue;
```

Option 2 – Ensure proper initialization in `create_memory_target` (if that is
the constructor):

```diff
--- a/drivers/acpi/numa/hmat.c
+++ b/drivers/acpi/numa/hmat.c
@@ -XXX, +XXX @@
        target = kzalloc(sizeof(*target), GFP_KERNEL);
        if (!target)
                return NULL;
+       /* Explicitly initialize the resource */
+       memset(&target->memregions, 0, sizeof(target->memregions));
+       target->memregions.start = 0;
+       target->memregions.end = 0;
        INIT_LIST_HEAD(&target->caches);
        ...
```

Option 3 – Both.

---

### **Code Analysis**

Relevant structures (inferred from context):
```c
struct memory_target {
    ...
    struct resource memregions;      // NOT a pointer, but embedded struct
    struct list_head caches;
    ...
};

struct resource {
    resource_size_t start;
    resource_size_t end;
    const char *name;
    unsigned long flags;
    struct resource *parent, *sibling, *child;
};
```

Since `memregions` is embedded, `&target->memregions` is always a valid address
(offset inside `target`). The bug is that its fields contain undefined values.

Function `resource_contains` (simplified):
```c
bool resource_contains(struct resource *res1, struct resource *res2)
{
    return res1->start <= res2->start && res1->end >= res2->end;
}
```

If `start`/`end` are uninitialized, the comparison is made with garbage,
possibly leading to incorrect logic flow.

---

### **Additional Notes**

- This is not a NULL dereference; it is an **uninitialized variable** bug.
- The bug is more subtle and may not crash unless the garbage values point to
invalid memory (e.g., if `resource_contains` is extended to follow
`parent`/`child` pointers).
- The fix is low-risk and defensive.
- Similar issues have been fixed in the resource subsystem before (e.g., commit
fffa9bb1b).

---

### **Regression Potential**

Low. The fix adds a safety check that should not affect correctly initialized
targets, and ensures buggy or maliciously crafted ACPI tables do not cause
undefined behavior.

---

### **Tested/Verified**

(To be filled by maintainer/reporter)
- [ ] Boot test on HMAT-capable system
- [ ] With CONFIG_KASAN, CONFIG_UBSAN
- [ ] Memory hotplug test cycle

---

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.

_______________________________________________
acpi-bugzilla mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/acpi-bugzilla

Reply via email to