diff --git a/SOURCES/0001-rootfs-add-mount-destination-validation.patch b/SOURCES/0001-rootfs-add-mount-destination-validation.patch
deleted file mode 100644
index 7d84489..0000000
--- a/SOURCES/0001-rootfs-add-mount-destination-validation.patch
+++ /dev/null
@@ -1,411 +0,0 @@
-From 9e0940c49a1b65f0fa656905a6b6a14ed2f70dfe Mon Sep 17 00:00:00 2001
-From: Kir Kolyshkin <kolyshkin@gmail.com>
-Date: Mon, 17 May 2021 14:11:35 -0700
-Subject: [PATCH] rootfs: add mount destination validation
-
-This is a manual backport of the CVE-2021-30465 fix. Original
-description follows.
-
----
-
-Because the target of a mount is inside a container (which may be a
-volume that is shared with another container), there exists a race
-condition where the target of the mount may change to a path containing
-a symlink after we have sanitised the path -- resulting in us
-inadvertently mounting the path outside of the container.
-
-This is not immediately useful because we are in a mount namespace with
-MS_SLAVE mount propagation applied to "/", so we cannot mount on top of
-host paths in the host namespace. However, if any subsequent mountpoints
-in the configuration use a subdirectory of that host path as a source,
-those subsequent mounts will use an attacker-controlled source path
-(resolved within the host rootfs) -- allowing the bind-mounting of "/"
-into the container.
-
-While arguably configuration issues like this are not entirely within
-runc's threat model, within the context of Kubernetes (and possibly
-other container managers that provide semi-arbitrary container creation
-privileges to untrusted users) this is a legitimate issue. Since we
-cannot block mounting from the host into the container, we need to block
-the first stage of this attack (mounting onto a path outside the
-container).
-
-The long-term plan to solve this would be to migrate to libpathrs, but
-as a stop-gap we implement libpathrs-like path verification through
-readlink(/proc/self/fd/$n) and then do mount operations through the
-procfd once it's been verified to be inside the container. The target
-could move after we've checked it, but if it is inside the container
-then we can assume that it is safe for the same reason that libpathrs
-operations would be safe.
-
-A slight wrinkle is the "copyup" functionality we provide for tmpfs,
-which is the only case where we want to do a mount on the host
-filesystem. To facilitate this, I split out the copy-up functionality
-entirely so that the logic isn't interspersed with the regular tmpfs
-logic. In addition, all dependencies on m.Destination being overwritten
-have been removed since that pattern was just begging to be a source of
-more mount-target bugs (we do still have to modify m.Destination for
-tmpfs-copyup but we only do it temporarily).
-
-Fixes: CVE-2021-30465
-Reported-by: Etienne Champetier <champetier.etienne@gmail.com>
-Co-authored-by: Noah Meyerhans <nmeyerha@amazon.com>
-Reviewed-by: Samuel Karp <skarp@amazon.com>
-Reviewed-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
-Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
-
-Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
----
- libcontainer/rootfs_linux.go | 158 ++++++++++++++++++-----------------
- libcontainer/utils/utils.go  |  56 +++++++++++++
- 2 files changed, 139 insertions(+), 75 deletions(-)
-
-diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go
-index 42b66141..56bfb39e 100644
---- a/runc-66aedde759f33c190954815fb765eedc1d782dd9/libcontainer/rootfs_linux.go
-+++ b/runc-66aedde759f33c190954815fb765eedc1d782dd9/libcontainer/rootfs_linux.go
-@@ -14,6 +14,7 @@ import (
- 	"syscall"
- 	"time"
- 
-+	"github.com/Sirupsen/logrus"
- 	securejoin "github.com/cyphar/filepath-securejoin"
- 	"github.com/docker/docker/pkg/mount"
- 	"github.com/mrunalp/fileutils"
-@@ -145,8 +146,6 @@ func prepareBindMount(m *configs.Mount, rootfs string) error {
- 	if err := checkProcMount(rootfs, dest, m.Source); err != nil {
- 		return err
- 	}
--	// update the mount with the correct dest after symlinks are resolved.
--	m.Destination = dest
- 	if err := createIfNotExists(dest, stat.IsDir()); err != nil {
- 		return err
- 	}
-@@ -154,12 +153,50 @@ func prepareBindMount(m *configs.Mount, rootfs string) error {
- 	return nil
- }
- 
-+func doTmpfsCopyUp(m *configs.Mount, rootfs, mountLabel string) (Err error) {
-+	// Set up a scratch dir for the tmpfs on the host.
-+	tmpDir, err := ioutil.TempDir("/tmp", "runctmpdir")
-+	if err != nil {
-+		return newSystemErrorWithCause(err, "tmpcopyup: failed to create tmpdir")
-+	}
-+	defer os.RemoveAll(tmpDir)
-+
-+	// Configure the *host* tmpdir as if it's the container mount. We change
-+	// m.Destination since we are going to mount *on the host*.
-+	oldDest := m.Destination
-+	m.Destination = tmpDir
-+	err = mountPropagate(m, "/", mountLabel)
-+	m.Destination = oldDest
-+	if err != nil {
-+		return err
-+	}
-+	defer func() {
-+		if Err != nil {
-+			if err := syscall.Unmount(tmpDir, syscall.MNT_DETACH); err != nil {
-+				logrus.Warnf("tmpcopyup: failed to unmount tmpdir on error: %v", err)
-+			}
-+		}
-+	}()
-+
-+	return libcontainerUtils.WithProcfd(rootfs, m.Destination, func(procfd string) (Err error) {
-+		// Copy the container data to the host tmpdir. We append "/" to force
-+		// CopyDirectory to resolve the symlink rather than trying to copy the
-+		// symlink itself.
-+		if err := fileutils.CopyDirectory(procfd+"/", tmpDir); err != nil {
-+			return fmt.Errorf("tmpcopyup: failed to copy %s to %s (%s): %v", m.Destination, procfd, tmpDir, err)
-+		}
-+		// Now move the mount into the container.
-+		if err := syscall.Mount(tmpDir, procfd, "", syscall.MS_MOVE, ""); err != nil {
-+			return fmt.Errorf("tmpcopyup: failed to move mount %s to %s (%s): %v", tmpDir, procfd, m.Destination, err)
-+		}
-+		return nil
-+	})
-+}
-+
- func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
--	var (
--		dest = m.Destination
--	)
--	if !strings.HasPrefix(dest, rootfs) {
--		dest = filepath.Join(rootfs, dest)
-+	dest, err := securejoin.SecureJoin(rootfs, m.Destination)
-+	if err != nil {
-+		return err
- 	}
- 
- 	switch m.Device {
-@@ -182,41 +219,20 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
- 		}
- 		return nil
- 	case "tmpfs":
--		copyUp := m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP
--		tmpDir := ""
- 		stat, err := os.Stat(dest)
- 		if err != nil {
- 			if err := os.MkdirAll(dest, 0755); err != nil {
- 				return err
- 			}
- 		}
--		if copyUp {
--			tmpDir, err = ioutil.TempDir("/tmp", "runctmpdir")
--			if err != nil {
--				return newSystemErrorWithCause(err, "tmpcopyup: failed to create tmpdir")
--			}
--			defer os.RemoveAll(tmpDir)
--			m.Destination = tmpDir
-+		if m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP {
-+			err = doTmpfsCopyUp(m, rootfs, mountLabel)
-+		} else {
-+			err = mountPropagate(m, rootfs, mountLabel)
- 		}
--		if err := mountPropagate(m, rootfs, mountLabel); err != nil {
-+		if err != nil {
- 			return err
- 		}
--		if copyUp {
--			if err := fileutils.CopyDirectory(dest, tmpDir); err != nil {
--				errMsg := fmt.Errorf("tmpcopyup: failed to copy %s to %s: %v", dest, tmpDir, err)
--				if err1 := syscall.Unmount(tmpDir, syscall.MNT_DETACH); err1 != nil {
--					return newSystemErrorWithCausef(err1, "tmpcopyup: %v: failed to unmount", errMsg)
--				}
--				return errMsg
--			}
--			if err := syscall.Mount(tmpDir, dest, "", syscall.MS_MOVE, ""); err != nil {
--				errMsg := fmt.Errorf("tmpcopyup: failed to move mount %s to %s: %v", tmpDir, dest, err)
--				if err1 := syscall.Unmount(tmpDir, syscall.MNT_DETACH); err1 != nil {
--					return newSystemErrorWithCausef(err1, "tmpcopyup: %v: failed to unmount", errMsg)
--				}
--				return errMsg
--			}
--		}
- 		if stat != nil {
- 			if err = os.Chmod(dest, stat.Mode()); err != nil {
- 				return err
-@@ -299,19 +315,9 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
- 			}
- 		}
- 	default:
--		// ensure that the destination of the mount is resolved of symlinks at mount time because
--		// any previous mounts can invalidate the next mount's destination.
--		// this can happen when a user specifies mounts within other mounts to cause breakouts or other
--		// evil stuff to try to escape the container's rootfs.
--		var err error
--		if dest, err = securejoin.SecureJoin(rootfs, m.Destination); err != nil {
--			return err
--		}
- 		if err := checkProcMount(rootfs, dest, m.Source); err != nil {
- 			return err
- 		}
--		// update the mount with the correct dest after symlinks are resolved.
--		m.Destination = dest
- 		if err := os.MkdirAll(dest, 0755); err != nil {
- 			return err
- 		}
-@@ -485,7 +491,7 @@ func createDevices(config *configs.Config) error {
- 	return nil
- }
- 
--func bindMountDeviceNode(dest string, node *configs.Device) error {
-+func bindMountDeviceNode(rootfs, dest string, node *configs.Device) error {
- 	f, err := os.Create(dest)
- 	if err != nil && !os.IsExist(err) {
- 		return err
-@@ -493,24 +499,29 @@ func bindMountDeviceNode(dest string, node *configs.Device) error {
- 	if f != nil {
- 		f.Close()
- 	}
--	return syscall.Mount(node.Path, dest, "bind", syscall.MS_BIND, "")
-+	return libcontainerUtils.WithProcfd(rootfs, dest, func(procfd string) error {
-+		return syscall.Mount(node.Path, procfd, "bind", syscall.MS_BIND, "")
-+	})
- }
- 
- // Creates the device node in the rootfs of the container.
- func createDeviceNode(rootfs string, node *configs.Device, bind bool) error {
--	dest := filepath.Join(rootfs, node.Path)
-+	dest, err := securejoin.SecureJoin(rootfs, node.Path)
-+	if err != nil {
-+		return err
-+	}
- 	if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil {
- 		return err
- 	}
- 
- 	if bind {
--		return bindMountDeviceNode(dest, node)
-+		return bindMountDeviceNode(rootfs, dest, node)
- 	}
- 	if err := mknodDevice(dest, node); err != nil {
- 		if os.IsExist(err) {
- 			return nil
- 		} else if os.IsPermission(err) {
--			return bindMountDeviceNode(dest, node)
-+			return bindMountDeviceNode(rootfs, dest, node)
- 		}
- 		return err
- 	}
-@@ -681,10 +692,6 @@ func pivotRoot(rootfs string) error {
- 
- 	// Make oldroot rprivate to make sure our unmounts don't propagate to the
- 	// host (and thus bork the machine).
--	if err := syscall.Mount("", ".", "", syscall.MS_PRIVATE|syscall.MS_REC, ""); err != nil {
--		return err
--	}
--	// Preform the unmount. MNT_DETACH allows us to unmount /proc/self/cwd.
- 	if err := syscall.Unmount(".", syscall.MNT_DETACH); err != nil {
- 		return err
- 	}
-@@ -807,43 +814,44 @@ func writeSystemProperty(key, value string) error {
- }
- 
- func remount(m *configs.Mount, rootfs string) error {
--	var (
--		dest = m.Destination
--	)
--	if !strings.HasPrefix(dest, rootfs) {
--		dest = filepath.Join(rootfs, dest)
--	}
--	if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil {
--		return err
--	}
--	return nil
-+	return libcontainerUtils.WithProcfd(rootfs, m.Destination, func(procfd string) error {
-+		return syscall.Mount(m.Source, procfd, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), "")
-+	})
- }
- 
- // Do the mount operation followed by additional mounts required to take care
--// of propagation flags.
-+// of propagation flags.  This will always be scoped inside the container rootfs.
- func mountPropagate(m *configs.Mount, rootfs string, mountLabel string) error {
- 	var (
--		dest  = m.Destination
- 		data  = label.FormatMountLabel(m.Data, mountLabel)
- 		flags = m.Flags
- 	)
--	if libcontainerUtils.CleanPath(dest) == "/dev" {
-+	if libcontainerUtils.CleanPath(m.Destination) == "/dev" {
- 		flags &= ^syscall.MS_RDONLY
- 	}
- 
--	copyUp := m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP
--	if !(copyUp || strings.HasPrefix(dest, rootfs)) {
--		dest = filepath.Join(rootfs, dest)
-+	// Because the destination is inside a container path which might be
-+	// mutating underneath us, we verify that we are actually going to mount
-+	// inside the container with WithProcfd() -- mounting through a procfd
-+	// mounts on the target.
-+	if err := libcontainerUtils.WithProcfd(rootfs, m.Destination, func(procfd string) error {
-+		return syscall.Mount(m.Source, procfd, m.Device, uintptr(flags), data)
-+	}); err != nil {
-+		return fmt.Errorf("mount through procfd: %v", err)
- 	}
- 
--	if err := syscall.Mount(m.Source, dest, m.Device, uintptr(flags), data); err != nil {
--		return err
--	}
--
--	for _, pflag := range m.PropagationFlags {
--		if err := syscall.Mount("", dest, "", uintptr(pflag), ""); err != nil {
--			return err
-+	// We have to apply mount propagation flags in a separate WithProcfd() call
-+	// because the previous call invalidates the passed procfd -- the mount
-+	// target needs to be re-opened.
-+	if err := libcontainerUtils.WithProcfd(rootfs, m.Destination, func(procfd string) error {
-+		for _, pflag := range m.PropagationFlags {
-+			if err := syscall.Mount("", procfd, "", uintptr(pflag), ""); err != nil {
-+				return err
-+			}
- 		}
-+		return nil
-+	}); err != nil {
-+		return fmt.Errorf("change mount propagation through procfd: %v", err)
- 	}
- 	return nil
- }
-diff --git a/libcontainer/utils/utils.go b/libcontainer/utils/utils.go
-index 2b35b9a7..a89fc6a2 100644
---- a/runc-66aedde759f33c190954815fb765eedc1d782dd9/libcontainer/utils/utils.go
-+++ b/runc-66aedde759f33c190954815fb765eedc1d782dd9/libcontainer/utils/utils.go
-@@ -4,12 +4,17 @@ import (
- 	"crypto/rand"
- 	"encoding/hex"
- 	"encoding/json"
-+	"fmt"
- 	"io"
- 	"os"
- 	"path/filepath"
-+	"strconv"
- 	"strings"
- 	"syscall"
- 	"unsafe"
-+
-+	securejoin "github.com/cyphar/filepath-securejoin"
-+	"golang.org/x/sys/unix"
- )
- 
- const (
-@@ -87,6 +92,57 @@ func CleanPath(path string) string {
- 	return filepath.Clean(path)
- }
- 
-+// stripRoot returns the passed path, stripping the root path if it was
-+// (lexicially) inside it. Note that both passed paths will always be treated
-+// as absolute, and the returned path will also always be absolute. In
-+// addition, the paths are cleaned before stripping the root.
-+func stripRoot(root, path string) string {
-+	// Make the paths clean and absolute.
-+	root, path = CleanPath("/"+root), CleanPath("/"+path)
-+	switch {
-+	case path == root:
-+		path = "/"
-+	case root == "/":
-+		// do nothing
-+	case strings.HasPrefix(path, root+"/"):
-+		path = strings.TrimPrefix(path, root+"/")
-+	}
-+	return CleanPath("/" + path)
-+}
-+
-+// WithProcfd runs the passed closure with a procfd path (/proc/self/fd/...)
-+// corresponding to the unsafePath resolved within the root. Before passing the
-+// fd, this path is verified to have been inside the root -- so operating on it
-+// through the passed fdpath should be safe. Do not access this path through
-+// the original path strings, and do not attempt to use the pathname outside of
-+// the passed closure (the file handle will be freed once the closure returns).
-+func WithProcfd(root, unsafePath string, fn func(procfd string) error) error {
-+	// Remove the root then forcefully resolve inside the root.
-+	unsafePath = stripRoot(root, unsafePath)
-+	path, err := securejoin.SecureJoin(root, unsafePath)
-+	if err != nil {
-+		return fmt.Errorf("resolving path inside rootfs failed: %v", err)
-+	}
-+
-+	// Open the target path.
-+	fh, err := os.OpenFile(path, unix.O_PATH|unix.O_CLOEXEC, 0)
-+	if err != nil {
-+		return fmt.Errorf("open o_path procfd: %v", err)
-+	}
-+	defer fh.Close()
-+
-+	// Double-check the path is the one we expected.
-+	procfd := "/proc/self/fd/" + strconv.Itoa(int(fh.Fd()))
-+	if realpath, err := os.Readlink(procfd); err != nil {
-+		return fmt.Errorf("procfd verification failed: %v", err)
-+	} else if realpath != path {
-+		return fmt.Errorf("possibly malicious path detected -- refusing to operate on %s", realpath)
-+	}
-+
-+	// Run the closure.
-+	return fn(procfd)
-+}
-+
- // SearchLabels searches a list of key-value pairs for the provided key and
- // returns the corresponding value. The pairs must be separated with '='.
- func SearchLabels(labels []string, query string) string {
--- 
-2.31.1
-
diff --git a/SOURCES/1.patch b/SOURCES/1.patch
new file mode 100644
index 0000000..c4f8e4c
--- /dev/null
+++ b/SOURCES/1.patch
@@ -0,0 +1,69 @@
+From 40fd67a5303214be8a6aeb30e4f30735dcaf3094 Mon Sep 17 00:00:00 2001
+From: y00316549 <yangshukui@huawei.com>
+Date: Thu, 11 Jan 2018 20:16:18 +0800
+Subject: [PATCH] Security: fix mem leak in containerd
+
+Change-Id: I79df63093835a28ff23074ebc0f75fffac592e66
+Signed-off-by: Shukui Yang <yangshukui@huawei.com>
+(cherry picked from commit 64456eccb7443ab68b1b5cf0c33be51fdfe5e346)
+Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
+---
+ supervisor/delete.go     | 7 +++++--
+ supervisor/exit.go       | 1 +
+ supervisor/supervisor.go | 8 ++++++--
+ 3 files changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/supervisor/delete.go b/supervisor/delete.go
+index 26cf1bb..9cf517f 100644
+--- a/containerd-9c53e35c39f214b128beed3dfb670ccf751c4173/supervisor/delete.go
++++ b/containerd-9c53e35c39f214b128beed3dfb670ccf751c4173/supervisor/delete.go
+@@ -27,11 +27,14 @@ func (s *Supervisor) delete(t *DeleteTask) error {
+ 			t.Process.Wait()
+ 		}
+ 		if !t.NoEvent {
+-			execMap := s.getExecSyncMap(t.ID)
+ 			go func() {
+ 				// Wait for all exec processe events to be sent (we seem
+ 				// to sometimes receive them after the init event)
+-				for _, ch := range execMap {
++				for {
++					ch := s.getExecSyncOneChannel(t.ID)
++					if ch == nil {
++						break
++					}
+ 					<-ch
+ 				}
+ 				s.deleteExecSyncMap(t.ID)
+diff --git a/supervisor/exit.go b/supervisor/exit.go
+index 2bce31e..537927b 100644
+--- a/containerd-9c53e35c39f214b128beed3dfb670ccf751c4173/supervisor/exit.go
++++ b/containerd-9c53e35c39f214b128beed3dfb670ccf751c4173/supervisor/exit.go
+@@ -89,6 +89,7 @@ func (s *Supervisor) execExit(t *ExecExitTask) error {
+ 			PID:       t.PID,
+ 			Status:    t.Status,
+ 		})
++		s.deleteExecSyncChannel(t.ID, t.PID)
+ 		close(synCh)
+ 	}()
+ 	return nil
+diff --git a/supervisor/supervisor.go b/supervisor/supervisor.go
+index e21ae7b..bbb001c 100644
+--- a/containerd-9c53e35c39f214b128beed3dfb670ccf751c4173/supervisor/supervisor.go
++++ b/containerd-9c53e35c39f214b128beed3dfb670ccf751c4173/supervisor/supervisor.go
+@@ -479,10 +479,14 @@ func (s *Supervisor) getExecSyncChannel(containerID, pid string) chan struct{} {
+ 	return ch
+ }
+ 
+-func (s *Supervisor) getExecSyncMap(containerID string) map[string]chan struct{} {
++func (s *Supervisor) getExecSyncOneChannel(containerID string) chan struct{} {
+ 	s.containerExecSyncLock.Lock()
+ 	defer s.containerExecSyncLock.Unlock()
+-	return s.containerExecSync[containerID]
++
++	for _, ch := range s.containerExecSync[containerID] {
++		return ch
++	}
++	return nil
+ }
+ 
+ func (s *Supervisor) deleteExecSyncMap(containerID string) {
diff --git a/SOURCES/54.patch b/SOURCES/54.patch
new file mode 100644
index 0000000..0af3708
--- /dev/null
+++ b/SOURCES/54.patch
@@ -0,0 +1,397 @@
+From 2a572d2d825735493a981b03b48877940ea2c17a Mon Sep 17 00:00:00 2001
+From: Kir Kolyshkin <kolyshkin@gmail.com>
+Date: Mon, 17 May 2021 14:11:35 -0700
+Subject: [PATCH] rootfs: add mount destination validation
+
+This is a manual backport of the CVE-2021-30465 fix. Original
+description follows.
+
+---
+
+Because the target of a mount is inside a container (which may be a
+volume that is shared with another container), there exists a race
+condition where the target of the mount may change to a path containing
+a symlink after we have sanitised the path -- resulting in us
+inadvertently mounting the path outside of the container.
+
+This is not immediately useful because we are in a mount namespace with
+MS_SLAVE mount propagation applied to "/", so we cannot mount on top of
+host paths in the host namespace. However, if any subsequent mountpoints
+in the configuration use a subdirectory of that host path as a source,
+those subsequent mounts will use an attacker-controlled source path
+(resolved within the host rootfs) -- allowing the bind-mounting of "/"
+into the container.
+
+While arguably configuration issues like this are not entirely within
+runc's threat model, within the context of Kubernetes (and possibly
+other container managers that provide semi-arbitrary container creation
+privileges to untrusted users) this is a legitimate issue. Since we
+cannot block mounting from the host into the container, we need to block
+the first stage of this attack (mounting onto a path outside the
+container).
+
+The long-term plan to solve this would be to migrate to libpathrs, but
+as a stop-gap we implement libpathrs-like path verification through
+readlink(/proc/self/fd/$n) and then do mount operations through the
+procfd once it's been verified to be inside the container. The target
+could move after we've checked it, but if it is inside the container
+then we can assume that it is safe for the same reason that libpathrs
+operations would be safe.
+
+A slight wrinkle is the "copyup" functionality we provide for tmpfs,
+which is the only case where we want to do a mount on the host
+filesystem. To facilitate this, I split out the copy-up functionality
+entirely so that the logic isn't interspersed with the regular tmpfs
+logic. In addition, all dependencies on m.Destination being overwritten
+have been removed since that pattern was just begging to be a source of
+more mount-target bugs (we do still have to modify m.Destination for
+tmpfs-copyup but we only do it temporarily).
+
+Fixes: CVE-2021-30465
+Reported-by: Etienne Champetier <champetier.etienne@gmail.com>
+Co-authored-by: Noah Meyerhans <nmeyerha@amazon.com>
+Reviewed-by: Samuel Karp <skarp@amazon.com>
+Reviewed-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
+Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
+
+Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
+---
+ libcontainer/rootfs_linux.go | 154 +++++++++++++++++++----------------
+ libcontainer/utils/utils.go  |  56 +++++++++++++
+ 2 files changed, 139 insertions(+), 71 deletions(-)
+
+diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go
+index 42b66141..984fe289 100644
+--- a/runc-66aedde759f33c190954815fb765eedc1d782dd9/libcontainer/rootfs_linux.go
++++ b/runc-66aedde759f33c190954815fb765eedc1d782dd9/libcontainer/rootfs_linux.go
+@@ -14,6 +14,7 @@ import (
+ 	"syscall"
+ 	"time"
+ 
++	"github.com/Sirupsen/logrus"
+ 	securejoin "github.com/cyphar/filepath-securejoin"
+ 	"github.com/docker/docker/pkg/mount"
+ 	"github.com/mrunalp/fileutils"
+@@ -145,8 +146,6 @@ func prepareBindMount(m *configs.Mount, rootfs string) error {
+ 	if err := checkProcMount(rootfs, dest, m.Source); err != nil {
+ 		return err
+ 	}
+-	// update the mount with the correct dest after symlinks are resolved.
+-	m.Destination = dest
+ 	if err := createIfNotExists(dest, stat.IsDir()); err != nil {
+ 		return err
+ 	}
+@@ -154,12 +153,50 @@ func prepareBindMount(m *configs.Mount, rootfs string) error {
+ 	return nil
+ }
+ 
++func doTmpfsCopyUp(m *configs.Mount, rootfs, mountLabel string) (Err error) {
++	// Set up a scratch dir for the tmpfs on the host.
++	tmpDir, err := ioutil.TempDir("/tmp", "runctmpdir")
++	if err != nil {
++		return newSystemErrorWithCause(err, "tmpcopyup: failed to create tmpdir")
++	}
++	defer os.RemoveAll(tmpDir)
++
++	// Configure the *host* tmpdir as if it's the container mount. We change
++	// m.Destination since we are going to mount *on the host*.
++	oldDest := m.Destination
++	m.Destination = tmpDir
++	err = mountPropagate(m, "/", mountLabel)
++	m.Destination = oldDest
++	if err != nil {
++		return err
++	}
++	defer func() {
++		if Err != nil {
++			if err := syscall.Unmount(tmpDir, syscall.MNT_DETACH); err != nil {
++				logrus.Warnf("tmpcopyup: failed to unmount tmpdir on error: %v", err)
++			}
++		}
++	}()
++
++	return libcontainerUtils.WithProcfd(rootfs, m.Destination, func(procfd string) (Err error) {
++		// Copy the container data to the host tmpdir. We append "/" to force
++		// CopyDirectory to resolve the symlink rather than trying to copy the
++		// symlink itself.
++		if err := fileutils.CopyDirectory(procfd+"/", tmpDir); err != nil {
++			return fmt.Errorf("tmpcopyup: failed to copy %s to %s (%s): %v", m.Destination, procfd, tmpDir, err)
++		}
++		// Now move the mount into the container.
++		if err := syscall.Mount(tmpDir, procfd, "", syscall.MS_MOVE, ""); err != nil {
++			return fmt.Errorf("tmpcopyup: failed to move mount %s to %s (%s): %v", tmpDir, procfd, m.Destination, err)
++		}
++		return nil
++	})
++}
++
+ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
+-	var (
+-		dest = m.Destination
+-	)
+-	if !strings.HasPrefix(dest, rootfs) {
+-		dest = filepath.Join(rootfs, dest)
++	dest, err := securejoin.SecureJoin(rootfs, m.Destination)
++	if err != nil {
++		return err
+ 	}
+ 
+ 	switch m.Device {
+@@ -182,41 +219,20 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
+ 		}
+ 		return nil
+ 	case "tmpfs":
+-		copyUp := m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP
+-		tmpDir := ""
+ 		stat, err := os.Stat(dest)
+ 		if err != nil {
+ 			if err := os.MkdirAll(dest, 0755); err != nil {
+ 				return err
+ 			}
+ 		}
+-		if copyUp {
+-			tmpDir, err = ioutil.TempDir("/tmp", "runctmpdir")
+-			if err != nil {
+-				return newSystemErrorWithCause(err, "tmpcopyup: failed to create tmpdir")
+-			}
+-			defer os.RemoveAll(tmpDir)
+-			m.Destination = tmpDir
++		if m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP {
++			err = doTmpfsCopyUp(m, rootfs, mountLabel)
++		} else {
++			err = mountPropagate(m, rootfs, mountLabel)
+ 		}
+-		if err := mountPropagate(m, rootfs, mountLabel); err != nil {
++		if err != nil {
+ 			return err
+ 		}
+-		if copyUp {
+-			if err := fileutils.CopyDirectory(dest, tmpDir); err != nil {
+-				errMsg := fmt.Errorf("tmpcopyup: failed to copy %s to %s: %v", dest, tmpDir, err)
+-				if err1 := syscall.Unmount(tmpDir, syscall.MNT_DETACH); err1 != nil {
+-					return newSystemErrorWithCausef(err1, "tmpcopyup: %v: failed to unmount", errMsg)
+-				}
+-				return errMsg
+-			}
+-			if err := syscall.Mount(tmpDir, dest, "", syscall.MS_MOVE, ""); err != nil {
+-				errMsg := fmt.Errorf("tmpcopyup: failed to move mount %s to %s: %v", tmpDir, dest, err)
+-				if err1 := syscall.Unmount(tmpDir, syscall.MNT_DETACH); err1 != nil {
+-					return newSystemErrorWithCausef(err1, "tmpcopyup: %v: failed to unmount", errMsg)
+-				}
+-				return errMsg
+-			}
+-		}
+ 		if stat != nil {
+ 			if err = os.Chmod(dest, stat.Mode()); err != nil {
+ 				return err
+@@ -299,19 +315,9 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
+ 			}
+ 		}
+ 	default:
+-		// ensure that the destination of the mount is resolved of symlinks at mount time because
+-		// any previous mounts can invalidate the next mount's destination.
+-		// this can happen when a user specifies mounts within other mounts to cause breakouts or other
+-		// evil stuff to try to escape the container's rootfs.
+-		var err error
+-		if dest, err = securejoin.SecureJoin(rootfs, m.Destination); err != nil {
+-			return err
+-		}
+ 		if err := checkProcMount(rootfs, dest, m.Source); err != nil {
+ 			return err
+ 		}
+-		// update the mount with the correct dest after symlinks are resolved.
+-		m.Destination = dest
+ 		if err := os.MkdirAll(dest, 0755); err != nil {
+ 			return err
+ 		}
+@@ -485,7 +491,7 @@ func createDevices(config *configs.Config) error {
+ 	return nil
+ }
+ 
+-func bindMountDeviceNode(dest string, node *configs.Device) error {
++func bindMountDeviceNode(rootfs, dest string, node *configs.Device) error {
+ 	f, err := os.Create(dest)
+ 	if err != nil && !os.IsExist(err) {
+ 		return err
+@@ -493,24 +499,29 @@ func bindMountDeviceNode(dest string, node *configs.Device) error {
+ 	if f != nil {
+ 		f.Close()
+ 	}
+-	return syscall.Mount(node.Path, dest, "bind", syscall.MS_BIND, "")
++	return libcontainerUtils.WithProcfd(rootfs, dest, func(procfd string) error {
++		return syscall.Mount(node.Path, procfd, "bind", syscall.MS_BIND, "")
++	})
+ }
+ 
+ // Creates the device node in the rootfs of the container.
+ func createDeviceNode(rootfs string, node *configs.Device, bind bool) error {
+-	dest := filepath.Join(rootfs, node.Path)
++	dest, err := securejoin.SecureJoin(rootfs, node.Path)
++	if err != nil {
++		return err
++	}
+ 	if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil {
+ 		return err
+ 	}
+ 
+ 	if bind {
+-		return bindMountDeviceNode(dest, node)
++		return bindMountDeviceNode(rootfs, dest, node)
+ 	}
+ 	if err := mknodDevice(dest, node); err != nil {
+ 		if os.IsExist(err) {
+ 			return nil
+ 		} else if os.IsPermission(err) {
+-			return bindMountDeviceNode(dest, node)
++			return bindMountDeviceNode(rootfs, dest, node)
+ 		}
+ 		return err
+ 	}
+@@ -807,43 +818,44 @@ func writeSystemProperty(key, value string) error {
+ }
+ 
+ func remount(m *configs.Mount, rootfs string) error {
+-	var (
+-		dest = m.Destination
+-	)
+-	if !strings.HasPrefix(dest, rootfs) {
+-		dest = filepath.Join(rootfs, dest)
+-	}
+-	if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil {
+-		return err
+-	}
+-	return nil
++	return libcontainerUtils.WithProcfd(rootfs, m.Destination, func(procfd string) error {
++		return syscall.Mount(m.Source, procfd, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), "")
++	})
+ }
+ 
+ // Do the mount operation followed by additional mounts required to take care
+-// of propagation flags.
++// of propagation flags.  This will always be scoped inside the container rootfs.
+ func mountPropagate(m *configs.Mount, rootfs string, mountLabel string) error {
+ 	var (
+-		dest  = m.Destination
+ 		data  = label.FormatMountLabel(m.Data, mountLabel)
+ 		flags = m.Flags
+ 	)
+-	if libcontainerUtils.CleanPath(dest) == "/dev" {
++	if libcontainerUtils.CleanPath(m.Destination) == "/dev" {
+ 		flags &= ^syscall.MS_RDONLY
+ 	}
+ 
+-	copyUp := m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP
+-	if !(copyUp || strings.HasPrefix(dest, rootfs)) {
+-		dest = filepath.Join(rootfs, dest)
++	// Because the destination is inside a container path which might be
++	// mutating underneath us, we verify that we are actually going to mount
++	// inside the container with WithProcfd() -- mounting through a procfd
++	// mounts on the target.
++	if err := libcontainerUtils.WithProcfd(rootfs, m.Destination, func(procfd string) error {
++		return syscall.Mount(m.Source, procfd, m.Device, uintptr(flags), data)
++	}); err != nil {
++		return fmt.Errorf("mount through procfd: %v", err)
+ 	}
+ 
+-	if err := syscall.Mount(m.Source, dest, m.Device, uintptr(flags), data); err != nil {
+-		return err
+-	}
+-
+-	for _, pflag := range m.PropagationFlags {
+-		if err := syscall.Mount("", dest, "", uintptr(pflag), ""); err != nil {
+-			return err
++	// We have to apply mount propagation flags in a separate WithProcfd() call
++	// because the previous call invalidates the passed procfd -- the mount
++	// target needs to be re-opened.
++	if err := libcontainerUtils.WithProcfd(rootfs, m.Destination, func(procfd string) error {
++		for _, pflag := range m.PropagationFlags {
++			if err := syscall.Mount("", procfd, "", uintptr(pflag), ""); err != nil {
++				return err
++			}
+ 		}
++		return nil
++	}); err != nil {
++		return fmt.Errorf("change mount propagation through procfd: %v", err)
+ 	}
+ 	return nil
+ }
+diff --git a/libcontainer/utils/utils.go b/libcontainer/utils/utils.go
+index 2b35b9a7..a89fc6a2 100644
+--- a/runc-66aedde759f33c190954815fb765eedc1d782dd9/libcontainer/utils/utils.go
++++ b/runc-66aedde759f33c190954815fb765eedc1d782dd9/libcontainer/utils/utils.go
+@@ -4,12 +4,17 @@ import (
+ 	"crypto/rand"
+ 	"encoding/hex"
+ 	"encoding/json"
++	"fmt"
+ 	"io"
+ 	"os"
+ 	"path/filepath"
++	"strconv"
+ 	"strings"
+ 	"syscall"
+ 	"unsafe"
++
++	securejoin "github.com/cyphar/filepath-securejoin"
++	"golang.org/x/sys/unix"
+ )
+ 
+ const (
+@@ -87,6 +92,57 @@ func CleanPath(path string) string {
+ 	return filepath.Clean(path)
+ }
+ 
++// stripRoot returns the passed path, stripping the root path if it was
++// (lexicially) inside it. Note that both passed paths will always be treated
++// as absolute, and the returned path will also always be absolute. In
++// addition, the paths are cleaned before stripping the root.
++func stripRoot(root, path string) string {
++	// Make the paths clean and absolute.
++	root, path = CleanPath("/"+root), CleanPath("/"+path)
++	switch {
++	case path == root:
++		path = "/"
++	case root == "/":
++		// do nothing
++	case strings.HasPrefix(path, root+"/"):
++		path = strings.TrimPrefix(path, root+"/")
++	}
++	return CleanPath("/" + path)
++}
++
++// WithProcfd runs the passed closure with a procfd path (/proc/self/fd/...)
++// corresponding to the unsafePath resolved within the root. Before passing the
++// fd, this path is verified to have been inside the root -- so operating on it
++// through the passed fdpath should be safe. Do not access this path through
++// the original path strings, and do not attempt to use the pathname outside of
++// the passed closure (the file handle will be freed once the closure returns).
++func WithProcfd(root, unsafePath string, fn func(procfd string) error) error {
++	// Remove the root then forcefully resolve inside the root.
++	unsafePath = stripRoot(root, unsafePath)
++	path, err := securejoin.SecureJoin(root, unsafePath)
++	if err != nil {
++		return fmt.Errorf("resolving path inside rootfs failed: %v", err)
++	}
++
++	// Open the target path.
++	fh, err := os.OpenFile(path, unix.O_PATH|unix.O_CLOEXEC, 0)
++	if err != nil {
++		return fmt.Errorf("open o_path procfd: %v", err)
++	}
++	defer fh.Close()
++
++	// Double-check the path is the one we expected.
++	procfd := "/proc/self/fd/" + strconv.Itoa(int(fh.Fd()))
++	if realpath, err := os.Readlink(procfd); err != nil {
++		return fmt.Errorf("procfd verification failed: %v", err)
++	} else if realpath != path {
++		return fmt.Errorf("possibly malicious path detected -- refusing to operate on %s", realpath)
++	}
++
++	// Run the closure.
++	return fn(procfd)
++}
++
+ // SearchLabels searches a list of key-value pairs for the provided key and
+ // returns the corresponding value. The pairs must be separated with '='.
+ func SearchLabels(labels []string, query string) string {
diff --git a/SOURCES/docker.service b/SOURCES/docker.service
index e67f0d2..d6c28fb 100644
--- a/SOURCES/docker.service
+++ b/SOURCES/docker.service
@@ -1,8 +1,9 @@
 [Unit]
 Description=Docker Application Container Engine
 Documentation=http://docs.docker.com
-After=network.target
+After=network.target rhel-push-plugin.service registries.service
 Wants=docker-storage-setup.service
+Requires=rhel-push-plugin.service registries.service
 Requires=docker-cleanup.timer
 
 [Service]
@@ -18,6 +19,7 @@ Environment=PATH=/usr/libexec/docker:/usr/bin:/usr/sbin
 ExecStart=/usr/bin/dockerd-current \
           --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current \
           --default-runtime=docker-runc \
+          --authorization-plugin=rhel-push-plugin \
           --exec-opt native.cgroupdriver=systemd \
           --userland-proxy-path=/usr/libexec/docker/docker-proxy-current \
           --init-path=/usr/libexec/docker/docker-init-current \
diff --git a/SPECS/docker.spec b/SPECS/docker.spec
index 42b5351..3d17c74 100644
--- a/SPECS/docker.spec
+++ b/SPECS/docker.spec
@@ -45,9 +45,9 @@
 %global shortcommit_novolume %(c=%{commit_novolume}; echo ${c:0:7})
 
 # rhel-push-plugin
-#%global git_rhel_push https://github.com/projectatomic/rhel-push-plugin
-#%global commit_rhel_push af9107b2aedb235338e32a3c19507cad3f218b0d
-#%global shortcommit_rhel_push %(c=%{commit_rhel_push}; echo ${c:0:7})
+%global git_rhel_push https://github.com/projectatomic/rhel-push-plugin
+%global commit_rhel_push af9107b2aedb235338e32a3c19507cad3f218b0d
+%global shortcommit_rhel_push %(c=%{commit_rhel_push}; echo ${c:0:7})
 
 # docker-lvm-plugin
 %global git_lvm https://github.com/projectatomic/%{repo}-lvm-plugin
@@ -77,15 +77,15 @@
 Name: %{repo}
 Epoch: 2
 Version: 1.13.1
-Release: 206.git%{shortcommit_docker}%{?dist}
+Release: 208.git%{shortcommit_docker}%{?dist}
 Summary: Automates deployment of containerized applications
 License: ASL 2.0
 URL: https://%{import_path}
-ExclusiveArch: aarch64 %{arm} ppc64le s390x x86_64 %{ix86}
+ExclusiveArch: aarch64 %{arm} ppc64le s390x x86_64
 Source0: %{git_docker}/archive/%{commit_docker}.tar.gz
 Source2: %{git_dss}/archive/%{commit_dss}/container-storage-setup-%{shortcommit_dss}.tar.gz
 Source4: %{git_novolume}/archive/%{commit_novolume}/%{repo}-novolume-plugin-%{shortcommit_novolume}.tar.gz
-#Source5: %{git_rhel_push}/archive/%{commit_rhel_push}/rhel-push-plugin-%{shortcommit_rhel_push}.tar.gz
+Source5: %{git_rhel_push}/archive/%{commit_rhel_push}/rhel-push-plugin-%{shortcommit_rhel_push}.tar.gz
 Source6: %{git_lvm}/archive/%{commit_lvm}/%{repo}-lvm-plugin-%{shortcommit_lvm}.tar.gz
 Source8: %{name}.service
 Source9: %{name}.sysconfig
@@ -127,12 +127,13 @@ Patch7: docker-CVE-2020-8945.patch
 # patch:       https://github.com/projectatomic/runc/pull/33.patch
 Patch8: docker-1879425.patch
 Patch9: docker-1787148.patch
-Patch10: 0001-rootfs-add-mount-destination-validation.patch
+Patch10: https://patch-diff.githubusercontent.com/raw/projectatomic/runc/pull/54.patch
+Patch11: https://patch-diff.githubusercontent.com/raw/kolyshkin/containerd-1/pull/1.patch
 BuildRequires: cmake
 BuildRequires: sed
 BuildRequires: git
 BuildRequires: glibc-static
-%if 0%{?fedora}
+%if 0%{?fedora} || 0%{?centos}
 BuildRequires: %{?go_compiler:compiler(go-compiler)}%{!?go_compiler:golang}
 %else
 BuildRequires: go-toolset-1.10
@@ -206,7 +207,7 @@ Requires: device-mapper-libs >= 7:1.02.97
 Requires: oci-umount >= 2:2.3.3-3
 Requires: oci-register-machine >= 1:0-5.13
 Requires: oci-systemd-hook >= 1:0.1.4-9
-#Requires: %{name}-rhel-push-plugin = %{epoch}:%{version}-%{release}
+Requires: %{name}-rhel-push-plugin = %{epoch}:%{version}-%{release}
 Requires: xz
 Requires: atomic-registries
 Requires: container-selinux >= 2:2.51-1
@@ -258,16 +259,16 @@ local volumes defined. In particular, the plugin will block `docker run` with:
 
 The only thing allowed will be just bind mounts.
 
-#%package rhel-push-plugin
-#License: GPLv2
-#Summary: Avoids pushing a RHEL-based image to docker.io registry
+%package rhel-push-plugin
+License: GPLv2
+Summary: Avoids pushing a RHEL-based image to docker.io registry
 
-#%description rhel-push-plugin
-#In order to use this plugin you must be running at least Docker 1.10 which
-#has support for authorization plugins.
+%description rhel-push-plugin
+In order to use this plugin you must be running at least Docker 1.10 which
+has support for authorization plugins.
 
-#This plugin avoids any RHEL based image to be pushed to the default docker.io
-#registry preventing users to violate the RH subscription agreement.
+This plugin avoids any RHEL based image to be pushed to the default docker.io
+registry preventing users to violate the RH subscription agreement.
 
 %package lvm-plugin
 License: LGPLv3
@@ -292,7 +293,7 @@ tar zxf %{SOURCE2}
 tar zxf %{SOURCE4}
 
 # untar rhel-push-plugin
-#tar zxf %{SOURCE5}
+tar zxf %{SOURCE5}
 
 # untar lvm-plugin
 tar zxf %{SOURCE6}
@@ -346,6 +347,7 @@ cd -
 %patch8 -p1
 %patch9 -p1
 %patch10 -p1
+%patch11 -p1
 
 %build
 # compile docker-proxy first - otherwise deps in gopath conflict with the others below and this fails. Remove libnetwork libs then.
@@ -367,7 +369,7 @@ pushd _build
   mkdir -p src/%{provider}.%{provider_tld}/{%{name},projectatomic}
   ln -s $(dirs +1 -l) src/%{import_path}
   ln -s $(dirs +1 -l)/%{repo}-novolume-plugin-%{commit_novolume} src/%{provider}.%{provider_tld}/projectatomic/%{repo}-novolume-plugin
-#  ln -s $(dirs +1 -l)/rhel-push-plugin-%{commit_rhel_push} src/%{provider}.%{provider_tld}/projectatomic/rhel-push-plugin
+  ln -s $(dirs +1 -l)/rhel-push-plugin-%{commit_rhel_push} src/%{provider}.%{provider_tld}/projectatomic/rhel-push-plugin
   ln -s $(dirs +1 -l)/%{repo}-lvm-plugin-%{commit_lvm} src/%{provider}.%{provider_tld}/projectatomic/%{repo}-lvm-plugin
 popd
 
@@ -376,10 +378,10 @@ pushd $(pwd)/_build/src
 %gobuild %{provider}.%{provider_tld}/projectatomic/%{repo}-novolume-plugin
 popd
 
-#export GOPATH=$(pwd)/rhel-push-plugin-%{commit_rhel_push}/Godeps/_workspace:$(pwd)/_build
-#pushd $(pwd)/_build/src
-#%gobuild %{provider}.%{provider_tld}/projectatomic/rhel-push-plugin
-#popd
+export GOPATH=$(pwd)/rhel-push-plugin-%{commit_rhel_push}/Godeps/_workspace:$(pwd)/_build
+pushd $(pwd)/_build/src
+%gobuild %{provider}.%{provider_tld}/projectatomic/rhel-push-plugin
+popd
 
 export GOPATH=$(pwd)/%{repo}-lvm-plugin-%{commit_lvm}/Godeps/_workspace:$(pwd)/_build
 pushd $(pwd)/_build/src
@@ -402,7 +404,7 @@ export GOPATH=$(pwd)/_build:$(pwd)/vendor
 # build %%{name} manpages
 man/md2man-all.sh
 go-md2man -in %{repo}-novolume-plugin-%{commit_novolume}/man/%{repo}-novolume-plugin.8.md -out %{repo}-novolume-plugin.8
-#go-md2man -in rhel-push-plugin-%{commit_rhel_push}/man/rhel-push-plugin.8.md -out rhel-push-plugin.8
+go-md2man -in rhel-push-plugin-%{commit_rhel_push}/man/rhel-push-plugin.8.md -out rhel-push-plugin.8
 go-md2man -in %{repo}-lvm-plugin-%{commit_lvm}/man/%{repo}-lvm-plugin.8.md -out %{repo}-lvm-plugin.8
 
 # build %%{name} binary
@@ -567,12 +569,12 @@ install -d %{buildroot}%{_mandir}/man8
 install -p -m 644 %{repo}-novolume-plugin.8 %{buildroot}%{_mandir}/man8
 
 # install rhel-push-plugin executable, unitfile, socket and man
-#install -d %{buildroot}%{_libexecdir}/%{repo}
-#install -p -m 755 _build/src/rhel-push-plugin %{buildroot}%{_libexecdir}/%{repo}/rhel-push-plugin
-#install -p -m 644 rhel-push-plugin-%{commit_rhel_push}/systemd/rhel-push-plugin.service %{buildroot}%{_unitdir}/rhel-push-plugin.service
-#install -p -m 644 rhel-push-plugin-%{commit_rhel_push}/systemd/rhel-push-plugin.socket %{buildroot}%{_unitdir}/rhel-push-plugin.socket
-#install -d %{buildroot}%{_mandir}/man8
-#install -p -m 644 rhel-push-plugin.8 %{buildroot}%{_mandir}/man8
+install -d %{buildroot}%{_libexecdir}/%{repo}
+install -p -m 755 _build/src/rhel-push-plugin %{buildroot}%{_libexecdir}/%{repo}/rhel-push-plugin
+install -p -m 644 rhel-push-plugin-%{commit_rhel_push}/systemd/rhel-push-plugin.service %{buildroot}%{_unitdir}/rhel-push-plugin.service
+install -p -m 644 rhel-push-plugin-%{commit_rhel_push}/systemd/rhel-push-plugin.socket %{buildroot}%{_unitdir}/rhel-push-plugin.socket
+install -d %{buildroot}%{_mandir}/man8
+install -p -m 644 rhel-push-plugin.8 %{buildroot}%{_mandir}/man8
 
 # install %%{repo}-lvm-plugin executable, unitfile, socket and man
 install -d %{buildroot}/%{_libexecdir}/%{repo}
@@ -652,14 +654,14 @@ exit 0
 %postun novolume-plugin
 %systemd_postun_with_restart %{name}-novolume-plugin.service
 
-#%post rhel-push-plugin
-#%systemd_post rhel-push-plugin.service
+%post rhel-push-plugin
+%systemd_post rhel-push-plugin.service
 
-#%preun rhel-push-plugin
-#%systemd_preun rhel-push-plugin.service
+%preun rhel-push-plugin
+%systemd_preun rhel-push-plugin.service
 
-#%postun rhel-push-plugin
-#%systemd_postun_with_restart rhel-push-plugin.service
+%postun rhel-push-plugin
+%systemd_postun_with_restart rhel-push-plugin.service
 
 %posttrans
 # Install a default docker-storage-setup based on kernel version.
@@ -755,12 +757,12 @@ fi
 %{_libexecdir}/%{repo}/%{repo}-novolume-plugin
 %{_unitdir}/%{repo}-novolume-plugin.*
 
-#%files rhel-push-plugin
-#%license rhel-push-plugin-%{commit_rhel_push}/LICENSE
-#%doc rhel-push-plugin-%{commit_rhel_push}/README.md
-#%{_mandir}/man8/rhel-push-plugin.8.gz
-#%{_libexecdir}/%{repo}/rhel-push-plugin
-#%{_unitdir}/rhel-push-plugin.*
+%files rhel-push-plugin
+%license rhel-push-plugin-%{commit_rhel_push}/LICENSE
+%doc rhel-push-plugin-%{commit_rhel_push}/README.md
+%{_mandir}/man8/rhel-push-plugin.8.gz
+%{_libexecdir}/%{repo}/rhel-push-plugin
+%{_unitdir}/rhel-push-plugin.*
 
 %files lvm-plugin
 %license %{repo}-lvm-plugin-%{commit_lvm}/LICENSE
@@ -776,6 +778,14 @@ fi
 %{_bindir}/%{name}-v1.10-migrator-*
 
 %changelog
+* Fri Jun 04 2021 Jindrich Novy <jnovy@redhat.com> - 2:1.13.1-208.git7d71120
+- propagate mounts to the host - fix regression introduced by fix of CVE-2021-30465
+- Resolves: #1966968
+
+* Wed May 26 2021 Jindrich Novy <jnovy@redhat.com> - 2:1.13.1-207.git7d71120
+- apply memory leak fix from Kir Kolyshkin
+- Resolves: #1951896
+
 * Tue May 18 2021 Jindrich Novy <jnovy@redhat.com> - 2:1.13.1-206.git7d71120
 - fix CVE-2021-30465
 - Related: #1959475