From 36caf4ee446a9f363cb76c629904e4ae165799b3 Mon Sep 17 00:00:00 2001
From: Ed Santiago <santiago@redhat.com>
Date: Thu, 3 Sep 2020 11:07:15 -0600
Subject: [PATCH] WIP: update VM images

(This is an adoption of #7533 because Brent is on PTO).

Pick up new crun and crio-runc.

Also: renames from useful fedora-32 and -31 to less-useful
names; presumably this is needed by something-something in
the new VM setup.

Also: tweak two e2e tests to more properly handle a kernel
(5.8.4) with a greater set of capabilities than what we
or crun can yet handle.

Signed-off-by: Ed Santiago <santiago@redhat.com>
---
 .cirrus.yml                         | 10 +++----
 contrib/cirrus/setup_environment.sh |  2 +-
 test/e2e/run_privileged_test.go     | 42 +++++++++++++++++++++++------
 3 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/.cirrus.yml b/.cirrus.yml
index 1bf35e142c..06ed7c5e0b 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -34,12 +34,12 @@ env:
     ####
     #### Cache-image names to test with (double-quotes around names are critical)
     ###
-    FEDORA_NAME: "fedora-32"
-    PRIOR_FEDORA_NAME: "fedora-31"
-    UBUNTU_NAME: "ubuntu-20"
-    PRIOR_UBUNTU_NAME: "ubuntu-19"
+    FEDORA_NAME: "fedora"
+    PRIOR_FEDORA_NAME: "prior-fedora"
+    UBUNTU_NAME: "ubuntu"
+    PRIOR_UBUNTU_NAME: "prior-ubuntu"
 
-    _BUILT_IMAGE_SUFFIX: "podman-6530021898584064"
+    _BUILT_IMAGE_SUFFIX: "c5809900649447424"
     FEDORA_CACHE_IMAGE_NAME: "${FEDORA_NAME}-${_BUILT_IMAGE_SUFFIX}"
     PRIOR_FEDORA_CACHE_IMAGE_NAME: "${PRIOR_FEDORA_NAME}-${_BUILT_IMAGE_SUFFIX}"
     UBUNTU_CACHE_IMAGE_NAME: "${UBUNTU_NAME}-${_BUILT_IMAGE_SUFFIX}"
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index e22f92a5b6..855866477f 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -68,7 +68,7 @@ case "$CG_FS_TYPE" in
     tmpfs)
         warn "Forcing testing with runc instead of crun"
 	# On ubuntu, the default runc is usually not new enough.
-	if ${OS_RELEASE_ID} == "ubuntu"; then
+	if [[ "${OS_RELEASE_ID}" == "ubuntu" ]]; then
         X=$(echo "export OCI_RUNTIME=/usr/lib/cri-o-runc/sbin/runc" | \
             tee -a /etc/environment) && eval "$X" && echo "$X"
 	else
diff --git a/test/e2e/run_privileged_test.go b/test/e2e/run_privileged_test.go
index ca8da981f4..064ba7d2cd 100644
--- a/test/e2e/run_privileged_test.go
+++ b/test/e2e/run_privileged_test.go
@@ -2,13 +2,36 @@ package integration
 
 import (
 	"os"
+	"strconv"
 	"strings"
 
 	. "github.com/containers/podman/v2/test/utils"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"github.com/syndtr/gocapability/capability"
 )
 
+// helper function for confirming that container capabilities are equal
+// to those of the host, but only to the extent of caps we (podman)
+// know about at compile time. That is: the kernel may have more caps
+// available than we are aware of, leading to host=FFF... and ctr=3FF...
+// because the latter is all we request. Accept that.
+func containerCapMatchesHost(ctr_cap string, host_cap string) {
+	ctr_cap_n, err := strconv.ParseUint(ctr_cap, 16, 64)
+	Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", ctr_cap)
+
+	host_cap_n, err := strconv.ParseUint(host_cap, 16, 64)
+	Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", host_cap)
+
+	// host caps can never be zero (except rootless, which we don't test).
+	// and host caps must always be a superset (inclusive) of container
+	Expect(host_cap_n).To(BeNumerically(">", 0), "host cap %q should be nonzero", host_cap)
+	Expect(host_cap_n).To(BeNumerically(">=", ctr_cap_n), "host cap %q should never be less than container cap %q", host_cap, ctr_cap)
+
+	host_cap_masked := host_cap_n & (1<<len(capability.List()) - 1)
+	Expect(ctr_cap_n).To(Equal(host_cap_masked), "container cap %q is not a subset of host cap %q", ctr_cap, host_cap)
+}
+
 var _ = Describe("Podman privileged container tests", func() {
 	var (
 		tempdir    string
@@ -44,24 +67,27 @@ var _ = Describe("Podman privileged container tests", func() {
 
 	It("podman privileged CapEff", func() {
 		SkipIfRootless()
-		cap := SystemExec("grep", []string{"CapEff", "/proc/self/status"})
-		Expect(cap.ExitCode()).To(Equal(0))
+		host_cap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
+		Expect(host_cap.ExitCode()).To(Equal(0))
 
-		session := podmanTest.Podman([]string{"run", "--privileged", "busybox", "grep", "CapEff", "/proc/self/status"})
+		session := podmanTest.Podman([]string{"run", "--privileged", "busybox", "awk", "/^CapEff/ { print $2 }", "/proc/self/status"})
 		session.WaitWithDefaultTimeout()
 		Expect(session.ExitCode()).To(Equal(0))
-		Expect(session.OutputToString()).To(Equal(cap.OutputToString()))
+
+		containerCapMatchesHost(session.OutputToString(), host_cap.OutputToString())
 	})
 
 	It("podman cap-add CapEff", func() {
 		SkipIfRootless()
-		cap := SystemExec("grep", []string{"CapEff", "/proc/self/status"})
-		Expect(cap.ExitCode()).To(Equal(0))
+		// Get caps of current process
+		host_cap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
+		Expect(host_cap.ExitCode()).To(Equal(0))
 
-		session := podmanTest.Podman([]string{"run", "--cap-add", "all", "busybox", "grep", "CapEff", "/proc/self/status"})
+		session := podmanTest.Podman([]string{"run", "--cap-add", "all", "busybox", "awk", "/^CapEff/ { print $2 }", "/proc/self/status"})
 		session.WaitWithDefaultTimeout()
 		Expect(session.ExitCode()).To(Equal(0))
-		Expect(session.OutputToString()).To(Equal(cap.OutputToString()))
+
+		containerCapMatchesHost(session.OutputToString(), host_cap.OutputToString())
 	})
 
 	It("podman cap-drop CapEff", func() {