Compare commits

..

No commits in common. "rawhide" and "f31" have entirely different histories.

14 changed files with 907 additions and 731 deletions

View file

@ -1 +0,0 @@
1

30
.gitignore vendored
View file

@ -73,33 +73,3 @@ rsyslog-4.6.3.tar.gz
/rsyslog-doc-8.2001.0.tar.gz
/rsyslog-8.2002.0.tar.gz
/rsyslog-doc-8.2002.0.tar.gz
/rsyslog-8.2008.0.tar.gz
/rsyslog-doc-8.2008.0.tar.gz
/rsyslog-8.2010.0.tar.gz
/rsyslog-doc-8.2010.0.tar.gz
/qpid-proton-0.31.0.tar.gz
/rsyslog-8.2102.0.tar.gz
/rsyslog-doc-8.2102.0.tar.gz
/qpid-proton-0.34.0.tar.gz
/rsyslog-8.2204.0.tar.gz
/rsyslog-doc-8.2204.0.tar.gz
/rsyslog-8.2210.0.tar.gz
/rsyslog-doc-8.2210.0.tar.gz
/rsyslog-8.2306.0.tar.gz
/rsyslog-doc-8.2306.0.tar.gz
/rsyslog-8.2308.0.tar.gz
/rsyslog-doc-8.2308.0.tar.gz
/qpid-proton-0.39.0.tar.gz
/rsyslog-8.2310.0.tar.gz
/rsyslog-doc-8.2310.0.tar.gz
/rsyslog-8.2312.0.tar.gz
/rsyslog-doc-8.2312.0.tar.gz
/rsyslog-8.2408.0.tar.gz
/rsyslog-doc-8.2408.0.tar.gz
/rsyslog-8.2412.0.tar.gz
/rsyslog-doc-8.2412.0.tar.gz
/rsyslog-8.2506.0.tar.gz
/rsyslog-doc-8.2506.0.tar.gz
/rsyslog-8.2508.0.tar.gz
/qpid-proton-0.40.0.tar.gz
/rsyslog-8.2510.0.tar.gz

752
imjournal-rewrite.patch Normal file
View file

@ -0,0 +1,752 @@
From 78976a9bc0592317be2e41b7f3703803f7971e1e Mon Sep 17 00:00:00 2001
From: Jiri Vymazal <jvymazal@redhat.com>
Date: Wed, 25 Sep 2019 15:18:57 +0200
Subject: [PATCH] plugin code restructuring, added remote option
Decomposed ReadJournal() a bit, also now coupling journald
variables in one struct, added few warning messages and debug
prints to help with bug hunts in future, also got rid of two
needless journald calls. WorkAroundJournalBug now deprecated.
Added option to pull journald records from outside local machine.
---
plugins/imjournal/imjournal.c | 368 ++++++++++++++++++++--------------
1 file changed, 214 insertions(+), 154 deletions(-)
diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c
index 2e27922b51..8008f159c4 100644
--- a/plugins/imjournal/imjournal.c
+++ b/plugins/imjournal/imjournal.c
@@ -81,8 +81,9 @@ static struct configSettings_s {
int iDfltFacility;
int bUseJnlPID;
char *usePid;
- int bWorkAroundJournalBug;
+ int bWorkAroundJournalBug; /* deprecated, left for backwards compatibility only */
int bFsync;
+ int bRemote;
} cs;
static rsRetVal facilityHdlr(uchar **pp, void *pVal);
@@ -100,7 +101,8 @@ static struct cnfparamdescr modpdescr[] = {
{ "usepidfromsystem", eCmdHdlrBinary, 0 },
{ "usepid", eCmdHdlrString, 0 },
{ "workaroundjournalbug", eCmdHdlrBinary, 0 },
- { "fsync", eCmdHdlrBinary, 0 }
+ { "fsync", eCmdHdlrBinary, 0 },
+ { "remote", eCmdHdlrBinary, 0 }
};
static struct cnfparamblk modpblk =
{ CNFPARAMBLK_VERSION,
@@ -120,8 +122,6 @@ static prop_t *pLocalHostIP = NULL; /* a pseudo-constant propterty for 127.0.0.1
static const char *pidFieldName; /* read-only after startup */
static int bPidFallBack;
static ratelimit_t *ratelimiter = NULL;
-static sd_journal *j;
-static sbool reloaded = 0;
static struct {
statsobj_t *stats;
STATSCOUNTER_DEF(ctrSubmitted, mutCtrSubmitted)
@@ -134,34 +134,58 @@ static struct {
uint64 ratelimitDiscardedInInterval;
uint64 diskUsageBytes;
} statsCounter;
-static char *last_cursor = NULL;
+struct journalContext_s { /* structure encapsulating all the journald_API-related stuff */
+ sd_journal *j; /* main object encapsulating journal for us, has to be used in every sd_journal*() call */
+ sbool reloaded; /* we have reloaded journal after detecting rotation */
+ sbool atHead; /* true if we are at start of journal (no seek was done) */
+ char *cursor; /* should point to last valid journald entry we processed */
+};
+static struct journalContext_s journalContext = {NULL, 0, 1, NULL};
#define J_PROCESS_PERIOD 1024 /* Call sd_journal_process() every 1,024 records */
-static rsRetVal persistJournalState(int trySave);
+static rsRetVal persistJournalState(void);
static rsRetVal loadJournalState(void);
static rsRetVal openJournal(void) {
int r;
DEFiRet;
- if ((r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY)) < 0) {
- LogError(-r, RS_RET_IO_ERROR, "imjournal: sd_journal_open() failed");
- iRet = RS_RET_IO_ERROR;
+ if (journalContext.j) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imjournal: opening journal when already opened.\n");
}
- if ((r = sd_journal_get_fd(j)) < 0) {
- LogError(-r, RS_RET_IO_ERROR, "imjournal: sd_journal_get_fd() failed");
+ if ((r = sd_journal_open(&journalContext.j, cs.bRemote? 0 : SD_JOURNAL_LOCAL_ONLY)) < 0) {
+ LogError(-r, RS_RET_IO_ERROR, "imjournal: sd_journal_open() failed");
iRet = RS_RET_IO_ERROR;
}
+ journalContext.atHead = 1;
RETiRet;
}
/* trySave shoulod only be true if there is no journald error preceeding this call */
-static void closeJournal(int trySave) {
- if (cs.stateFile) { /* can't persist without a state file */
- persistJournalState(trySave);
+static void closeJournal(void) {
+ if (!journalContext.j) {
+ LogMsg(0, RS_RET_OK_WARN, LOG_WARNING, "imjournal: closing NULL journal.\n");
}
- sd_journal_close(j);
+ sd_journal_close(journalContext.j);
+ journalContext.j = NULL; /* setting to NULL here as journald API will not do that for us... */
+}
+
+static int journalGetData(const char *field, const void **data, size_t *length)
+{
+ int ret;
+
+ ret = sd_journal_get_data(journalContext.j, field, data, length);
+ if (ret == -EADDRNOTAVAIL) {
+ LogError(-ret, RS_RET_ERR, "imjournal: Tried to get data without a 'next' call.\n");
+ if ((ret = sd_journal_next(journalContext.j)) < 0) {
+ LogError(-ret, RS_RET_ERR, "imjournal: sd_journal_next() failed\n");
+ } else {
+ ret = sd_journal_get_data(journalContext.j, field, data, length);
+ }
+ }
+
+ return ret;
}
@@ -223,12 +247,84 @@ sanitizeValue(const char *in, size_t len, char **out)
}
+/* Read JSON part of single journald message and return it as JSON object
+ */
+static rsRetVal
+readJSONfromJournalMsg(struct fjson_object **json)
+{
+ DEFiRet;
+ const void *get;
+ const void *equal_sign;
+ struct fjson_object *jval;
+ size_t l;
+ long prefixlen = 0;
+
+ CHKmalloc(*json = fjson_object_new_object());
+
+ SD_JOURNAL_FOREACH_DATA(journalContext.j, get, l) {
+ char *data;
+ char *name;
+
+ /* locate equal sign, this is always present */
+ equal_sign = memchr(get, '=', l);
+
+ /* ... but we know better than to trust the specs */
+ if (equal_sign == NULL) {
+ LogError(0, RS_RET_ERR, "SD_JOURNAL_FOREACH_DATA()"
+ "returned a malformed field (has no '='): '%s'", (char*)get);
+ continue; /* skip the entry */
+ }
+
+ /* get length of journal data prefix */
+ prefixlen = ((char *)equal_sign - (char *)get);
+
+ CHKmalloc(name = strndup(get, prefixlen));
+
+ prefixlen++; /* remove '=' */
+
+ CHKiRet_Hdlr(sanitizeValue(((const char *)get) + prefixlen, l - prefixlen, &data)) {
+ free (name);
+ FINALIZE;
+ }
+
+ /* and save them to json object */
+ jval = fjson_object_new_string((char *)data);
+ fjson_object_object_add(*json, name, jval);
+ free (data);
+ free (name);
+ }
+finalize_it:
+ RETiRet;
+}
+
+
+/* Try to obtain current journald cursor and save it to journalContext struct.
+ */
+static rsRetVal
+updateJournalCursor(void)
+{
+ DEFiRet;
+ char *c = NULL;
+ int r;
+
+ if ((r = sd_journal_get_cursor(journalContext.j, &c)) < 0) {
+ LogError(-r, RS_RET_ERR, "imjournal: Could not get journald cursor!\n");
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+ /* save journal cursor (at this point we can be sure it is valid) */
+ free(journalContext.cursor);
+ journalContext.cursor = c;
+finalize_it:
+ RETiRet;
+}
+
+
/* enqueue the the journal message into the message queue.
* The provided msg string is not freed - thus must be done
* by the caller.
*/
static rsRetVal
-enqMsg(uchar *msg, uchar *pszTag, int iFacility, int iSeverity, struct timeval *tp, struct json_object *json,
+enqMsg(uchar *msg, uchar *pszTag, int iFacility, int iSeverity, struct timeval *tp, struct fjson_object *json,
int sharedJsonProperties)
{
struct syslogTime st;
@@ -267,15 +363,17 @@ int sharedJsonProperties)
STATSCOUNTER_INC(statsCounter.ctrSubmitted, statsCounter.mutCtrSubmitted);
finalize_it:
- if (iRet == RS_RET_DISCARDMSG)
+ if (iRet == RS_RET_DISCARDMSG) {
STATSCOUNTER_INC(statsCounter.ctrDiscarded, statsCounter.mutCtrDiscarded);
+ } else if (iRet != RS_RET_OK) {
+ LogError(0, RS_RET_ERR, "imjournal: error during enqMsg().\n");
+ }
RETiRet;
}
-/* Read journal log while data are available, each read() reads one
- * record of printk buffer.
+/* Read journal log while data are available, each read() reads one journald record.
*/
static rsRetVal
readjournal(void)
@@ -285,39 +383,32 @@ readjournal(void)
struct timeval tv;
uint64_t timestamp;
- struct json_object *json = NULL;
+ struct fjson_object *json = NULL;
int r;
/* Information from messages */
char *message = NULL;
char *sys_iden;
char *sys_iden_help = NULL;
- char *c = NULL;
const void *get;
const void *pidget;
size_t length;
size_t pidlength;
- const void *equal_sign;
- struct json_object *jval;
- size_t l;
-
- long prefixlen = 0;
-
int severity = cs.iDfltSeverity;
int facility = cs.iDfltFacility;
/* Get message text */
- if (sd_journal_get_data(j, "MESSAGE", &get, &length) < 0) {
- message = strdup("");
+ if (journalGetData("MESSAGE", &get, &length) < 0) {
+ CHKmalloc(message = strdup(""));
} else {
CHKiRet(sanitizeValue(((const char *)get) + 8, length - 8, &message));
}
STATSCOUNTER_INC(statsCounter.ctrRead, statsCounter.mutCtrRead);
/* Get message severity ("priority" in journald's terminology) */
- if (sd_journal_get_data(j, "PRIORITY", &get, &length) >= 0) {
+ if (journalGetData("PRIORITY", &get, &length) >= 0) {
if (length == 10) {
severity = ((char *)get)[9] - '0';
if (severity < 0 || 7 < severity) {
@@ -332,7 +423,7 @@ readjournal(void)
}
/* Get syslog facility */
- if (sd_journal_get_data(j, "SYSLOG_FACILITY", &get, &length) >= 0) {
+ if (journalGetData("SYSLOG_FACILITY", &get, &length) >= 0) {
// Note: the journal frequently contains invalid facilities!
if (length == 17 || length == 18) {
facility = ((char *)get)[16] - '0';
@@ -352,14 +443,14 @@ readjournal(void)
}
/* Get message identifier, client pid and add ':' */
- if (sd_journal_get_data(j, "SYSLOG_IDENTIFIER", &get, &length) >= 0) {
+ if (journalGetData("SYSLOG_IDENTIFIER", &get, &length) >= 0) {
CHKiRet(sanitizeValue(((const char *)get) + 18, length - 18, &sys_iden));
} else {
CHKmalloc(sys_iden = strdup("journal"));
}
/* trying to get PID, default is "SYSLOG_PID" property */
- if (sd_journal_get_data(j, pidFieldName, &pidget, &pidlength) >= 0) {
+ if (journalGetData(pidFieldName, &pidget, &pidlength) >= 0) {
char *sys_pid;
int val_ofs;
@@ -372,7 +463,7 @@ readjournal(void)
free (sys_pid);
} else {
/* this is fallback, "SYSLOG_PID" doesn't exist so trying to get "_PID" property */
- if (bPidFallBack && sd_journal_get_data(j, "_PID", &pidget, &pidlength) >= 0) {
+ if (bPidFallBack && journalGetData("_PID", &pidget, &pidlength) >= 0) {
char *sys_pid;
int val_ofs;
@@ -396,55 +487,15 @@ readjournal(void)
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
}
- json = json_object_new_object();
-
- SD_JOURNAL_FOREACH_DATA(j, get, l) {
- char *data;
- char *name;
-
- /* locate equal sign, this is always present */
- equal_sign = memchr(get, '=', l);
-
- /* ... but we know better than to trust the specs */
- if (equal_sign == NULL) {
- LogError(0, RS_RET_ERR, "SD_JOURNAL_FOREACH_DATA()"
- "returned a malformed field (has no '='): '%s'", (char*)get);
- continue; /* skip the entry */
- }
-
- /* get length of journal data prefix */
- prefixlen = ((char *)equal_sign - (char *)get);
-
- name = strndup(get, prefixlen);
- CHKmalloc(name);
-
- prefixlen++; /* remove '=' */
-
- CHKiRet_Hdlr(sanitizeValue(((const char *)get) + prefixlen, l - prefixlen, &data)) {
- free (name);
- FINALIZE;
- }
-
- /* and save them to json object */
- jval = json_object_new_string((char *)data);
- json_object_object_add(json, name, jval);
- free (data);
- free (name);
- }
+ CHKiRet(readJSONfromJournalMsg(&json));
/* calculate timestamp */
- if (sd_journal_get_realtime_usec(j, &timestamp) >= 0) {
+ if (sd_journal_get_realtime_usec(journalContext.j, &timestamp) >= 0) {
tv.tv_sec = timestamp / 1000000;
tv.tv_usec = timestamp % 1000000;
}
- if (cs.bWorkAroundJournalBug) {
- /* save journal cursor (at this point we can be sure it is valid) */
- if (!sd_journal_get_cursor(j, &c)) {
- free(last_cursor);
- last_cursor = c;
- }
- }
+ iRet = updateJournalCursor();
/* submit message */
enqMsg((uchar *)message, (uchar *) sys_iden_help, facility, severity, &tv, json, 0);
@@ -456,32 +507,22 @@ readjournal(void)
}
-/* This function gets journal cursor and saves it into state file.
- * If WorkAroundJournalBug option is turned on it does use cursor saved previously.
- * If it is false and if "trySave" is false it skips altogether.
+/* This function saves journal cursor into state file.
+ * It must be checked that stateFile is configured prior to calling this.
*/
static rsRetVal
-persistJournalState(int trySave)
+persistJournalState(void)
{
DEFiRet;
FILE *sf = NULL; /* state file */
char tmp_sf[MAXFNAME];
size_t n;
- if (cs.bWorkAroundJournalBug) {
- /* first check that we have valid cursor */
- if (!last_cursor) {
- ABORT_FINALIZE(RS_RET_OK);
- }
- } else if (trySave) {
- int ret;
- free(last_cursor);
- if ((ret = sd_journal_get_cursor(j, &last_cursor))) {
- LogError(-ret, RS_RET_ERR, "imjournal: sd_journal_get_cursor() failed");
- last_cursor = NULL;
- ABORT_FINALIZE(RS_RET_ERR);
- }
- } else { /* not trying to get cursor out of invalid journal state */
+ DBGPRINTF("Persisting journal position, cursor: %s, at head? %d\n",
+ journalContext.cursor, journalContext.atHead);
+
+ /* first check that we have valid cursor */
+ if (!journalContext.cursor) {
ABORT_FINALIZE(RS_RET_OK);
}
@@ -500,7 +541,7 @@ persistJournalState(int trySave)
ABORT_FINALIZE(RS_RET_FOPEN_FAILURE);
}
- if(fputs(last_cursor, sf) == EOF) {
+ if(fputs(journalContext.cursor, sf) == EOF) {
LogError(errno, RS_RET_IO_ERROR, "imjournal: failed to save cursor to: '%s'", tmp_sf);
ABORT_FINALIZE(RS_RET_IO_ERROR);
}
@@ -541,43 +582,59 @@ persistJournalState(int trySave)
static rsRetVal skipOldMessages(void);
-#define POLL_TIMEOUT 900000 /* timeout for poll is 900ms */
-
static rsRetVal
-pollJournal(void)
+handleRotation(void)
{
DEFiRet;
- int err;
+ int r;
- err = sd_journal_wait(j, POLL_TIMEOUT);
- if (err == SD_JOURNAL_INVALIDATE && !reloaded) {
- STATSCOUNTER_INC(statsCounter.ctrRotations, statsCounter.mutCtrRotations);
- closeJournal(0);
+ LogMsg(0, RS_RET_OK, LOG_NOTICE, "imjournal: journal files changed, reloading...\n");
+ STATSCOUNTER_INC(statsCounter.ctrRotations, statsCounter.mutCtrRotations);
+ closeJournal();
- iRet = openJournal();
- if (iRet != RS_RET_OK) {
- ABORT_FINALIZE(RS_RET_ERR);
- }
+ iRet = openJournal();
+ if (iRet != RS_RET_OK) {
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
- /* If we have locally saved cursor there is no need to read it from state file */
- if (cs.bWorkAroundJournalBug && last_cursor)
- {
- if (sd_journal_seek_cursor(j, last_cursor) != 0) {
- LogError(0, RS_RET_ERR, "imjournal: "
- "couldn't seek to cursor `%s'\n", last_cursor);
- iRet = RS_RET_ERR;
- }
- /* Need to advance because cursor points at last processed message */
- sd_journal_next(j);
+ /* If we have locally saved cursor there is no need to read it from state file */
+ if (journalContext.cursor)
+ {
+ if (sd_journal_seek_cursor(journalContext.j, journalContext.cursor) != 0) {
+ LogError(0, RS_RET_ERR, "imjournal: "
+ "couldn't seek to cursor `%s'\n", journalContext.cursor);
+ iRet = RS_RET_ERR;
}
- else if (cs.stateFile) {
- iRet = loadJournalState();
+ journalContext.atHead = 0;
+ /* Need to advance because cursor points at last processed message */
+ if ((r = sd_journal_next(journalContext.j)) < 0) {
+ LogError(-r, RS_RET_ERR, "imjournal: sd_journal_next() failed");
+ iRet = RS_RET_ERR;
}
- LogMsg(0, RS_RET_OK, LOG_NOTICE, "imjournal: journal reloaded...");
- reloaded = 1;
+ }
+ else if (cs.stateFile) {
+ iRet = loadJournalState();
+ }
+ journalContext.reloaded = 1;
+
+finalize_it:
+ RETiRet;
+}
+
+#define POLL_TIMEOUT 900000 /* timeout for poll is 900ms */
+
+static rsRetVal
+pollJournal(void)
+{
+ DEFiRet;
+ int err;
+
+ err = sd_journal_wait(journalContext.j, POLL_TIMEOUT);
+ if (err == SD_JOURNAL_INVALIDATE && !journalContext.reloaded) {
+ CHKiRet(handleRotation());
}
else {
- reloaded = 0;
+ journalContext.reloaded = 0;
}
finalize_it:
@@ -591,12 +648,13 @@ skipOldMessages(void)
int r;
DEFiRet;
- if ((r = sd_journal_seek_tail(j)) < 0) {
+ if ((r = sd_journal_seek_tail(journalContext.j)) < 0) {
LogError(-r, RS_RET_ERR,
"imjournal: sd_journal_seek_tail() failed");
ABORT_FINALIZE(RS_RET_ERR);
}
- if ((r = sd_journal_previous(j)) < 0) {
+ journalContext.atHead = 0;
+ if ((r = sd_journal_previous(journalContext.j)) < 0) {
LogError(-r, RS_RET_ERR,
"imjournal: sd_journal_previous() failed");
ABORT_FINALIZE(RS_RET_ERR);
@@ -615,6 +673,9 @@ loadJournalState(void)
int r;
FILE *r_sf;
+ DBGPRINTF("Loading journal position, at head? %d, reloaded? %d\n",
+ journalContext.atHead, journalContext.reloaded);
+
if (cs.stateFile[0] != '/') {
char *new_stateFile;
if (-1 == asprintf(&new_stateFile, "%s/%s", (char *)glbl.GetWorkDir(), cs.stateFile)) {
@@ -639,13 +700,14 @@ loadJournalState(void)
if ((r_sf = fopen(cs.stateFile, "rb")) != NULL) {
char readCursor[128 + 1];
if (fscanf(r_sf, "%128s\n", readCursor) != EOF) {
- if (sd_journal_seek_cursor(j, readCursor) != 0) {
+ if (sd_journal_seek_cursor(journalContext.j, readCursor) != 0) {
LogError(0, RS_RET_ERR, "imjournal: "
"couldn't seek to cursor `%s'\n", readCursor);
iRet = RS_RET_ERR;
} else {
+ journalContext.atHead = 0;
char * tmp_cursor = NULL;
- sd_journal_next(j);
+ sd_journal_next(journalContext.j);
/*
* This is resolving the situation when system is after reboot and boot_id
* doesn't match so cursor pointing into "future".
@@ -658,14 +720,15 @@ loadJournalState(void)
* but if cursor has been intentionally compromised it could stop logging even
* with persistent journal.
* */
- if ((r = sd_journal_get_cursor(j, &tmp_cursor)) < 0) {
+ if ((r = sd_journal_get_cursor(journalContext.j, &tmp_cursor)) < 0) {
LogError(-r, RS_RET_IO_ERROR, "imjournal: "
"loaded invalid cursor, seeking to the head of journal\n");
- if ((r = sd_journal_seek_head(j)) < 0) {
+ if ((r = sd_journal_seek_head(journalContext.j)) < 0) {
LogError(-r, RS_RET_ERR, "imjournal: "
"sd_journal_seek_head() failed, when cursor is invalid\n");
iRet = RS_RET_ERR;
}
+ journalContext.atHead = 1;
}
free(tmp_cursor);
}
@@ -680,18 +743,15 @@ loadJournalState(void)
if (iRet != RS_RET_OK && cs.bIgnoreNonValidStatefile) {
/* ignore state file errors */
iRet = RS_RET_OK;
- LogError(0, NO_ERRCODE, "imjournal: ignoring invalid state file %s",
- cs.stateFile);
+ LogError(0, NO_ERRCODE, "imjournal: ignoring invalid state file %s", cs.stateFile);
if (cs.bIgnorePrevious) {
skipOldMessages();
}
}
} else {
- LogError(0, RS_RET_FOPEN_FAILURE, "imjournal: "
- "open on state file `%s' failed\n", cs.stateFile);
+ LogError(0, RS_RET_FOPEN_FAILURE, "imjournal: open on state file `%s' failed\n", cs.stateFile);
if (cs.bIgnorePrevious) {
- /* Seek to the very end of the journal and ignore all
- * older messages. */
+ /* Seek to the very end of the journal and ignore all older messages. */
skipOldMessages();
}
}
@@ -704,7 +764,7 @@ static void
tryRecover(void) {
LogMsg(0, RS_RET_OK, LOG_INFO, "imjournal: trying to recover from journal error");
STATSCOUNTER_INC(statsCounter.ctrRecoveryAttempts, statsCounter.mutCtrRecoveryAttempts);
- closeJournal(0);
+ closeJournal();
srSleep(10, 0); // do not hammer machine with too-frequent retries
openJournal();
}
@@ -723,8 +783,7 @@ CODESTARTrunInput
/* Load our position in the journal from the state file. */
CHKiRet(loadJournalState());
} else if (cs.bIgnorePrevious) {
- /* Seek to the very end of the journal and ignore all
- * older messages. */
+ /* Seek to the very end of the journal and ignore all older messages. */
skipOldMessages();
}
@@ -758,7 +817,7 @@ CODESTARTrunInput
while (glbl.GetGlobalInputTermState() == 0) {
int r;
- r = sd_journal_next(j);
+ r = sd_journal_next(journalContext.j);
if (r < 0) {
LogError(-r, RS_RET_ERR, "imjournal: sd_journal_next() failed");
tryRecover();
@@ -766,8 +825,12 @@ CODESTARTrunInput
}
if (r == 0) {
+ if (journalContext.atHead) {
+ LogMsg(0, RS_RET_OK, LOG_WARNING, "imjournal: "
+ "Journal indicates no msgs when positioned at head.\n");
+ }
/* No new messages, wait for activity. */
- if (pollJournal() != RS_RET_OK && !reloaded) {
+ if (pollJournal() != RS_RET_OK && !journalContext.reloaded) {
tryRecover();
}
continue;
@@ -776,7 +839,7 @@ CODESTARTrunInput
/*
* update journal disk usage before reading the new message.
*/
- const int e = sd_journal_get_usage(j, (uint64_t *)&statsCounter.diskUsageBytes);
+ const int e = sd_journal_get_usage(journalContext.j, (uint64_t *)&statsCounter.diskUsageBytes);
if (e < 0) {
LogError(-e, RS_RET_ERR, "imjournal: sd_get_usage() failed");
}
@@ -787,21 +850,12 @@ CODESTARTrunInput
}
count++;
-
- if ((count % J_PROCESS_PERIOD) == 0) {
- /* Give the journal a periodic chance to detect rotated journal files to be cleaned up. */
- r = sd_journal_process(j);
- if (r < 0) {
- LogError(-r, RS_RET_ERR, "imjournal: sd_journal_process() failed");
- tryRecover();
- continue;
- }
- }
+ journalContext.atHead = 0;
if (cs.stateFile) { /* can't persist without a state file */
/* TODO: This could use some finer metric. */
if ((count % cs.iPersistStateInterval) == 0) {
- persistJournalState(1);
+ persistJournalState();
}
}
}
@@ -825,6 +879,7 @@ CODESTARTbeginCnfLoad
cs.usePid = NULL;
cs.bWorkAroundJournalBug = 1;
cs.bFsync = 0;
+ cs.bRemote = 0;
ENDbeginCnfLoad
@@ -881,7 +936,7 @@ BEGINfreeCnf
CODESTARTfreeCnf
free(cs.stateFile);
free(cs.usePid);
- free(last_cursor);
+ free(journalContext.cursor);
statsobj.Destruct(&(statsCounter.stats));
ENDfreeCnf
@@ -894,7 +949,10 @@ ENDwillRun
/* close journal */
BEGINafterRun
CODESTARTafterRun
- closeJournal(1);
+ if (cs.stateFile) { /* can't persist without a state file */
+ persistJournalState();
+ }
+ closeJournal();
ratelimitDestruct(ratelimiter);
ENDafterRun
@@ -966,6 +1024,8 @@ CODESTARTsetModCnf
cs.bWorkAroundJournalBug = (int) pvals[i].val.d.n;
} else if (!strcmp(modpblk.descr[i].name, "fsync")) {
cs.bFsync = (int) pvals[i].val.d.n;
+ } else if (!strcmp(modpblk.descr[i].name, "remote")) {
+ cs.bRemote = (int) pvals[i].val.d.n;
} else {
dbgprintf("imjournal: program error, non-handled "
"param '%s' in beginCnfLoad\n", modpblk.descr[i].name);
diff --git a/plugins/imjournal/imjournal.c b/plugins/imjournal/imjournal.c
index 8008f159c4..18e4d25ebb 100644
--- a/plugins/imjournal/imjournal.c
+++ b/plugins/imjournal/imjournal.c
@@ -3,7 +3,7 @@
* To test under Linux:
* emmit log message into systemd journal
*
- * Copyright (C) 2008-2017 Adiscon GmbH
+ * Copyright (C) 2008-2019 Adiscon GmbH
*
* This file is part of rsyslog.
*
@@ -676,16 +676,6 @@ loadJournalState(void)
DBGPRINTF("Loading journal position, at head? %d, reloaded? %d\n",
journalContext.atHead, journalContext.reloaded);
- if (cs.stateFile[0] != '/') {
- char *new_stateFile;
- if (-1 == asprintf(&new_stateFile, "%s/%s", (char *)glbl.GetWorkDir(), cs.stateFile)) {
- LogError(0, RS_RET_OUT_OF_MEMORY, "imjournal: asprintf failed\n");
- ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
- }
- free (cs.stateFile);
- cs.stateFile = new_stateFile;
- }
-
/* if state file not exists (on very first run), skip */
if (access(cs.stateFile, F_OK|R_OK) == -1 && errno == ENOENT) {
if (cs.bIgnorePrevious) {
@@ -885,6 +875,17 @@ ENDbeginCnfLoad
BEGINendCnfLoad
CODESTARTendCnfLoad
+ /* bad trick to handle old and new style config all in old-style var */
+ if(cs.stateFile != NULL && cs.stateFile[0] != '/') {
+ char *new_stateFile;
+ if (-1 == asprintf(&new_stateFile, "%s/%s", (char *)glbl.GetWorkDir(), cs.stateFile)) {
+ LogError(0, RS_RET_OUT_OF_MEMORY, "imjournal: asprintf failed\n");
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+ }
+ free (cs.stateFile);
+ cs.stateFile = new_stateFile;
+ }
+finalize_it:
ENDendCnfLoad
@@ -1032,7 +1033,6 @@ CODESTARTsetModCnf
}
}
-
finalize_it:
if (pvals != NULL)
cnfparamvalsDestruct(pvals, &modpblk);

View file

@ -1,6 +0,0 @@
summary: Run all tests
execute:
how: tmt
discover:
how: fmf

View file

@ -0,0 +1,14 @@
diff -up rsyslog-7.4.1/rsyslog.service.in.orig rsyslog-7.4.1/rsyslog.service.in
--- rsyslog-7.4.1/rsyslog.service.in.orig 2013-06-17 15:28:54.430023493 +0200
+++ rsyslog-7.4.1/rsyslog.service.in 2013-06-17 15:30:05.874378084 +0200
@@ -6,7 +6,9 @@ Requires=syslog.socket
[Service]
Type=notify
-ExecStart=@sbindir@/rsyslogd -n -iNONE
+EnvironmentFile=-/etc/sysconfig/rsyslog
+ExecStart=@sbindir@/rsyslogd -n $SYSLOGD_OPTIONS
+UMask=0066
StandardOutput=null
Restart=on-failure

View file

@ -9,22 +9,19 @@
# Where to place auxiliary files
global(workDirectory="/var/lib/rsyslog")
#### MODULES ####
# Use default timestamp format
module(load="builtin:omfile" Template="RSYSLOG_TraditionalFileFormat")
module(load="imuxsock" # provides support for local system logging (e.g. via logger command)
SysSock.Use="off") # Turn off message reception via local log socket;
# local messages are retrieved through imjournal now.
module(load="imjournal" # provides access to the systemd journal
FileCreateMode="0600" # Quiet warning and ensure privacy
UsePid="system" # PID nummber is retrieved as the ID of the process the journal entry originates from
StateFile="imjournal.state") # File to store the position in the journal
# Include all config files in /etc/rsyslog.d/
include(file="/etc/rsyslog.d/*.conf" mode="optional")
#### MODULES ####
module(load="imuxsock" # provides support for local system logging (e.g. via logger command)
SysSock.Use="off") # Turn off message reception via local log socket;
# local messages are retrieved through imjournal now.
module(load="imjournal" # provides access to the systemd journal
StateFile="imjournal.state") # File to store the position in the journal
#module(load="imklog") # reads kernel messages (the same are read from journald)
#module(load="immark") # provides --MARK-- message capability

View file

@ -7,6 +7,6 @@
missingok
sharedscripts
postrotate
/usr/bin/systemctl reload rsyslog.service >/dev/null 2>&1 || true
/usr/bin/systemctl kill -s HUP rsyslog.service >/dev/null 2>&1 || true
endscript
}

View file

@ -1,37 +0,0 @@
[Unit]
Description=System Logging Service
;Requires=syslog.socket
Documentation=man:rsyslogd(8)
Documentation=https://www.rsyslog.com/doc/
Wants=network.target network-online.target
After=network.target network-online.target
[Service]
Type=notify
EnvironmentFile=-/etc/sysconfig/rsyslog
ExecStart=/usr/sbin/rsyslogd -n $SYSLOGD_OPTIONS
ExecReload=/usr/bin/kill -HUP $MAINPID
UMask=0066
StandardOutput=null
Restart=on-failure
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictNamespaces=net
NoNewPrivileges=yes
ProtectControlGroups=yes
ProtectHome=read-only
ProtectKernelModules=yes
ProtectKernelTunables=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
SystemCallFilter=~@clock @debug @module @raw-io @reboot @swap @cpu-emulation @obsolete
LockPersonality=yes
MemoryDenyWriteExecute=yes
# Increase the default a bit in order to allow many simultaneous
# files to be monitored, we might need a lot of fds.
LimitNOFILE=16384
[Install]
WantedBy=multi-user.target
;Alias=syslog.service

File diff suppressed because it is too large Load diff

View file

@ -1,2 +1,2 @@
SHA512 (rsyslog-8.2510.0.tar.gz) = d2e693fd8c7112e4ccc36ea6fbb19909df885e7cb2778e95c04b7c5e9db8240224decfee52308a46865b7deffcf1e31ade0104c90d84b768a4dece15e5ea190e
SHA512 (qpid-proton-0.40.0.tar.gz) = 3e7fe56ca1423f45f71d81f5e1d6ec5f21c073cc580628e12a8dbd545a86805b7312834e0d1234dde43797633d575ed639f21a96239b217500cc0a824482aae3
SHA512 (rsyslog-8.2002.0.tar.gz) = a01bb2f67d21ab6d96dd1302bc351b509892834ef44956983db912a63ba23201653ca1e6b176a574c47568665b4d92579bb8bb0fe6911646bc841a3754c2754f
SHA512 (rsyslog-doc-8.2002.0.tar.gz) = 5d6bd8fe09b49644f000416c87c8600cd3df3facb07845afd85012279df203a44b234e94a7be90ad83709d5f2ad1a2bf8cb51571c5c0cd76383f76f81455945e

View file

@ -1,2 +0,0 @@
gef config gef.disable_color True
got-audit --all

View file

@ -1,10 +0,0 @@
summary: Audit the GOT for signs of tampering
description: |
Pointers in the server process GOT will be checked to ensure that
each function pointer's value is within a shared object file
that exports a symbol of that name, and that no shared object
files export conflicting symbols.
contact: Gordon Messmer <gordon.messmer@gmail.com>
require+:
- gdb-gef # needed to test got-audit

View file

@ -1,41 +0,0 @@
#!/bin/bash
# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# runtest.sh of /CoreOS/rsyslog/Sanity/got-audit
# Description: Check pointers in the server process GOT for signs of tampering
# Author: Gordon Messmer <gordon.messmer@gmail.com>
#
# Include Beaker environment
. /usr/share/beakerlib/beakerlib.sh || exit 1
rlJournalStart
rlPhaseStartSetup
rlServiceStart rsyslog
rlRun "TestDir=\$(pwd)"
rlRun "TmpDir=\$(mktemp -d)" 0 "Creating tmp directory"
rlRun "pushd $TmpDir"
rlRun "auditfile=\$(mktemp --tmpdir=${TmpDir})"
rlPhaseEnd
rlPhaseStartTest "Run GEF got-audit"
rlRun "SERVICE_PID=\$( systemctl show --property=MainPID rsyslog.service | cut -f2 -d= )"
rlRun "echo SERVICE_PID is '$SERVICE_PID'"
[ -n "$SERVICE_PID" ] || rlFail "No service pid was found"
rlRun "gdb-gef --pid '$SERVICE_PID' --command='$TestDir'/got-audit.gdb --batch > '$auditfile'"
# Basic test: ensure that at least one symbol is found in libc.so,
# to verify that the report looks plausible.
rlAssertGrep " : /.*/libc.so" "$auditfile"
# Ensure the got-audit did not report any errors
rlAssertNotGrep " :: ERROR" "$auditfile"
rlRun "cp '$auditfile' '$TMT_TEST_DATA'/got-audit.txt"
rlPhaseEnd
rlPhaseStartCleanup
rlServiceRestore rsyslog
rlRun "popd"
rlRun "rm -r $TmpDir" 0 "Removing tmp directory"
rlPhaseEnd
rlJournalPrintText
rlJournalEnd

View file

@ -1,2 +0,0 @@
test: ./runtest.sh
framework: beakerlib