IMAP authentication periodically segfaults #884

Open
opened 2026-10-05 04:50:36 +02:00 by adam · 8 comments
Owner

We have around 200 users on a ZNC installation authenticated from IMAP, and periodically (a few times / week) it seems to segfault in the IMAP auth plugin.

Here's a stack trace:

Thread 1 "znc" received signal SIGSEGV, Segmentation fault.
0x0000555555d7af10 in ?? ()
#0  0x0000555555d7af10 in ?? ()
No symbol table info available.
#1  0x00007ffff6f89861 in ucnv_close_60 () from /usr/lib/x86_64-linux-gnu/libicuuc.so.60
No symbol table info available.
#2  0x00005555555a48c9 in Csock::SetEncoding (this=this@entry=0x55555603fd00, sEncoding=...)
    at src/Csocket.cpp:2452
No locals.
#3  0x00005555556895ef in CZNCSock::SetEncoding (this=this@entry=0x55555603fd00, sEncoding=...)
    at src/Socket.cpp:184
No locals.
#4  0x0000555555602cd2 in CClient::AcceptLogin (this=0x55555603fd00, User=...)
    at src/Client.cpp:389
No locals.
#5  0x00005555555f9361 in CAuthBase::AcceptLogin (this=0x5555564c6e90, User=...)
    at src/Client.cpp:344
No locals.
#6  0x00007ffff3fe6bb5 in CIMAPSock::ReadLine (this=0x55555601c0e0, sLine=...)
    at imapauth.cpp:149
        pUser = 0x55555596ebd0
#7  0x00005555555a67ab in Csock::PushBuff (this=0x55555601c0e0, data=<optimized out>, 
    len=<optimized out>, bStartAtZero=<optimized out>) at src/Csocket.cpp:2381
        sBuff = {<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >> = "AUTH OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN N"..., static CaseSensitive = CaseSensitivity::CaseSensitive, 
          static CaseInsensitive = CaseSensitivity::CaseInsensitive}
        iFind = <optimized out>
        iStartPos = <optimized out>
#8  0x00005555555ae71a in CSocketManager::Loop (this=0x55555590af20) at src/Csocket.cpp:3458
        iLen = <optimized out>
        cBuff = {
          m_pBuffer = 0x555556546010 "AUTH OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN N"...}
        bytes = 375
        pcSock = 0x55555601c0e0
        iErrno = <optimized out>
        itSock = {first = 0x55555601c0e0, second = CSocketManager::SUCCESS}
        mpeSocks = std::map with 1 element = {[0x55555601c0e0] = CSocketManager::SUCCESS}
        iMilliNow = <optimized out>
#9  0x00005555555a3b70 in CSocketManager::DynamicSelectLoop (this=0x55555590af20, 
    iLowerBounds=<optimized out>, iUpperBounds=<optimized out>, iMaxResolution=<optimized out>)
    at src/Csocket.cpp:3516
No locals.
#10 0x00005555555c54cd in CZNC::Loop (this=0x55555590ae70) at src/znc.cpp:252
        sError = {<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >> = "", static CaseSensitive = CaseSensitivity::CaseSensitive, 
          static CaseInsensitive = CaseSensitivity::CaseInsensitive}
        eState = <optimized out>
#11 0x000055555559081d in main (argc=<optimized out>, argv=0x7fffffffdff8) at src/main.cpp:525
        SignalHandler = std::unique_ptr<CSignalHandler> = {get() = 0x5555559de730}
        iRet = 0
        sConfig = {<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >> = "", static CaseSensitive = CaseSensitivity::CaseSensitive, 
          static CaseInsensitive = CaseSensitivity::CaseInsensitive}
        sDataDir = {<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >> = "", static CaseSensitive = CaseSensitivity::CaseSensitive, 
          static CaseInsensitive = CaseSensitivity::CaseInsensitive}
        iArg = <optimized out>
        iOptIndex = -1
        bMakeConf = false
        bMakePass = false
        bAllowRoot = false
        bForeground = true
        bMakePem = <optimized out>
        pZNC = 0x55555590ae70
        sConfigError = {<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >> = "", static CaseSensitive = CaseSensitivity::CaseSensitive, 
          static CaseInsensitive = CaseSensitivity::CaseInsensitive}
We have around 200 users on a ZNC installation authenticated from IMAP, and periodically (a few times / week) it seems to segfault in the IMAP auth plugin. Here's a stack trace: ``` Thread 1 "znc" received signal SIGSEGV, Segmentation fault. 0x0000555555d7af10 in ?? () #0 0x0000555555d7af10 in ?? () No symbol table info available. #1 0x00007ffff6f89861 in ucnv_close_60 () from /usr/lib/x86_64-linux-gnu/libicuuc.so.60 No symbol table info available. #2 0x00005555555a48c9 in Csock::SetEncoding (this=this@entry=0x55555603fd00, sEncoding=...) at src/Csocket.cpp:2452 No locals. #3 0x00005555556895ef in CZNCSock::SetEncoding (this=this@entry=0x55555603fd00, sEncoding=...) at src/Socket.cpp:184 No locals. #4 0x0000555555602cd2 in CClient::AcceptLogin (this=0x55555603fd00, User=...) at src/Client.cpp:389 No locals. #5 0x00005555555f9361 in CAuthBase::AcceptLogin (this=0x5555564c6e90, User=...) at src/Client.cpp:344 No locals. #6 0x00007ffff3fe6bb5 in CIMAPSock::ReadLine (this=0x55555601c0e0, sLine=...) at imapauth.cpp:149 pUser = 0x55555596ebd0 #7 0x00005555555a67ab in Csock::PushBuff (this=0x55555601c0e0, data=<optimized out>, len=<optimized out>, bStartAtZero=<optimized out>) at src/Csocket.cpp:2381 sBuff = {<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >> = "AUTH OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN N"..., static CaseSensitive = CaseSensitivity::CaseSensitive, static CaseInsensitive = CaseSensitivity::CaseInsensitive} iFind = <optimized out> iStartPos = <optimized out> #8 0x00005555555ae71a in CSocketManager::Loop (this=0x55555590af20) at src/Csocket.cpp:3458 iLen = <optimized out> cBuff = { m_pBuffer = 0x555556546010 "AUTH OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN N"...} bytes = 375 pcSock = 0x55555601c0e0 iErrno = <optimized out> itSock = {first = 0x55555601c0e0, second = CSocketManager::SUCCESS} mpeSocks = std::map with 1 element = {[0x55555601c0e0] = CSocketManager::SUCCESS} iMilliNow = <optimized out> #9 0x00005555555a3b70 in CSocketManager::DynamicSelectLoop (this=0x55555590af20, iLowerBounds=<optimized out>, iUpperBounds=<optimized out>, iMaxResolution=<optimized out>) at src/Csocket.cpp:3516 No locals. #10 0x00005555555c54cd in CZNC::Loop (this=0x55555590ae70) at src/znc.cpp:252 sError = {<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >> = "", static CaseSensitive = CaseSensitivity::CaseSensitive, static CaseInsensitive = CaseSensitivity::CaseInsensitive} eState = <optimized out> #11 0x000055555559081d in main (argc=<optimized out>, argv=0x7fffffffdff8) at src/main.cpp:525 SignalHandler = std::unique_ptr<CSignalHandler> = {get() = 0x5555559de730} iRet = 0 sConfig = {<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >> = "", static CaseSensitive = CaseSensitivity::CaseSensitive, static CaseInsensitive = CaseSensitivity::CaseInsensitive} sDataDir = {<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >> = "", static CaseSensitive = CaseSensitivity::CaseSensitive, static CaseInsensitive = CaseSensitivity::CaseInsensitive} iArg = <optimized out> iOptIndex = -1 bMakeConf = false bMakePass = false bAllowRoot = false bForeground = true bMakePem = <optimized out> pZNC = 0x55555590ae70 sConfigError = {<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >> = "", static CaseSensitive = CaseSensitivity::CaseSensitive, static CaseInsensitive = CaseSensitivity::CaseInsensitive} ``` <!-- github-sync-id:375721656 -->
Author
Owner

version?

version? <!-- github-comment-id:434496470 -->
Author
Owner

Sorry, I should have mentioned that. We have seen this both with 1.7 from the Ubuntu PPA as well as this nightly I built for debugging:

znc@office:/home/znc$ znc --version
ZNC 1.8.x+deb1.8.0~finchamgit1-nightly-20180930-b00cc309 - https://znc.in
IPv6: yes, SSL: yes, DNS: threads, charset: yes, i18n: no, build: autoconf

Sorry, I should have mentioned that. We have seen this both with 1.7 from the Ubuntu PPA as well as this nightly I built for debugging: znc@office:/home/znc$ znc --version ZNC 1.8.x+deb1.8.0~finchamgit1-nightly-20180930-b00cc309 - https://znc.in IPv6: yes, SSL: yes, DNS: threads, charset: yes, i18n: no, build: autoconf <!-- github-comment-id:434497188 -->
Author
Owner

We've seen this on Ubuntu Trusty and Ubuntu Bionic

We've seen this on Ubuntu Trusty and Ubuntu Bionic <!-- github-comment-id:434497326 -->
Author
Owner

Talking to @douglasbagnall he recommends this patch:

--- Csocket.cpp~I2018-10-31 12:49:34.148351871 +1300
+++ Csocket.cppI2018-10-31 12:52:59.091431310 +1300
@@ -1033,7 +1033,9 @@
 
 #ifdef HAVE_ICU
         if( m_cnvExt ) ucnv_close( m_cnvExt );
+        m_cnvExt = NULL;
         if( m_cnvInt ) ucnv_close( m_cnvInt );
+        m_cnvInt = NULL;
 #endif
Talking to @douglasbagnall he recommends this patch: ``` --- Csocket.cpp~I2018-10-31 12:49:34.148351871 +1300 +++ Csocket.cppI2018-10-31 12:52:59.091431310 +1300 @@ -1033,7 +1033,9 @@ #ifdef HAVE_ICU if( m_cnvExt ) ucnv_close( m_cnvExt ); + m_cnvExt = NULL; if( m_cnvInt ) ucnv_close( m_cnvInt ); + m_cnvInt = NULL; #endif ``` <!-- github-comment-id:434514321 -->
Author
Owner

Does that patch help? I don't see how it would...

Can you show output of grep Encoding znc.conf and grep LoadModule znc.conf? (verify that it doesn't contains any passwords)

Does that patch help? I don't see how it would... Can you show output of `grep Encoding znc.conf` and `grep LoadModule znc.conf`? (verify that it doesn't contains any passwords) <!-- github-comment-id:434600020 -->
Author
Owner

I'll grep those tomorrow when I'm back in the office, thanks. I'll also get some further commentary as to the suitability of that fix.

We switched to using a different authentication module for now, so replicating the problem in production again is going to be difficult I suspect.

I'll grep those tomorrow when I'm back in the office, thanks. I'll also get some further commentary as to the suitability of that fix. We switched to using a different authentication module for now, so replicating the problem in production again is going to be difficult I suspect. <!-- github-comment-id:434622028 -->
Author
Owner

The reasoning behind that patch is based on the traceback which could be caused by a double uncv_close(), which could happen if m_cnvExt was closed somewhere and not set to NULL, like Csocket.cpp does there. I haven't looked at all at the program flow, so I understand that it could have nothing to do with it, but wouldn't you want the patch anyway?

The reasoning behind that patch is based on the traceback which could be caused by a double `uncv_close()`, which could happen if `m_cnvExt` was closed somewhere and not set to NULL, like Csocket.cpp does there. I haven't looked at all at the program flow, so I understand that it could have nothing to do with it, but wouldn't you want the patch anyway? <!-- github-comment-id:434911886 -->
Author
Owner

@douglasbagnall the patch changes code in destructor of Csock. If SetEncoding() is called after the socket was destroyed, we have problems regardless of what was the value of the field of the destroyed object, since the memory can be reused for something else anyway.
Well, your patch doesn't hurt...

I tried to reproduce this, including case when client disconnects before IMAP server replies, but that still works for me.

One more thing which you can try, is to compile ZNC with ASan and watch for much better error message of when it crashes.

@douglasbagnall the patch changes code in destructor of `Csock`. If `SetEncoding()` is called after the socket was destroyed, we have problems regardless of what was the value of the field of the destroyed object, since the memory can be reused for something else anyway. Well, your patch doesn't hurt... I tried to reproduce this, including case when client disconnects before IMAP server replies, but that still works for me. One more thing which you can try, is to compile ZNC with [ASan](https://clang.llvm.org/docs/AddressSanitizer.html) and watch for much better error message of when it crashes. <!-- github-comment-id:434961106 -->
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/znc#884