tevent signal - access after free?

Stefan (metze) Metzmacher metze at samba.org
Tue Jun 2 04:25:19 MDT 2015


Hi Pavel,

thanks for the report. I've created
https://bugzilla.samba.org/show_bug.cgi?id=11308

Does the following patch fixes the problem?

metze

Am 02.06.2015 um 11:05 schrieb Pavel Březina:
> We found a crash in SSSD when a tevent signal is freed in its handler,
> tevent than crashes when it access siginfo.
> 
> sig_info is freed in signal destructor:
> 
>> #ifdef SA_SIGINFO
>>         if (se->sa_flags & SA_SIGINFO) {
>>             if (sig_state->sig_info[se->signum]) {
>>                 talloc_free(sig_state->sig_info[se->signum]);
>>                 sig_state->sig_info[se->signum] = NULL;
>>             }
>>         }
>> #endif
> 
> (gdb) bt
> #0  0x00007f5d4d86cc74 in tevent_signal_destructor (se=0x7f5d5370f920)
> at ../tevent_signal.c:213
> #1  0x00007f5d4d65f233 in _talloc_free_internal () from
> /lib64/libtalloc.so.2
> #2  0x00007f5d4d6593a3 in _talloc_free () from /lib64/libtalloc.so.2
> #3  0x00007f5d4342f3d4 in proxy_child_init_done (subreq=0x7f5d5370f600)
> at src/providers/proxy/proxy_auth.c:436
> #4  0x00007f5d4d86b0c2 in _tevent_req_error
> (req=req at entry=0x7f5d5370f600, error=error at entry=5,
> location=location at entry=0x7f5d43433010
> "src/providers/proxy/proxy_auth.c:356")
>     at ../tevent_req.c:167
> #5  0x00007f5d4342ef5e in pc_init_sig_handler (ev=<optimized out>,
> sige=<optimized out>, signum=<optimized out>, count=<optimized out>,
> __siginfo=<optimized out>, pvt=<optimized out>)
>     at src/providers/proxy/proxy_auth.c:356
> #6  0x00007f5d4d86d48c in tevent_common_check_signal (ev=0x7f5d536de670)
> at ../tevent_signal.c:428
> #7  0x00007f5d4d86f28c in epoll_event_loop (tvalp=0x7fff7b568490,
> epoll_ev=0x7f5d536de8b0) at ../tevent_epoll.c:647
> #8  epoll_event_loop_once (ev=<optimized out>, location=<optimized out>)
> at ../tevent_epoll.c:926
> #9  0x00007f5d4d86d7d7 in std_event_loop_once (ev=0x7f5d536de670,
> location=0x7f5d50faedc3 "src/util/server.c:668") at
> ../tevent_standard.c:114
> #10 0x00007f5d4d869fbd in _tevent_loop_once (ev=ev at entry=0x7f5d536de670,
> location=location at entry=0x7f5d50faedc3 "src/util/server.c:668") at
> ../tevent.c:530
> #11 0x00007f5d4d86a15b in tevent_common_loop_wait (ev=0x7f5d536de670,
> location=0x7f5d50faedc3 "src/util/server.c:668") at ../tevent.c:634
> #12 0x00007f5d4d86d777 in std_event_loop_wait (ev=0x7f5d536de670,
> location=0x7f5d50faedc3 "src/util/server.c:668") at
> ../tevent_standard.c:140
> #13 0x00007f5d50f96863 in server_loop (main_ctx=0x7f5d536dfac0) at
> src/util/server.c:668
> #14 0x00007f5d5180aa42 in main (argc=8, argv=<optimized out>) at
> src/providers/data_provider_be.c:2909
> 
> But then it is accessed again in tevent_common_check_signal:
> 
>> #ifdef SA_SIGINFO
>>         if (clear_processed_siginfo) {
>>             uint32_t j;
>>             for (j=0;j<count;j++) {
>>                 uint32_t ofs = (counter.seen + j)
>>                     % TEVENT_SA_INFO_QUEUE_COUNT;
>>                 memset((void*)&sig_state->sig_info[i][ofs],
>>                     '\0',
>>                     sizeof(siginfo_t));
>>             }
>>         }
>> #endif
> 
> (gdb) bt
> #0  0x00007fd7ba400505 in memset (__len=<optimized out>, __ch=<optimized
> out>, __dest=<optimized out>) at /usr/include/bits/string3.h:84
> #1  tevent_common_check_signal (ev=0x7fd7bfddf670) at
> ../tevent_signal.c:459
> #2  0x00007fd7ba40228c in epoll_event_loop (tvalp=0x7fff85536430,
> epoll_ev=0x7fd7bfddf8b0) at ../tevent_epoll.c:647
> #3  epoll_event_loop_once (ev=<optimized out>, location=<optimized out>)
> at ../tevent_epoll.c:926
> #4  0x00007fd7ba4007d7 in std_event_loop_once (ev=0x7fd7bfddf670,
> location=0x7fd7bdb417c3 "src/util/server.c:668") at
> ../tevent_standard.c:114
> #5  0x00007fd7ba3fcfbd in _tevent_loop_once (ev=ev at entry=0x7fd7bfddf670,
> location=location at entry=0x7fd7bdb417c3 "src/util/server.c:668") at
> ../tevent.c:530
> #6  0x00007fd7ba3fd15b in tevent_common_loop_wait (ev=0x7fd7bfddf670,
> location=0x7fd7bdb417c3 "src/util/server.c:668") at ../tevent.c:634
> #7  0x00007fd7ba400777 in std_event_loop_wait (ev=0x7fd7bfddf670,
> location=0x7fd7bdb417c3 "src/util/server.c:668") at
> ../tevent_standard.c:140
> #8  0x00007fd7bdb29343 in server_loop (main_ctx=0x7fd7bfde0ac0) at
> src/util/server.c:668
> #9  0x00007fd7be39ca42 in main (argc=8, argv=<optimized out>) at
> src/providers/data_provider_be.c:2909
-------------- next part --------------
From d022768519a54663f47cdf931e7df88cf1425dc9 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 2 Jun 2015 12:18:22 +0200
Subject: [PATCH] tevent: fix access after free in tevent_common_check_signal()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This was reported by Pavel Březina <pbrezina at redhat.com>:

    We found a crash in SSSD when a tevent signal is freed in its handler, tevent
    than crashes when it access siginfo.

    sig_info is freed in signal destructor:

    > #ifdef SA_SIGINFO
    >         if (se->sa_flags & SA_SIGINFO) {
    >             if (sig_state->sig_info[se->signum]) {
    >                 talloc_free(sig_state->sig_info[se->signum]);
    >                 sig_state->sig_info[se->signum] = NULL;
    >             }
    >         }
    > #endif

    (gdb) bt
    #0  0x00007f5d4d86cc74 in tevent_signal_destructor (se=0x7f5d5370f920) at
    ../tevent_signal.c:213
    #1  0x00007f5d4d65f233 in _talloc_free_internal () from /lib64/libtalloc.so.2
    #2  0x00007f5d4d6593a3 in _talloc_free () from /lib64/libtalloc.so.2
    #3  0x00007f5d4342f3d4 in proxy_child_init_done (subreq=0x7f5d5370f600) at
    src/providers/proxy/proxy_auth.c:436
    #4  0x00007f5d4d86b0c2 in _tevent_req_error (req=req at entry=0x7f5d5370f600,
    error=error at entry=5, location=location at entry=0x7f5d43433010
    "src/providers/proxy/proxy_auth.c:356")
        at ../tevent_req.c:167
    #5  0x00007f5d4342ef5e in pc_init_sig_handler (ev=<optimized out>,
    sige=<optimized out>, signum=<optimized out>, count=<optimized out>,
    __siginfo=<optimized out>, pvt=<optimized out>)
        at src/providers/proxy/proxy_auth.c:356
    #6  0x00007f5d4d86d48c in tevent_common_check_signal (ev=0x7f5d536de670) at
    ../tevent_signal.c:428
    #7  0x00007f5d4d86f28c in epoll_event_loop (tvalp=0x7fff7b568490,
    epoll_ev=0x7f5d536de8b0) at ../tevent_epoll.c:647
    #8  epoll_event_loop_once (ev=<optimized out>, location=<optimized out>) at
    ../tevent_epoll.c:926
    #9  0x00007f5d4d86d7d7 in std_event_loop_once (ev=0x7f5d536de670,
    location=0x7f5d50faedc3 "src/util/server.c:668") at ../tevent_standard.c:114
    #10 0x00007f5d4d869fbd in _tevent_loop_once (ev=ev at entry=0x7f5d536de670,
    location=location at entry=0x7f5d50faedc3 "src/util/server.c:668") at
    ../tevent.c:530
    #11 0x00007f5d4d86a15b in tevent_common_loop_wait (ev=0x7f5d536de670,
    location=0x7f5d50faedc3 "src/util/server.c:668") at ../tevent.c:634
    #12 0x00007f5d4d86d777 in std_event_loop_wait (ev=0x7f5d536de670,
    location=0x7f5d50faedc3 "src/util/server.c:668") at ../tevent_standard.c:140
    #13 0x00007f5d50f96863 in server_loop (main_ctx=0x7f5d536dfac0) at
    src/util/server.c:668
    #14 0x00007f5d5180aa42 in main (argc=8, argv=<optimized out>) at
    src/providers/data_provider_be.c:2909

    But then it is accessed again in tevent_common_check_signal:

    > #ifdef SA_SIGINFO
    >         if (clear_processed_siginfo) {
    >             uint32_t j;
    >             for (j=0;j<count;j++) {
    >                 uint32_t ofs = (counter.seen + j)
    >                     % TEVENT_SA_INFO_QUEUE_COUNT;
    >                 memset((void*)&sig_state->sig_info[i][ofs],
    >                     '\0',
    >                     sizeof(siginfo_t));
    >             }
    >         }
    > #endif

    (gdb) bt
    #0  0x00007fd7ba400505 in memset (__len=<optimized out>, __ch=<optimized out>,
    __dest=<optimized out>) at /usr/include/bits/string3.h:84
    #1  tevent_common_check_signal (ev=0x7fd7bfddf670) at ../tevent_signal.c:459
    #2  0x00007fd7ba40228c in epoll_event_loop (tvalp=0x7fff85536430,
    epoll_ev=0x7fd7bfddf8b0) at ../tevent_epoll.c:647
    #3  epoll_event_loop_once (ev=<optimized out>, location=<optimized out>) at
    ../tevent_epoll.c:926
    #4  0x00007fd7ba4007d7 in std_event_loop_once (ev=0x7fd7bfddf670,
    location=0x7fd7bdb417c3 "src/util/server.c:668") at ../tevent_standard.c:114
    #5  0x00007fd7ba3fcfbd in _tevent_loop_once (ev=ev at entry=0x7fd7bfddf670,
    location=location at entry=0x7fd7bdb417c3 "src/util/server.c:668") at
    ../tevent.c:530
    #6  0x00007fd7ba3fd15b in tevent_common_loop_wait (ev=0x7fd7bfddf670,
    location=0x7fd7bdb417c3 "src/util/server.c:668") at ../tevent.c:634
    #7  0x00007fd7ba400777 in std_event_loop_wait (ev=0x7fd7bfddf670,
    location=0x7fd7bdb417c3 "src/util/server.c:668") at ../tevent_standard.c:140
    #8  0x00007fd7bdb29343 in server_loop (main_ctx=0x7fd7bfde0ac0) at
    src/util/server.c:668
    #9  0x00007fd7be39ca42 in main (argc=8, argv=<optimized out>) at
    src/providers/data_provider_be.c:2909

BUG: https://bugzilla.samba.org/show_bug.cgi?id=11308

Signed-off-by: Stefan Metzmacher <metze at samba.org>
---
 lib/tevent/tevent_signal.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c
index b54da2e..924dc05 100644
--- a/lib/tevent/tevent_signal.c
+++ b/lib/tevent/tevent_signal.c
@@ -457,7 +457,7 @@ int tevent_common_check_signal(struct tevent_context *ev)
 		}
 
 #ifdef SA_SIGINFO
-		if (clear_processed_siginfo) {
+		if (clear_processed_siginfo && sig_state->sig_info[i] != NULL) {
 			uint32_t j;
 			for (j=0;j<count;j++) {
 				uint32_t ofs = (counter.seen + j)
-- 
1.9.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20150602/a8407135/attachment.pgp>


More information about the samba-technical mailing list