pam: fix out-of-bounds read in pam_passkey_child_read_data#8622
Conversation
There was a problem hiding this comment.
Code Review
This pull request improves memory management and data handling in the PAM passkey responder by ensuring proper buffer allocation and null termination. It also introduces error reporting for memory allocation failures. Feedback suggests adding a safety check for the buffer length before performing a memory copy to avoid potential undefined behavior.
sssd-bot
left a comment
There was a problem hiding this comment.
Review done using Claude Code / claude-opus-4-6
Functional Issues
-
Undefined behavior when
buf_lenis 0 andbufis NULL (src/responder/pam/pamsrv_passkey.c:823)read_pipe_recvcan returnEOKwithbuf == NULLandbuf_len == 0when the child process closes the pipe immediately (EOF on first read — see_read_pipe_doneinsrc/util/child_io.c:292-295wheretevent_req_doneis called without accumulating any data, leavingstate->buf == NULLandstate->len == 0).In that case,
malloc(0 + 1)succeeds, butmemcpy(str, NULL, 0)is undefined behavior per C11 §7.1.4 ("If an argument to a function has an invalid value... the behavior is undefined"), even though the count is zero. Add a guard:if (buf_len == 0 || buf == NULL) { tevent_req_error(req, EINVAL); return; }
-
Return value of
sss_authtok_set_passkey_replyis not checked (src/responder/pam/pamsrv_passkey.c:826)sss_authtok_set_passkey_replycallssss_authtok_set_string, which can fail withEINVAL(e.g. zero-length string after NUL stripping) orENOMEM. The return value is silently discarded, andtevent_req_done(req)is called unconditionally at line 830, signaling success to the caller even when the authtok was not set. This is pre-existing, but since this patch is already improving error handling in this function (addingENOMEMpropagation onmallocfailure), the same treatment should apply here:ret = sss_authtok_set_passkey_reply(state->pd->authtok, str, 0); free(str); if (ret != EOK) { tevent_req_error(req, ret); return; }
-
Missing
:relnote:tagThis commit fixes CVE-2026-6245 (an out-of-bounds read reachable via the PAM passkey flow). Security fixes are user-visible and should carry a
:relnote:entry in the commit message so they appear in release notes.
Nits & Non-functional Issues
-
malloc/freeinstead oftalloc(src/responder/pam/pamsrv_passkey.c:817,828)The rest of this function (and SSSD in general) uses talloc for memory management. The
strbuffer is the only allocation in this function using libc malloc. Usingtalloc_size(state, buf_len + 1)would be more consistent, would allow talloc's leak reporting to track it, and would eliminate the need for the explicitfree(str)call (the buffer would be freed whenstateis freed). Pre-existing, but worth aligning while the code is being touched. -
Missing
FD_CLOSEforread_from_child_fd(src/responder/pam/pamsrv_passkey.c:830)Compare with the p11 child handler in
src/responder/pam/pamsrv_p11.c:949, which callsFD_CLOSE(state->io->read_from_child_fd)afterread_pipe_recv. This function does not close the read fd, leaving it to be cleaned up implicitly. Pre-existing, but inconsistent with the p11 pattern.
Confirmed Issues from Existing Review Comments
- gemini-code-assist[bot] flagged the missing
buf_len > 0check beforememcpy(src/responder/pam/pamsrv_passkey.c:823). This is valid and maps to functional issue #1 above — it is not merely a defensive coding preference but addresses real undefined behavior whenbufis NULL on immediate EOF.
@xuraoqing, those 2 items need to be addressed. |
thank you for reviewing, i will fix it。 |
sumit-bose
left a comment
There was a problem hiding this comment.
Hi,
thank you for the fix for this important issue. I find to usage of malloc()/free() a bit odd here as well, but since it is coming from the original code it should not stop the fix from being committed, ACK.
bye,
Sumit
ikerexxe
left a comment
There was a problem hiding this comment.
LGTM! Thank you for the patch and for taking the feedback into account.
@alexey-tikhonov I see system test for fedora 44 failing, but they don't seem related to this change. Should we retrigger CI before merging?
I'll take care of this. |
|
Note: Covscan is clean. |
The pam_passkey_child_read_data() function failed to properly handle raw bytes received from a pipe. The data was treated as a NUL-terminated C string without explicit termination, resulting in an out-of-bounds read when processed by snprintf() with %s format. Fix by using memcpy instead of snprintf and explicitly NUL-terminating the buffer. Add checks for buf_len == 0 or buf == NULL to avoid undefined behavior. Check the return value of sss_authtok_set_passkey_reply and propagate errors properly. Fixes: CVE-2026-6245 :relnote: Security fix for CVE-2026-6245: out-of-bounds read in PAM passkey responder Reviewed-by: Alexey Tikhonov <[email protected]> Reviewed-by: Iker Pedrosa <[email protected]> Reviewed-by: Sumit Bose <[email protected]>
The pam_passkey_child_read_data() function failed to properly handle raw bytes received from a pipe. The data was treated as a NUL-terminated C string without explicit termination, resulting in an out-of-bounds read when processed by snprintf() with %s format.
Fix by using memcpy instead of snprintf and explicitly NUL-terminating the buffer. Also fix the error handling to return ENOMEM on allocation failure.
Fixes: CVE-2026-6245