VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/HostDnsService.cpp@ 77506

最後變更 在這個檔案從77506是 77506,由 vboxsync 提交於 6 年 前

Main/HostDnsService: fix a use-after-free running VBoxSVC in debug mode.
bugref:9144: AddressSanitizer: heap-use-after-free in VBoxSVC in HostDnsMonitor::pollGlobalExtraData()
This did not trigger during normal usage, but when debugging and keeping
VBoxSVC around it did. The change terminates the Host DNS monitor thread
properly when the VirtualBox object is destroyed, which in normal use also
ends the process.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 9.9 KB
 
1/* $Id: HostDnsService.cpp 77506 2019-02-28 16:25:19Z vboxsync $ */
2/** @file
3 * Base class for Host DNS & Co services.
4 */
5
6/*
7 * Copyright (C) 2013-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_MAIN_HOST
19#include <VBox/com/array.h>
20#include <VBox/com/ptr.h>
21#include <VBox/com/string.h>
22
23#include <iprt/cpp/utils.h>
24
25#include "LoggingNew.h"
26#include "VirtualBoxImpl.h"
27#include <iprt/time.h>
28#include <iprt/thread.h>
29#include <iprt/semaphore.h>
30#include <iprt/critsect.h>
31
32#include <algorithm>
33#include <set>
34#include <string>
35#include "HostDnsService.h"
36
37
38static void dumpHostDnsInformation(const HostDnsInformation&);
39static void dumpHostDnsStrVector(const std::string&, const std::vector<std::string>&);
40
41
42bool HostDnsInformation::equals(const HostDnsInformation &info, uint32_t fLaxComparison) const
43{
44 bool fSameServers;
45 if ((fLaxComparison & IGNORE_SERVER_ORDER) == 0)
46 {
47 fSameServers = (servers == info.servers);
48 }
49 else
50 {
51 std::set<std::string> l(servers.begin(), servers.end());
52 std::set<std::string> r(info.servers.begin(), info.servers.end());
53
54 fSameServers = (l == r);
55 }
56
57 bool fSameDomain, fSameSearchList;
58 if ((fLaxComparison & IGNORE_SUFFIXES) == 0)
59 {
60 fSameDomain = (domain == info.domain);
61 fSameSearchList = (searchList == info.searchList);
62 }
63 else
64 {
65 fSameDomain = fSameSearchList = true;
66 }
67
68 return fSameServers && fSameDomain && fSameSearchList;
69}
70
71inline static void detachVectorOfString(const std::vector<std::string>& v,
72 std::vector<com::Utf8Str> &aArray)
73{
74 aArray.resize(v.size());
75 size_t i = 0;
76 for (std::vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it, ++i)
77 aArray[i] = Utf8Str(it->c_str());
78}
79
80struct HostDnsMonitor::Data
81{
82 Data(bool aThreaded)
83 : proxy(NULL),
84 fThreaded(aThreaded)
85 {}
86
87 HostDnsMonitorProxy *proxy;
88
89 const bool fThreaded;
90 RTSEMEVENT hDnsInitEvent;
91 RTTHREAD hMonitoringThread;
92
93 HostDnsInformation info;
94};
95
96struct HostDnsMonitorProxy::Data
97{
98 Data(HostDnsMonitor *aMonitor, VirtualBox *aParent)
99 : virtualbox(aParent),
100 monitor(aMonitor),
101 uLastExtraDataPoll(0),
102 fLaxComparison(0),
103 info()
104 {}
105
106 VirtualBox *virtualbox;
107 HostDnsMonitor *monitor;
108
109 uint64_t uLastExtraDataPoll;
110 uint32_t fLaxComparison;
111 HostDnsInformation info;
112};
113
114
115HostDnsMonitor::HostDnsMonitor(bool fThreaded)
116 : m(NULL)
117{
118 m = new HostDnsMonitor::Data(fThreaded);
119}
120
121HostDnsMonitor::~HostDnsMonitor()
122{
123 if (m)
124 {
125 delete m;
126 m = NULL;
127 }
128}
129
130HostDnsMonitor *HostDnsMonitor::createHostDnsMonitor()
131{
132 HostDnsMonitor *monitor = NULL;
133
134#if defined (RT_OS_DARWIN)
135 monitor = new HostDnsServiceDarwin();
136#elif defined(RT_OS_WINDOWS)
137 monitor = new HostDnsServiceWin();
138#elif defined(RT_OS_LINUX)
139 monitor = new HostDnsServiceLinux();
140#elif defined(RT_OS_SOLARIS)
141 monitor = new HostDnsServiceSolaris();
142#elif defined(RT_OS_FREEBSD)
143 monitor = new HostDnsServiceFreebsd();
144#elif defined(RT_OS_OS2)
145 monitor = new HostDnsServiceOs2();
146#else
147 monitor = new HostDnsService();
148#endif
149
150 return monitor;
151}
152
153
154void HostDnsMonitor::shutdown()
155{
156 monitorThreadShutdown();
157 int rc = RTThreadWait(m->hMonitoringThread, 5000, NULL);
158 AssertRCSuccess(rc);
159}
160
161
162void HostDnsMonitor::setInfo(const HostDnsInformation &info)
163{
164 if (m->proxy != NULL)
165 m->proxy->notify(info);
166}
167
168HRESULT HostDnsMonitor::init(HostDnsMonitorProxy *proxy)
169{
170 m->proxy = proxy;
171
172 if (m->fThreaded)
173 {
174 int rc = RTSemEventCreate(&m->hDnsInitEvent);
175 AssertRCReturn(rc, E_FAIL);
176
177 rc = RTThreadCreate(&m->hMonitoringThread,
178 HostDnsMonitor::threadMonitoringRoutine,
179 this, 128 * _1K, RTTHREADTYPE_IO,
180 RTTHREADFLAGS_WAITABLE, "dns-monitor");
181 AssertRCReturn(rc, E_FAIL);
182
183 RTSemEventWait(m->hDnsInitEvent, RT_INDEFINITE_WAIT);
184 }
185 return S_OK;
186}
187
188
189void HostDnsMonitorProxy::pollGlobalExtraData()
190{
191 VirtualBox *virtualbox = m->virtualbox;
192 if (RT_UNLIKELY(virtualbox == NULL))
193 return;
194
195 uint64_t uNow = RTTimeNanoTS();
196 if (uNow - m->uLastExtraDataPoll >= RT_NS_30SEC || m->uLastExtraDataPoll == 0)
197 {
198 m->uLastExtraDataPoll = uNow;
199
200 /*
201 * Should we ignore the order of DNS servers?
202 */
203 const com::Bstr bstrHostDNSOrderIgnoreKey("VBoxInternal2/HostDNSOrderIgnore");
204 com::Bstr bstrHostDNSOrderIgnore;
205 virtualbox->GetExtraData(bstrHostDNSOrderIgnoreKey.raw(),
206 bstrHostDNSOrderIgnore.asOutParam());
207 uint32_t fDNSOrderIgnore = 0;
208 if (bstrHostDNSOrderIgnore.isNotEmpty())
209 {
210 if (bstrHostDNSOrderIgnore != "0")
211 fDNSOrderIgnore = HostDnsInformation::IGNORE_SERVER_ORDER;
212 }
213
214 if (fDNSOrderIgnore != (m->fLaxComparison & HostDnsInformation::IGNORE_SERVER_ORDER))
215 {
216
217 m->fLaxComparison ^= HostDnsInformation::IGNORE_SERVER_ORDER;
218 LogRel(("HostDnsMonitor: %ls=%ls\n",
219 bstrHostDNSOrderIgnoreKey.raw(),
220 bstrHostDNSOrderIgnore.raw()));
221 }
222
223 /*
224 * Should we ignore changes to the domain name or the search list?
225 */
226 const com::Bstr bstrHostDNSSuffixesIgnoreKey("VBoxInternal2/HostDNSSuffixesIgnore");
227 com::Bstr bstrHostDNSSuffixesIgnore;
228 virtualbox->GetExtraData(bstrHostDNSSuffixesIgnoreKey.raw(),
229 bstrHostDNSSuffixesIgnore.asOutParam());
230 uint32_t fDNSSuffixesIgnore = 0;
231 if (bstrHostDNSSuffixesIgnore.isNotEmpty())
232 {
233 if (bstrHostDNSSuffixesIgnore != "0")
234 fDNSSuffixesIgnore = HostDnsInformation::IGNORE_SUFFIXES;
235 }
236
237 if (fDNSSuffixesIgnore != (m->fLaxComparison & HostDnsInformation::IGNORE_SUFFIXES))
238 {
239
240 m->fLaxComparison ^= HostDnsInformation::IGNORE_SUFFIXES;
241 LogRel(("HostDnsMonitor: %ls=%ls\n",
242 bstrHostDNSSuffixesIgnoreKey.raw(),
243 bstrHostDNSSuffixesIgnore.raw()));
244 }
245 }
246}
247
248void HostDnsMonitor::monitorThreadInitializationDone()
249{
250 RTSemEventSignal(m->hDnsInitEvent);
251}
252
253
254DECLCALLBACK(int) HostDnsMonitor::threadMonitoringRoutine(RTTHREAD, void *pvUser)
255{
256 HostDnsMonitor *pThis = static_cast<HostDnsMonitor *>(pvUser);
257 return pThis->monitorWorker();
258}
259
260/* HostDnsMonitorProxy */
261HostDnsMonitorProxy::HostDnsMonitorProxy()
262 : m(NULL)
263{
264}
265
266HostDnsMonitorProxy::~HostDnsMonitorProxy()
267{
268 Assert(!m);
269}
270
271void HostDnsMonitorProxy::init(VirtualBox* aParent)
272{
273 HostDnsMonitor *monitor = HostDnsMonitor::createHostDnsMonitor();
274 m = new HostDnsMonitorProxy::Data(monitor, aParent);
275 m->monitor->init(this);
276}
277
278
279void HostDnsMonitorProxy::uninit()
280{
281 m->monitor->shutdown();
282 delete m;
283 m = NULL;
284}
285
286void HostDnsMonitorProxy::notify(const HostDnsInformation &info)
287{
288 bool fNotify = updateInfo(info);
289 if (fNotify)
290 m->virtualbox->i_onHostNameResolutionConfigurationChange();
291}
292
293HRESULT HostDnsMonitorProxy::GetNameServers(std::vector<com::Utf8Str> &aNameServers)
294{
295 AssertReturn(m != NULL, E_FAIL);
296 RTCLock grab(m_LockMtx);
297
298 LogRel(("HostDnsMonitorProxy::GetNameServers:\n"));
299 dumpHostDnsStrVector("name server", m->info.servers);
300
301 detachVectorOfString(m->info.servers, aNameServers);
302
303 return S_OK;
304}
305
306HRESULT HostDnsMonitorProxy::GetDomainName(com::Utf8Str *pDomainName)
307{
308 AssertReturn(m != NULL, E_FAIL);
309 RTCLock grab(m_LockMtx);
310
311 LogRel(("HostDnsMonitorProxy::GetDomainName: %s\n",
312 m->info.domain.empty() ? "no domain set" : m->info.domain.c_str()));
313
314 *pDomainName = m->info.domain.c_str();
315
316 return S_OK;
317}
318
319HRESULT HostDnsMonitorProxy::GetSearchStrings(std::vector<com::Utf8Str> &aSearchStrings)
320{
321 AssertReturn(m != NULL, E_FAIL);
322 RTCLock grab(m_LockMtx);
323
324 LogRel(("HostDnsMonitorProxy::GetSearchStrings:\n"));
325 dumpHostDnsStrVector("search string", m->info.searchList);
326
327 detachVectorOfString(m->info.searchList, aSearchStrings);
328
329 return S_OK;
330}
331
332bool HostDnsMonitorProxy::updateInfo(const HostDnsInformation &info)
333{
334 LogRel(("HostDnsMonitor::updateInfo\n"));
335 RTCLock grab(m_LockMtx);
336
337 if (info.equals(m->info))
338 {
339 LogRel(("HostDnsMonitor: unchanged\n"));
340 return false;
341 }
342
343 pollGlobalExtraData();
344
345 LogRel(("HostDnsMonitor: old information\n"));
346 dumpHostDnsInformation(m->info);
347 LogRel(("HostDnsMonitor: new information\n"));
348 dumpHostDnsInformation(info);
349
350 bool fIgnore = m->fLaxComparison != 0 && info.equals(m->info, m->fLaxComparison);
351 m->info = info;
352
353 if (fIgnore)
354 {
355 LogRel(("HostDnsMonitor: lax comparison %#x, not notifying\n", m->fLaxComparison));
356 return false;
357 }
358
359 return true;
360}
361
362
363static void dumpHostDnsInformation(const HostDnsInformation& info)
364{
365 dumpHostDnsStrVector("server", info.servers);
366
367 if (!info.domain.empty())
368 LogRel((" domain: %s\n", info.domain.c_str()));
369 else
370 LogRel((" no domain set\n"));
371
372 dumpHostDnsStrVector("search string", info.searchList);
373}
374
375
376static void dumpHostDnsStrVector(const std::string& prefix, const std::vector<std::string>& v)
377{
378 int i = 1;
379 for (std::vector<std::string>::const_iterator it = v.begin();
380 it != v.end();
381 ++it, ++i)
382 LogRel((" %s %d: %s\n", prefix.c_str(), i, it->c_str()));
383 if (v.empty())
384 LogRel((" no %s entries\n", prefix.c_str()));
385}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette