From 67869273a810621e979c55757343b076f2d32706 Mon Sep 17 00:00:00 2001 From: Filipe Brandenburger Date: Wed, 3 Jan 2018 10:58:39 -0800 Subject: [PATCH 1/4] Don't assume ipcmk command supports size suffix. Expand the use of "1M" to the corresponding number of bytes, since support for size suffix was only added to `ipcmk` in util-linux 2.27 which is not yet available in some Linux distributions. Tested by running `make test-e2e-node` against distributions with ipcmk that supports and doesn't support the suffix syntax, all of them passed. --- test/e2e_node/security_context_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e_node/security_context_test.go b/test/e2e_node/security_context_test.go index 7e30d167fc..e6f19a1147 100644 --- a/test/e2e_node/security_context_test.go +++ b/test/e2e_node/security_context_test.go @@ -150,7 +150,7 @@ var _ = framework.KubeDescribe("Security Context", func() { hostSharedMemoryID := "" BeforeEach(func() { - output, err := exec.Command("sh", "-c", "ipcmk -M 1M | awk '{print $NF}'").Output() + output, err := exec.Command("sh", "-c", "ipcmk -M 1048576 | awk '{print $NF}'").Output() if err != nil { framework.Failf("Failed to create the shared memory on the host: %v", err) } From ab219f2765cdf33e1117bfadbc5afa87a6f78872 Mon Sep 17 00:00:00 2001 From: Filipe Brandenburger Date: Mon, 22 Jan 2018 14:29:43 -0800 Subject: [PATCH 2/4] Refactor handling of IpcMode for the actual container Having the field set in modifyCommonNamespaceOptions is misleading, since for the actual container it is later unconditionally overwritten to point to the sandbox container. So let's move its setting to modifyHostOptionsForSandbox (renamed from modifyHostNetworkOptionForSandbox as it's not about network only), since that reflects what actually happens in practice. This commit is purely a refactor, it doesn't change any behavior. --- pkg/kubelet/dockershim/security_context.go | 27 +++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/pkg/kubelet/dockershim/security_context.go b/pkg/kubelet/dockershim/security_context.go index 5cb2dd481d..f29bd9668b 100644 --- a/pkg/kubelet/dockershim/security_context.go +++ b/pkg/kubelet/dockershim/security_context.go @@ -123,11 +123,13 @@ func modifyHostConfig(sc *runtimeapi.LinuxContainerSecurityContext, hostConfig * // modifySandboxNamespaceOptions apply namespace options for sandbox func modifySandboxNamespaceOptions(nsOpts *runtimeapi.NamespaceOption, hostConfig *dockercontainer.HostConfig, network *knetwork.PluginManager) { hostNetwork := false + hostIpc := false if nsOpts != nil { hostNetwork = nsOpts.HostNetwork + hostIpc = nsOpts.HostIpc } modifyCommonNamespaceOptions(nsOpts, hostConfig) - modifyHostNetworkOptionForSandbox(hostNetwork, network, hostConfig) + modifyHostOptionsForSandbox(hostNetwork, hostIpc, network, hostConfig) } // modifyContainerNamespaceOptions apply namespace options for container @@ -138,23 +140,22 @@ func modifyContainerNamespaceOptions(nsOpts *runtimeapi.NamespaceOption, podSand } hostConfig.PidMode = dockercontainer.PidMode(fmt.Sprintf("container:%v", podSandboxID)) modifyCommonNamespaceOptions(nsOpts, hostConfig) - modifyHostNetworkOptionForContainer(hostNetwork, podSandboxID, hostConfig) + modifyHostOptionsForContainer(hostNetwork, podSandboxID, hostConfig) } // modifyCommonNamespaceOptions apply common namespace options for sandbox and container func modifyCommonNamespaceOptions(nsOpts *runtimeapi.NamespaceOption, hostConfig *dockercontainer.HostConfig) { - if nsOpts != nil { - if nsOpts.HostPid { - hostConfig.PidMode = namespaceModeHost - } - if nsOpts.HostIpc { - hostConfig.IpcMode = namespaceModeHost - } + if nsOpts != nil && nsOpts.HostPid { + hostConfig.PidMode = namespaceModeHost } } -// modifyHostNetworkOptionForSandbox applies NetworkMode/UTSMode to sandbox's dockercontainer.HostConfig. -func modifyHostNetworkOptionForSandbox(hostNetwork bool, network *knetwork.PluginManager, hc *dockercontainer.HostConfig) { +// modifyHostOptionsForSandbox applies NetworkMode/UTSMode to sandbox's dockercontainer.HostConfig. +func modifyHostOptionsForSandbox(hostNetwork bool, hostIpc bool, network *knetwork.PluginManager, hc *dockercontainer.HostConfig) { + if hostIpc { + hc.IpcMode = namespaceModeHost + } + if hostNetwork { hc.NetworkMode = namespaceModeHost return @@ -175,8 +176,8 @@ func modifyHostNetworkOptionForSandbox(hostNetwork bool, network *knetwork.Plugi } } -// modifyHostNetworkOptionForContainer applies NetworkMode/UTSMode to container's dockercontainer.HostConfig. -func modifyHostNetworkOptionForContainer(hostNetwork bool, podSandboxID string, hc *dockercontainer.HostConfig) { +// modifyHostOptionsForContainer applies NetworkMode/UTSMode to container's dockercontainer.HostConfig. +func modifyHostOptionsForContainer(hostNetwork bool, podSandboxID string, hc *dockercontainer.HostConfig) { sandboxNSMode := fmt.Sprintf("container:%v", podSandboxID) hc.NetworkMode = dockercontainer.NetworkMode(sandboxNSMode) hc.IpcMode = dockercontainer.IpcMode(sandboxNSMode) From c9e5bfbbbb22c9f678b2d12b2ecbad043078d3f9 Mon Sep 17 00:00:00 2001 From: Filipe Brandenburger Date: Mon, 22 Jan 2018 14:13:17 -0800 Subject: [PATCH 3/4] Add new e2e-test container to export ipcs from util-linux This container will be used to exercise the HostIPC functionality in e2e-node tests. The version of `ipcs` shipped in busybox performs operations that get blocked by SELinux on hosts where it is enabled. The version of `ipcs` in util-linux does not perform those operations, rather it checks whether the /proc files it needs are available and proceeds to reading from them directly. Using `ipcs` from util-linux makes these tests pass, even when running under SELinux enabled, so let's use them here. Tested: On a host where Docker with SELinux enabled: - Checked that `ipcs` from busybox does not work: $ docker run busybox ipcs -m kernel not configured for shared memory - Checked that the one from this container does work: $ docker run gcr.io/kubernetes-e2e-test-images/ipc-utils-amd64:1.0 ipcs -m ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status --- test/images/ipc-utils/BASEIMAGE | 4 ++++ test/images/ipc-utils/Dockerfile | 19 +++++++++++++++++++ test/images/ipc-utils/VERSION | 1 + 3 files changed, 24 insertions(+) create mode 100644 test/images/ipc-utils/BASEIMAGE create mode 100644 test/images/ipc-utils/Dockerfile create mode 100644 test/images/ipc-utils/VERSION diff --git a/test/images/ipc-utils/BASEIMAGE b/test/images/ipc-utils/BASEIMAGE new file mode 100644 index 0000000000..114844f395 --- /dev/null +++ b/test/images/ipc-utils/BASEIMAGE @@ -0,0 +1,4 @@ +amd64=alpine:3.6 +arm=arm32v6/alpine:3.6 +arm64=arm64v8/alpine:3.6 +ppc64le=ppc64le/alpine:3.6 diff --git a/test/images/ipc-utils/Dockerfile b/test/images/ipc-utils/Dockerfile new file mode 100644 index 0000000000..3edaa27208 --- /dev/null +++ b/test/images/ipc-utils/Dockerfile @@ -0,0 +1,19 @@ +# Copyright 2018 The Kubernetes Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM BASEIMAGE + +CROSS_BUILD_COPY qemu-QEMUARCH-static /usr/bin/ + +RUN apk add --no-cache util-linux diff --git a/test/images/ipc-utils/VERSION b/test/images/ipc-utils/VERSION new file mode 100644 index 0000000000..d3827e75a5 --- /dev/null +++ b/test/images/ipc-utils/VERSION @@ -0,0 +1 @@ +1.0 From 46a83c28835d1f79bbcb6da1f65120845dd39a51 Mon Sep 17 00:00:00 2001 From: Filipe Brandenburger Date: Mon, 22 Jan 2018 14:44:36 -0800 Subject: [PATCH 4/4] Use ipc-utils container in HostIPC tests. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures the `ipcs` command from util-linux will be used, which succeeds when Docker is running with SELinux enabled (while the one from busybox fails.) Tested: On a host with Docker running with SELinux enabled: $ make test-e2e-node REMOTE=true FOCUS="host IPC" • [SLOW TEST:17.272 seconds] (passed) [k8s.io] Security Context when creating a pod in the host IPC namespace should show the shared memory ID in the host IPC containers • [SLOW TEST:20.419 seconds] (passed) [k8s.io] Security Context when creating a pod in the host IPC namespace should not show the shared memory ID in the non-hostIPC containers Ran 2 of 257 Specs in 43.934 seconds SUCCESS! -- 2 Passed | 0 Failed | 0 Pending | 255 Skipped --- test/e2e/common/util.go | 1 + test/e2e_node/security_context_test.go | 22 +++++++++++----------- test/utils/image/manifest.go | 1 + 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/test/e2e/common/util.go b/test/e2e/common/util.go index 2edfd8de7e..2743207f02 100644 --- a/test/e2e/common/util.go +++ b/test/e2e/common/util.go @@ -53,6 +53,7 @@ var CurrentSuite Suite var CommonImageWhiteList = sets.NewString( "busybox", imageutils.GetE2EImage(imageutils.EntrypointTester), + imageutils.GetE2EImage(imageutils.IpcUtils), imageutils.GetE2EImage(imageutils.Liveness), imageutils.GetE2EImage(imageutils.Mounttest), imageutils.GetE2EImage(imageutils.MounttestUser), diff --git a/test/e2e_node/security_context_test.go b/test/e2e_node/security_context_test.go index e6f19a1147..90d325a166 100644 --- a/test/e2e_node/security_context_test.go +++ b/test/e2e_node/security_context_test.go @@ -140,7 +140,7 @@ var _ = framework.KubeDescribe("Security Context", func() { } createAndWaitHostIPCPod := func(podName string, hostNetwork bool) { podClient.Create(makeHostIPCPod(podName, - busyboxImage, + imageutils.GetE2EImage(imageutils.IpcUtils), []string{"sh", "-c", "ipcs -m | awk '{print $2}'"}, hostNetwork, )) @@ -159,30 +159,30 @@ var _ = framework.KubeDescribe("Security Context", func() { }) It("should show the shared memory ID in the host IPC containers", func() { - busyboxPodName := "busybox-hostipc-" + string(uuid.NewUUID()) - createAndWaitHostIPCPod(busyboxPodName, true) - logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName) + ipcutilsPodName := "ipcutils-hostipc-" + string(uuid.NewUUID()) + createAndWaitHostIPCPod(ipcutilsPodName, true) + logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, ipcutilsPodName, ipcutilsPodName) if err != nil { - framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err) + framework.Failf("GetPodLogs for pod %q failed: %v", ipcutilsPodName, err) } podSharedMemoryIDs := strings.TrimSpace(logs) - framework.Logf("Got shared memory IDs %q from pod %q", podSharedMemoryIDs, busyboxPodName) + framework.Logf("Got shared memory IDs %q from pod %q", podSharedMemoryIDs, ipcutilsPodName) if !strings.Contains(podSharedMemoryIDs, hostSharedMemoryID) { framework.Failf("hostIPC container should show shared memory IDs on host") } }) It("should not show the shared memory ID in the non-hostIPC containers", func() { - busyboxPodName := "busybox-non-hostipc-" + string(uuid.NewUUID()) - createAndWaitHostIPCPod(busyboxPodName, false) - logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, busyboxPodName, busyboxPodName) + ipcutilsPodName := "ipcutils-non-hostipc-" + string(uuid.NewUUID()) + createAndWaitHostIPCPod(ipcutilsPodName, false) + logs, err := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, ipcutilsPodName, ipcutilsPodName) if err != nil { - framework.Failf("GetPodLogs for pod %q failed: %v", busyboxPodName, err) + framework.Failf("GetPodLogs for pod %q failed: %v", ipcutilsPodName, err) } podSharedMemoryIDs := strings.TrimSpace(logs) - framework.Logf("Got shared memory IDs %q from pod %q", podSharedMemoryIDs, busyboxPodName) + framework.Logf("Got shared memory IDs %q from pod %q", podSharedMemoryIDs, ipcutilsPodName) if strings.Contains(podSharedMemoryIDs, hostSharedMemoryID) { framework.Failf("non-hostIPC container should not show shared memory IDs on host") } diff --git a/test/utils/image/manifest.go b/test/utils/image/manifest.go index bac1716548..3e9ebdadd9 100644 --- a/test/utils/image/manifest.go +++ b/test/utils/image/manifest.go @@ -65,6 +65,7 @@ var ( GBRedisSlave = ImageConfig{sampleRegistry, "gb-redisslave", "v2", true} Goproxy = ImageConfig{e2eRegistry, "goproxy", "1.0", true} Hostexec = ImageConfig{e2eRegistry, "hostexec", "1.0", true} + IpcUtils = ImageConfig{e2eRegistry, "ipc-utils", "1.0", true} Iperf = ImageConfig{e2eRegistry, "iperf", "1.0", true} JessieDnsutils = ImageConfig{e2eRegistry, "jessie-dnsutils", "1.0", true} Kitten = ImageConfig{e2eRegistry, "kitten", "1.0", true}