diff --git a/SOURCES/rsyslog-8.24.0-rhbz1805675-file-id.patch b/SOURCES/rsyslog-8.24.0-rhbz1805675-file-id.patch
new file mode 100644
index 0000000..4843de4
--- /dev/null
+++ b/SOURCES/rsyslog-8.24.0-rhbz1805675-file-id.patch
@@ -0,0 +1,610 @@
+From 70ea76962bfe9ffed2bd604898e43e0e3b17645d Mon Sep 17 00:00:00 2001
+From: Rainer Gerhards <rgerhards@adiscon.com>
+Date: Thu, 23 Aug 2018 10:15:21 +0200
+Subject: [PATCH] omfile: implement file-id, used in state file
+
+This ensures that files with the same inodes are not accidently treated
+as equal, at least within the limits of the file id hash (see doc for
+details).
+
+We use the siphash reference implementation to generate our non-cryptographic
+hash.
+
+State file handling was invalid. When a file was moved and re-created
+rsyslog could use the file_id if the new file to write the old files'
+state file. This could make the file reader stuck until it reached the
+previous offset. Depending on file sizes this could never happen AND
+would cause large message loss. This situation was timing dependent
+(a race) and most frequently occurred under log rotation. In polling
+mode the bug was less likely, but could also occur.
+---
+ plugins/imfile/Makefile.am      |   2 +-
+ plugins/imfile/imfile.c         | 190 ++++++++++++++++++-----
+ plugins/imfile/siphash.c        | 185 ++++++++++++++++++++++++++++++++
+ 3 files changed, 381 insertions(+), 19 deletions(-)
+ create mode 100644 plugins/imfile/siphash.c
+
+diff --git a/plugins/imfile/Makefile.am b/plugins/imfile/Makefile.am
+index f4df0ed687..9e137efdc8 100644
+--- a/plugins/imfile/Makefile.am
++++ b/plugins/imfile/Makefile.am
+@@ -1,6 +1,6 @@
+ pkglib_LTLIBRARIES = imfile.la
+ 
+-imfile_la_SOURCES = imfile.c
++imfile_la_SOURCES = imfile.c siphash.c
+ imfile_la_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+ imfile_la_LDFLAGS = -module -avoid-version
+ imfile_la_LIBADD = 
+diff --git a/plugins/imfile/imfile.c b/plugins/imfile/imfile.c
+index 4bc6078bda..14f4f1f495 100644
+--- a/plugins/imfile/imfile.c
++++ b/plugins/imfile/imfile.c
+@@ -66,6 +66,8 @@
+ MODULE_CNFNAME("imfile")
+ 
+ /* defines */
++#define FILE_ID_HASH_SIZE 20	/* max size of a file_id hash */
++#define FILE_ID_SIZE	512	/* how many bytes are used for file-id? */
+ 
+ /* Module static data */
+ DEF_IMOD_STATIC_DATA	/* must be present, starts static data */
+@@ -75,6 +77,9 @@
+ DEFobjCurrIf(prop)
+ DEFobjCurrIf(ruleset)
+ 
++extern int rs_siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
++	uint8_t *out, const size_t outlen); /* see siphash.c */
++
+ static int bLegacyCnfModGlobalsPermitted;/* are legacy module-global config parameters permitted? */
+ 
+ #define NUM_MULTISUB 1024 /* default max number of submits */
+@@ -155,8 +160,10 @@
+ 	int wd;
+ 	time_t timeoutBase; /* what time to calculate the timeout against? */
+ 	/* file dynamic data */
++	char file_id[FILE_ID_HASH_SIZE]; /* file id for this entry, once we could obtain it */
+ 	int in_move;	/* workaround for inotify move: if set, state file must not be deleted */
+ 	ino_t ino;	/* current inode nbr */
++	int fd;		/* fd to file in order to obtain file_id (needs to be preserved across move) */
+ 	strm_t *pStrm;	/* its stream (NULL if not assigned) */
+ 	int nRecords; /**< How many records did we process before persisting the stream? */
+ 	ratelimit_t *ratelimiter;
+@@ -187,7 +194,7 @@
+ static int getBasename(uchar *const __restrict__ basen, uchar *const __restrict__ path);
+ static void act_obj_unlink(act_obj_t *act);
+ static uchar * getStateFileName(const act_obj_t *, uchar *, const size_t);
+-static int getFullStateFileName(const uchar *const, uchar *const pszout, const size_t ilenout);
++static int getFullStateFileName(const uchar *const, const char *const, uchar *const pszout, const size_t ilenout);
+ 
+ 
+ #define OPMODE_POLLING 0
+@@ -328,7 +335,7 @@
+ 		  act->name, statefn);
+ 
+ 	/* Get full path and file name */
+-	lenSFNam = getFullStateFileName(statefn, pszSFNam, sizeof(pszSFNam));
++	lenSFNam = getFullStateFileName(statefn, "", pszSFNam, sizeof(pszSFNam));
+ 
+ 	/* check if the file exists */
+ 	if(stat((char*) pszSFNam, &stat_buf) == -1) {
+@@ -561,16 +568,25 @@
+                        }
+ 		}
+ 	}
++	DBGPRINTF("need to add new active object '%s' in '%s' - checking if accessible\n", name, edge->path);
++	const int fd = open(name, O_RDONLY | O_CLOEXEC);
++	if(fd < 0) {
++		if (is_file) { LogMsg(errno, RS_RET_ERR, LOG_WARNING, "imfile: error accessing file '%s'", name);
++		} else { DBGPRINTF("imfile: error accessing file '%s'", name); }
++		FINALIZE;
++	}
+ 	DBGPRINTF("add new active object '%s' in '%s'\n", name, edge->path);
+ 	CHKmalloc(act = calloc(sizeof(act_obj_t), 1));
+ 	CHKmalloc(act->name = strdup(name));
+-       if (-1 == getBasename((uchar*)basename, (uchar*)name)) {
+-               CHKmalloc(act->basename = strdup(name)); /* assume basename is same as name */
+-       } else {
+-               CHKmalloc(act->basename = strdup(basename));
+-       }
++	if (-1 == getBasename((uchar*)basename, (uchar*)name)) {
++		CHKmalloc(act->basename = strdup(name)); /* assume basename is same as name */
++	} else {
++		CHKmalloc(act->basename = strdup(basename));
++	}
+ 	act->edge = edge;
+ 	act->ino = ino;
++	act->fd = fd;
++	act->file_id[0] = '\0';
+ 	act->is_symlink = is_symlink;
+        if (source) { /* we are target of symlink */
+                CHKmalloc(act->source_name = strdup(source));
+@@ -813,7 +828,7 @@
+ 		pollFile(act); /* get any left-over data */
+ 		if(inst->bRMStateOnDel) {
+ 			statefn = getStateFileName(act, statefile, sizeof(statefile));
+-			getFullStateFileName(statefn, toDel, sizeof(toDel));
++			getFullStateFileName(statefn, "", toDel, sizeof(toDel)); // TODO: check!
+ 			statefn = toDel;
+ 		}
+ 		persistStrmState(act);
+@@ -832,6 +847,9 @@
+ 		wdmapDel(act->wd);
+ 	}
+ 	#endif
++	if(act->fd >= 0) {
++		close(act->fd);
++	}
+ 	#if defined(OS_SOLARIS) && defined (HAVE_PORT_SOURCE_FILE)
+ 	if(act->pfinf != NULL) {
+ 		free(act->pfinf->fobj.fo_name);
+@@ -1029,7 +1047,7 @@
+  * open or otherwise modify disk file state.
+  */
+ static int
+-getFullStateFileName(const uchar *const pszstatefile, uchar *const pszout, const size_t ilenout)
++getFullStateFileName(const uchar *const pszstatefile, const char *const file_id, uchar *const pszout, const size_t ilenout)
+ {
+ 	int lenout;
+ 	const uchar* pszworkdir;
+@@ -1038,14 +1056,68 @@
+ 	pszworkdir = glblGetWorkDirRaw();
+ 
+ 	/* Construct file name */
+-	lenout = snprintf((char*)pszout, ilenout, "%s/%s",
+-			     (char*) (pszworkdir == NULL ? "." : (char*) pszworkdir), (char*)pszstatefile);
++	lenout = snprintf((char*)pszout, ilenout, "%s/%s%s%s",
++		(char*) (pszworkdir == NULL ? "." : (char*) pszworkdir), (char*)pszstatefile,
++		(*file_id == '\0') ? "" : ":", file_id);
+ 
+ 	/* return out length */
+ 	return lenout;
+ }
+ 
+ 
++/* hash function for file-id
++ * Takes a block of data and returns a string with the hash value.
++ *
++ * Currently one provided by Aaaron Wiebe based on perl's hashing algorithm
++ * (so probably pretty generic). Not for excessively large strings!
++ * TODO: re-think the hash function!
++ */
++#if defined(__clang__)
++#pragma GCC diagnostic ignored "-Wunknown-attributes"
++#endif
++static void __attribute__((nonnull(1,3)))
++#if defined(__clang__)
++__attribute__((no_sanitize("unsigned-integer-overflow")))
++#endif
++get_file_id_hash(const char *data, size_t lendata,
++	char *const hash_str, const size_t len_hash_str)
++{
++	assert(len_hash_str >= 17); /* we always generate 8-byte strings */
++
++	size_t i;
++	uint8_t out[8], k[16];
++	for (i = 0; i < 16; ++i)
++		k[i] = i;
++	memset(out, 0, sizeof(out));
++	rs_siphash((const uint8_t *)data, lendata, k, out, 8);
++
++	for(i = 0 ; i < 8 ; ++i) {
++		if(2 * i+1 >= len_hash_str)
++			break;
++		snprintf(hash_str+(2*i), 3, "%2.2x", out[i]);
++	}
++}
++
++
++
++/* this returns the file-id for a given file
++ */
++static void getFileID(act_obj_t *const act)
++{
++	/* save the old id for cleaning purposes */
++	strncpy(act->file_id_prev, (const char*)act->file_id, FILE_ID_HASH_SIZE);
++	act->file_id[0] = '\0';
++	assert(act->fd >= 0); /* fd must have been opened at act_obj_t creation! */
++	char filedata[FILE_ID_SIZE];
++	const int r = read(act->fd, filedata, FILE_ID_SIZE);
++	if(r == FILE_ID_SIZE) {
++		get_file_id_hash(filedata, sizeof(filedata), act->file_id, sizeof(act->file_id));
++	} else {
++		DBGPRINTF("getFileID partial or error read, ret %d\n", r);
++	}
++	DBGPRINTF("getFileID for '%s', file_id_hash '%s'\n", act->name, act->file_id);
++}
++
+ /* this generates a state file name suitable for the given file. To avoid
+  * malloc calls, it must be passed a buffer which should be MAXFNAME large.
+  * Note: the buffer is not necessarily populated ... always ONLY use the
+@@ -1060,7 +1135,7 @@
+ {
+ 	DBGPRINTF("getStateFileName for '%s'\n", act->name);
+ 	snprintf((char*)buf, lenbuf - 1, "imfile-state:%lld", (long long) act->ino);
+-	DBGPRINTF("getStateFileName:  stat file name now is %s\n", buf);
++	DBGPRINTF("getStateFileName:  state file name now is %s\n", buf);
+ 	return buf;
+ }
+ 
+@@ -1136,18 +1209,45 @@
+ 	const instanceConf_t *const inst = act->edge->instarr[0];// TODO: same file, multiple instances?
+ 
+ 	uchar *const statefn = getStateFileName(act, statefile, sizeof(statefile));
++	getFileID(act);
+ 
+-	getFullStateFileName(statefn, pszSFNam, sizeof(pszSFNam));
++	getFullStateFileName(statefn, act->file_id, pszSFNam, sizeof(pszSFNam));
+ 	DBGPRINTF("trying to open state for '%s', state file '%s'\n", act->name, pszSFNam);
+ 
+ 	/* check if the file exists */
+ 	fd = open((char*)pszSFNam, O_CLOEXEC | O_NOCTTY | O_RDONLY, 0600);
+ 	if(fd < 0) {
+ 		if(errno == ENOENT) {
+-			DBGPRINTF("NO state file (%s) exists for '%s' - trying to see if "
+-				"old-style file exists\n", pszSFNam, act->name);
+-			CHKiRet(OLD_openFileWithStateFile(act));
+-			FINALIZE;
++			if(act->file_id[0] != '\0') {
++				const char *pszSFNamHash = strdup((const char*)pszSFNam);
++				CHKmalloc(pszSFNamHash);
++				DBGPRINTF("state file %s for %s does not exist - trying to see if "
++					"inode-only file exists\n", pszSFNam, act->name);
++				getFullStateFileName(statefn, "", pszSFNam, sizeof(pszSFNam));
++				fd = open((char*)pszSFNam, O_CLOEXEC | O_NOCTTY | O_RDONLY, 0600);
++				if(fd >= 0) {
++					dbgprintf("found inode-only state file, renaming it now that we "
++						"know the file_id, new name: %s\n", pszSFNamHash);
++					/* we now can use identify the file, so let's rename it */
++					if(rename((const char*)pszSFNam, pszSFNamHash) != 0) {
++						LogError(errno, RS_RET_IO_ERROR,
++							"imfile error trying to rename state file for '%s' - "
++							"ignoring this error, usually this means a file no "
++							"longer file is left over, but this may also cause "
++							"some real trouble. Still the best we can do ",
++							act->name);
++						free((void*) pszSFNamHash);
++						ABORT_FINALIZE(RS_RET_IO_ERROR);
++					}
++				}
++				free((void*) pszSFNamHash);
++			}
++			if(fd < 0) {
++				DBGPRINTF("state file %s for %s does not exist - trying to see if "
++					"old-style file exists\n", pszSFNam, act->name);
++				CHKiRet(OLD_openFileWithStateFile(act));
++				FINALIZE;
++			}
+ 		} else {
+ 			LogError(errno, RS_RET_IO_ERROR,
+ 				"imfile error trying to access state file for '%s'",
+@@ -1156,6 +1256,7 @@
+ 		}
+ 	}
+ 
++	DBGPRINTF("opened state file %s for %s\n", pszSFNam, act->name);
+ 	CHKiRet(strm.Construct(&act->pStrm));
+ 
+ 	struct json_object *jval;
+@@ -1289,6 +1390,7 @@
+ {
+ 	int64 strtOffs;
+ 	DEFiRet;
++	int64_t startOffs = 0;
+ 	int nProcessed = 0;
+ 
+ 	DBGPRINTF("pollFileReal enter, pStrm %p, name '%s'\n", act->pStrm, act->name);
+@@ -1301,6 +1403,7 @@
+ 		CHKiRet(openFile(act)); /* open file */
+ 	}
+ 
++	startOffs = act->pStrm->iCurrOffs;	
+ 	/* loop below will be exited when strmReadLine() returns EOF */
+ 	while(glbl.GetGlobalInputTermState() == 0) {
+ 		if(inst->maxLinesAtOnce != 0 && nProcessed >= inst->maxLinesAtOnce)
+@@ -1313,6 +1416,11 @@
+ 				inst->escapeLF, &strtOffs));
+ 		}
+ 		++nProcessed;
++		if(startOffs < FILE_ID_SIZE && act->pStrm->iCurrOffs >= FILE_ID_SIZE) {
++			dbgprintf("initiating state file write as sufficient data is now present; file=%s\n", act->name);
++			persistStrmState(act);
++			startOffs = act->pStrm->iCurrOffs; /* disable check */
++		}
+ 		runModConf->bHadFileData = 1; /* this is just a flag, so set it and forget it */
+ 		CHKiRet(enqLine(act, *pCStr, strtOffs)); /* process line */
+ 		rsCStrDestruct(pCStr); /* discard string (must be done by us!) */
+@@ -2122,7 +2230,8 @@
+ 	uchar statefname[MAXFNAME];
+ 
+ 	uchar *const statefn = getStateFileName(act, statefile, sizeof(statefile));
+-	getFullStateFileName(statefn, statefname, sizeof(statefname));
++	getFileID(act);
++	getFullStateFileName(statefn, act->file_id, statefname, sizeof(statefname));
+ 	DBGPRINTF("persisting state for '%s', state file '%s'\n", act->name, statefname);
+ 
+ 	struct json_object *jval = NULL;
+diff --git a/plugins/imfile/siphash.c b/plugins/imfile/siphash.c
+new file mode 100644
+index 0000000000..8d5fac7343
+--- /dev/null
++++ b/plugins/imfile/siphash.c
+@@ -0,0 +1,185 @@
++/* SipHash reference C implementation
++ *
++ * Copyright (c) 2012-2016 Jean-Philippe Aumasson
++ * <jeanphilippe.aumasson@gmail.com>
++ * Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
++ *
++ * Slightly adapted by rsyslog in regard to build system and code style
++ * check.
++ *
++ * To the extent possible under law, the author(s) have dedicated all copyright
++ * and related and neighboring rights to this software to the public domain
++ * worldwide. This software is distributed without any warranty.
++ *
++ * You should have received a copy of the CC0 Public Domain Dedication along
++ * with
++ * this software. If not, see
++ * <http://creativecommons.org/publicdomain/zero/1.0/>.
++ *
++ * For details on siphash see https://131002.net/siphash/
++ */
++#include <assert.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <string.h>
++
++/* default: SipHash-2-4 */
++#define cROUNDS 2
++#define dROUNDS 4
++
++#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
++
++#define U32TO8_LE(p, v)                                                        \
++	(p)[0] = (uint8_t)((v));                                                   \
++	(p)[1] = (uint8_t)((v) >> 8);                                              \
++	(p)[2] = (uint8_t)((v) >> 16);                                             \
++	(p)[3] = (uint8_t)((v) >> 24);
++
++#define U64TO8_LE(p, v)                                                        \
++	U32TO8_LE((p), (uint32_t)((v)));                                           \
++	U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
++
++#define U8TO64_LE(p)                                                           \
++	(((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) |                        \
++	((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) |                 \
++	((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) |                 \
++	((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
++
++#define SIPROUND                                                               \
++	do {                                                                       \
++		v0 += v1;                                                              \
++		v1 = ROTL(v1, 13);                                                     \
++		v1 ^= v0;                                                              \
++		v0 = ROTL(v0, 32);                                                     \
++		v2 += v3;                                                              \
++		v3 = ROTL(v3, 16);                                                     \
++		v3 ^= v2;                                                              \
++		v0 += v3;                                                              \
++		v3 = ROTL(v3, 21);                                                     \
++		v3 ^= v0;                                                              \
++		v2 += v1;                                                              \
++		v1 = ROTL(v1, 17);                                                     \
++		v1 ^= v2;                                                              \
++		v2 = ROTL(v2, 32);                                                     \
++	} while (0)
++
++#ifdef DEBUG
++#define TRACE                                                                  \
++	do {                                                                       \
++		printf("(%3d) v0 %08x %08x\n", (int)inlen, (uint32_t)(v0 >> 32),       \
++		       (uint32_t)v0);                                                  \
++		printf("(%3d) v1 %08x %08x\n", (int)inlen, (uint32_t)(v1 >> 32),       \
++		       (uint32_t)v1);                                                  \
++		printf("(%3d) v2 %08x %08x\n", (int)inlen, (uint32_t)(v2 >> 32),       \
++		       (uint32_t)v2);                                                  \
++		printf("(%3d) v3 %08x %08x\n", (int)inlen, (uint32_t)(v3 >> 32),       \
++		       (uint32_t)v3);                                                  \
++	} while (0)
++#else
++#define TRACE
++#endif
++
++extern int rs_siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
++	uint8_t *out, const size_t outlen); /* avoid compiler warning */
++#if defined(__clang__)
++#pragma GCC diagnostic ignored "-Wunknown-attributes"
++#endif
++int
++#if defined(__clang__)
++__attribute__((no_sanitize("unsigned-integer-overflow")))
++#endif
++rs_siphash(const uint8_t *in, const size_t inlen, const uint8_t *k,
++	uint8_t *out, const size_t outlen) {
++
++	uint64_t v0 = 0x736f6d6570736575ULL;
++	uint64_t v1 = 0x646f72616e646f6dULL;
++	uint64_t v2 = 0x6c7967656e657261ULL;
++	uint64_t v3 = 0x7465646279746573ULL;
++	uint64_t k0 = U8TO64_LE(k);
++	uint64_t k1 = U8TO64_LE(k + 8);
++	uint64_t m;
++	int i;
++	const uint8_t *end = in + inlen - (inlen % sizeof(uint64_t));
++	const int left = inlen & 7;
++	uint64_t b = ((uint64_t)inlen) << 56;
++	assert((outlen == 8) || (outlen == 16));
++	v3 ^= k1;
++	v2 ^= k0;
++	v1 ^= k1;
++	v0 ^= k0;
++
++	if (outlen == 16)
++	v1 ^= 0xee;
++
++	for (; in != end; in += 8) {
++		m = U8TO64_LE(in);
++		v3 ^= m;
++
++		TRACE;
++		for (i = 0; i < cROUNDS; ++i)
++		    SIPROUND;
++
++		v0 ^= m;
++	}
++
++	switch (left) {
++	case 7:
++		b |= ((uint64_t)in[6]) << 48;
++		/*FALLTHROUGH*/
++	case 6:
++		b |= ((uint64_t)in[5]) << 40;
++		/*FALLTHROUGH*/
++	case 5:
++		b |= ((uint64_t)in[4]) << 32;
++		/*FALLTHROUGH*/
++	case 4:
++		b |= ((uint64_t)in[3]) << 24;
++		/*FALLTHROUGH*/
++	case 3:
++		b |= ((uint64_t)in[2]) << 16;
++		/*FALLTHROUGH*/
++	case 2:
++		b |= ((uint64_t)in[1]) << 8;
++		/*FALLTHROUGH*/
++	case 1:
++		b |= ((uint64_t)in[0]);
++		break;
++	case 0:
++	default:
++		break;
++	}
++
++	v3 ^= b;
++
++	TRACE;
++	for (i = 0; i < cROUNDS; ++i)
++		SIPROUND;
++
++	v0 ^= b;
++
++	if (outlen == 16)
++		v2 ^= 0xee;
++	else
++		v2 ^= 0xff;
++
++	TRACE;
++	for (i = 0; i < dROUNDS; ++i)
++		SIPROUND;
++
++	b = v0 ^ v1 ^ v2 ^ v3;
++	U64TO8_LE(out, b);
++
++	if (outlen == 8)
++		return 0;
++
++	v1 ^= 0xdd;
++
++	TRACE;
++	for (i = 0; i < dROUNDS; ++i)
++		SIPROUND;
++
++	b = v0 ^ v1 ^ v2 ^ v3;
++	U64TO8_LE(out + 8, b);
++
++	return 0;
++}
+--- a/plugins/imfile/imfile.c
++++ b/plugins/imfile/imfile.c
+@@ -182,6 +182,7 @@ struct act_obj_s {
+ 	time_t timeoutBase; /* what time to calculate the timeout against? */
+ 	/* file dynamic data */
+ 	char file_id[FILE_ID_HASH_SIZE]; /* file id for this entry, once we could obtain it */
++	char file_id_prev[FILE_ID_HASH_SIZE]; /* previous file id for this entry, set if changed */
+ 	int in_move;	/* workaround for inotify move: if set, state file must not be deleted */
+ 	ino_t ino;	/* current inode nbr */
+ 	int fd;		/* fd to file in order to obtain file_id (needs to be preserved across move) */
+@@ -727,6 +728,7 @@ act_obj_add(fs_edge_t *const edge, const char *const name, const int is_file,
+ 	act->ino = ino;
+ 	act->fd = fd;
+ 	act->file_id[0] = '\0';
++	act->file_id_prev[0] = '\0';
+ 	act->is_symlink = is_symlink;
+        if (source) { /* we are target of symlink */
+                CHKmalloc(act->source_name = strdup(source));
+@@ -1378,28 +1380,13 @@ openFileWithStateFile(act_obj_t *const act)
+ 	if(fd < 0) {
+ 		if(errno == ENOENT) {
+ 			if(act->file_id[0] != '\0') {
+-				const char *pszSFNamHash = strdup((const char*)pszSFNam);
+-				CHKmalloc(pszSFNamHash);
+ 				DBGPRINTF("state file %s for %s does not exist - trying to see if "
+ 					"inode-only file exists\n", pszSFNam, act->name);
+ 				getFullStateFileName(statefn, "", pszSFNam, sizeof(pszSFNam));
+ 				fd = open((char*)pszSFNam, O_CLOEXEC | O_NOCTTY | O_RDONLY, 0600);
+ 				if(fd >= 0) {
+-					dbgprintf("found inode-only state file, renaming it now that we "
+-						"know the file_id, new name: %s\n", pszSFNamHash);
+-					/* we now can use identify the file, so let's rename it */
+-					if(rename((const char*)pszSFNam, pszSFNamHash) != 0) {
+-						LogError(errno, RS_RET_IO_ERROR,
+-							"imfile error trying to rename state file for '%s' - "
+-							"ignoring this error, usually this means a file no "
+-							"longer file is left over, but this may also cause "
+-							"some real trouble. Still the best we can do ",
+-							act->name);
+-						free((void*) pszSFNamHash);
+-						ABORT_FINALIZE(RS_RET_IO_ERROR);
+-					}
++					dbgprintf("found inode-only state file, will be renamed at next persist\n");
+ 				}
+-				free((void*) pszSFNamHash);
+ 			}
+ 			if(fd < 0) {
+ 				DBGPRINTF("state file %s for %s does not exist - trying to see if "
+@@ -2609,6 +2596,28 @@ atomicWriteStateFile(const char *fn, const char *content)
+ 	RETiRet;
+ }
+ 
++static void
++removeOldStatefile(const uchar *statefn, const char *hashToDelete)
++{
++	int ret;
++	uchar statefname[MAXFNAME];
++
++	getFullStateFileName(statefn, hashToDelete, statefname, sizeof(statefname));
++	ret = unlink((const char*)statefname);
++	if(ret != 0) {
++		if (errno != ENOENT) {
++			LogError(errno, RS_RET_IO_ERROR,
++				"imfile error trying to delete old state file: '%s' - ignoring this "
++				"error, usually this means a file no longer file is left over, but "
++				"this may also cause some real trouble. Still the best we can do ",
++				statefname);
++		} else {
++			DBGPRINTF("trying to delete no longer valid statefile '%s' which no "
++				  "longer exists (probably already deleted)\n", statefname);
++		}
++	}
++}
++
+ 
+ /* This function persists information for a specific file being monitored.
+  * To do so, it simply persists the stream object. We do NOT abort on error
+@@ -2660,6 +2664,15 @@ persistStrmState(act_obj_t *const act)
+ 	CHKiRet(atomicWriteStateFile((const char*)statefname, jstr));
+ 	json_object_put(json);
+ 
++	/* check for presence of inode-only statefile and delete if exitsts */
++	if (act->file_id[0] != '\0') {
++		removeOldStatefile(statefn, "");
++	}
++	/* file-id changed (truncated?), remove the old hash statefile */
++	if (strncmp((const char *)act->file_id_prev, (const char *)act->file_id, FILE_ID_HASH_SIZE)) {
++		removeOldStatefile(statefn, act->file_id_prev);
++	}
++
+ finalize_it:
+ 	if(iRet != RS_RET_OK) {
+ 		errmsg.LogError(0, iRet, "imfile: could not persist state "
diff --git a/SPECS/rsyslog.spec b/SPECS/rsyslog.spec
index 17c0763..4473e21 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: 41%{?dist}.2
+Release: 41%{?dist}.4
 License: (GPLv3+ and ASL 2.0)
 Group: System Environment/Daemons
 URL: http://www.rsyslog.com/
@@ -116,6 +116,7 @@ Patch53: rsyslog-8.24.0-rhbz1656860-imfile-buffer-overflow.patch
 Patch54: rsyslog-8.24.0-rhbz1725067-imjournal-memleak.patch
 
 Patch55: rsyslog-8.24.0-rhbz1746497-ratelimiter-segfault.patch
+Patch56: rsyslog-8.24.0-rhbz1805675-file-id.patch
 
 %package crypto
 Summary: Encryption support
@@ -422,6 +423,7 @@ mv build doc
 %patch54 -p1 -b .imjournal-memleak
 
 %patch55 -p1 -b .ratelimit-crash
+%patch56 -p1 -b .file_id-fix
 
 autoreconf 
 
@@ -681,6 +683,17 @@ done
 %{_libdir}/rsyslog/mmkubernetes.so
 
 %changelog
+* Tue Mar 03 2020 Jiri Vymazal <jvymazal@redhat.com> - 8.24.0-41.4
+RHEL 7.7.z ERRATUM
+- edited patch fixing hashed file_ids for imfile statefiles
+  resolves: rhbz#1805675
+
+* Fri Feb 21 2020 Jiri Vymazal <jvymazal@redhat.com> - 8.24.0-41.3
+RHEL 7.7.z ERRATUM
+- added patch fixing hash file_id feature to properly monitor files
+  after rotation
+  resolves: rhbz#1805675
+
 * Mon Sep 23 2019 Jiri Vymazal <jvymazal@redhat.com> - 8.24.0-41.2
 RHEL 7.7.z ERRATUM
 - edited imjournal memleaks patch to fix introduced regression