diff --git a/SOURCES/rsyslog-8.24.0-rhbz1545582-imjournal-duplicates.patch b/SOURCES/rsyslog-8.24.0-rhbz1545582-imjournal-duplicates.patch
new file mode 100644
index 0000000..1b392c4
--- /dev/null
+++ b/SOURCES/rsyslog-8.24.0-rhbz1545582-imjournal-duplicates.patch
@@ -0,0 +1,318 @@
+From: Jiri Vymazal <jvymazal@redhat.com>
+Date: Wed, 14 Mar 2018 90:05:01 -0500
+
+modification and merge of below patches for RHEL consumers, 
+also modified journal invalidate/rotation handling to keep possibility
+to continue after switch of persistent journal
+original:
+%
+%From a99f9b4b42d261c384aee09306fc421df2cca7a5 Mon Sep 17 00:00:00 2001
+%From: Peter Portante <peter.a.portante@gmail.com>
+%Date: Wed, 24 Jan 2018 19:34:41 -0500
+%Subject: [PATCH] Proposed fix for handling journal correctly
+%
+%The fix is to immediately setup the inotify file descriptor via
+%`sd_journal_get_fd()` right after a journal open, and then
+%periodically call `sd_journal_process()` to give the client API
+%library a chance to detect deleted journal files on disk that need to
+%be closed so they can be properly erased by the file system.
+%
+%We remove the open/close dance and simplify that code as a result.
+%
+%Fixes issue #2436.
+and also:
+%From 27f96c84d34ee000fbb5d45b00233f2ec3cf2d8a Mon Sep 17 00:00:00 2001
+%From: Rainer Gerhards <rgerhards@adiscon.com>
+%Date: Tue, 24 Oct 2017 16:14:13 +0200
+%Subject: [PATCH] imjournal bugfix: do not disable itself on error
+%
+%If some functions calls inside the main loop failed, imjournal exited
+%with an error code, actually disabling all logging from the journal.
+%This was probably never intended.
+%
+%This patch makes imjournal recover the situation instead.
+%
+%closes https://github.com/rsyslog/rsyslog/issues/1895
+---
+ plugins/imjournal/imjournal.c | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------
+ 1 file changed, 104 insertions(+), 102 deletions(-)
+
+--- a/plugins/imjournal/imjournal.c
++++ b/plugins/imjournal/imjournal.c
+@@ -114,6 +114,10 @@ /* module-global parameters */
+ static const char *pid_field_name;	/* read-only after startup */
+ static ratelimit_t *ratelimiter = NULL;
+ static sd_journal *j;
++static int j_inotify_fd;
++static char *last_cursor = NULL;
++
++#define J_PROCESS_PERIOD 1024  /* Call sd_journal_process() every 1,024 records */
+ 
+ static rsRetVal persistJournalState(void);
+ static rsRetVal loadJournalState(void);
+@@ -123,6 +127,14 @@ openJournal(sd_journal** jj)
+ 
+ 	if (sd_journal_open(jj, SD_JOURNAL_LOCAL_ONLY) < 0)
+ 		iRet = RS_RET_IO_ERROR;
++	int r;
++
++	if ((r = sd_journal_get_fd(j)) < 0) {
++		errmsg.LogError(-r, RS_RET_IO_ERROR, "imjournal: sd_journal_get_fd() failed");
++		iRet = RS_RET_IO_ERROR;
++	} else {
++		j_inotify_fd = r;
++	}	
+ 	RETiRet;
+ }
+ 
+@@ -132,6 +144,7 @@ closeJournal(sd_journal** jj)
+ 		persistJournalState();
+ 	}
+ 	sd_journal_close(*jj);
++	j_inotify_fd = 0;
+ }
+ 
+ 
+@@ -262,6 +275,7 @@ readjournal(void)
+ 	char *message = NULL;
+ 	char *sys_iden = NULL;
+ 	char *sys_iden_help = NULL;
++	char *c = NULL;
+ 
+ 	const void *get;
+ 	const void *pidget;
+@@ -393,6 +407,12 @@ readjournal(void)
+ 		tv.tv_usec = timestamp % 1000000;
+ 	}
+ 
++        sd_journal_get_cursor(j, &c);
++        if (c) {
++                free(last_cursor);
++                last_cursor = c;
++        }
++
+ 	/* submit message */
+ 	enqMsg((uchar *)message, (uchar *) sys_iden_help, facility, severity, &tv, json, 0);
+ 
+@@ -413,44 +433,41 @@ persistJournalState (void)
+ 	DEFiRet;
+ 	FILE *sf; /* state file */
+ 	char tmp_sf[MAXFNAME];
+-	char *cursor;
+-	int ret = 0;
++	int r = 0;
+ 
+-	/* On success, sd_journal_get_cursor()  returns 1 in systemd
+-	   197 or older and 0 in systemd 198 or newer */
+-	if ((ret = sd_journal_get_cursor(j, &cursor)) >= 0) {
+-               /* we create a temporary name by adding a ".tmp"
+-                * suffix to the end of our state file's name
+-                */
+-               snprintf(tmp_sf, sizeof(tmp_sf), "%s.tmp", cs.stateFile);
+-               if ((sf = fopen(tmp_sf, "wb")) != NULL) {
+-			if (fprintf(sf, "%s", cursor) < 0) {
+-				iRet = RS_RET_IO_ERROR;
+-			}
+-			fclose(sf);
+-			free(cursor);
+-                       /* change the name of the file to the configured one */
+-                       if (iRet == RS_RET_OK && rename(tmp_sf, cs.stateFile) == -1) {
+-                               char errStr[256];
+-                               rs_strerror_r(errno, errStr, sizeof(errStr));
+-                               iRet = RS_RET_IO_ERROR;
+-                               errmsg.LogError(0, iRet, "rename() failed: "
+-                                       "'%s', new path: '%s'\n", errStr, cs.stateFile);
+-                       }
++	if (!last_cursor)
++		ABORT_FINALIZE(RS_RET_OK);
+ 
+-		} else {
+-			char errStr[256];
+-			rs_strerror_r(errno, errStr, sizeof(errStr));
+-			errmsg.LogError(0, RS_RET_FOPEN_FAILURE, "fopen() failed: "
+-				"'%s', path: '%s'\n", errStr, tmp_sf);
+-			iRet = RS_RET_FOPEN_FAILURE;
+-		}
+-	} else {
+-		char errStr[256];
+-		rs_strerror_r(-(ret), errStr, sizeof(errStr));
+-		errmsg.LogError(0, RS_RET_ERR, "sd_journal_get_cursor() failed: '%s'\n", errStr);
+-		iRet = RS_RET_ERR;
+-	}
++	/* we create a temporary name by adding a ".tmp"
++	 * suffix to the end of our state file's name
++	 */
++	snprintf(tmp_sf, sizeof(tmp_sf), "%s.tmp", cs.stateFile);
++
++	sf = fopen(tmp_sf, "wb");
++	if (!sf) {
++		errmsg.LogError(errno, RS_RET_FOPEN_FAILURE, "imjournal: fopen() failed for path: '%s'", tmp_sf);
++		ABORT_FINALIZE(RS_RET_FOPEN_FAILURE);
++	}
++
++	r = fprintf(sf, "%s", last_cursor);
++	if (r < 0) {
++		errmsg.LogError(errno, RS_RET_FOPEN_FAILURE, "imjournal: failed to save cursor to: '%s'", tmp_sf);
++		ABORT_FINALIZE(RS_RET_IO_ERROR);
++	}
++
++	r = fclose(sf);
++	if (r < 0) {
++		errmsg.LogError(errno, iRet, "imjournal: fclose() failed for path: '%s'", tmp_sf);
++		ABORT_FINALIZE(RS_RET_IO_ERROR);
++	}
++
++	r = rename(tmp_sf, cs.stateFile);
++	if (r < 0) {
++		errmsg.LogError(errno, iRet, "imjournal: rename() failed for new path: '%s'", cs.stateFile);
++		ABORT_FINALIZE(RS_RET_IO_ERROR);
++	}
++
++finalize_it:
+ 	RETiRet;
+ }
+ 
+@@ -473,64 +473,29 @@
+  * except for the special handling of EINTR.
+  */
+ 
+-#define POLL_TIMEOUT 1000 /* timeout for poll is 1s */
++#define POLL_TIMEOUT 900000 /* timeout for poll is 900ms */
+ 
+ static rsRetVal
+ pollJournal(void)
+ {
+ 	DEFiRet;
+-	struct pollfd pollfd;
+-	int pr = 0;
+-	int jr = 0;
+-
+-	pollfd.fd = sd_journal_get_fd(j);
+-	pollfd.events = sd_journal_get_events(j);
+-	pr = poll(&pollfd, 1, POLL_TIMEOUT);
+-	if (pr == -1) {
+-		if (errno == EINTR) {
+-			/* EINTR is also received during termination
+-			 * so return now to check the term state.
+-			 */
+-			ABORT_FINALIZE(RS_RET_OK);
+-		} else {
+-			char errStr[256];
+-
+-			rs_strerror_r(errno, errStr, sizeof(errStr));
+-			errmsg.LogError(0, RS_RET_ERR,
+-				"poll() failed: '%s'", errStr);
+-			ABORT_FINALIZE(RS_RET_ERR);
+-		}
+-	}
++	int r;
+ 
++	for (;;) {
++		r = sd_journal_wait(j, POLL_TIMEOUT);
++		break;
++	}
+ 
+-	jr = sd_journal_process(j);
+-	
+-	if (pr == 1 && jr == SD_JOURNAL_INVALIDATE) {
+-		/* do not persist stateFile sd_journal_get_cursor will fail! */
+-		char* tmp = cs.stateFile;
+-		cs.stateFile = NULL;
++	if (r == SD_JOURNAL_INVALIDATE) {
+ 		closeJournal(&j);
+-		cs.stateFile = tmp;
+ 
+ 		iRet = openJournal(&j);
+-		if (iRet != RS_RET_OK) {
+-			char errStr[256];
+-			rs_strerror_r(errno, errStr, sizeof(errStr));
+-			errmsg.LogError(0, RS_RET_IO_ERROR,
+-				"sd_journal_open() failed: '%s'", errStr);
++		if (iRet != RS_RET_OK)
+ 			ABORT_FINALIZE(RS_RET_ERR);
+-		}
+ 
+-		if(cs.stateFile != NULL){
++		if (cs.stateFile)
+ 			iRet = loadJournalState();
+-		}
+-		LogMsg(0, RS_RET_OK, LOG_NOTICE, "imjournal: journal reloaded...");
+-	} else if (jr < 0) {
+-		char errStr[256];
+-		rs_strerror_r(errno, errStr, sizeof(errStr));
+-		errmsg.LogError(0, RS_RET_ERR,
+-			"sd_journal_process() failed: '%s'", errStr);
+-		ABORT_FINALIZE(RS_RET_ERR);
++		errmsg.LogMsg(0, RS_RET_OK, LOG_NOTICE, "imjournal: journal reloaded...");
+ 	}
+ 
+ finalize_it:
+@@ -631,8 +612,17 @@ loadJournalState(void)
+ 	RETiRet;
+ }
+ 
++static void
++tryRecover(void) {
++	errmsg.LogMsg(0, RS_RET_OK, LOG_INFO, "imjournal: trying to recover from unexpected "
++		"journal error");
++	closeJournal(&j);
++	srSleep(10, 0);	// do not hammer machine with too-frequent retries
++	openJournal(&j);
++}
++
+ BEGINrunInput
+-	int count = 0;
++	uint64_t count = 0;
+ CODESTARTrunInput
+ 	CHKiRet(ratelimitNew(&ratelimiter, "imjournal", NULL));
+ 	dbgprintf("imjournal: ratelimiting burst %d, interval %d\n", cs.ratelimitBurst,
+@@ -665,26 +655,38 @@ CODESTARTrunInput
+ 
+ 		r = sd_journal_next(j);
+ 		if (r < 0) {
+-			char errStr[256];
+-
+-			rs_strerror_r(errno, errStr, sizeof(errStr));
+-			errmsg.LogError(0, RS_RET_ERR,
+-				"sd_journal_next() failed: '%s'", errStr);
+-			ABORT_FINALIZE(RS_RET_ERR);
++			tryRecover();
++			continue;
+ 		}
+ 
+ 		if (r == 0) {
+ 			/* No new messages, wait for activity. */
+-			CHKiRet(pollJournal());
++			if (pollJournal() != RS_RET_OK) {
++ 				tryRecover();
++ 			}
+ 			continue;
+ 		}
+ 
+-		CHKiRet(readjournal());
++		if (readjournal() != RS_RET_OK) {
++ 			tryRecover();
++ 			continue;
++ 		}
++
++		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) {
++				errmsg.LogError(-r, RS_RET_ERR, "imjournal: sd_journal_process() failed");
++				tryRecover();
++				continue;
++			}
++		}
++
+ 		if (cs.stateFile) { /* can't persist without a state file */
+ 			/* TODO: This could use some finer metric. */
+-			count++;
+-			if (count == cs.iPersistStateInterval) {
+-				count = 0;
++			if ((count % cs.iPersistStateInterval) == 0) {
+ 				persistJournalState();
+ 			}
+ 		}
diff --git a/SPECS/rsyslog.spec b/SPECS/rsyslog.spec
index 9b4df2f..9eeefb8 100644
--- a/SPECS/rsyslog.spec
+++ b/SPECS/rsyslog.spec
@@ -14,7 +14,7 @@
 Summary: Enhanced system logging and kernel message trapping daemon
 Name: rsyslog
 Version: 8.24.0
-Release: 16%{?dist}
+Release: 16%{?dist}.4
 License: (GPLv3+ and ASL 2.0)
 Group: System Environment/Daemons
 ExcludeArch: i686 ppc s390
@@ -87,6 +87,8 @@ Patch26: rsyslog-8.24.0-rhbz1462160-set.statement-crash.patch
 Patch27: rsyslog-8.24.0-rhbz1488186-fixed-nullptr-check.patch
 Patch28: rsyslog-8.24.0-rhbz1505103-omrelp-rebindinterval.patch
 
+Patch29: rsyslog-8.24.0-rhbz1545582-imjournal-duplicates.patch
+
 %package crypto
 Summary: Encryption support
 Group: System Environment/Daemons
@@ -338,6 +340,8 @@ mv build doc
 %patch27 -p1 -b .nullptr-check
 %patch28 -p1 -b .rebindinterval
 
+%patch29 -p1 -b .imjournal-duplicates
+
 autoreconf 
 
 %build
@@ -587,6 +591,11 @@ done
 %{_libdir}/rsyslog/omudpspoof.so
 
 %changelog
+* Mon Apr 16 2018 Jiri Vymazal <jvymazal@redhat.com> - 8.24.0-16.5
+RHEL 7.5.z ERRATUM
+- fixed imjournal duplicating msgs under some conditions
+  resolves: rhbz#1545582
+
 * Thu Nov 09 2017 Jiri Vymazal <jvymazal@redhat.com> - 8.24.0-16
 RHEL 7.5 ERRATUM
 - edited the patch to conform to latest upstream doc