diff --git a/.gitignore b/.gitignore
index 7668d0d..d7c4a2d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/v1.0.0-rc93.tar.gz
+SOURCES/v1.0.0-rc95.tar.gz
diff --git a/.runc.metadata b/.runc.metadata
index 0a7c604..3f0f3fc 100644
--- a/.runc.metadata
+++ b/.runc.metadata
@@ -1 +1 @@
-e8693109441696536710e5751e0fee6e6fa32590 SOURCES/v1.0.0-rc93.tar.gz
+23f05a9f1ae2907117385a48f1a464608fd75d30 SOURCES/v1.0.0-rc95.tar.gz
diff --git a/SOURCES/rc93-0001-libct-newInitConfig-nit.patch b/SOURCES/rc93-0001-libct-newInitConfig-nit.patch
deleted file mode 100644
index 2040586..0000000
--- a/SOURCES/rc93-0001-libct-newInitConfig-nit.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 28daf0653d324fad545a7031e64b6891f399969b Mon Sep 17 00:00:00 2001
-From: Kir Kolyshkin <kolyshkin@gmail.com>
-Date: Tue, 23 Feb 2021 17:58:07 -0800
-Subject: [PATCH 1/5] libct/newInitConfig: nit
-
-Move the initialization of Console* fields as they are unconditional.
-
-Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
----
- libcontainer/container_linux.go | 7 ++++---
- 1 file changed, 4 insertions(+), 3 deletions(-)
-
-diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go
-index 3dca29e4c3f2..b6100aae9d5a 100644
---- a/libcontainer/container_linux.go
-+++ b/libcontainer/container_linux.go
-@@ -594,6 +594,9 @@ func (c *linuxContainer) newInitConfig(process *Process) *initConfig {
- 		AppArmorProfile:  c.config.AppArmorProfile,
- 		ProcessLabel:     c.config.ProcessLabel,
- 		Rlimits:          c.config.Rlimits,
-+		CreateConsole:    process.ConsoleSocket != nil,
-+		ConsoleWidth:     process.ConsoleWidth,
-+		ConsoleHeight:    process.ConsoleHeight,
- 	}
- 	if process.NoNewPrivileges != nil {
- 		cfg.NoNewPrivileges = *process.NoNewPrivileges
-@@ -607,9 +610,7 @@ func (c *linuxContainer) newInitConfig(process *Process) *initConfig {
- 	if len(process.Rlimits) > 0 {
- 		cfg.Rlimits = process.Rlimits
- 	}
--	cfg.CreateConsole = process.ConsoleSocket != nil
--	cfg.ConsoleWidth = process.ConsoleWidth
--	cfg.ConsoleHeight = process.ConsoleHeight
-+
- 	return cfg
- }
- 
--- 
-2.31.1
-
diff --git a/SOURCES/rc93-0002-libct-rootfs-introduce-and-use-mountConfig.patch b/SOURCES/rc93-0002-libct-rootfs-introduce-and-use-mountConfig.patch
deleted file mode 100644
index 3df9b15..0000000
--- a/SOURCES/rc93-0002-libct-rootfs-introduce-and-use-mountConfig.patch
+++ /dev/null
@@ -1,139 +0,0 @@
-From 46ec7b5a94d370c4963ca361e9d96cb78d75d118 Mon Sep 17 00:00:00 2001
-From: Kir Kolyshkin <kolyshkin@gmail.com>
-Date: Tue, 23 Feb 2021 18:14:37 -0800
-Subject: [PATCH 2/5] libct/rootfs: introduce and use mountConfig
-
-The code is already passing three parameters around from
-mountToRootfs to mountCgroupV* to mountToRootfs again.
-
-I am about to add another parameter, so let's introduce and
-use struct mountConfig to pass around.
-
-Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
----
- libcontainer/rootfs_linux.go | 42 ++++++++++++++++++++++--------------
- 1 file changed, 26 insertions(+), 16 deletions(-)
-
-diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go
-index 411496ab7c6d..a384abb7e8a5 100644
---- a/libcontainer/rootfs_linux.go
-+++ b/libcontainer/rootfs_linux.go
-@@ -29,6 +29,12 @@ import (
- 
- const defaultMountFlags = unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV
- 
-+type mountConfig struct {
-+	root     string
-+	label    string
-+	cgroupns bool
-+}
-+
- // needsSetupDev returns true if /dev needs to be set up.
- func needsSetupDev(config *configs.Config) bool {
- 	for _, m := range config.Mounts {
-@@ -48,7 +54,11 @@ func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig) (err error) {
- 		return newSystemErrorWithCause(err, "preparing rootfs")
- 	}
- 
--	hasCgroupns := config.Namespaces.Contains(configs.NEWCGROUP)
-+	mountConfig := &mountConfig{
-+		root:     config.Rootfs,
-+		label:    config.MountLabel,
-+		cgroupns: config.Namespaces.Contains(configs.NEWCGROUP),
-+	}
- 	setupDev := needsSetupDev(config)
- 	for _, m := range config.Mounts {
- 		for _, precmd := range m.PremountCmds {
-@@ -56,7 +66,7 @@ func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig) (err error) {
- 				return newSystemErrorWithCause(err, "running premount command")
- 			}
- 		}
--		if err := mountToRootfs(m, config.Rootfs, config.MountLabel, hasCgroupns); err != nil {
-+		if err := mountToRootfs(m, mountConfig); err != nil {
- 			return newSystemErrorWithCausef(err, "mounting %q to rootfs at %q", m.Source, m.Destination)
- 		}
- 
-@@ -222,7 +232,7 @@ func prepareBindMount(m *configs.Mount, rootfs string) error {
- 	return nil
- }
- 
--func mountCgroupV1(m *configs.Mount, rootfs, mountLabel string, enableCgroupns bool) error {
-+func mountCgroupV1(m *configs.Mount, c *mountConfig) error {
- 	binds, err := getCgroupMounts(m)
- 	if err != nil {
- 		return err
-@@ -242,12 +252,12 @@ func mountCgroupV1(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
- 		Data:             "mode=755",
- 		PropagationFlags: m.PropagationFlags,
- 	}
--	if err := mountToRootfs(tmpfs, rootfs, mountLabel, enableCgroupns); err != nil {
-+	if err := mountToRootfs(tmpfs, c); err != nil {
- 		return err
- 	}
- 	for _, b := range binds {
--		if enableCgroupns {
--			subsystemPath := filepath.Join(rootfs, b.Destination)
-+		if c.cgroupns {
-+			subsystemPath := filepath.Join(c.root, b.Destination)
- 			if err := os.MkdirAll(subsystemPath, 0755); err != nil {
- 				return err
- 			}
-@@ -266,7 +276,7 @@ func mountCgroupV1(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
- 				return err
- 			}
- 		} else {
--			if err := mountToRootfs(b, rootfs, mountLabel, enableCgroupns); err != nil {
-+			if err := mountToRootfs(b, c); err != nil {
- 				return err
- 			}
- 		}
-@@ -276,7 +286,7 @@ func mountCgroupV1(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
- 			// symlink(2) is very dumb, it will just shove the path into
- 			// the link and doesn't do any checks or relative path
- 			// conversion. Also, don't error out if the cgroup already exists.
--			if err := os.Symlink(mc, filepath.Join(rootfs, m.Destination, ss)); err != nil && !os.IsExist(err) {
-+			if err := os.Symlink(mc, filepath.Join(c.root, m.Destination, ss)); err != nil && !os.IsExist(err) {
- 				return err
- 			}
- 		}
-@@ -284,8 +294,8 @@ func mountCgroupV1(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
- 	return nil
- }
- 
--func mountCgroupV2(m *configs.Mount, rootfs, mountLabel string, enableCgroupns bool) error {
--	cgroupPath, err := securejoin.SecureJoin(rootfs, m.Destination)
-+func mountCgroupV2(m *configs.Mount, c *mountConfig) error {
-+	cgroupPath, err := securejoin.SecureJoin(c.root, m.Destination)
- 	if err != nil {
- 		return err
- 	}
-@@ -302,10 +312,10 @@ func mountCgroupV2(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
- 	return nil
- }
- 
--func mountToRootfs(m *configs.Mount, rootfs, mountLabel string, enableCgroupns bool) error {
--	var (
--		dest = m.Destination
--	)
-+func mountToRootfs(m *configs.Mount, c *mountConfig) error {
-+	rootfs := c.root
-+	mountLabel := c.label
-+	dest := m.Destination
- 	if !strings.HasPrefix(dest, rootfs) {
- 		dest = filepath.Join(rootfs, dest)
- 	}
-@@ -424,9 +434,9 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
- 		}
- 	case "cgroup":
- 		if cgroups.IsCgroup2UnifiedMode() {
--			return mountCgroupV2(m, rootfs, mountLabel, enableCgroupns)
-+			return mountCgroupV2(m, c)
- 		}
--		return mountCgroupV1(m, rootfs, mountLabel, enableCgroupns)
-+		return mountCgroupV1(m, c)
- 	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.
--- 
-2.31.1
-
diff --git a/SOURCES/rc93-0003-libct-rootfs-mountCgroupV2-minor-refactor.patch b/SOURCES/rc93-0003-libct-rootfs-mountCgroupV2-minor-refactor.patch
deleted file mode 100644
index 2ded660..0000000
--- a/SOURCES/rc93-0003-libct-rootfs-mountCgroupV2-minor-refactor.patch
+++ /dev/null
@@ -1,52 +0,0 @@
-From 198a2806b0b5522cff1c53bf4671cfee85e45608 Mon Sep 17 00:00:00 2001
-From: Kir Kolyshkin <kolyshkin@gmail.com>
-Date: Tue, 23 Feb 2021 18:25:56 -0800
-Subject: [PATCH 3/5] libct/rootfs/mountCgroupV2: minor refactor
-
-1. s/cgroupPath/dest/
-
-2. don't hardcode /sys/fs/cgroup
-
-Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
----
- libcontainer/rootfs_linux.go | 10 ++++++----
- 1 file changed, 6 insertions(+), 4 deletions(-)
-
-diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go
-index a384abb7e8a5..0f0495b93b3e 100644
---- a/libcontainer/rootfs_linux.go
-+++ b/libcontainer/rootfs_linux.go
-@@ -17,6 +17,7 @@ import (
- 	"github.com/moby/sys/mountinfo"
- 	"github.com/mrunalp/fileutils"
- 	"github.com/opencontainers/runc/libcontainer/cgroups"
-+	"github.com/opencontainers/runc/libcontainer/cgroups/fs2"
- 	"github.com/opencontainers/runc/libcontainer/configs"
- 	"github.com/opencontainers/runc/libcontainer/devices"
- 	"github.com/opencontainers/runc/libcontainer/system"
-@@ -295,17 +296,18 @@ func mountCgroupV1(m *configs.Mount, c *mountConfig) error {
- }
- 
- func mountCgroupV2(m *configs.Mount, c *mountConfig) error {
--	cgroupPath, err := securejoin.SecureJoin(c.root, m.Destination)
-+	dest, err := securejoin.SecureJoin(c.root, m.Destination)
- 	if err != nil {
- 		return err
- 	}
--	if err := os.MkdirAll(cgroupPath, 0755); err != nil {
-+	if err := os.MkdirAll(dest, 0755); err != nil {
- 		return err
- 	}
--	if err := unix.Mount(m.Source, cgroupPath, "cgroup2", uintptr(m.Flags), m.Data); err != nil {
-+	if err := unix.Mount(m.Source, dest, "cgroup2", uintptr(m.Flags), m.Data); err != nil {
- 		// when we are in UserNS but CgroupNS is not unshared, we cannot mount cgroup2 (#2158)
- 		if err == unix.EPERM || err == unix.EBUSY {
--			return unix.Mount("/sys/fs/cgroup", cgroupPath, "", uintptr(m.Flags)|unix.MS_BIND, "")
-+			src := fs2.UnifiedMountpoint
-+			return unix.Mount(src, dest, "", uintptr(m.Flags)|unix.MS_BIND, "")
- 		}
- 		return err
- 	}
--- 
-2.31.1
-
diff --git a/SOURCES/rc93-0004-Fix-cgroup2-mount-for-rootless-case.patch b/SOURCES/rc93-0004-Fix-cgroup2-mount-for-rootless-case.patch
deleted file mode 100644
index 971ded9..0000000
--- a/SOURCES/rc93-0004-Fix-cgroup2-mount-for-rootless-case.patch
+++ /dev/null
@@ -1,180 +0,0 @@
-From ce352accdfb07a91b5527e70ec8bce658a8b68de Mon Sep 17 00:00:00 2001
-From: Kir Kolyshkin <kolyshkin@gmail.com>
-Date: Tue, 23 Feb 2021 18:27:42 -0800
-Subject: [PATCH 4/5] Fix cgroup2 mount for rootless case
-
-In case of rootless, cgroup2 mount is not possible (see [1] for more
-details), so since commit 9c81440fb5a7 runc bind-mounts the whole
-/sys/fs/cgroup into container.
-
-Problem is, if cgroupns is enabled, /sys/fs/cgroup inside the container
-is supposed to show the cgroup files for this cgroup, not the root one.
-
-The fix is to pass through and use the cgroup path in case cgroup2
-mount failed, cgroupns is enabled, and the path is non-empty.
-
-Surely this requires the /sys/fs/cgroup mount in the spec, so modify
-runc spec --rootless to keep it.
-
-Before:
-
-	$ ./runc run aaa
-	# find /sys/fs/cgroup/ -type d
-	/sys/fs/cgroup
-	/sys/fs/cgroup/user.slice
-	/sys/fs/cgroup/user.slice/user-1000.slice
-	/sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service
-	...
-	# ls -l /sys/fs/cgroup/cgroup.controllers
-	-r--r--r--    1 nobody   nogroup          0 Feb 24 02:22 /sys/fs/cgroup/cgroup.controllers
-	# wc -w /sys/fs/cgroup/cgroup.procs
-	142 /sys/fs/cgroup/cgroup.procs
-	# cat /sys/fs/cgroup/memory.current
-	cat: can't open '/sys/fs/cgroup/memory.current': No such file or directory
-
-After:
-
-	# find /sys/fs/cgroup/ -type d
-	/sys/fs/cgroup/
-	# ls -l /sys/fs/cgroup/cgroup.controllers
-	-r--r--r--    1 root     root             0 Feb 24 02:43 /sys/fs/cgroup/cgroup.controllers
-	# wc -w /sys/fs/cgroup/cgroup.procs
-	2 /sys/fs/cgroup/cgroup.procs
-	# cat /sys/fs/cgroup/memory.current
-	577536
-
-[1] https://github.com/opencontainers/runc/issues/2158
-
-Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
----
- libcontainer/container_linux.go  |  3 +++
- libcontainer/init_linux.go       |  1 +
- libcontainer/rootfs_linux.go     | 28 +++++++++++++++++++++-------
- libcontainer/specconv/example.go | 18 +++++++++---------
- 4 files changed, 34 insertions(+), 16 deletions(-)
-
-diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go
-index b6100aae9d5a..1cbc734172d0 100644
---- a/libcontainer/container_linux.go
-+++ b/libcontainer/container_linux.go
-@@ -610,6 +610,9 @@ func (c *linuxContainer) newInitConfig(process *Process) *initConfig {
- 	if len(process.Rlimits) > 0 {
- 		cfg.Rlimits = process.Rlimits
- 	}
-+	if cgroups.IsCgroup2UnifiedMode() {
-+		cfg.Cgroup2Path = c.cgroupManager.Path("")
-+	}
- 
- 	return cfg
- }
-diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go
-index c57af0eebb8b..681797099f46 100644
---- a/libcontainer/init_linux.go
-+++ b/libcontainer/init_linux.go
-@@ -70,6 +70,7 @@ type initConfig struct {
- 	RootlessEUID     bool                  `json:"rootless_euid,omitempty"`
- 	RootlessCgroups  bool                  `json:"rootless_cgroups,omitempty"`
- 	SpecState        *specs.State          `json:"spec_state,omitempty"`
-+	Cgroup2Path      string                `json:"cgroup2_path,omitempty"`
- }
- 
- type initer interface {
-diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go
-index 0f0495b93b3e..5d2d74cf924b 100644
---- a/libcontainer/rootfs_linux.go
-+++ b/libcontainer/rootfs_linux.go
-@@ -31,9 +31,11 @@ import (
- const defaultMountFlags = unix.MS_NOEXEC | unix.MS_NOSUID | unix.MS_NODEV
- 
- type mountConfig struct {
--	root     string
--	label    string
--	cgroupns bool
-+	root            string
-+	label           string
-+	cgroup2Path     string
-+	rootlessCgroups bool
-+	cgroupns        bool
- }
- 
- // needsSetupDev returns true if /dev needs to be set up.
-@@ -56,9 +58,11 @@ func prepareRootfs(pipe io.ReadWriter, iConfig *initConfig) (err error) {
- 	}
- 
- 	mountConfig := &mountConfig{
--		root:     config.Rootfs,
--		label:    config.MountLabel,
--		cgroupns: config.Namespaces.Contains(configs.NEWCGROUP),
-+		root:            config.Rootfs,
-+		label:           config.MountLabel,
-+		cgroup2Path:     iConfig.Cgroup2Path,
-+		rootlessCgroups: iConfig.RootlessCgroups,
-+		cgroupns:        config.Namespaces.Contains(configs.NEWCGROUP),
- 	}
- 	setupDev := needsSetupDev(config)
- 	for _, m := range config.Mounts {
-@@ -307,7 +311,17 @@ func mountCgroupV2(m *configs.Mount, c *mountConfig) error {
- 		// when we are in UserNS but CgroupNS is not unshared, we cannot mount cgroup2 (#2158)
- 		if err == unix.EPERM || err == unix.EBUSY {
- 			src := fs2.UnifiedMountpoint
--			return unix.Mount(src, dest, "", uintptr(m.Flags)|unix.MS_BIND, "")
-+			if c.cgroupns && c.cgroup2Path != "" {
-+				// Emulate cgroupns by bind-mounting
-+				// the container cgroup path rather than
-+				// the whole /sys/fs/cgroup.
-+				src = c.cgroup2Path
-+			}
-+			err = unix.Mount(src, dest, "", uintptr(m.Flags)|unix.MS_BIND, "")
-+			if err == unix.ENOENT && c.rootlessCgroups {
-+				err = nil
-+			}
-+			return err
- 		}
- 		return err
- 	}
-diff --git a/libcontainer/specconv/example.go b/libcontainer/specconv/example.go
-index 8a201bc78dd9..56bab3bfbfa5 100644
---- a/libcontainer/specconv/example.go
-+++ b/libcontainer/specconv/example.go
-@@ -2,6 +2,7 @@ package specconv
- 
- import (
- 	"os"
-+	"path/filepath"
- 	"strings"
- 
- 	"github.com/opencontainers/runc/libcontainer/cgroups"
-@@ -200,8 +201,14 @@ func ToRootless(spec *specs.Spec) {
- 	// Fix up mounts.
- 	var mounts []specs.Mount
- 	for _, mount := range spec.Mounts {
--		// Ignore all mounts that are under /sys.
--		if strings.HasPrefix(mount.Destination, "/sys") {
-+		// Replace the /sys mount with an rbind.
-+		if filepath.Clean(mount.Destination) == "/sys" {
-+			mounts = append(mounts, specs.Mount{
-+				Source:      "/sys",
-+				Destination: "/sys",
-+				Type:        "none",
-+				Options:     []string{"rbind", "nosuid", "noexec", "nodev", "ro"},
-+			})
- 			continue
- 		}
- 
-@@ -216,13 +223,6 @@ func ToRootless(spec *specs.Spec) {
- 		mount.Options = options
- 		mounts = append(mounts, mount)
- 	}
--	// Add the sysfs mount as an rbind.
--	mounts = append(mounts, specs.Mount{
--		Source:      "/sys",
--		Destination: "/sys",
--		Type:        "none",
--		Options:     []string{"rbind", "nosuid", "noexec", "nodev", "ro"},
--	})
- 	spec.Mounts = mounts
- 
- 	// Remove cgroup settings.
--- 
-2.31.1
-
diff --git a/SOURCES/rc93-0005-rootfs-add-mount-destination-validation.patch b/SOURCES/rc93-0005-rootfs-add-mount-destination-validation.patch
deleted file mode 100644
index 6236232..0000000
--- a/SOURCES/rc93-0005-rootfs-add-mount-destination-validation.patch
+++ /dev/null
@@ -1,562 +0,0 @@
-From 14faf1c20948688a48edb9b41367ab07ac11ca91 Mon Sep 17 00:00:00 2001
-From: Aleksa Sarai <cyphar@cyphar.com>
-Date: Thu, 1 Apr 2021 12:00:31 -0700
-Subject: [PATCH 5/5] rootfs: add mount destination validation
-
-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: Kir Kolyshkin <kolyshkin@gmail.com> (@kolyshkin)
-Reviewed-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
-Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
----
- libcontainer/container_linux.go  |   1 -
- libcontainer/rootfs_linux.go     | 251 +++++++++++++++----------------
- libcontainer/utils/utils.go      |  54 +++++++
- libcontainer/utils/utils_test.go |  35 +++++
- 4 files changed, 213 insertions(+), 128 deletions(-)
-
-diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go
-index 1cbc734172d0..70b388b1252e 100644
---- a/libcontainer/container_linux.go
-+++ b/libcontainer/container_linux.go
-@@ -1202,7 +1202,6 @@ func (c *linuxContainer) makeCriuRestoreMountpoints(m *configs.Mount) error {
- 		if err := checkProcMount(c.config.Rootfs, dest, ""); err != nil {
- 			return err
- 		}
--		m.Destination = dest
- 		if err := os.MkdirAll(dest, 0755); err != nil {
- 			return err
- 		}
-diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go
-index 5d2d74cf924b..96be669c365e 100644
---- a/libcontainer/rootfs_linux.go
-+++ b/libcontainer/rootfs_linux.go
-@@ -25,6 +25,7 @@ import (
- 	libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils"
- 	"github.com/opencontainers/runtime-spec/specs-go"
- 	"github.com/opencontainers/selinux/go-selinux/label"
-+	"github.com/sirupsen/logrus"
- 	"golang.org/x/sys/unix"
- )
- 
-@@ -228,8 +229,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
- 	}
-@@ -266,18 +265,21 @@ func mountCgroupV1(m *configs.Mount, c *mountConfig) error {
- 			if err := os.MkdirAll(subsystemPath, 0755); err != nil {
- 				return err
- 			}
--			flags := defaultMountFlags
--			if m.Flags&unix.MS_RDONLY != 0 {
--				flags = flags | unix.MS_RDONLY
--			}
--			cgroupmount := &configs.Mount{
--				Source:      "cgroup",
--				Device:      "cgroup", // this is actually fstype
--				Destination: subsystemPath,
--				Flags:       flags,
--				Data:        filepath.Base(subsystemPath),
--			}
--			if err := mountNewCgroup(cgroupmount); err != nil {
-+			if err := utils.WithProcfd(c.root, b.Destination, func(procfd string) error {
-+				flags := defaultMountFlags
-+				if m.Flags&unix.MS_RDONLY != 0 {
-+					flags = flags | unix.MS_RDONLY
-+				}
-+				var (
-+					source = "cgroup"
-+					data   = filepath.Base(subsystemPath)
-+				)
-+				if data == "systemd" {
-+					data = cgroups.CgroupNamePrefix + data
-+					source = "systemd"
-+				}
-+				return unix.Mount(source, procfd, "cgroup", uintptr(flags), data)
-+			}); err != nil {
- 				return err
- 			}
- 		} else {
-@@ -307,33 +309,79 @@ func mountCgroupV2(m *configs.Mount, c *mountConfig) error {
- 	if err := os.MkdirAll(dest, 0755); err != nil {
- 		return err
- 	}
--	if err := unix.Mount(m.Source, dest, "cgroup2", uintptr(m.Flags), m.Data); err != nil {
--		// when we are in UserNS but CgroupNS is not unshared, we cannot mount cgroup2 (#2158)
--		if err == unix.EPERM || err == unix.EBUSY {
--			src := fs2.UnifiedMountpoint
--			if c.cgroupns && c.cgroup2Path != "" {
--				// Emulate cgroupns by bind-mounting
--				// the container cgroup path rather than
--				// the whole /sys/fs/cgroup.
--				src = c.cgroup2Path
--			}
--			err = unix.Mount(src, dest, "", uintptr(m.Flags)|unix.MS_BIND, "")
--			if err == unix.ENOENT && c.rootlessCgroups {
--				err = nil
-+	return utils.WithProcfd(c.root, m.Destination, func(procfd string) error {
-+		if err := unix.Mount(m.Source, procfd, "cgroup2", uintptr(m.Flags), m.Data); err != nil {
-+			// when we are in UserNS but CgroupNS is not unshared, we cannot mount cgroup2 (#2158)
-+			if err == unix.EPERM || err == unix.EBUSY {
-+				src := fs2.UnifiedMountpoint
-+				if c.cgroupns && c.cgroup2Path != "" {
-+					// Emulate cgroupns by bind-mounting
-+					// the container cgroup path rather than
-+					// the whole /sys/fs/cgroup.
-+					src = c.cgroup2Path
-+				}
-+				err = unix.Mount(src, procfd, "", uintptr(m.Flags)|unix.MS_BIND, "")
-+				if err == unix.ENOENT && c.rootlessCgroups {
-+					err = nil
-+				}
- 			}
- 			return err
- 		}
-+		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 := prepareTmp("/tmp")
-+	if err != nil {
-+		return newSystemErrorWithCause(err, "tmpcopyup: failed to setup tmpdir")
-+	}
-+	defer cleanupTmp(tmpdir)
-+	tmpDir, err := ioutil.TempDir(tmpdir, "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
- 	}
--	return nil
-+	defer func() {
-+		if Err != nil {
-+			if err := unix.Unmount(tmpDir, unix.MNT_DETACH); err != nil {
-+				logrus.Warnf("tmpcopyup: failed to unmount tmpdir on error: %v", err)
-+			}
-+		}
-+	}()
-+
-+	return utils.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): %w", m.Destination, procfd, tmpDir, err)
-+		}
-+		// Now move the mount into the container.
-+		if err := unix.Mount(tmpDir, procfd, "", unix.MS_MOVE, ""); err != nil {
-+			return fmt.Errorf("tmpcopyup: failed to move mount %s to %s (%s): %w", tmpDir, procfd, m.Destination, err)
-+		}
-+		return nil
-+	})
- }
- 
- func mountToRootfs(m *configs.Mount, c *mountConfig) error {
- 	rootfs := c.root
- 	mountLabel := c.label
--	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 {
-@@ -364,53 +412,21 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error {
- 		}
- 		return label.SetFileLabel(dest, mountLabel)
- 	case "tmpfs":
--		copyUp := m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP
--		tmpDir := ""
--		// dest might be an absolute symlink, so it needs
--		// to be resolved under rootfs.
--		dest, err := securejoin.SecureJoin(rootfs, m.Destination)
--		if err != nil {
--			return err
--		}
--		m.Destination = dest
- 		stat, err := os.Stat(dest)
- 		if err != nil {
- 			if err := os.MkdirAll(dest, 0755); err != nil {
- 				return err
- 			}
- 		}
--		if copyUp {
--			tmpdir, err := prepareTmp("/tmp")
--			if err != nil {
--				return newSystemErrorWithCause(err, "tmpcopyup: failed to setup tmpdir")
--			}
--			defer cleanupTmp(tmpdir)
--			tmpDir, err = ioutil.TempDir(tmpdir, "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 := unix.Unmount(tmpDir, unix.MNT_DETACH); err1 != nil {
--					return newSystemErrorWithCausef(err1, "tmpcopyup: %v: failed to unmount", errMsg)
--				}
--				return errMsg
--			}
--			if err := unix.Mount(tmpDir, dest, "", unix.MS_MOVE, ""); err != nil {
--				errMsg := fmt.Errorf("tmpcopyup: failed to move mount %s to %s: %v", tmpDir, dest, err)
--				if err1 := unix.Unmount(tmpDir, unix.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
-@@ -454,19 +470,9 @@ func mountToRootfs(m *configs.Mount, c *mountConfig) error {
- 		}
- 		return mountCgroupV1(m, c)
- 	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
- 		}
-@@ -649,7 +655,7 @@ func createDevices(config *configs.Config) error {
- 	return nil
- }
- 
--func bindMountDeviceNode(dest string, node *devices.Device) error {
-+func bindMountDeviceNode(rootfs, dest string, node *devices.Device) error {
- 	f, err := os.Create(dest)
- 	if err != nil && !os.IsExist(err) {
- 		return err
-@@ -657,7 +663,9 @@ func bindMountDeviceNode(dest string, node *devices.Device) error {
- 	if f != nil {
- 		f.Close()
- 	}
--	return unix.Mount(node.Path, dest, "bind", unix.MS_BIND, "")
-+	return utils.WithProcfd(rootfs, dest, func(procfd string) error {
-+		return unix.Mount(node.Path, procfd, "bind", unix.MS_BIND, "")
-+	})
- }
- 
- // Creates the device node in the rootfs of the container.
-@@ -666,18 +674,21 @@ func createDeviceNode(rootfs string, node *devices.Device, bind bool) error {
- 		// The node only exists for cgroup reasons, ignore it here.
- 		return nil
- 	}
--	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
- 	}
-@@ -1013,61 +1024,47 @@ 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)
--	}
--	return unix.Mount(m.Source, dest, m.Device, uintptr(m.Flags|unix.MS_REMOUNT), "")
-+	return utils.WithProcfd(rootfs, m.Destination, func(procfd string) error {
-+		return unix.Mount(m.Source, procfd, m.Device, uintptr(m.Flags|unix.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" {
--		flags &= ^unix.MS_RDONLY
--	}
--
--	// Mount it rw to allow chmod operation. A remount will be performed
--	// later to make it ro if set.
--	if m.Device == "tmpfs" {
-+	// Delay mounting the filesystem read-only if we need to do further
-+	// operations on it. We need to set up files in "/dev" and tmpfs mounts may
-+	// need to be chmod-ed after mounting. The mount will be remounted ro later
-+	// in finalizeRootfs() if necessary.
-+	if libcontainerUtils.CleanPath(m.Destination) == "/dev" || m.Device == "tmpfs" {
- 		flags &= ^unix.MS_RDONLY
- 	}
- 
--	copyUp := m.Extensions&configs.EXT_COPYUP == configs.EXT_COPYUP
--	if !(copyUp || strings.HasPrefix(dest, rootfs)) {
--		dest = filepath.Join(rootfs, dest)
--	}
--
--	if err := unix.Mount(m.Source, dest, m.Device, uintptr(flags), data); err != nil {
--		return err
--	}
--
--	for _, pflag := range m.PropagationFlags {
--		if err := unix.Mount("", dest, "", uintptr(pflag), ""); err != nil {
--			return err
-+	// 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 := utils.WithProcfd(rootfs, m.Destination, func(procfd string) error {
-+		return unix.Mount(m.Source, procfd, m.Device, uintptr(flags), data)
-+	}); err != nil {
-+		return fmt.Errorf("mount through procfd: %w", 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 := utils.WithProcfd(rootfs, m.Destination, func(procfd string) error {
-+		for _, pflag := range m.PropagationFlags {
-+			if err := unix.Mount("", procfd, "", uintptr(pflag), ""); err != nil {
-+				return err
-+			}
- 		}
--	}
--	return nil
--}
--
--func mountNewCgroup(m *configs.Mount) error {
--	var (
--		data   = m.Data
--		source = m.Source
--	)
--	if data == "systemd" {
--		data = cgroups.CgroupNamePrefix + data
--		source = "systemd"
--	}
--	if err := unix.Mount(source, m.Destination, m.Device, uintptr(m.Flags), data); err != nil {
--		return err
-+		return nil
-+	}); err != nil {
-+		return fmt.Errorf("change mount propagation through procfd: %w", err)
- 	}
- 	return nil
- }
-diff --git a/libcontainer/utils/utils.go b/libcontainer/utils/utils.go
-index 1b72b7a1c1ba..cd78f23e1bd0 100644
---- a/libcontainer/utils/utils.go
-+++ b/libcontainer/utils/utils.go
-@@ -3,12 +3,15 @@ package utils
- import (
- 	"encoding/binary"
- 	"encoding/json"
-+	"fmt"
- 	"io"
- 	"os"
- 	"path/filepath"
-+	"strconv"
- 	"strings"
- 	"unsafe"
- 
-+	"github.com/cyphar/filepath-securejoin"
- 	"golang.org/x/sys/unix"
- )
- 
-@@ -88,6 +91,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: %w", 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: %w", 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/libcontainer/utils/utils_test.go b/libcontainer/utils/utils_test.go
-index 7f38ed169a6b..d33662238d36 100644
---- a/libcontainer/utils/utils_test.go
-+++ b/libcontainer/utils/utils_test.go
-@@ -143,3 +143,38 @@ func TestCleanPath(t *testing.T) {
- 		t.Errorf("expected to receive '/foo' and received %s", path)
- 	}
- }
-+
-+func TestStripRoot(t *testing.T) {
-+	for _, test := range []struct {
-+		root, path, out string
-+	}{
-+		// Works with multiple components.
-+		{"/a/b", "/a/b/c", "/c"},
-+		{"/hello/world", "/hello/world/the/quick-brown/fox", "/the/quick-brown/fox"},
-+		// '/' must be a no-op.
-+		{"/", "/a/b/c", "/a/b/c"},
-+		// Must be the correct order.
-+		{"/a/b", "/a/c/b", "/a/c/b"},
-+		// Must be at start.
-+		{"/abc/def", "/foo/abc/def/bar", "/foo/abc/def/bar"},
-+		// Must be a lexical parent.
-+		{"/foo/bar", "/foo/barSAMECOMPONENT", "/foo/barSAMECOMPONENT"},
-+		// Must only strip the root once.
-+		{"/foo/bar", "/foo/bar/foo/bar/baz", "/foo/bar/baz"},
-+		// Deal with .. in a fairly sane way.
-+		{"/foo/bar", "/foo/bar/../baz", "/foo/baz"},
-+		{"/foo/bar", "../../../../../../foo/bar/baz", "/baz"},
-+		{"/foo/bar", "/../../../../../../foo/bar/baz", "/baz"},
-+		{"/foo/bar/../baz", "/foo/baz/bar", "/bar"},
-+		{"/foo/bar/../baz", "/foo/baz/../bar/../baz/./foo", "/foo"},
-+		// All paths are made absolute before stripping.
-+		{"foo/bar", "/foo/bar/baz/bee", "/baz/bee"},
-+		{"/foo/bar", "foo/bar/baz/beef", "/baz/beef"},
-+		{"foo/bar", "foo/bar/baz/beets", "/baz/beets"},
-+	} {
-+		got := stripRoot(test.root, test.path)
-+		if got != test.out {
-+			t.Errorf("stripRoot(%q, %q) -- got %q, expected %q", test.root, test.path, got, test.out)
-+		}
-+	}
-+}
--- 
-2.31.1
-
diff --git a/SOURCES/runc-1947432.patch b/SOURCES/runc-1947432.patch
deleted file mode 100644
index 79ae82e..0000000
--- a/SOURCES/runc-1947432.patch
+++ /dev/null
@@ -1,102 +0,0 @@
-From a2050ea471b0eb3c7240282219773c0f1d7ec554 Mon Sep 17 00:00:00 2001
-From: Kir Kolyshkin <kolyshkin@gmail.com>
-Date: Wed, 7 Apr 2021 16:45:39 -0700
-Subject: [PATCH 1/2] runc run: fix start for rootless + host pidns
-
-Currently, runc fails like this when used from rootless podman
-with host PID namespace:
-
-> $ podman --runtime=runc run --pid=host --rm -it busybox sh
-> WARN[0000] additional gid=10 is not present in the user namespace, skip setting it
-> Error: container_linux.go:380: starting container process caused:
-> process_linux.go:545: container init caused: readonly path /proc/asound:
-> operation not permitted: OCI permission denied
-
-(Here /proc/asound is the first path from OCI spec's readonlyPaths).
-
-The code uses MS_BIND|MS_REMOUNT flags that have a special meaning in
-the kernel ("keep the flags like nodev, nosuid, noexec as is").
-For some reason, this "special meaning" trick is not working for the
-above use case (rootless podman + no PID namespace), and I don't know
-how to reproduce this without podman.
-
-Instead of relying on the kernel feature, let's just get the current
-mount flags using fstatfs(2) and add those that needs to be preserved.
-
-While at it, wrap errors from unix.Mount into os.PathError to make
-errors a bit less cryptic.
-
-Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
----
- libcontainer/rootfs_linux.go | 15 +++++++++++++--
- 1 file changed, 13 insertions(+), 2 deletions(-)
-
-diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go
-index ed38e77219..3d67287926 100644
---- a/libcontainer/rootfs_linux.go
-+++ b/libcontainer/rootfs_linux.go
-@@ -931,9 +931,20 @@ func readonlyPath(path string) error {
- 		if os.IsNotExist(err) {
- 			return nil
- 		}
--		return err
-+		return &os.PathError{Op: "bind-mount", Path: path, Err: err}
-+	}
-+
-+	var s unix.Statfs_t
-+	if err := unix.Statfs(path, &s); err != nil {
-+		return &os.PathError{Op: "statfs", Path: path, Err: err}
- 	}
--	return unix.Mount(path, path, "", unix.MS_BIND|unix.MS_REMOUNT|unix.MS_RDONLY|unix.MS_REC, "")
-+	flags := uintptr(s.Flags) & (unix.MS_NOSUID | unix.MS_NODEV | unix.MS_NOEXEC)
-+
-+	if err := unix.Mount(path, path, "", flags|unix.MS_BIND|unix.MS_REMOUNT|unix.MS_RDONLY, ""); err != nil {
-+		return &os.PathError{Op: "bind-mount-ro", Path: path, Err: err}
-+	}
-+
-+	return nil
- }
- 
- // remountReadonly will remount an existing mount point and ensure that it is read-only.
-
-From 31dd1e499b2f590cd3bcf59153491967ea2a8e1f Mon Sep 17 00:00:00 2001
-From: Kir Kolyshkin <kolyshkin@gmail.com>
-Date: Wed, 14 Apr 2021 10:58:42 -0700
-Subject: [PATCH 2/2] tests/int: add rootless + host pidns test case
-
-For the fix, see previous commit. Without the fix, this test case fails:
-
-> container_linux.go:380: starting container process caused:
-> process_linux.go:545: container init caused: readonly path /proc/bus:
-> operation not permitted
-
-Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
----
- tests/integration/start_hello.bats | 17 +++++++++++++++++
- 1 file changed, 17 insertions(+)
-
-diff --git a/tests/integration/start_hello.bats b/tests/integration/start_hello.bats
-index 5c2a66fdb1..858847032c 100644
---- a/tests/integration/start_hello.bats
-+++ b/tests/integration/start_hello.bats
-@@ -59,3 +59,20 @@ function teardown() {
- 
- 	[[ "$(cat pid.txt)" =~ [0-9]+ ]]
- }
-+
-+# https://github.com/opencontainers/runc/pull/2897
-+@test "runc run [rootless with host pidns]" {
-+	requires rootless_no_features
-+
-+	# Remove pid namespace, and replace /proc mount
-+	# with a bind mount from the host.
-+	update_config '	  .linux.namespaces -= [{"type": "pid"}]
-+			| .mounts |= map((select(.type == "proc")
-+				| .type = "none"
-+				| .source = "/proc"
-+				| .options = ["rbind", "nosuid", "nodev", "noexec"]
-+			  ) // .)'
-+
-+	runc run test_hello
-+	[ "$status" -eq 0 ]
-+}
diff --git a/SPECS/runc.spec b/SPECS/runc.spec
index 5f6e4f7..ba36e15 100644
--- a/SPECS/runc.spec
+++ b/SPECS/runc.spec
@@ -19,11 +19,11 @@ go build -buildmode pie -compiler gc -tags="rpm_crashtraceback libtrust_openssl 
 # https://github.com/opencontainers/runc
 %global import_path %{provider}.%{provider_tld}/%{project}/%{repo}
 %global git0 https://%{import_path}
-%global release_candidate rc93
+%global release_candidate rc95
 
 Name: %{repo}
 Version: 1.0.0
-Release: 73.%{release_candidate}%{?dist}
+Release: 74.%{release_candidate}%{?dist}
 Summary: CLI for running Open Containers
 # https://fedoraproject.org/wiki/PackagingDrafts/Go#Go_Language_Architectures
 #ExclusiveArch: %%{go_arches}
@@ -33,14 +33,6 @@ ExcludeArch: %{ix86}
 License: ASL 2.0
 URL: %{git0}
 Source0: %{git0}/archive/v1.0.0-%{release_candidate}.tar.gz
-Patch1: rc93-0001-libct-newInitConfig-nit.patch
-Patch2: rc93-0002-libct-rootfs-introduce-and-use-mountConfig.patch
-Patch3: rc93-0003-libct-rootfs-mountCgroupV2-minor-refactor.patch
-Patch4: rc93-0004-Fix-cgroup2-mount-for-rootless-case.patch
-Patch5: rc93-0005-rootfs-add-mount-destination-validation.patch
-# related bug: https://bugzilla.redhat.com/show_bug.cgi?id=1947432
-# patch:       https://github.com/opencontainers/runc/pull/2897.patch
-Patch6: runc-1947432.patch
 Provides: oci-runtime = 1
 BuildRequires: golang >= 1.12.12-4
 BuildRequires: git
@@ -65,6 +57,7 @@ pushd GOPATH
 popd
 
 pushd GOPATH/src/%{import_path}
+export GO111MODULE=off
 export GOPATH=%{gopath}:$(pwd)/GOPATH
 export CGO_CFLAGS="%{optflags} -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64"
 export BUILDTAGS="selinux seccomp"
@@ -98,6 +91,10 @@ install -p -m 0644 contrib/completions/bash/%{name} %{buildroot}%{_datadir}/bash
 %{_datadir}/bash-completion/completions/%{name}
 
 %changelog
+* Thu Jul 01 2021 Jindrich Novy <jnovy@redhat.com> - 1.0.0-74.rc95
+- updated to rc95 to fix CVE-2021-30465
+- Related: #1954702
+
 * Thu May 13 2021 Jindrich Novy <jnovy@redhat.com> - 1.0.0-73.rc93
 - fix "podman run --pid=host command causes OCI permission error"
 - Related: #1954702