[PATCH AUTOSEL 6.19-6.12] dlm: validate length in dlm_search_rsb_tree

Sasha Levin <[email protected]>
Newsgroups dev.linux.lists.gfs2,dev.linux.lists.patches,org.kernel.vger.stable
Message-ID <[email protected]>
From: Ezrak1e <[email protected]>

[ Upstream commit 080e5563f878c64e697b89e7439d730d0daad882 ]

The len parameter in dlm_dump_rsb_name() is not validated and comes
from network messages. When it exceeds DLM_RESNAME_MAXLEN, it can
cause out-of-bounds write in dlm_search_rsb_tree().

Add length validation to prevent potential buffer overflow.

Signed-off-by: Ezrak1e <[email protected]>
Signed-off-by: Alexander Aring <[email protected]>
Signed-off-by: David Teigland <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---

LLM Generated explanations, may be completely bogus:

Indeed, `dlm_copy_master_names` calls `find_rsb_root` with `inlen` that
comes from network data (`receive_rcom_names` →
`dlm_copy_master_names`). `inlen` is derived from
`rc_in->rc_header.h_length - sizeof(struct dlm_rcom)` with no bounds
check. And `find_rsb_root` doesn't validate it before passing to
`dlm_search_rsb_tree`.

So there are **at least two** unvalidated network-
to-`dlm_search_rsb_tree` paths:
1. `receive_rcom_lookup` → `dlm_dump_rsb_name` → `dlm_search_rsb_tree`
   (debug dump path)
2. `receive_rcom_names` → `dlm_copy_master_names` → `find_rsb_root` →
   `dlm_search_rsb_tree`

Both can pass `len > DLM_RESNAME_MAXLEN` (64), causing `memcpy(key,
name, len)` to overflow the stack buffer `key[DLM_RESNAME_MAXLEN]`.

Now let me verify what `DLM_RESNAME_MAXLEN` is:

The value is 64 (from `include/uapi/linux/dlmconstants.h`). The stack
buffer `key` is 64 bytes. If `len` > 64, `memcpy(key, name, len)` writes
beyond the buffer — a classic **stack buffer overflow**.

This is exploitable from a malicious DLM cluster node sending a crafted
network message.

## Detailed Analysis

### 1. COMMIT MESSAGE ANALYSIS

The commit message clearly states:
- The `len` parameter comes from **network messages** (untrusted input)
- When `len` exceeds `DLM_RESNAME_MAXLEN` (64), it causes an **out-of-
  bounds write** in `dlm_search_rsb_tree()`
- The fix adds length validation to prevent the buffer overflow

### 2. CODE CHANGE ANALYSIS

The change is extremely small and surgical — just 2 lines added:

```625:636:fs/dlm/lock.c
int dlm_search_rsb_tree(struct rhashtable *rhash, const void *name, int
len,
                        struct dlm_rsb **r_ret)
{
        char key[DLM_RESNAME_MAXLEN] = {};
        // NEW: if (len > DLM_RESNAME_MAXLEN) return -EINVAL;
        memcpy(key, name, len);
        // ...
}
```

Without the check, `memcpy(key, name, len)` with `len > 64` writes past
the end of the 64-byte stack buffer `key`. This is a **stack buffer
overflow** — one of the most dangerous vulnerability classes in C.

### 3. VULNERABLE CODE PATHS

I traced all 6 callers of `dlm_search_rsb_tree`:

| Caller | Validates `len`? | Network-reachable? |
|--------|------------------|--------------------|
| `find_rsb_dir` | YES (via `find_rsb` at line 1089) | Yes |
| `find_rsb_nodir` | YES (via `find_rsb` at line 1089) | Yes |
| `_dlm_master_lookup` | YES (line 1268) | Yes |
| `receive_remove` | YES (line 4300) | Yes |
| **`dlm_dump_rsb_name`** | **NO** | **Yes** (via `receive_rcom_lookup`)
|
| **`find_rsb_root`** | **NO** | **Yes** (via `receive_rcom_names` →
`dlm_copy_master_names`) |

Two callers do NOT validate `len` before calling `dlm_search_rsb_tree`,
and both are reachable from network messages:

1. **`receive_rcom_lookup`** (rcom.c:379): When `rc_in->rc_id ==
   0xFFFFFFFF`, it calls `dlm_dump_rsb_name(ls, rc_in->rc_buf, len)`
   where `len` is derived from `rc_in->rc_header.h_length` (a network-
   supplied 16-bit field). No bounds check.

2. **`receive_rcom_names`** (rcom.c:336): Calculates `inlen` from
   `rc_in->rc_header.h_length - sizeof(struct dlm_rcom)` and passes it
   directly to `dlm_copy_master_names` → `find_rsb_root` →
   `dlm_search_rsb_tree`. No bounds check.

### 4. BUG SEVERITY

This is a **stack buffer overflow triggered by network input** in the
DLM (Distributed Lock Manager) subsystem:

- **Type**: Out-of-bounds write (stack buffer overflow)
- **Attack vector**: Network (DLM cluster communication protocol)
- **Trigger**: A malicious or buggy DLM cluster node sending a message
  with `h_length` large enough to make the extracted `len` exceed 64
- **Impact**: Stack corruption, potential code execution, kernel
  crash/panic
- **DLM context**: DLM is used in cluster filesystems like GFS2 and
  OCFS2, which are used in production enterprise environments

While the attack surface requires being part of a DLM cluster (not
publicly internet-reachable in most deployments), this is still a
serious security bug. In shared hosting or cloud environments, cluster
node compromise could lead to kernel-level exploitation of other cluster
members.

### 5. FIX QUALITY

The fix is **defense-in-depth at the right layer**:
- Rather than fixing each individual caller, it adds the validation in
  `dlm_search_rsb_tree` itself
- This protects against any future caller that might forget to validate
- The fix returns `-EINVAL`, which all callers handle (they all check
  the return value)
- It's only 2 lines, extremely low risk of regression
- The pattern is identical to the existing checks in
  `_dlm_master_lookup` (line 1268) and `receive_remove` (line 4300)

### 6. SCOPE AND RISK

- **Lines changed**: 2 (added `if` check and return)
- **Files changed**: 1 (`fs/dlm/lock.c`)
- **Risk of regression**: Extremely low — it adds a bounds check that
  was already present in 4 of 6 callers
- **Subsystem**: DLM (mature, production-critical for cluster
  filesystems)

### 7. APPLICABILITY TO STABLE

- The function `dlm_search_rsb_tree` was introduced in commit
  `5be323b0c64db` ("dlm: move dlm_search_rsb_tree() out of lock") from
  August 2024, which was merged in 6.12
- Older kernels may have equivalent vulnerable code but with different
  structure
- For 6.12+ stable trees, the fix should apply cleanly

### 8. STABLE CRITERIA CHECK

- Obviously correct and tested: YES (trivial bounds check, accepted by
  DLM maintainers Alexander Aring and David Teigland)
- Fixes a real bug: YES (stack buffer overflow from network input)
- Fixes an important issue: YES (security vulnerability — buffer
  overflow exploitable from network)
- Small and contained: YES (2 lines in 1 file)
- No new features or APIs: YES (pure bug fix)

**YES**

 fs/dlm/lock.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index c01a291db401b..a393ecaf3442a 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -626,7 +626,8 @@ int dlm_search_rsb_tree(struct rhashtable *rhash, const void *name, int len,
 			struct dlm_rsb **r_ret)
 {
 	char key[DLM_RESNAME_MAXLEN] = {};
-
+	if (len > DLM_RESNAME_MAXLEN)
+		return -EINVAL;
 	memcpy(key, name, len);
 	*r_ret = rhashtable_lookup_fast(rhash, &key, dlm_rhash_rsb_params);
 	if (*r_ret)
-- 
2.51.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.