Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
5.3.2
-
None
-
Running a Qt daemon application inside a docker container
-
306c32f50e289c401e4636976c97dc2b40fdd69b
Description
Description
A segmentation fault occur in (src/network/kernel/qdnslookup_unix.cpp) when using QDnsLookup to acces large TXT fields (561 byte) on a DNS query.
According to RFC, UDP DNS query over 512 byte can be truncated and the requester should retry to query over TCP. This is what is happening currently in my use case using QDnsLookup on Unix. I wasn't able to reproduce the crash on Windows or OSX
Steps To Reproduce
- Perform a QDNSLookup on TXT fields. ex:
QDnsLookup* txtLookup = new QDnsLookup(this); txtLookup->setNameserver(dns); txtLookup->setType(QDnsLookup::TXT); txtLookup->setName(TXTLOOKUPNAME); connect(txtLookup, &QDnsLookup::finished,......); txtLookup->lookup();
- Package the application as a deamon in a docker based on Debian Jessie
- Run the query periodically and wait for it to crash
Observed Behavior
When not crashing, results are truncated to 512 byte. TXT fields are returned by the name sever in random order so the fields that will be missing or truncated can vary. According the the order of the TXT fields, Qt can crash from a buffer overflow error because the response header state that the response contain more fields that what Qt is accepting from the request. Qt buffer size is set to PACKETSZ in unix
Expected behavior
The DNS query over TCP should parse the full content of the reply.
Possible solution
Increasing the size of the response buffer to 65536 (large enough for the largest DNS message) fixed the crash and the truncated responses content for me.
Call stack
From GDB with all QT debug symbol and no optimization:
(gdb) bt full #0 0x00007ffff714c473 in QDnsLookupRunnable::query (requestType=16, requestName=..., nameserver=..., reply=0x7fffe5 be8d20) at kernel/qdnslookup_unix.cpp:357 length = 0 '\000' length = 0 '\000' txt = 0x7fffe5bea000 "" record = {d = {d = 0x7fffd00037f0}} name = {static null = {<No data fields>}, d = 0x7fffd0003860} type = 16 ttl = 6973814 size = 25902 p = 0x7fffe5be8395 "com" state = {retrans = 5, retry = 2, options = 524993, nscount = 1, nsaddr_list = {{sin_family = 2, sin_port = 1 3568, sin_addr = {s_addr = 21080256}, sin_zero = "\000\000\000\000\000\000\000"}, {sin_family = 0, sin_port = 0, sin _addr = {s_addr = 0}, sin_zero = "\000\000\000\000\000\000\000"}, {sin_family = 0, sin_port = 0, sin_addr = {s_addr = 0}, sin_zero = "\000\000\000\000\000\000\000"}}, id = 4324, dnsrch = {0x7fffe5be8810 "cgocable.ca", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, defdname = "cgocable.ca", '\000' <repeats 244 times>, pfcode = 0, ndots = 1, nsort = 0, ipv6_unavai l = 0, unused = 0, sort_list = {{addr = {s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {a ddr = {s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = {s_addr = 0}, mask = 0}, {addr = {s_addr = 0 }, mask = 0}}, qhook = 0x0, rhook = 0x0, res_h_errno = 0, _vcsock = -1, _flags = 0, _u = {pad = "\001\000\000\000\00 0\000\000\000\377\377\377\377", '\000' <repeats 12 times>, "\240\023\000\320\377\177", '\000' <repeats 18 times>, "\ 004\000\000", _ext = {nscount = 1, nsmap = {0, 0, 0}, nssocks = {-1, 0, 0}, nscount6 = 0, nsinit = 0, nsaddrs = {0x7 fffd00013a0, 0x0, 0x0}, _initstamp = {4, 0}}}} state_ptr = {d = 0x7fffe5be8790} response = "\344\020\201\200\000\001\000\a\000\000\000\000\004jive\003com\000\000\020\000\001\300\f\000\020\ 000\001\000\000\000$\000-,status-page-domain-verification=0drlhdrwfd27\300\f\000\020\000\001\000\000\000$\000>=citri x-verification-code=4bd0f3e9-f63e-4b7c-842f-1c8afd5fd746\300\f\000\020\000\001\000\000\000$\000EDgoogle-site-verific ation=_4GdMM"... responseLength = 512 responseLength = 512 answerCount = 7 host = "jive.com", '\000' <repeats 503 times> status = 2 triedResolve = {_q_value = 1} header = 0x7fffe5be8190 answer = '\000' <repeats 511 times> answerIndex = 6 #1 0x00007ffff7135038 in QDnsLookupRunnable::run (this=0x7ea790) at kernel/qdnslookup.cpp:998 reply = {error = QDnsLookup::NoError, errorString = {static null = {<No data fields>}, d = 0x7ffff644d8a0 <Q ArrayData::shared_null>}, canonicalNameRecords = {{p = {static shared_null = {ref = {atomic = {_q_value = -1}}, allo c = 0, begin = 0, end = 0, array = {0x0}}, d = 0x7ffff6451570 <QListData::shared_null>}, d = 0x7ffff6451570 <QListDa ta::shared_null>}}, hostAddressRecords = {{p = {static shared_null = {ref = {atomic = {_q_value = -1}}, alloc = 0, b egin = 0, end = 0, array = {0x0}}, d = 0x7ffff6451570 <QListData::shared_null>}, d = 0x7ffff6451570 <QListData::shar ed_null>}}, mailExchangeRecords = {{p = {static shared_null = {ref = {atomic = {_q_value = -1}}, alloc = 0, begin = 0, end = 0, array = {0x0}}, d = 0x7ffff6451570 <QListData::shared_null>}, d = 0x7ffff6451570 <QListData::shared_null >}}, nameServerRecords = {{p = {static shared_null = {ref = {atomic = {_q_value = -1}}, alloc = 0, begin = 0, end = 0, array = {0x0}}, d = 0x7ffff6451570 <QListData::shared_null>}, d = 0x7ffff6451570 <QListData::shared_null>}}, poin terRecords = {{p = {static shared_null = {ref = {atomic = {_q_value = -1}}, alloc = 0, begin = 0, end = 0, array = { 0x0}}, d = 0x7ffff6451570 <QListData::shared_null>}, d = 0x7ffff6451570 <QListData::shared_null>}}, serviceRecords = {{p = {static shared_null = {ref = {atomic = {_q_value = -1}}, alloc = 0, begin = 0, end = 0, array = {0x0}}, d = 0 x7ffff6451570 <QListData::shared_null>}, d = 0x7ffff6451570 <QListData::shared_null>}}, textRecords = {{p = {static shared_null = {ref = {atomic = {_q_value = -1}}, alloc = 0, begin = 0, end = 0, array = {0x0}}, d = 0x7fffd00034d0}, d = 0x7fffd00034d0}}} #2 0x00007ffff60fdf9d in QThreadPoolThread::run (this=0x7ea8c0) at thread/qthreadpool.cpp:101 autoDelete = true autoDelete = true r = 0x7ea7a0 expired = false locker = {val = 8298288} __PRETTY_FUNCTION__ = "virtual void QThreadPoolThread::run()" #3 0x00007ffff61043c1 in QThreadPrivate::start (arg=0x7ea8c0) at thread/qthread_unix.cpp:345 __clframe = {__cancel_routine = 0x7ffff6104448 <QThreadPrivate::finish(void*)>, __cancel_arg = 0x7ea8c0, __d o_it = 1, __cancel_type = 0} thr = 0x7ea8c0 data = 0x7eabd0 objectName = {static null = {<No data fields>}, d = 0x7eacc0} #4 0x00007ffff5baa064 in start_thread (arg=0x7fffe5be9700) at pthread_create.c:309 __res = <optimized out> pd = 0x7fffe5be9700 now = <optimized out> unwind_buf = {cancel_jmp_buf = {{jmp_buf = {140737047860992, -5318128364370376861, 1, 140737354125408, 14073 7338628140, 140737047860992, 5318184984417552227, 5318149832888305507}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x 0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}} not_first_call = <optimized out> pagesize_m1 = <optimized out> sp = <optimized out> freesize = <optimized out> __PRETTY_FUNCTION__ = "start_thread" #5 0x00007ffff50bd62d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
Here is the full content on the response (truncated by Qt) after the segmentation fault. You can compare it with the attached packet capture to see the actual content of the full request >512 byte:
(gdb) x/70s &response 0x7fffe5be8190: "\252w\201\200" 0x7fffe5be8195: "\001" 0x7fffe5be8197: "\a" 0x7fffe5be8199: "" 0x7fffe5be819a: "" 0x7fffe5be819b: "" 0x7fffe5be819c: "\004jive\003com" 0x7fffe5be81a6: "" 0x7fffe5be81a7: "\020" 0x7fffe5be81a9: "\001\300\f" 0x7fffe5be81ad: "\020" 0x7fffe5be81af: "\001" 0x7fffe5be81b1: "" 0x7fffe5be81b2: "" 0x7fffe5be81b3: "\t" 0x7fffe5be81b5: ">=citrix-verification-code=4bd0f3e9-f63e-4b7c-842f-1c8afd5fd746\300\f" 0x7fffe5be81f7: "\020" 0x7fffe5be81f9: "\001" 0x7fffe5be81fb: "" 0x7fffe5be81fc: "" 0x7fffe5be81fd: "\t" 0x7fffe5be81ff: "EDgoogle-site-verification=_4GdMM2-9DuMtEdksMjatJYREN3UzvegKUw4z3QkjRU\300\f" 0x7fffe5be8248: "\020" 0x7fffe5be824a: "\001" 0x7fffe5be824c: "" 0x7fffe5be824d: "" 0x7fffe5be824e: "\t" 0x7fffe5be8250: "\307\306v=spf1 ip4:199.36.248.1/22 ip4:199.87.120.1/22 ip4:199.87.120.0/22 +include:stspg-customer.co m +include:_spf.google.com +include:_spf.salesforce.com +include:mktomail.com +include:amazonses.com ~all"... 0x7fffe5be8318: "\300\f" 0x7fffe5be831b: "\020" 0x7fffe5be831d: "\001" 0x7fffe5be831f: "" 0x7fffe5be8320: "" 0x7fffe5be8321: "\t" 0x7fffe5be8323: "\016\rMS=ms35084001\300\f" 0x7fffe5be8335: "\020" 0x7fffe5be8337: "\001" 0x7fffe5be8339: "" 0x7fffe5be833a: "" 0x7fffe5be833b: "\t" 0x7fffe5be833d: "\022\021\066\065\070\070\062\063\062\064\067-3475009\300\f" 0x7fffe5be8353: "\020" 0x7fffe5be8355: "\001" 0x7fffe5be8357: "" 0x7fffe5be8358: "" 0x7fffe5be8359: "\t" 0x7fffe5be835b: ",+MS=2F8792E977E20CDBD10A4BF28CDE7AD18CCEE50B\300\f" 0x7fffe5be838b: "\020" 0x7fffe5be838d: "\001" 0x7fffe5be838f: "" 0x7fffe5be8390: "jive.com" 0x7fffe5be8399: "" 0x7fffe5be839a: "" 0x7fffe5be839b: "" 0x7fffe5be839c: "" 0x7fffe5be839d: "" 0x7fffe5be839e: "" 0x7fffe5be839f: "" 0x7fffe5be83a0: "" 0x7fffe5be83a1: "" 0x7fffe5be83a2: "" 0x7fffe5be83a3: "" 0x7fffe5be83a4: "" 0x7fffe5be83a5: ""
The last TXT field is missing :
status-page-domain-verification=0drlhdrwfd27
Attachments
For Gerrit Dashboard: QTBUG-64742 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
212782,20 | Fix out of bounds reads in qdnslookup_unix | 5.9 | qt/qtbase | Status: MERGED | +2 | 0 |