- bugfix: race condition in deferred name resolution (id=238)
from v5.8.0 candidate. OBS-URL: https://build.opensuse.org/package/show/Base:System/rsyslog?expand=0&rev=44
This commit is contained in:
parent
5288ed8f83
commit
b7e23bedcb
281
rsyslog-deferred-dns-query-race.diff
Normal file
281
rsyslog-deferred-dns-query-race.diff
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
From 21f69b2c3a95c990ea123d078b08c554cab1d121 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Rainer Gerhards <rgerhards@adiscon.com>
|
||||||
|
Date: Fri, 8 Apr 2011 11:04:38 +0200
|
||||||
|
Subject: [PATCH] bugfix: race condition in deferred name resolution
|
||||||
|
|
||||||
|
Note that this actually is a very small change, but I needed
|
||||||
|
to shuffle a lot of code around in order to make it compile
|
||||||
|
(due to required define order...).
|
||||||
|
|
||||||
|
Signed-off-by: Marius Tomaschewski <mt@suse.de>
|
||||||
|
---
|
||||||
|
runtime/msg.c | 232 +++++++++++++++++++++++++++++----------------------------
|
||||||
|
1 files changed, 117 insertions(+), 115 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/runtime/msg.c b/runtime/msg.c
|
||||||
|
index 409515a..8a1e66a 100644
|
||||||
|
--- a/runtime/msg.c
|
||||||
|
+++ b/runtime/msg.c
|
||||||
|
@@ -287,6 +287,121 @@ static pthread_mutex_t mutTrimCtr; /* mutex to handle malloc trim */
|
||||||
|
static int getAPPNAMELen(msg_t *pM, sbool bLockMutex);
|
||||||
|
|
||||||
|
|
||||||
|
+/* The following functions will support advanced output module
|
||||||
|
+ * multithreading, once this is implemented. Currently, we
|
||||||
|
+ * include them as hooks only. The idea is that we need to guard
|
||||||
|
+ * some msg objects data fields against concurrent access if
|
||||||
|
+ * we run on multiple threads. Please note that in any case this
|
||||||
|
+ * is not necessary for calls from INPUT modules, because they
|
||||||
|
+ * construct the message object and do this serially. Only when
|
||||||
|
+ * the message is in the processing queue, multiple threads may
|
||||||
|
+ * access a single object. Consequently, there are no guard functions
|
||||||
|
+ * for "set" methods, as these are called during input. Only "get"
|
||||||
|
+ * functions that modify important structures have them.
|
||||||
|
+ * rgerhards, 2007-07-20
|
||||||
|
+ * We now support locked and non-locked operations, depending on
|
||||||
|
+ * the configuration of rsyslog. To support this, we use function
|
||||||
|
+ * pointers. Initially, we start in non-locked mode. There, all
|
||||||
|
+ * locking operations call into dummy functions. When locking is
|
||||||
|
+ * enabled, the function pointers are changed to functions doing
|
||||||
|
+ * actual work. We also introduced another MsgPrepareEnqueue() function
|
||||||
|
+ * which initializes the locking structures, if needed. This is
|
||||||
|
+ * necessary because internal messages during config file startup
|
||||||
|
+ * processing are always created in non-locking mode. So we can
|
||||||
|
+ * not initialize locking structures during constructions. We now
|
||||||
|
+ * postpone this until when the message is fully constructed and
|
||||||
|
+ * enqueued. Then we know the status of locking. This has a nice
|
||||||
|
+ * side effect, and that is that during the initial creation of
|
||||||
|
+ * the Msg object no locking needs to be done, which results in better
|
||||||
|
+ * performance. -- rgerhards, 2008-01-05
|
||||||
|
+ */
|
||||||
|
+static void (*funcLock)(msg_t *pMsg);
|
||||||
|
+static void (*funcUnlock)(msg_t *pMsg);
|
||||||
|
+static void (*funcDeleteMutex)(msg_t *pMsg);
|
||||||
|
+void (*funcMsgPrepareEnqueue)(msg_t *pMsg);
|
||||||
|
+#if 1 /* This is a debug aid */
|
||||||
|
+#define MsgLock(pMsg) funcLock(pMsg)
|
||||||
|
+#define MsgUnlock(pMsg) funcUnlock(pMsg)
|
||||||
|
+#else
|
||||||
|
+#define MsgLock(pMsg) {dbgprintf("MsgLock line %d\n - ", __LINE__); funcLock(pMsg);; }
|
||||||
|
+#define MsgUnlock(pMsg) {dbgprintf("MsgUnlock line %d - ", __LINE__); funcUnlock(pMsg); }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+/* the next function is a dummy to be used by the looking functions
|
||||||
|
+ * when the class is not yet running in an environment where locking
|
||||||
|
+ * is necessary. Please note that the need to lock can (and will) change
|
||||||
|
+ * during a single run. Typically, this is depending on the operation mode
|
||||||
|
+ * of the message queues (which is operator-configurable). -- rgerhards, 2008-01-05
|
||||||
|
+ */
|
||||||
|
+static void MsgLockingDummy(msg_t __attribute__((unused)) *pMsg)
|
||||||
|
+{
|
||||||
|
+ /* empty be design */
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* The following function prepares a message for enqueue into the queue. This is
|
||||||
|
+ * where a message may be accessed by multiple threads. This implementation here
|
||||||
|
+ * is the version for multiple concurrent acces. It initializes the locking
|
||||||
|
+ * structures.
|
||||||
|
+ * TODO: change to an iRet interface! -- rgerhards, 2008-07-14
|
||||||
|
+ */
|
||||||
|
+static void MsgPrepareEnqueueLockingCase(msg_t *pThis)
|
||||||
|
+{
|
||||||
|
+ BEGINfunc
|
||||||
|
+ assert(pThis != NULL);
|
||||||
|
+ pthread_mutex_init(&pThis->mut, NULL);
|
||||||
|
+ pThis->bDoLock = 1;
|
||||||
|
+ ENDfunc
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* ... and now the locking and unlocking implementations: */
|
||||||
|
+static void MsgLockLockingCase(msg_t *pThis)
|
||||||
|
+{
|
||||||
|
+ /* DEV debug only! dbgprintf("MsgLock(0x%lx)\n", (unsigned long) pThis); */
|
||||||
|
+ assert(pThis != NULL);
|
||||||
|
+ if(pThis->bDoLock == 1) /* TODO: this is a testing hack, we should find a way with better performance! -- rgerhards, 2009-01-27 */
|
||||||
|
+ pthread_mutex_lock(&pThis->mut);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void MsgUnlockLockingCase(msg_t *pThis)
|
||||||
|
+{
|
||||||
|
+ /* DEV debug only! dbgprintf("MsgUnlock(0x%lx)\n", (unsigned long) pThis); */
|
||||||
|
+ assert(pThis != NULL);
|
||||||
|
+ if(pThis->bDoLock == 1) /* TODO: this is a testing hack, we should find a way with better performance! -- rgerhards, 2009-01-27 */
|
||||||
|
+ pthread_mutex_unlock(&pThis->mut);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* delete the mutex object on message destruction (locking case)
|
||||||
|
+ */
|
||||||
|
+static void MsgDeleteMutexLockingCase(msg_t *pThis)
|
||||||
|
+{
|
||||||
|
+ assert(pThis != NULL);
|
||||||
|
+ pthread_mutex_destroy(&pThis->mut);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* enable multiple concurrent access on the message object
|
||||||
|
+ * This works on a class-wide basis and can bot be undone.
|
||||||
|
+ * That is, if it is once enabled, it can not be disabled during
|
||||||
|
+ * the same run. When this function is called, no other thread
|
||||||
|
+ * must manipulate message objects. Then we would have race conditions,
|
||||||
|
+ * but guarding against this is counter-productive because it
|
||||||
|
+ * would cost additional time. Plus, it would be a programming error.
|
||||||
|
+ * rgerhards, 2008-01-05
|
||||||
|
+ */
|
||||||
|
+rsRetVal MsgEnableThreadSafety(void)
|
||||||
|
+{
|
||||||
|
+ DEFiRet;
|
||||||
|
+ funcLock = MsgLockLockingCase;
|
||||||
|
+ funcUnlock = MsgUnlockLockingCase;
|
||||||
|
+ funcMsgPrepareEnqueue = MsgPrepareEnqueueLockingCase;
|
||||||
|
+ funcDeleteMutex = MsgDeleteMutexLockingCase;
|
||||||
|
+ RETiRet;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* end locking functions */
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static inline int getProtocolVersion(msg_t *pM)
|
||||||
|
{
|
||||||
|
return(pM->iProtocolVersion);
|
||||||
|
@@ -306,6 +421,7 @@ resolveDNS(msg_t *pMsg) {
|
||||||
|
uchar fromHostFQDN[NI_MAXHOST];
|
||||||
|
DEFiRet;
|
||||||
|
|
||||||
|
+ MsgLock(pMsg);
|
||||||
|
CHKiRet(objUse(net, CORE_COMPONENT));
|
||||||
|
if(pMsg->msgFlags & NEEDS_DNSRESOL) {
|
||||||
|
localRet = net.cvthname(pMsg->rcvFrom.pfrominet, fromHost, fromHostFQDN, fromHostIP);
|
||||||
|
@@ -315,6 +431,7 @@ resolveDNS(msg_t *pMsg) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finalize_it:
|
||||||
|
+ MsgUnlock(pMsg);
|
||||||
|
if(iRet != RS_RET_OK) {
|
||||||
|
/* best we can do: remove property */
|
||||||
|
MsgSetRcvFromStr(pMsg, UCHAR_CONSTANT(""), 0, &propFromHost);
|
||||||
|
@@ -531,121 +648,6 @@ uchar *propIDToName(propid_t propID)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-/* The following functions will support advanced output module
|
||||||
|
- * multithreading, once this is implemented. Currently, we
|
||||||
|
- * include them as hooks only. The idea is that we need to guard
|
||||||
|
- * some msg objects data fields against concurrent access if
|
||||||
|
- * we run on multiple threads. Please note that in any case this
|
||||||
|
- * is not necessary for calls from INPUT modules, because they
|
||||||
|
- * construct the message object and do this serially. Only when
|
||||||
|
- * the message is in the processing queue, multiple threads may
|
||||||
|
- * access a single object. Consequently, there are no guard functions
|
||||||
|
- * for "set" methods, as these are called during input. Only "get"
|
||||||
|
- * functions that modify important structures have them.
|
||||||
|
- * rgerhards, 2007-07-20
|
||||||
|
- * We now support locked and non-locked operations, depending on
|
||||||
|
- * the configuration of rsyslog. To support this, we use function
|
||||||
|
- * pointers. Initially, we start in non-locked mode. There, all
|
||||||
|
- * locking operations call into dummy functions. When locking is
|
||||||
|
- * enabled, the function pointers are changed to functions doing
|
||||||
|
- * actual work. We also introduced another MsgPrepareEnqueue() function
|
||||||
|
- * which initializes the locking structures, if needed. This is
|
||||||
|
- * necessary because internal messages during config file startup
|
||||||
|
- * processing are always created in non-locking mode. So we can
|
||||||
|
- * not initialize locking structures during constructions. We now
|
||||||
|
- * postpone this until when the message is fully constructed and
|
||||||
|
- * enqueued. Then we know the status of locking. This has a nice
|
||||||
|
- * side effect, and that is that during the initial creation of
|
||||||
|
- * the Msg object no locking needs to be done, which results in better
|
||||||
|
- * performance. -- rgerhards, 2008-01-05
|
||||||
|
- */
|
||||||
|
-static void (*funcLock)(msg_t *pMsg);
|
||||||
|
-static void (*funcUnlock)(msg_t *pMsg);
|
||||||
|
-static void (*funcDeleteMutex)(msg_t *pMsg);
|
||||||
|
-void (*funcMsgPrepareEnqueue)(msg_t *pMsg);
|
||||||
|
-#if 1 /* This is a debug aid */
|
||||||
|
-#define MsgLock(pMsg) funcLock(pMsg)
|
||||||
|
-#define MsgUnlock(pMsg) funcUnlock(pMsg)
|
||||||
|
-#else
|
||||||
|
-#define MsgLock(pMsg) {dbgprintf("MsgLock line %d\n - ", __LINE__); funcLock(pMsg);; }
|
||||||
|
-#define MsgUnlock(pMsg) {dbgprintf("MsgUnlock line %d - ", __LINE__); funcUnlock(pMsg); }
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
-/* the next function is a dummy to be used by the looking functions
|
||||||
|
- * when the class is not yet running in an environment where locking
|
||||||
|
- * is necessary. Please note that the need to lock can (and will) change
|
||||||
|
- * during a single run. Typically, this is depending on the operation mode
|
||||||
|
- * of the message queues (which is operator-configurable). -- rgerhards, 2008-01-05
|
||||||
|
- */
|
||||||
|
-static void MsgLockingDummy(msg_t __attribute__((unused)) *pMsg)
|
||||||
|
-{
|
||||||
|
- /* empty be design */
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-/* The following function prepares a message for enqueue into the queue. This is
|
||||||
|
- * where a message may be accessed by multiple threads. This implementation here
|
||||||
|
- * is the version for multiple concurrent acces. It initializes the locking
|
||||||
|
- * structures.
|
||||||
|
- * TODO: change to an iRet interface! -- rgerhards, 2008-07-14
|
||||||
|
- */
|
||||||
|
-static void MsgPrepareEnqueueLockingCase(msg_t *pThis)
|
||||||
|
-{
|
||||||
|
- BEGINfunc
|
||||||
|
- assert(pThis != NULL);
|
||||||
|
- pthread_mutex_init(&pThis->mut, NULL);
|
||||||
|
- pThis->bDoLock = 1;
|
||||||
|
- ENDfunc
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-/* ... and now the locking and unlocking implementations: */
|
||||||
|
-static void MsgLockLockingCase(msg_t *pThis)
|
||||||
|
-{
|
||||||
|
- /* DEV debug only! dbgprintf("MsgLock(0x%lx)\n", (unsigned long) pThis); */
|
||||||
|
- assert(pThis != NULL);
|
||||||
|
- if(pThis->bDoLock == 1) /* TODO: this is a testing hack, we should find a way with better performance! -- rgerhards, 2009-01-27 */
|
||||||
|
- pthread_mutex_lock(&pThis->mut);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void MsgUnlockLockingCase(msg_t *pThis)
|
||||||
|
-{
|
||||||
|
- /* DEV debug only! dbgprintf("MsgUnlock(0x%lx)\n", (unsigned long) pThis); */
|
||||||
|
- assert(pThis != NULL);
|
||||||
|
- if(pThis->bDoLock == 1) /* TODO: this is a testing hack, we should find a way with better performance! -- rgerhards, 2009-01-27 */
|
||||||
|
- pthread_mutex_unlock(&pThis->mut);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-/* delete the mutex object on message destruction (locking case)
|
||||||
|
- */
|
||||||
|
-static void MsgDeleteMutexLockingCase(msg_t *pThis)
|
||||||
|
-{
|
||||||
|
- assert(pThis != NULL);
|
||||||
|
- pthread_mutex_destroy(&pThis->mut);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-/* enable multiple concurrent access on the message object
|
||||||
|
- * This works on a class-wide basis and can bot be undone.
|
||||||
|
- * That is, if it is once enabled, it can not be disabled during
|
||||||
|
- * the same run. When this function is called, no other thread
|
||||||
|
- * must manipulate message objects. Then we would have race conditions,
|
||||||
|
- * but guarding against this is counter-productive because it
|
||||||
|
- * would cost additional time. Plus, it would be a programming error.
|
||||||
|
- * rgerhards, 2008-01-05
|
||||||
|
- */
|
||||||
|
-rsRetVal MsgEnableThreadSafety(void)
|
||||||
|
-{
|
||||||
|
- DEFiRet;
|
||||||
|
- funcLock = MsgLockLockingCase;
|
||||||
|
- funcUnlock = MsgUnlockLockingCase;
|
||||||
|
- funcMsgPrepareEnqueue = MsgPrepareEnqueueLockingCase;
|
||||||
|
- funcDeleteMutex = MsgDeleteMutexLockingCase;
|
||||||
|
- RETiRet;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-/* end locking functions */
|
||||||
|
-
|
||||||
|
-
|
||||||
|
/* This is common code for all Constructors. It is defined in an
|
||||||
|
* inline'able function so that we can save a function call in the
|
||||||
|
* actual constructors (otherwise, the msgConstruct would need
|
||||||
|
--
|
||||||
|
1.7.3.4
|
||||||
|
|
@ -1,3 +1,9 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Apr 8 13:24:34 UTC 2011 - mt@suse.de
|
||||||
|
|
||||||
|
- bugfix: race condition in deferred name resolution (id=238)
|
||||||
|
from v5.8.0 candidate.
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Thu Mar 24 16:34:31 UTC 2011 - mt@suse.de
|
Thu Mar 24 16:34:31 UTC 2011 - mt@suse.de
|
||||||
|
|
||||||
|
@ -68,6 +68,7 @@ Source4: rsyslog.d.remote.conf.in
|
|||||||
%if 0%{?suse_version} >= 1140
|
%if 0%{?suse_version} >= 1140
|
||||||
Patch1: rsyslog-systemd-integration.bnc656104.diff
|
Patch1: rsyslog-systemd-integration.bnc656104.diff
|
||||||
%endif
|
%endif
|
||||||
|
Patch2: rsyslog-deferred-dns-query-race.diff
|
||||||
|
|
||||||
%description
|
%description
|
||||||
Rsyslog is an enhanced multi-threaded syslogd supporting, among others,
|
Rsyslog is an enhanced multi-threaded syslogd supporting, among others,
|
||||||
@ -215,6 +216,7 @@ This module provides a UDP forwarder that allows changing the sender address.
|
|||||||
%setup -q -n %{name}-%{upstream_version}
|
%setup -q -n %{name}-%{upstream_version}
|
||||||
%if 0%{?suse_version} >= 1140
|
%if 0%{?suse_version} >= 1140
|
||||||
%patch1 -p1
|
%patch1 -p1
|
||||||
|
%patch2 -p1
|
||||||
# install the files systemd provides rather than what we provide.
|
# install the files systemd provides rather than what we provide.
|
||||||
cp -a /usr/share/doc/packages/systemd/sd-daemon.[ch] runtime/
|
cp -a /usr/share/doc/packages/systemd/sd-daemon.[ch] runtime/
|
||||||
%endif
|
%endif
|
||||||
|
Loading…
Reference in New Issue
Block a user