trusteddomainproject / OpenDMARC

This is the Trusted Domain Project's impementation of the DMARC protocol libary and mail filter, called OpenDMARC. A "milter" connects to unix-based mailers (originally, sendmail, but now many) and provides a standard filtering API.
Other
98 stars 52 forks source link

Segfault in opendmarc_arcseal_parse() #236

Open minfrin opened 1 year ago

minfrin commented 1 year ago

I'm seeing a sudden crash of opendmarc as below.

Managed to catch it in a debugger.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7f6a22ffd700 (LWP 31339)]
0x00007f6a2b270a84 in strlcpy (dst=dst@entry=0x7f6a14008749 "", src=src@entry=0x0, dsize=dsize@entry=513) at strlcpy.c:36
36              if ((*dst++ = *src++) == '\0')
(gdb) bt
#0  0x00007f6a2b270a84 in strlcpy (dst=dst@entry=0x7f6a14008749 "", src=src@entry=0x0, dsize=dsize@entry=513) at strlcpy.c:36
#1  0x000000000040c16e in opendmarc_arcseal_parse (hdr=<optimized out>, as=as@entry=0x7f6a14008240) at opendmarc-arcseal.c:201
#2  0x0000000000408673 in mlfi_eom (ctx=0x959c90) at opendmarc.c:2625
#3  0x00007f6a2bdd3535 in st_bodyend (g=g@entry=0x7f6a22ffce80) at engine.c:1614
#4  0x00007f6a2bdd38d7 in mi_engine (ctx=ctx@entry=0x959c90) at engine.c:405
#5  0x00007f6a2bdd5a08 in mi_handle_session (ctx=0x959c90) at handler.c:45
#6  0x00007f6a2bdd4549 in mi_thread_handle_wrapper (arg=<optimized out>) at listener.c:579
#7  0x00007f6a2bbb9ea5 in start_thread (arg=0x7f6a22ffd700) at pthread_create.c:307
#8  0x00007f6a2ad8cb0d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
(gdb) bt full
#0  0x00007f6a2b270a84 in strlcpy (dst=dst@entry=0x7f6a14008749 "", src=src@entry=0x0, dsize=dsize@entry=513) at strlcpy.c:36
        osrc = 0x0
        nleft = 512
#1  0x000000000040c16e in opendmarc_arcseal_parse (hdr=<optimized out>, as=as@entry=0x7f6a14008240) at opendmarc-arcseal.c:201
        leading_space_len = 74
        tag_label = 0x7f6a22fd81aa "b"
        token_ptr = <optimized out>
        tmp_ptr = 0x0
        token = 0x7f6a22fd8160 "i"
        tmp = "i\000\061\000 cv\000none\000 a\000rsa-sha256\000 d\000list.sys4.de\000 s\000\062\065\061\060\062\062-rsa\000\n t\000\061\066\067\070\061\071\071\065\065\065\000\n b\000UyvjKJW4/yrM8FTYMRb3BLzaJc3t9tzCsjDWSC4gI2IjEl90q3yREArPeiLbhF2qZTL5JlBbRboMzgMBVO7rffYQI+zosMgCrnmHQ+pAU0UGSVtUeYyWXsgcvYY9"...
        result = 0
        __PRETTY_FUNCTION__ = "opendmarc_arcseal_parse"
#2  0x0000000000408673 in mlfi_eom (ctx=0x959c90) at opendmarc.c:2625
        as_hdr_new = 0x7f6a14008240
        wspf = false
        c = <optimized out>
        pc = <optimized out>
        policy = <optimized out>
        status = <optimized out>
        adkim = 0
        aspf = 0
        pct = 0
        p = 0
        sp = 0
        align_dkim = 0
        align_spf = 0
        limit_arc = 0
        result = <optimized out>
        ret = <optimized out>
        ostatus = <optimized out>
        apused = <optimized out>
        apolicy = 0x0
        aresult = 0x0
        adisposition = 0x0
        hostname = 0x7f6a14005963 "server.example.com"
        authservid = 0x7f6a14005963 "server.example.com"
        spfaddr = <optimized out>
        cc = 0x7f6a140008c0
        dfc = 0x7f6a140019f0
        conf = 0x942010
        hdr = 0x7f6a140054d0
---Type <return> to continue, or q <return> to quit---
        from = <optimized out>
        as_hdr = <optimized out>
        reqhdrs_error = <optimized out>
        user = 0x7f6a22ffbd50 "postfix-devel"
        users = 0x7f6a140067c0
        domain = 0x7f6a22ffbd5e "postfix.org"
        domains = 0x7f6a14006680
        bang = <optimized out>
        ruv = <optimized out>
        header = "OpenDMARC Filter v1.4.1 server.example.com A26462295C9\000.from=apache.org", '\000' <repeats 626 times>...
        addrbuf = "postfix-devel\000postfix.org\000devel <postfix-devel@postfix.org>", '\000' <repeats 1989 times>
        replybuf = "d\205\341*j\177", '\000' <repeats 90 times>, "\020\000\000\000\060\000\000\000\060\314\377\"j\177\000\000p\313\377\"j\177", '\000' <repeats 830 times>...
        pdomain = "apache.org", '\000' <repeats 54 times>
        ar = {ares_count = 0, ares_host = '\000' <repeats 256 times>, ares_version = '\000' <repeats 256 times>, ares_result = {
            {result_props = 0, result_method = 0, result_result = 0, result_ptype = {0 <repeats 16 times>}, 
              result_reason = '\000' <repeats 256 times>, result_property = {'\000' <repeats 256 times> <repeats 16 times>}, 
              result_value = {'\000' <repeats 256 times> <repeats 16 times>}} <repeats 16 times>}}
        __PRETTY_FUNCTION__ = "mlfi_eom"
        arcares = {instance = 0, authserv_id = '\000' <repeats 256 times>, arc = '\000' <repeats 512 times>, 
          dkim = '\000' <repeats 512 times>, dmarc = '\000' <repeats 512 times>, spf = '\000' <repeats 512 times>}
        arcares_arc_field = {arcresult = '\000' <repeats 256 times>, smtpclientip = '\000' <repeats 256 times>, 
          arcchain = '\000' <repeats 512 times>}
#3  0x00007f6a2bdd3535 in st_bodyend (g=g@entry=0x7f6a22ffce80) at engine.c:1614
        r = <optimized out>
        fi_body = <optimized out>
        fi_eom = <optimized out>
#4  0x00007f6a2bdd38d7 in mi_engine (ctx=ctx@entry=0x959c90) at engine.c:405
        len = 0
        i = 4
        sd = 5
        ret = 0
        curstate = 10
        newstate = 10
        call_abort = 0
        r = -2
        cmd = 69 'E'
        buf = 0x0
        arg = {a_len = 0, a_buf = 0x0, a_idx = 5, a_ctx = 0x959c90}
        timeout = {tv_sec = 7209, tv_usec = 999999}
        f = 0x7f6a2bdd34e0 <st_bodyend>
        fi_abort = 0x406050 <mlfi_abort>
        fi_close = <optimized out>
---Type <return> to continue, or q <return> to quit---
#5  0x00007f6a2bdd5a08 in mi_handle_session (ctx=0x959c90) at handler.c:45
        ret = <optimized out>
#6  0x00007f6a2bdd4549 in mi_thread_handle_wrapper (arg=<optimized out>) at listener.c:579
No locals.
#7  0x00007f6a2bbb9ea5 in start_thread (arg=0x7f6a22ffd700) at pthread_create.c:307
        __res = <optimized out>
        pd = 0x7f6a22ffd700
        now = <optimized out>
        unwind_buf = {cancel_jmp_buf = {{jmp_buf = {140093830452992, -1895300315694036816, 1, 8392704, 3, 140093830452992, 
                1974493738560325808, 1974508550265047216}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {
              prev = 0x0, cleanup = 0x0, canceltype = 0}}}
        not_first_call = <optimized out>
        pagesize_m1 = <optimized out>
        sp = <optimized out>
        freesize = <optimized out>
#8  0x00007f6a2ad8cb0d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
No locals.

I see a flurry of segfaults today, not sure if this is one of those or a new one.

minfrin commented 1 year ago

Other segaults:

https://github.com/trusteddomainproject/OpenDMARC/issues/183

glts commented 1 year ago

Did this crash happen with the patch from #183 applied? (The patch has been included in distros like Debian for a while.)

I haven’t experienced crashes with the patch applied. If you do see crashes even with the patch, please say exactly what commit you are using and what patches you did apply, so that we know exactly what the line numbers in the stack trace refer to.

tachtler commented 1 year ago

Hi,

same problem on my OpenDMARC on CentOS-7. Is there a patch for CentOS-7/EPEL available?

Thank you! Klaus.

Django-BOfH commented 1 year ago

I can confirm the problem with opendmarc-daemon on CentOS 7. An update of the opendmarc package for CentOS-7/EPEL would help a lot.

glts commented 1 year ago

To be clear: I am not aware of any crashing bugs in current OpenDMARC 1.4.2, with the necessary patch linked above applied. The patch is included for example in current Debian or current Ubuntu. If the patch is not applied in CentOS 7/EPEL, report the issue to the maintainers of the package, not here.

BastienDurel commented 1 year ago

Hello. I have many of these crashes too. The patch adds NULL checks in opendmarc_arcseal_lookup(), but in my (and OP's) case, it's the opendmarc_arcseal_parse() which crashes.

It's the same problem :

        tag_label = strsep(&token_ptr, "=");
        tag_value = opendmarc_arcares_strip_whitespace(token_ptr);

strsep() may set token_ptr NULL (In case no delimiter was found, the token is taken to be the entire string stringp, and stringp is made NULL), which triggers the assert in opendmarc_arcares_strip_whitespace()

Any mail from postfix mailing list trigger the crash, you can try, for example, this one

root@corrin:/tmp # opendmarc -f -c /tmp/opendmarc.conf
opendmarc: opendmarc-arcares.c:104: opendmarc_arcares_strip_whitespace: Assertion `string != NULL' failed.
Abandon (core dumped)
root@corrin:/ # milter-test-server -s unix:/tmp/opendmarc.sock -m /tmp/xhmo7mg8nvx.fsf@yw-1130.YW
KIC-8462852 commented 1 year ago

You are wrong @BastienDurel. First, there is no function opendmarc_arcseal_lookup() here. Second, the mentioned patch #183 is all about adding NULL checks precisely in opendmarc_arcseal_parse(). Did you apply the patch #183?

BastienDurel commented 1 year ago

You're right, I messed up my explanations. it's opendmarc_arcares_arc_parse that misses NULL check (so not the OP's crash, do I need to open a new issue ?).

I run Debian 11 package, which has the patch.

Here is the backtrace of the crash :

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ff7740d4537 in __GI_abort () at abort.c:79
#2  0x00007ff7740d440f in __assert_fail_base (fmt=0x7ff77424b688 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x557ce52d31a7 "string != NULL", file=0x557ce52d316b "opendmarc-arcares.c", line=104, function=<optimized out>)
    at assert.c:92
#3  0x00007ff7740e3662 in __GI___assert_fail (assertion=assertion@entry=0x557ce52d31a7 "string != NULL", file=file@entry=0x557ce52d316b "opendmarc-arcares.c", line=line@entry=104,
    function=function@entry=0x557ce52d3260 <__PRETTY_FUNCTION__.2> "opendmarc_arcares_strip_whitespace") at assert.c:101
#4  0x0000557ce52cda44 in opendmarc_arcares_strip_whitespace (string=<optimized out>) at opendmarc-arcares.c:104
#5  opendmarc_arcares_arc_parse (hdr_arc=hdr_arc@entry=0x7ff771fc2ee5 "arc=none (Message is not ARC signed)", arc=arc@entry=0x7ff771fc29d0) at opendmarc-arcares.c:327
#6  0x0000557ce52c913f in mlfi_eom (ctx=0x557ce5a76bc0) at opendmarc.c:3734
#7  0x00007ff7742c55ec in mi_engine () from /usr/lib/x86_64-linux-gnu/libmilter.so.1.0.1
#8  0x00007ff7742c7f6e in ?? () from /usr/lib/x86_64-linux-gnu/libmilter.so.1.0.1
#9  0x00007ff77428dea7 in start_thread (arg=<optimized out>) at pthread_create.c:477
#10 0x00007ff7741ada2f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

This is a the strsep that (I think) nullifies token_ptr https://github.com/trusteddomainproject/OpenDMARC/blob/9cebf724d601452d1a671ed5331551dbc18df83a/opendmarc/opendmarc-arcares.c#L268

KIC-8462852 commented 1 year ago

Open #242