diff --git a/SOURCES/0001-Add-limits-to-autopatch-macro.patch b/SOURCES/0001-Add-limits-to-autopatch-macro.patch
new file mode 100644
index 0000000..3235922
--- /dev/null
+++ b/SOURCES/0001-Add-limits-to-autopatch-macro.patch
@@ -0,0 +1,44 @@
+From f00bb5be9caa62220c6aeaf3f7264840d5c089e3 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
+Date: Tue, 5 Feb 2019 18:15:47 +0100
+Subject: [PATCH] Add limits to autopatch macro
+
+Limits allow to apply only range of patches with given parameters.
+Useful if something needs to be done between patch sets. Allows applying
+of patches with different -pX parameter in one spec file.
+
+Resolves: #626
+Co-authored-by: Florian Festi <ffesti@redhat.com>
+---
+ macros.in | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/macros.in b/macros.in
+index 7b5b63020..912ad5997 100644
+--- a/macros.in
++++ b/macros.in
+@@ -1265,11 +1265,19 @@ else\
+ end}
+ 
+ # Automatically apply all patches
+-%autopatch(vp:)\
++# -m<min>       Apply patches with number >= min only
++# -M<max>       Apply patches with number <= max only
++%autopatch(vp:m:M:)\
+ %{lua:\
+ local options = rpm.expand("%{!-v:-q} %{-p:-p%{-p*}} ")\
++local low_limit = tonumber(rpm.expand("%{-m:%{-m*}}"))\
++local high_limit = tonumber(rpm.expand("%{-M:%{-M*}}"))\
+ for i, p in ipairs(patches) do\
+-    print(rpm.expand("%apply_patch -m %{basename:"..p.."}  "..options..p.." "..i.."\\n"))\
++    local inum = patch_nums[i]\
++    if ((not low_limit or inum>=low_limit) and (not high_limit or inum<=high_limit)) \
++    then\
++        print(rpm.expand("%apply_patch -m %{basename:"..p.."}  "..options..p.." "..i.."\\n")) \
++    end\
+ end}
+ 
+ # One macro to (optionally) do it all.
+-- 
+2.26.2
+
diff --git a/SOURCES/0001-Always-close-libelf-handle-1313.patch b/SOURCES/0001-Always-close-libelf-handle-1313.patch
new file mode 100644
index 0000000..81a1296
--- /dev/null
+++ b/SOURCES/0001-Always-close-libelf-handle-1313.patch
@@ -0,0 +1,32 @@
+From 38c03ddb18e86c84d89af695f72442d8365eb64e Mon Sep 17 00:00:00 2001
+From: Florian Festi <ffesti@redhat.com>
+Date: Tue, 21 Jul 2020 10:45:20 +0200
+Subject: [PATCH] Always close libelf handle (#1313)
+
+Otherwise executables that are not proper elf files are leaking libelf
+handles. This results in file being left open (mmap'ed) and fails the
+build on NFS as those files can't be deleted properly there.
+
+Resolves: rhbz#1840728
+See also: https://bugzilla.redhat.com/show_bug.cgi?id=1840728
+---
+ build/files.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/build/files.c b/build/files.c
+index f675306f7..62489c07c 100644
+--- a/build/files.c
++++ b/build/files.c
+@@ -1935,8 +1935,8 @@ static int generateBuildIDs(FileList fl, ARGV_t *files)
+ 			if (terminate)
+ 			    rc = 1;
+ 		    }
+-		    elf_end (elf);
+ 		}
++		elf_end (elf);
+ 		close (fd);
+ 	    }
+ 	}
+-- 
+2.26.2
+
diff --git a/SOURCES/0001-Fix-python-ts.addErase-not-raising-exception-on-not-.patch b/SOURCES/0001-Fix-python-ts.addErase-not-raising-exception-on-not-.patch
new file mode 100644
index 0000000..809f065
--- /dev/null
+++ b/SOURCES/0001-Fix-python-ts.addErase-not-raising-exception-on-not-.patch
@@ -0,0 +1,102 @@
+From 60066aba510b3ff4a7db092021aae71948e3f8be Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Thu, 4 Jun 2020 11:18:01 +0300
+Subject: [PATCH] Fix python ts.addErase() not raising exception on not-found
+ packages
+
+The code would only raise an exception if TransactionSetCore.addErase()
+returned an error, but the catch is that with many kinds of argument
+types we'd silently skip the whole addition because no headers were found.
+This looks to be a regression introduced some eleven years ago in
+commit 9b20c706a4f93266450fae2f94007343b2e8fd9e.
+
+As a special case, a match iterator argument will not raise an exception
+if it doesn't actually match anything.
+
+Fixes: #1214
+---
+ python/rpm/transaction.py | 26 +++++++++++++++-----------
+ tests/rpmpython.at        | 22 ++++++++++++++++++++++
+ 2 files changed, 37 insertions(+), 11 deletions(-)
+
+diff --git a/python/rpm/transaction.py b/python/rpm/transaction.py
+index 7c4a551d3..3c9ddb207 100644
+--- a/python/rpm/transaction.py
++++ b/python/rpm/transaction.py
+@@ -91,14 +91,22 @@ class TransactionSet(TransactionSetCore):
+ 
+     def addErase(self, item):
+         hdrs = []
+-        if isinstance(item, rpm.hdr):
+-            hdrs = [item]
+-        elif isinstance(item, rpm.mi):
++        # match iterators are passed on as-is
++        if isinstance(item, rpm.mi):
+             hdrs = item
+-        elif isinstance(item, int):
+-            hdrs = self.dbMatch(rpm.RPMDBI_PACKAGES, item)
+-        elif isinstance(item, _string_types):
+-            hdrs = self.dbMatch(rpm.RPMDBI_LABEL, item)
++        elif isinstance(item, rpm.hdr):
++            hdrs.append(item)
++        elif isinstance(item, (int, _string_types)):
++            if isinstance(item, int):
++                dbi = rpm.RPMDBI_PACKAGES
++            else:
++                dbi = rpm.RPMDBI_LABEL
++
++            for h in self.dbMatch(dbi, item):
++                hdrs.append(h)
++
++            if not hdrs:
++                raise rpm.error("package not installed")
+         else:
+             raise TypeError("invalid type %s" % type(item))
+ 
+@@ -106,10 +114,6 @@ class TransactionSet(TransactionSetCore):
+             if not TransactionSetCore.addErase(self, h):
+                 raise rpm.error("package not installed")
+ 
+-        # garbage collection should take care but just in case...
+-        if isinstance(hdrs, rpm.mi):
+-            del hdrs
+-
+     def run(self, callback, data):
+         rc = TransactionSetCore.run(self, callback, data, self._probFilter)
+ 
+diff --git a/tests/rpmpython.at b/tests/rpmpython.at
+index 3a7c251f1..de39c8417 100644
+--- a/tests/rpmpython.at
++++ b/tests/rpmpython.at
+@@ -201,6 +201,28 @@ for e in ts:
+ [foo-1.0-1.noarch]
+ )
+ 
++RPMPY_TEST([add erasure to transaction],[
++ts = rpm.ts()
++for i in ['foo', 1234]:
++    myprint('addErase %s' % i)
++    try:
++        ts.addErase(i)
++    except rpm.error as err:
++        myprint(err)
++myprint('addErase mi')
++mi = ts.dbMatch('name', 'foo')
++try:
++    ts.addErase(mi)
++except rpm.error as err:
++    myprint(err)
++],
++[addErase foo
++package not installed
++addErase 1234
++package not installed
++addErase mi]
++)
++
+ RPMPY_TEST([add bogus package to transaction 1],[
+ ts = rpm.ts()
+ h = rpm.hdr()
+-- 
+2.26.2
+
diff --git a/SOURCES/0001-Introduce-patch_nums-and-source_nums-Lua-variables-i.patch b/SOURCES/0001-Introduce-patch_nums-and-source_nums-Lua-variables-i.patch
new file mode 100644
index 0000000..ccf39e3
--- /dev/null
+++ b/SOURCES/0001-Introduce-patch_nums-and-source_nums-Lua-variables-i.patch
@@ -0,0 +1,63 @@
+From 9ad4b813483f8cf6c641f56387248b33b6dfc570 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Wed, 20 Feb 2019 15:28:30 +0200
+Subject: [PATCH] Introduce patch_nums and source_nums Lua variables in spec
+ context
+
+The pre-existing patches and sources variables only contains patch and
+source filenames, but for some purposes we need access to the associated
+patch/source number too. We could use the number as the table key, but
+that would make the table unsorted. That we could handle in our own
+macros, but would break compatibility for anybody doing custom stuff
+with these. So it seems best to just add parallel arrays sharing the
+same array indexes so that both values are as easily accessible,
+depending on the need.
+
+Inspired by Pascal "Pixel" Rigaux's similar patch in Mageia, which differs
+in that the number-arrays are indexed by the filename and is unordered.
+Compared to patches/sources this seemed against principle of least
+surprise, and is slightly more cumbersome int the case we want the number
+directly, such as in PR #626. The variable names differ so there
+is no incompatibility to that downstream patch introduced.
+---
+ build/parsePreamble.c | 9 +++++++++
+ build/spec.c          | 3 ++-
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/build/parsePreamble.c b/build/parsePreamble.c
+index 812c41f9f..9520bac4b 100644
+--- a/build/parsePreamble.c
++++ b/build/parsePreamble.c
+@@ -322,6 +322,15 @@ static int addSource(rpmSpec spec, Package pkg, const char *field, rpmTagVal tag
+ 	    rpmluaSetVar(lua, var);
+ 	    rpmluavFree(var);
+ 	    rpmluaPop(lua);
++
++	    what = (flag & RPMBUILD_ISPATCH) ? "patch_nums" : "source_nums";
++	    rpmluaPushTable(lua, what);
++	    var = rpmluavNew();
++	    rpmluavSetListMode(var, 1);
++	    rpmluavSetValueNum(var, p->num);
++	    rpmluaSetVar(lua, var);
++	    rpmluavFree(var);
++	    rpmluaPop(lua);
+ 	}
+ #endif
+ 	free(body);
+diff --git a/build/spec.c b/build/spec.c
+index 80eaca611..55095c6ce 100644
+--- a/build/spec.c
++++ b/build/spec.c
+@@ -305,7 +305,8 @@ rpmSpec newSpec(void)
+ #ifdef WITH_LUA
+     /* make sure patches and sources tables always exist */
+     rpmlua lua = NULL; /* global state */
+-    const char * luavars[] = { "patches", "sources", NULL, };
++    const char * luavars[] = { "patches", "sources",
++			       "patch_nums", "source_nums", NULL, };
+     for (const char **vp = luavars; vp && *vp; vp++) {
+ 	rpmluaDelVar(lua, *vp);
+ 	rpmluaPushTable(lua, *vp);
+-- 
+2.26.2
+
diff --git a/SOURCES/0001-Unblock-signals-in-forked-scriptlets.patch b/SOURCES/0001-Unblock-signals-in-forked-scriptlets.patch
new file mode 100644
index 0000000..fb1e8d4
--- /dev/null
+++ b/SOURCES/0001-Unblock-signals-in-forked-scriptlets.patch
@@ -0,0 +1,37 @@
+From cb6aa82dbc10d554f8d234e934ae7c77e39a3ce2 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Tue, 12 Jan 2021 13:35:23 +0200
+Subject: [PATCH] Unblock signals in forked scriptlets
+
+Since commit c5f82d3f6223ebd0c5cc0a07ea60393ae7284929 we've blocked
+most signals during transactions, which makes sense to rpm itself but
+the signal mask is inherited to childs and carried even across exec(),
+so all scriptlets are executing with those signals blocked as well.
+Which in turn does not make sense, the scriptlets could run stuff that
+actually depends on signal delivery (such as SIGALARM in RhBug:1913765).
+
+Unblock all signals for forked scriptlet execution (Lua scriptlets are
+totally different as they execute in-process for now)
+---
+ lib/rpmscript.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/lib/rpmscript.c b/lib/rpmscript.c
+index 2ae3378f7..c69d29554 100644
+--- a/lib/rpmscript.c
++++ b/lib/rpmscript.c
+@@ -152,6 +152,11 @@ static void doScriptExec(ARGV_const_t argv, ARGV_const_t prefixes,
+ 			FD_t scriptFd, FD_t out)
+ {
+     int xx;
++    sigset_t set;
++
++    /* Unmask all signals, the scripts may need them */
++    sigfillset(&set);
++    sigprocmask(SIG_UNBLOCK, &set, NULL);
+ 
+     /* SIGPIPE is ignored in rpm, reset to default for the scriptlet */
+     (void) signal(SIGPIPE, SIG_DFL);
+-- 
+2.29.2
+
diff --git a/SOURCES/0001-When-doing-the-same-thing-more-than-once-use-a-loop.patch b/SOURCES/0001-When-doing-the-same-thing-more-than-once-use-a-loop.patch
new file mode 100644
index 0000000..9e9ee45
--- /dev/null
+++ b/SOURCES/0001-When-doing-the-same-thing-more-than-once-use-a-loop.patch
@@ -0,0 +1,38 @@
+From 9cbc1fe444b048c3f7cf5ea09ab650d1c146d54a Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Wed, 20 Feb 2019 14:49:19 +0200
+Subject: [PATCH] When doing the same thing more than once, use a loop...
+
+No functional changes but this'll simplify the next commit quite a bit.
+---
+ build/spec.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+diff --git a/build/spec.c b/build/spec.c
+index e414e4102..80eaca611 100644
+--- a/build/spec.c
++++ b/build/spec.c
+@@ -303,15 +303,13 @@ rpmSpec newSpec(void)
+     spec->pool = rpmstrPoolCreate();
+     
+ #ifdef WITH_LUA
+-    {
+     /* make sure patches and sources tables always exist */
+     rpmlua lua = NULL; /* global state */
+-    rpmluaDelVar(lua, "patches");
+-    rpmluaDelVar(lua, "sources");
+-    rpmluaPushTable(lua, "patches");
+-    rpmluaPushTable(lua, "sources");
+-    rpmluaPop(lua);
+-    rpmluaPop(lua);
++    const char * luavars[] = { "patches", "sources", NULL, };
++    for (const char **vp = luavars; vp && *vp; vp++) {
++	rpmluaDelVar(lua, *vp);
++	rpmluaPushTable(lua, *vp);
++	rpmluaPop(lua);
+     }
+ #endif
+     return spec;
+-- 
+2.26.2
+
diff --git a/SOURCES/0001-Work-around-buggy-signature-region-preventing-resign.patch b/SOURCES/0001-Work-around-buggy-signature-region-preventing-resign.patch
new file mode 100644
index 0000000..54dd45f
--- /dev/null
+++ b/SOURCES/0001-Work-around-buggy-signature-region-preventing-resign.patch
@@ -0,0 +1,44 @@
+From 8fefd2bd21b30996ad0748eab6baadf915610642 Mon Sep 17 00:00:00 2001
+From: Panu Matilainen <pmatilai@redhat.com>
+Date: Thu, 13 Aug 2020 13:29:10 +0300
+Subject: [PATCH] Work around buggy signature region preventing resigning
+ (RhBug:1851508)
+
+Various proprietary packages in the wild have subtly malformed data
+in the signature header, in particular wrt the immutable region size,
+presumably from using some in-house/3rd party signing tools which do
+not understand the immutable region business at all. This can prevent
+resigning and signature deletion on such packages due to the more
+thorough checking that rpmsign does.
+
+As the old wisdom goes, be liberal in what you accept... we can easily
+work around the crud by just taking a fresh copy of the contents that
+are legit as such (otherwise the package would be uninstallable).
+
+
+Adjusted for 4.14.3
+
+--- rpm-4.14.3/sign/rpmgensig.c.orig	2020-10-29 16:00:38.785229048 +0100
++++ rpm-4.14.3/sign/rpmgensig.c	2020-10-29 16:08:55.997791345 +0100
+@@ -401,12 +401,19 @@
+ 
+     if (headerGet(*hdrp, tag, utd, HEADERGET_DEFAULT)) {
+ 	oh = headerCopyLoad(utd->data);
+-	nh = headerCopy(oh);
+-	headerFree(oh);
+ 	rpmtdFreeData(utd);
++    } else {
++	/* XXX should we warn if the immutable region is corrupt/missing? */
++	oh = headerLink(*hdrp);
++    }
++
++    if (oh) {
++	/* Perform a copy to eliminate crud from buggy signing tools etc */
++	nh = headerCopy(oh);
+ 	headerFree(*hdrp);
+ 	*hdrp = headerLink(nh);
+ 	headerFree(nh);
++	headerFree(oh);
+     }
+ }
+ 
diff --git a/SOURCES/rpm-4.14.3-ELF-files-strip-when-debuginfo-disabled.patch b/SOURCES/rpm-4.14.3-ELF-files-strip-when-debuginfo-disabled.patch
new file mode 100644
index 0000000..05ca170
--- /dev/null
+++ b/SOURCES/rpm-4.14.3-ELF-files-strip-when-debuginfo-disabled.patch
@@ -0,0 +1,14 @@
+diff -up rpm-4.14.3/scripts/brp-strip.orig rpm-4.14.3/scripts/brp-strip
+--- rpm-4.14.3/scripts/brp-strip.orig	2021-02-09 14:43:35.393940550 +0100
++++ rpm-4.14.3/scripts/brp-strip	2021-02-09 14:43:49.459222054 +0100
+@@ -12,9 +12,8 @@ Darwin*) exit 0 ;;
+ esac
+ 
+ # Strip ELF binaries
+-for f in `find "$RPM_BUILD_ROOT" -type f \( -perm -0100 -or -perm -0010 -or -perm -0001 \) -exec file {} \; | \
++for f in `find "$RPM_BUILD_ROOT" -type f -exec file {} \; | \
+         grep -v "^${RPM_BUILD_ROOT}/\?usr/lib/debug"  | \
+-	grep -v ' shared object,' | \
+ 	sed -n -e 's/^\(.*\):[ 	]*ELF.*, not stripped.*/\1/p'`; do
+ 	$STRIP -g "$f" || :
+ done
diff --git a/SOURCES/rpm-4.14.3-add-fapolicyd-rpm-plugin.patch b/SOURCES/rpm-4.14.3-add-fapolicyd-rpm-plugin.patch
new file mode 100644
index 0000000..3a9e808
--- /dev/null
+++ b/SOURCES/rpm-4.14.3-add-fapolicyd-rpm-plugin.patch
@@ -0,0 +1,378 @@
+From c33faabc2d09b9ad8c80b941b6114c1e4c2be80f Mon Sep 17 00:00:00 2001
+Message-Id: <c33faabc2d09b9ad8c80b941b6114c1e4c2be80f.1612252390.git.pmatilai@redhat.com>
+From: Radovan Sroka <rsroka@redhat.com>
+Date: Tue, 27 Oct 2020 16:18:04 +0100
+Subject: [PATCH] Added fapolicyd rpm plugin
+
+Fapolicyd (File Access Policy Daemon) implements application whitelisting
+to decide file access rights. Applications that are known via a reputation
+source are allowed access while unknown applications are not.
+
+The rpm plugin allows us to use rpm database as a source of trust.
+We used dnf plugin since the beggining but it only provides notification
+when transaction ends. With "integrity checking" requirement we need
+a continual addition of files which are installed during the system
+update. With fapolicyd rpm plugin we can allow using of recently
+added/updated files in scriptlets during rpm transaction.
+
+The fapolicyd plugin gathers metadata of currently installed files.
+It sends the information about files and about ongoing rpm transaction
+to the fapolicyd daemon. The information is written to Linux pipe which
+is placed in /var/run/fapolicyd/fapolicyd.fifo.
+
+The data format is "%s %lu %64s\n". [path, size, sha256]
+
+The fapolicyd rpm plugin can be enabled with "--with-fapolicyd"
+configure option.
+
+Related PRs:
+https://github.com/linux-application-whitelisting/fapolicyd/pull/105
+https://github.com/linux-application-whitelisting/fapolicyd/pull/106
+
+Signed-off-by: Radovan Sroka <rsroka@redhat.com>
+(cherry picked from commit 39595ccee321497dc3b08c7cab8a10304345429c)
+
+Backported from commit 39595ccee321497dc3b08c7cab8a10304345429c
+---
+ Makefile.am                |   1 +
+ configure.ac               |   8 ++
+ doc/Makefile.am            |   2 +-
+ doc/rpm-plugin-fapolicyd.8 |  21 +++++
+ macros.in                  |   1 +
+ plugins/Makefile.am        |   6 ++
+ plugins/fapolicyd.c        | 189 +++++++++++++++++++++++++++++++++++++
+ 7 files changed, 227 insertions(+), 1 deletion(-)
+ create mode 100644 doc/rpm-plugin-fapolicyd.8
+ create mode 100644 plugins/fapolicyd.c
+
+diff --git a/Makefile.am b/Makefile.am
+index 1f20f05b7..8e92f0cde 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -16,6 +16,7 @@ DISTCHECK_CONFIGURE_FLAGS = \
+ 	--with-selinux \
+ 	--with-imaevm \
+ 	--with-crypto=openssl \
++	--with-fapolicyd \
+ 	--disable-dependency-tracking
+ 
+ include $(top_srcdir)/rpm.am
+diff --git a/configure.ac b/configure.ac
+index 3fcb3ff20..3d0e9ef91 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -983,6 +983,14 @@ AS_IF([test "$enable_inhibit_plugin" = yes],[
+ ])
+ AM_CONDITIONAL(ENABLE_INHIBIT_PLUGIN,[test "$enable_inhibit_plugin" = yes])
+ 
++#=================
++# Check for fapolicyd support
++AC_ARG_WITH(fapolicyd,
++AS_HELP_STRING([--with-fapolicyd],[build with File Access Policy Daemon support]),
++with_fapolicyd=$withval,
++with_fapolicyd=auto)
++AM_CONDITIONAL(FAPOLICYD,[test "$with_fapolicyd" = yes])
++
+ with_dbus=no
+ AS_IF([test "$enable_plugins" != no],[
+  AS_IF([test "$enable_inhibit_plugin" != no],[
+diff --git a/doc/Makefile.am b/doc/Makefile.am
+index d2f520d64..535ad3ec3 100644
+--- a/doc/Makefile.am
++++ b/doc/Makefile.am
+@@ -9,7 +9,7 @@ EXTRA_DIST += $(man_man1_DATA)
+ man_man8dir = $(mandir)/man8
+ man_man8_DATA = rpm.8 rpm-misc.8 rpmbuild.8 rpmdeps.8 rpmgraph.8 rpm2cpio.8
+ man_man8_DATA += rpmdb.8 rpmkeys.8 rpmsign.8 rpmspec.8
+-man_man8_DATA += rpm-plugin-systemd-inhibit.8
++man_man8_DATA += rpm-plugin-systemd-inhibit.8 rpm-plugin-fapolicyd.8
+ EXTRA_DIST += $(man_man8_DATA)
+ 
+ man_fr_man8dir = $(mandir)/fr/man8
+diff --git a/doc/rpm-plugin-fapolicyd.8 b/doc/rpm-plugin-fapolicyd.8
+new file mode 100644
+index 000000000..fe7a8c78e
+--- /dev/null
++++ b/doc/rpm-plugin-fapolicyd.8
+@@ -0,0 +1,21 @@
++'\" t
++.TH "RPM-FAPOLICYD" "8" "28 Jan 2021" "Red Hat, Inc."
++.SH NAME
++rpm-plugin-fapolicyd \- Fapolicyd plugin for the RPM Package Manager
++
++.SH Description
++
++The plugin gathers metadata of currently installed files. It sends the
++information about files and about ongoing rpm transaction to the fapolicyd daemon.
++The information is written to Linux pipe which is placed in
++/var/run/fapolicyd/fapolicyd.fifo.
++
++.SH Configuration
++
++There are currently no options for this plugin in particular. See
++.BR rpm-plugins (8)
++on how to control plugins in general.
++
++.SH SEE ALSO
++.IR fapolicyd (8)
++.IR rpm-plugins (8)
+diff --git a/macros.in b/macros.in
+index a6069ee4d..2fbda64cc 100644
+--- a/macros.in
++++ b/macros.in
+@@ -1173,6 +1173,7 @@ package or when debugging this package.\
+ %__transaction_selinux		%{__plugindir}/selinux.so
+ %__transaction_syslog		%{__plugindir}/syslog.so
+ %__transaction_ima		%{__plugindir}/ima.so
++%__transaction_fapolicyd	%{__plugindir}/fapolicyd.so
+ %__transaction_prioreset	%{__plugindir}/prioreset.so
+ 
+ #------------------------------------------------------------------------------
+diff --git a/plugins/Makefile.am b/plugins/Makefile.am
+index ab4eee34f..cbfb81e19 100644
+--- a/plugins/Makefile.am
++++ b/plugins/Makefile.am
+@@ -42,3 +42,9 @@ ima_la_sources = ima.c
+ ima_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
+ plugins_LTLIBRARIES += ima.la
+ endif
++
++if FAPOLICYD
++fapolicyd_la_sources = fapolicyd.c
++fapolicyd_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
++plugins_LTLIBRARIES += fapolicyd.la
++endif
+diff --git a/plugins/fapolicyd.c b/plugins/fapolicyd.c
+new file mode 100644
+index 000000000..50f50155c
+--- /dev/null
++++ b/plugins/fapolicyd.c
+@@ -0,0 +1,189 @@
++#include "system.h"
++
++#include <rpm/rpmts.h>
++#include <rpm/rpmlog.h>
++#include "lib/rpmplugin.h"
++
++#include <fcntl.h>
++#include <errno.h>
++#include <unistd.h>
++#include <sys/stat.h>
++
++struct fapolicyd_data {
++    int fd;
++    long changed_files;
++    const char * fifo_path;
++};
++
++static struct fapolicyd_data fapolicyd_state = {
++    .fd = -1,
++    .changed_files = 0,
++    .fifo_path = "/run/fapolicyd/fapolicyd.fifo",
++};
++
++static rpmRC open_fifo(struct fapolicyd_data* state)
++{
++    int fd = -1;
++    struct stat s;
++
++    fd = open(state->fifo_path, O_RDWR);
++    if (fd == -1) {
++        rpmlog(RPMLOG_DEBUG, "Open: %s -> %s\n", state->fifo_path, strerror(errno));
++        goto bad;
++    }
++
++    if (stat(state->fifo_path, &s) == -1) {
++        rpmlog(RPMLOG_DEBUG, "Stat: %s -> %s\n", state->fifo_path, strerror(errno));
++        goto bad;
++    }
++
++    if (!S_ISFIFO(s.st_mode)) {
++        rpmlog(RPMLOG_DEBUG, "File: %s exists but it is not a pipe!\n", state->fifo_path);
++        goto bad;
++    }
++
++    /* keep only file's permition bits */
++    mode_t mode = s.st_mode & ~S_IFMT;
++
++    /* we require pipe to have 0660 permission */
++    if (mode != 0660) {
++        rpmlog(RPMLOG_ERR, "File: %s has %o instead of 0660 \n",
++               state->fifo_path,
++               mode );
++        goto bad;
++    }
++
++    state->fd = fd;
++    /* considering success */
++    return RPMRC_OK;
++
++ bad:
++    if (fd > 0)
++        close(fd);
++    return RPMRC_FAIL;
++}
++
++static rpmRC write_fifo(struct fapolicyd_data* state, const char * str)
++{
++    ssize_t len = strlen(str);
++    ssize_t written = 0;
++    ssize_t n = 0;
++
++    while (written < len) {
++        if ((n = write(state->fd, str + written, len - written)) < 0) {
++            if (errno == EINTR || errno == EAGAIN)
++                continue;
++            rpmlog(RPMLOG_DEBUG, "Write: %s -> %s\n", state->fifo_path, strerror(errno));
++            goto bad;
++        }
++        written += n;
++    }
++
++    return RPMRC_OK;
++
++ bad:
++    return RPMRC_FAIL;
++}
++
++static rpmRC fapolicyd_init(rpmPlugin plugin, rpmts ts)
++{
++    if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
++        goto end;
++
++    if (!rstreq(rpmtsRootDir(ts), "/"))
++        goto end;
++
++    (void) open_fifo(&fapolicyd_state);
++
++ end:
++    return RPMRC_OK;
++}
++
++static void fapolicyd_cleanup(rpmPlugin plugin)
++{
++    if (fapolicyd_state.fd > 0)
++        (void) close(fapolicyd_state.fd);
++
++    fapolicyd_state.fd = -1;
++}
++
++static rpmRC fapolicyd_tsm_post(rpmPlugin plugin, rpmts ts, int res)
++{
++    if (rpmtsFlags(ts) & (RPMTRANS_FLAG_TEST|RPMTRANS_FLAG_BUILD_PROBS))
++        goto end;
++
++    /* we are ready */
++    if (fapolicyd_state.fd > 0) {
++        /* send a signal that transaction is over */
++        (void) write_fifo(&fapolicyd_state, "1\n");
++        /* flush cache */
++        (void) write_fifo(&fapolicyd_state, "2\n");
++    }
++
++ end:
++    return RPMRC_OK;
++}
++
++static rpmRC fapolicyd_scriptlet_pre(rpmPlugin plugin, const char *s_name,
++                                     int type)
++{
++    if (fapolicyd_state.fd == -1)
++        goto end;
++
++    if (fapolicyd_state.changed_files > 0) {
++        /* send signal to flush cache */
++        (void) write_fifo(&fapolicyd_state, "2\n");
++
++        /* optimize flushing */
++        /* flush only when there was an actual change */
++        fapolicyd_state.changed_files = 0;
++    }
++
++ end:
++    return RPMRC_OK;
++}
++
++static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
++                                        const char *path, const char *dest,
++                                        mode_t file_mode, rpmFsmOp op)
++{
++    /* not ready  */
++    if (fapolicyd_state.fd == -1)
++        goto end;
++
++    rpmFileAction action = XFO_ACTION(op);
++
++    /* Ignore skipped files and unowned directories */
++    if (XFA_SKIPPING(action) || (op & FAF_UNOWNED)) {
++        rpmlog(RPMLOG_DEBUG, "fapolicyd skipping early: path %s dest %s\n",
++               path, dest);
++        goto end;
++    }
++
++    if (!S_ISREG(rpmfiFMode(fi))) {
++        rpmlog(RPMLOG_DEBUG, "fapolicyd skipping non regular: path %s dest %s\n",
++               path, dest);
++        goto end;
++    }
++
++    fapolicyd_state.changed_files++;
++
++    char buffer[4096];
++
++    rpm_loff_t size = rpmfiFSize(fi);
++    char * sha = rpmfiFDigestHex(fi, NULL);
++
++    snprintf(buffer, 4096, "%s %lu %64s\n", dest, size, sha);
++    (void) write_fifo(&fapolicyd_state, buffer);
++
++ end:
++    return RPMRC_OK;
++}
++
++struct rpmPluginHooks_s fapolicyd_hooks = {
++    .init = fapolicyd_init,
++    .cleanup = fapolicyd_cleanup,
++    .scriptlet_pre = fapolicyd_scriptlet_pre,
++    .tsm_post = fapolicyd_tsm_post,
++    .fsm_file_prepare = fapolicyd_fsm_file_prepare,
++};
+-- 
+2.29.2
+
+commit c66cee32e74ce1e507c031605e3d7b2c1391a52c
+Author: Radovan Sroka <rsroka@redhat.com>
+Date:   Wed Feb 10 17:04:55 2021 +0100
+
+    Fixed issues find by coverity
+    
+    - enhance the check for the file descriptor fd because 0 is also a valid
+    descriptor
+    
+    - added free() for sha so it doesn't leak memory for every file that is
+    processed
+    
+    Signed-off-by: Radovan Sroka <rsroka@redhat.com>
+
+diff --git a/plugins/fapolicyd.c b/plugins/fapolicyd.c
+index 50f50155c..48f65ae11 100644
+--- a/plugins/fapolicyd.c
++++ b/plugins/fapolicyd.c
+@@ -58,7 +58,7 @@ static rpmRC open_fifo(struct fapolicyd_data* state)
+     return RPMRC_OK;
+ 
+  bad:
+-    if (fd > 0)
++    if (fd >= 0)
+         close(fd);
+     return RPMRC_FAIL;
+ }
+@@ -176,6 +176,8 @@ static rpmRC fapolicyd_fsm_file_prepare(rpmPlugin plugin, rpmfi fi,
+     snprintf(buffer, 4096, "%s %lu %64s\n", dest, size, sha);
+     (void) write_fifo(&fapolicyd_state, buffer);
+ 
++    free(sha);
++
+  end:
+     return RPMRC_OK;
+ }
diff --git a/SOURCES/rpm-4.14.3-bump-up-the-limit-of-signature-header-to-64MB.patch b/SOURCES/rpm-4.14.3-bump-up-the-limit-of-signature-header-to-64MB.patch
new file mode 100644
index 0000000..58606e9
--- /dev/null
+++ b/SOURCES/rpm-4.14.3-bump-up-the-limit-of-signature-header-to-64MB.patch
@@ -0,0 +1,12 @@
+diff -up rpm-4.14.3/lib/header.c.orig rpm-4.14.3/lib/header.c
+--- rpm-4.14.3/lib/header.c.orig	2020-04-28 14:50:11.816399041 +0200
++++ rpm-4.14.3/lib/header.c	2021-02-03 16:47:23.567245743 +0100
+@@ -1910,7 +1910,7 @@ rpmRC hdrblobRead(FD_t fd, int magic, in
+ 
+     if (regionTag == RPMTAG_HEADERSIGNATURES) {
+ 	il_max = 32;
+-	dl_max = 8192;
++	dl_max = 64 * 1024 * 1024;
+     }
+ 
+     memset(block, 0, sizeof(block));
diff --git a/SOURCES/rpm-4.14.3-fix-ambiguous-diagnostics-on-file-triggers.patch b/SOURCES/rpm-4.14.3-fix-ambiguous-diagnostics-on-file-triggers.patch
new file mode 100644
index 0000000..48039c7
--- /dev/null
+++ b/SOURCES/rpm-4.14.3-fix-ambiguous-diagnostics-on-file-triggers.patch
@@ -0,0 +1,101 @@
+diff -up rpm-4.14.3/lib/rpmscript.c.orig rpm-4.14.3/lib/rpmscript.c
+--- rpm-4.14.3/lib/rpmscript.c.orig	2021-02-08 14:07:44.527197946 +0100
++++ rpm-4.14.3/lib/rpmscript.c	2021-02-08 14:09:05.732749080 +0100
+@@ -46,27 +46,27 @@ struct scriptInfo_s {
+ };
+ 
+ static const struct scriptInfo_s scriptInfo[] = {
+-    { RPMSCRIPT_PREIN, "%prein", 0,
++    { RPMSCRIPT_PREIN, "prein", 0,
+ 	RPMTAG_PREIN, RPMTAG_PREINPROG, RPMTAG_PREINFLAGS },
+-    { RPMSCRIPT_PREUN, "%preun", 0,
++    { RPMSCRIPT_PREUN, "preun", 0,
+ 	RPMTAG_PREUN, RPMTAG_PREUNPROG, RPMTAG_PREUNFLAGS },
+-    { RPMSCRIPT_POSTIN, "%post", 0,
++    { RPMSCRIPT_POSTIN, "post", 0,
+ 	RPMTAG_POSTIN, RPMTAG_POSTINPROG, RPMTAG_POSTINFLAGS },
+-    { RPMSCRIPT_POSTUN, "%postun", 0,
++    { RPMSCRIPT_POSTUN, "postun", 0,
+ 	RPMTAG_POSTUN, RPMTAG_POSTUNPROG, RPMTAG_POSTUNFLAGS },
+-    { RPMSCRIPT_PRETRANS, "%pretrans", 0,
++    { RPMSCRIPT_PRETRANS, "pretrans", 0,
+ 	RPMTAG_PRETRANS, RPMTAG_PRETRANSPROG, RPMTAG_PRETRANSFLAGS },
+-    { RPMSCRIPT_POSTTRANS, "%posttrans", 0,
++    { RPMSCRIPT_POSTTRANS, "posttrans", 0,
+ 	RPMTAG_POSTTRANS, RPMTAG_POSTTRANSPROG, RPMTAG_POSTTRANSFLAGS },
+-    { RPMSCRIPT_TRIGGERPREIN, "%triggerprein", RPMSENSE_TRIGGERPREIN,
++    { RPMSCRIPT_TRIGGERPREIN, "triggerprein", RPMSENSE_TRIGGERPREIN,
+ 	RPMTAG_TRIGGERPREIN, 0, 0 },
+-    { RPMSCRIPT_TRIGGERUN, "%triggerun", RPMSENSE_TRIGGERUN,
++    { RPMSCRIPT_TRIGGERUN, "triggerun", RPMSENSE_TRIGGERUN,
+ 	RPMTAG_TRIGGERUN, 0, 0 },
+-    { RPMSCRIPT_TRIGGERIN, "%triggerin", RPMSENSE_TRIGGERIN,
++    { RPMSCRIPT_TRIGGERIN, "triggerin", RPMSENSE_TRIGGERIN,
+ 	RPMTAG_TRIGGERIN, 0, 0 },
+-    { RPMSCRIPT_TRIGGERPOSTUN, "%triggerpostun", RPMSENSE_TRIGGERPOSTUN,
++    { RPMSCRIPT_TRIGGERPOSTUN, "triggerpostun", RPMSENSE_TRIGGERPOSTUN,
+ 	RPMTAG_TRIGGERPOSTUN, 0, 0 },
+-    { RPMSCRIPT_VERIFY, "%verify", 0,
++    { RPMSCRIPT_VERIFY, "verify", 0,
+ 	RPMTAG_VERIFYSCRIPT, RPMTAG_VERIFYSCRIPTPROG, RPMTAG_VERIFYSCRIPTFLAGS},
+     { 0, "unknown", 0,
+ 	RPMTAG_NOT_FOUND, RPMTAG_NOT_FOUND, RPMTAG_NOT_FOUND }
+@@ -457,7 +457,7 @@ static const char * tag2sln(rpmTagVal ta
+ }
+ 
+ static rpmScript rpmScriptNew(Header h, rpmTagVal tag, const char *body,
+-			      rpmscriptFlags flags)
++			      rpmscriptFlags flags, const char *prefix)
+ {
+     char *nevra = headerGetAsString(h, RPMTAG_NEVRA);
+     rpmScript script = xcalloc(1, sizeof(*script));
+@@ -465,7 +465,7 @@ static rpmScript rpmScriptNew(Header h,
+     script->type = getScriptType(tag);
+     script->flags = flags;
+     script->body = (body != NULL) ? xstrdup(body) : NULL;
+-    rasprintf(&script->descr, "%s(%s)", tag2sln(tag), nevra);
++    rasprintf(&script->descr, "%%%s%s(%s)", prefix, tag2sln(tag), nevra);
+ 
+     /* macros need to be expanded before possible queryformat */
+     if (script->body && (script->flags & RPMSCRIPT_FLAG_EXPAND)) {
+@@ -556,6 +556,7 @@ rpmScript rpmScriptFromTriggerTag(Header
+     rpmScript script = NULL;
+     struct rpmtd_s tscripts, tprogs, tflags;
+     headerGetFlags hgflags = HEADERGET_MINMEM;
++    const char *prefix = "";
+ 
+     switch (tm) {
+ 	case RPMSCRIPT_NORMALTRIGGER:
+@@ -567,11 +568,13 @@ rpmScript rpmScriptFromTriggerTag(Header
+ 	    headerGet(h, RPMTAG_FILETRIGGERSCRIPTS, &tscripts, hgflags);
+ 	    headerGet(h, RPMTAG_FILETRIGGERSCRIPTPROG, &tprogs, hgflags);
+ 	    headerGet(h, RPMTAG_FILETRIGGERSCRIPTFLAGS, &tflags, hgflags);
++	    prefix = "file";
+ 	    break;
+ 	case RPMSCRIPT_TRANSFILETRIGGER:
+ 	    headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTS, &tscripts, hgflags);
+ 	    headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTPROG, &tprogs, hgflags);
+ 	    headerGet(h, RPMTAG_TRANSFILETRIGGERSCRIPTFLAGS, &tflags, hgflags);
++	    prefix = "transfile";
+ 	    break;
+     }
+ 
+@@ -582,7 +585,8 @@ rpmScript rpmScriptFromTriggerTag(Header
+ 	if (rpmtdSetIndex(&tflags, ix) >= 0)
+ 	    sflags = rpmtdGetNumber(&tflags);
+ 
+-	script = rpmScriptNew(h, triggerTag, rpmtdGetString(&tscripts), sflags);
++	script = rpmScriptNew(h, triggerTag,
++				rpmtdGetString(&tscripts), sflags, prefix);
+ 
+ 	/* hack up a hge-style NULL-terminated array */
+ 	script->args = xmalloc(2 * sizeof(*script->args) + strlen(prog) + 1);
+@@ -608,7 +612,7 @@ rpmScript rpmScriptFromTag(Header h, rpm
+ 
+ 	script = rpmScriptNew(h, scriptTag,
+ 			      headerGetString(h, scriptTag),
+-			      headerGetNumber(h, getFlagTag(scriptTag)));
++			      headerGetNumber(h, getFlagTag(scriptTag)), "");
+ 
+ 	if (headerGet(h, progTag, &prog, (HEADERGET_ALLOC|HEADERGET_ARGV))) {
+ 	    script->args = prog.data;
diff --git a/SPECS/rpm.spec b/SPECS/rpm.spec
index 1cef8f9..09c2d5c 100644
--- a/SPECS/rpm.spec
+++ b/SPECS/rpm.spec
@@ -30,7 +30,7 @@
 
 %global rpmver 4.14.3
 #global snapver rc2
-%global rel 4
+%global rel 13
 
 %global srcver %{version}%{?snapver:-%{snapver}}
 %global srcdir %{?snapver:testing}%{!?snapver:%{name}-%(echo %{version} | cut -d'.' -f1-2).x}
@@ -92,6 +92,17 @@ Patch140: 0001-Fix-resource-leaks-on-zstd-open-error-paths.patch
 # XXX should be before 0001-Pass-RPM_BUILD_NCPUS-to-build-scripts.patch
 Patch141: 0001-Isolate-_smp_build_ncpus-and-use-it-for-_smp_mflags.patch
 Patch142: rpm-4.14.3-GPG-Switch-back-to-pipe-7-for-signing.patch
+Patch143: 0001-Work-around-buggy-signature-region-preventing-resign.patch
+Patch144: 0001-Fix-python-ts.addErase-not-raising-exception-on-not-.patch
+Patch145: 0001-Always-close-libelf-handle-1313.patch
+Patch146: 0001-When-doing-the-same-thing-more-than-once-use-a-loop.patch
+Patch147: 0001-Introduce-patch_nums-and-source_nums-Lua-variables-i.patch
+Patch148: 0001-Add-limits-to-autopatch-macro.patch
+Patch149: rpm-4.14.3-bump-up-the-limit-of-signature-header-to-64MB.patch
+Patch150: rpm-4.14.3-add-fapolicyd-rpm-plugin.patch
+Patch151: 0001-Unblock-signals-in-forked-scriptlets.patch
+Patch152: rpm-4.14.3-fix-ambiguous-diagnostics-on-file-triggers.patch
+Patch153: rpm-4.14.3-ELF-files-strip-when-debuginfo-disabled.patch
 
 # Python 3 string API sanity
 Patch500: 0001-In-Python-3-return-all-our-string-data-as-surrogate-.patch
@@ -390,6 +401,15 @@ Requires: rpm-libs%{_isa} = %{version}-%{release}
 Useful on legacy SysV init systems if you run rpm transactions with
 nice/ionice priorities. Should not be used on systemd systems.
 
+%package plugin-fapolicyd
+Summary: Rpm plugin for fapolicyd functionality
+Requires: rpm-libs%{_isa} = %{version}-%{release}
+Provides: fapolicyd-plugin
+Obsoletes: fapolicyd-dnf-plugin
+
+%description plugin-fapolicyd
+%{summary}.
+
 %endif # with plugins
 
 %prep
@@ -434,9 +454,11 @@ done;
     --with-cap \
     --with-acl \
     %{?with_ndb: --enable-ndb} \
+    %{!?with_libarchive: --without-archive} \
     %{?with_libimaevm: --with-imaevm} \
     %{?with_zstd: --enable-zstd} \
     %{?with_lmdb: --enable-lmdb} \
+    --with-fapolicyd \
     --enable-python \
     --with-crypto=openssl \
     PYTHON=python3
@@ -531,7 +553,9 @@ make check || cat tests/rpmtests.log
 %attr(0644, root, root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/lib/rpm/*
 
 %{_bindir}/rpm
+%if %{with libarchive}
 %{_bindir}/rpm2archive
+%endif
 %{_bindir}/rpm2cpio
 %{_bindir}/rpmdb
 %{_bindir}/rpmkeys
@@ -591,6 +615,10 @@ make check || cat tests/rpmtests.log
 
 %files plugin-prioreset
 %{_libdir}/rpm-plugins/prioreset.so
+
+%files plugin-fapolicyd
+%{_libdir}/rpm-plugins/fapolicyd.so
+%{_mandir}/man8/rpm-plugin-fapolicyd.8*
 %endif # with plugins
 
 %files build-libs
@@ -653,6 +681,31 @@ make check || cat tests/rpmtests.log
 %doc doc/librpm/html/*
 
 %changelog
+* Fri Feb 12 2021 Michal Domonkos <mdomonko@redhat.com> - 4.14.3-13
+- Fix minor issues found by COVSCAN in fapolicyd plugin
+- Actually honor libarchive bcond at configure time (#1902887)
+
+* Tue Feb 09 2021 Michal Domonkos <mdomonko@redhat.com> - 4.14.3-12
+- Bump up the limit of signature header to 64MB (#1918777)
+- Add fapolicyd plugin (#1923167)
+- Unblock signals in forked scriptlets (#1913765)
+- Fix ambiguous diagnostics output on file triggers (#1883338)
+- Ensure ELF files get stripped when debuginfo is disabled (#1634084)
+
+* Sun Jan 10 2021 Michal Domonkos <mdomonko@redhat.com> - 4.14.3-10
+- Rebuild for libimaevm soname bump, now for real (#1896046)
+
+* Thu Jan 07 2021 Florian Festi <ffesti@redhat.com> - 4.14.3-8
+- Add limits to autopatch macro (#1834931)
+
+* Thu Dec 03 2020 Michal Domonkos <mdomonko@redhat.com> - 4.14.3-6
+- Rebuild for libimaevm soname bump (#1896046)
+
+* Fri Oct 30 2020 Florian Festi <ffesti@redhat.com> - 4.14.3-5
+- Don't error out when replacing an invalid signature (#1874062)
+- Raise an expection when erasing a package fails in Python (#1872623)
+- Fix builds on NFS filesystems (#1840728)
+
 * Fri Jun 26 2020 Michal Domonkos <mdomonko@redhat.com> - 4.14.3-4
 - Fix hang when signing with expired key (#1746353)