github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/test/e2e/run_privileged_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"os"
     5  	"strconv"
     6  	"strings"
     7  
     8  	. "github.com/hanks177/podman/v4/test/utils"
     9  	. "github.com/onsi/ginkgo"
    10  	. "github.com/onsi/gomega"
    11  	. "github.com/onsi/gomega/gexec"
    12  	"github.com/syndtr/gocapability/capability"
    13  )
    14  
    15  // helper function for confirming that container capabilities are equal
    16  // to those of the host, but only to the extent of caps we (podman)
    17  // know about at compile time. That is: the kernel may have more caps
    18  // available than we are aware of, leading to host=FFF... and ctr=3FF...
    19  // because the latter is all we request. Accept that.
    20  func containerCapMatchesHost(ctrCap string, hostCap string) {
    21  	if isRootless() {
    22  		return
    23  	}
    24  	ctrCapN, err := strconv.ParseUint(ctrCap, 16, 64)
    25  	Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", ctrCap)
    26  
    27  	hostCapN, err := strconv.ParseUint(hostCap, 16, 64)
    28  	Expect(err).NotTo(HaveOccurred(), "Error parsing %q as hex", hostCap)
    29  
    30  	// host caps can never be zero (except rootless).
    31  	// and host caps must always be a superset (inclusive) of container
    32  	Expect(hostCapN).To(BeNumerically(">", 0), "host cap %q should be nonzero", hostCap)
    33  	Expect(hostCapN).To(BeNumerically(">=", ctrCapN), "host cap %q should never be less than container cap %q", hostCap, ctrCap)
    34  	hostCapMasked := hostCapN & (1<<len(capability.List()) - 1)
    35  	Expect(ctrCapN).To(Equal(hostCapMasked), "container cap %q is not a subset of host cap %q", ctrCap, hostCap)
    36  }
    37  
    38  var _ = Describe("Podman privileged container tests", func() {
    39  	var (
    40  		tempdir    string
    41  		err        error
    42  		podmanTest *PodmanTestIntegration
    43  	)
    44  
    45  	BeforeEach(func() {
    46  		tempdir, err = CreateTempDirInTempDir()
    47  		if err != nil {
    48  			os.Exit(1)
    49  		}
    50  		podmanTest = PodmanTestCreate(tempdir)
    51  		podmanTest.Setup()
    52  	})
    53  
    54  	AfterEach(func() {
    55  		podmanTest.Cleanup()
    56  		f := CurrentGinkgoTestDescription()
    57  		processTestResult(f)
    58  
    59  	})
    60  
    61  	It("podman privileged make sure sys is mounted rw", func() {
    62  		session := podmanTest.Podman([]string{"run", "--privileged", BB, "mount"})
    63  		session.WaitWithDefaultTimeout()
    64  		Expect(session).Should(Exit(0))
    65  		Expect(session.OutputToString()).To(ContainSubstring("sysfs (rw,"))
    66  	})
    67  
    68  	It("podman privileged CapEff", func() {
    69  		hostCap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
    70  		Expect(hostCap).Should(Exit(0))
    71  
    72  		session := podmanTest.Podman([]string{"run", "--privileged", BB, "awk", "/^CapEff/ { print $2 }", "/proc/self/status"})
    73  		session.WaitWithDefaultTimeout()
    74  		Expect(session).Should(Exit(0))
    75  
    76  		containerCapMatchesHost(session.OutputToString(), hostCap.OutputToString())
    77  	})
    78  
    79  	It("podman cap-add CapEff", func() {
    80  		// Get caps of current process
    81  		hostCap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
    82  		Expect(hostCap).Should(Exit(0))
    83  
    84  		session := podmanTest.Podman([]string{"run", "--cap-add", "all", BB, "awk", "/^CapEff/ { print $2 }", "/proc/self/status"})
    85  		session.WaitWithDefaultTimeout()
    86  		Expect(session).Should(Exit(0))
    87  
    88  		containerCapMatchesHost(session.OutputToString(), hostCap.OutputToString())
    89  	})
    90  
    91  	It("podman cap-add CapEff with --user", func() {
    92  		// Get caps of current process
    93  		hostCap := SystemExec("awk", []string{"/^CapEff/ { print $2 }", "/proc/self/status"})
    94  		Expect(hostCap).Should(Exit(0))
    95  
    96  		session := podmanTest.Podman([]string{"run", "--user=bin", "--cap-add", "all", BB, "awk", "/^CapEff/ { print $2 }", "/proc/self/status"})
    97  		session.WaitWithDefaultTimeout()
    98  		Expect(session).Should(Exit(0))
    99  
   100  		containerCapMatchesHost(session.OutputToString(), hostCap.OutputToString())
   101  	})
   102  
   103  	It("podman cap-drop CapEff", func() {
   104  		session := podmanTest.Podman([]string{"run", "--cap-drop", "all", BB, "grep", "CapEff", "/proc/self/status"})
   105  		session.WaitWithDefaultTimeout()
   106  		Expect(session).Should(Exit(0))
   107  		capEff := strings.Split(session.OutputToString(), " ")
   108  		Expect("0000000000000000").To(Equal(capEff[1]))
   109  	})
   110  
   111  	It("podman privileged should disable seccomp by default", func() {
   112  		hostSeccomp := SystemExec("grep", []string{"-Ei", "^Seccomp:\\s+0$", "/proc/self/status"})
   113  		Expect(hostSeccomp).Should(Exit(0))
   114  
   115  		session := podmanTest.Podman([]string{"run", "--privileged", ALPINE, "grep", "-Ei", "^Seccomp:\\s+0$", "/proc/self/status"})
   116  		session.WaitWithDefaultTimeout()
   117  		Expect(session).Should(Exit(0))
   118  	})
   119  
   120  	It("podman non-privileged should have very few devices", func() {
   121  		session := podmanTest.Podman([]string{"run", "-t", BB, "ls", "-l", "/dev"})
   122  		session.WaitWithDefaultTimeout()
   123  		Expect(session).Should(Exit(0))
   124  		Expect(session.OutputToStringArray()).To(HaveLen(17))
   125  	})
   126  
   127  	It("podman privileged should inherit host devices", func() {
   128  		session := podmanTest.Podman([]string{"run", "--privileged", ALPINE, "ls", "-l", "/dev"})
   129  		session.WaitWithDefaultTimeout()
   130  		Expect(session).Should(Exit(0))
   131  		Expect(len(session.OutputToStringArray())).To(BeNumerically(">", 20))
   132  	})
   133  
   134  	It("podman privileged should restart after host devices change", func() {
   135  		containerName := "privileged-restart-test"
   136  		SkipIfRootless("Cannot create devices in /dev in rootless mode")
   137  		Expect(os.MkdirAll("/dev/foodevdir", os.ModePerm)).To(BeNil())
   138  
   139  		mknod := SystemExec("mknod", []string{"/dev/foodevdir/null", "c", "1", "3"})
   140  		mknod.WaitWithDefaultTimeout()
   141  		Expect(mknod).Should(Exit(0))
   142  
   143  		session := podmanTest.Podman([]string{"run", "--name=" + containerName, "--privileged", "-it", fedoraMinimal, "ls", "/dev"})
   144  		session.WaitWithDefaultTimeout()
   145  		Expect(session).Should(Exit(0))
   146  
   147  		deviceFiles := session.OutputToStringArray()
   148  
   149  		os.RemoveAll("/dev/foodevdir")
   150  		session = podmanTest.Podman([]string{"start", "--attach", containerName})
   151  		session.WaitWithDefaultTimeout()
   152  		Expect(session).Should(Exit(0))
   153  
   154  		deviceFilesAfterRemoval := session.OutputToStringArray()
   155  		Expect(deviceFiles).To(Not(Equal(deviceFilesAfterRemoval)))
   156  	})
   157  
   158  	It("run no-new-privileges test", func() {
   159  		// Check if our kernel is new enough
   160  		k, err := IsKernelNewerThan("4.14")
   161  		Expect(err).To(BeNil())
   162  		if !k {
   163  			Skip("Kernel is not new enough to test this feature")
   164  		}
   165  
   166  		cap := SystemExec("grep", []string{"NoNewPrivs", "/proc/self/status"})
   167  		if cap.ExitCode() != 0 {
   168  			Skip("Can't determine NoNewPrivs")
   169  		}
   170  
   171  		session := podmanTest.Podman([]string{"run", BB, "grep", "NoNewPrivs", "/proc/self/status"})
   172  		session.WaitWithDefaultTimeout()
   173  		Expect(session).Should(Exit(0))
   174  
   175  		privs := strings.Split(session.OutputToString(), ":")
   176  		session = podmanTest.Podman([]string{"run", "--security-opt", "no-new-privileges", BB, "grep", "NoNewPrivs", "/proc/self/status"})
   177  		session.WaitWithDefaultTimeout()
   178  		Expect(session).Should(Exit(0))
   179  
   180  		noprivs := strings.Split(session.OutputToString(), ":")
   181  		Expect(privs[1]).To(Not(Equal(noprivs[1])))
   182  	})
   183  
   184  })