[Bug 2167] Connection remains when fork() fails.

bugzilla-daemon at natsu.mindrot.org bugzilla-daemon at natsu.mindrot.org
Fri Nov 1 15:34:10 EST 2013


https://bugzilla.mindrot.org/show_bug.cgi?id=2167

--- Comment #4 from Tetsuo Handa <penguin-kernel at I-love.SAKURA.ne.jp> ---
OK. I found the exact location.

fatal("fork of unprivileged child failed") calls cleanup_exit(255).
cleanup_exit(255) calls destroy_sensitive_data(1).
destroy_sensitive_data(1) calls mm_audit_destroy_sensitive_data(fp,
pid, uid).

mm_audit_destroy_sensitive_data() uses global pmonitor->m_recvfd which
now
references a socket pair.

---------- mm_audit_destroy_sensitive_data() in monitor_wrap.c
----------
void
mm_audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid)
{
        Buffer m;

        buffer_init(&m);
        buffer_put_cstring(&m, fp);
        buffer_put_int64(&m, pid);
        buffer_put_int64(&m, uid);

        mm_request_send(pmonitor->m_recvfd,
MONITOR_REQ_AUDIT_SERVER_KEY_FREE, &m);
        mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_AUDIT_SERVER_KEY_FREE,
                                  &m);
        buffer_free(&m);
}
---------- mm_audit_destroy_sensitive_data() in monitor_wrap.c
----------

Regarding privsep_preauth(), pmonitor = monitor_init() causes this
problem
when fork() fails. Fortunately, timeout was previously configured via
alarm()
which will eventually terminate the process even if fork() failed.

---------- privsep_preauth() in sshd.c ----------
static int
privsep_preauth(Authctxt *authctxt)
{
        int status;
        pid_t pid;

        /* Set up unprivileged child process to deal with network data
*/
        pmonitor = monitor_init();
        /* Store a pointer to the kex for later rekeying */
        pmonitor->m_pkex = &xxx_kex;

        pid = fork();
        if (pid == -1) {
                fatal("fork of unprivileged child failed");
(...snipped...)
---------- privsep_preauth() in sshd.c ----------

Regarding privsep_postauth(), monitor_reinit(pmonitor) causes this
problem
when fork() fails. Unfortunately, timeout previously configured via
alarm()
was disabled, which results in forever wait when fork() failed.

---------- privsep_postauth() in sshd.c ----------
static void
privsep_postauth(Authctxt *authctxt)
{
        u_int32_t rnd[256];

#ifdef DISABLE_FD_PASSING
        if (1) {
#else
        if (authctxt->pw->pw_uid == 0 || options.use_login) {
#endif
                /* File descriptor passing is broken or root login */
                use_privsep = 0;
                goto skip;
        }

        /* New socket pair */
        monitor_reinit(pmonitor);

        pmonitor->m_pid = fork();
        if (pmonitor->m_pid == -1)
                fatal("fork of unprivileged child failed");
(...snipped...)
---------- privsep_postauth() in sshd.c ----------

I confirmed that the patch in Comment 3 can fix this problem.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.
You are watching someone on the CC list of the bug.


More information about the openssh-bugs mailing list