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 })