k8s.io/kubernetes@v1.29.3/pkg/volume/util/hostutil/hostutil_linux_test.go (about) 1 //go:build linux 2 // +build linux 3 4 /* 5 Copyright 2014 The Kubernetes Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 package hostutil 21 22 import ( 23 "os" 24 "path/filepath" 25 "testing" 26 ) 27 28 func TestIsSharedSuccess(t *testing.T) { 29 successMountInfo := 30 `62 0 253:0 / / rw,relatime shared:1 - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered 31 76 62 8:1 / /boot rw,relatime shared:29 - ext4 /dev/sda1 rw,seclabel,data=ordered 32 78 62 0:41 / /tmp rw,nosuid,nodev shared:30 - tmpfs tmpfs rw,seclabel 33 80 62 0:42 / /var/lib/nfs/rpc_pipefs rw,relatime shared:31 - rpc_pipefs sunrpc rw 34 82 62 0:43 / /var/lib/foo rw,relatime shared:32 - tmpfs tmpfs rw 35 83 63 0:44 / /var/lib/bar rw,relatime - tmpfs tmpfs rw 36 227 62 253:0 /var/lib/docker/devicemapper /var/lib/docker/devicemapper rw,relatime - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered 37 224 62 253:0 /var/lib/docker/devicemapper/test/shared /var/lib/docker/devicemapper/test/shared rw,relatime master:1 shared:44 - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered 38 ` 39 tempDir, filename, err := writeFile(successMountInfo) 40 if err != nil { 41 t.Fatalf("cannot create temporary file: %v", err) 42 } 43 defer os.RemoveAll(tempDir) 44 45 tests := []struct { 46 name string 47 path string 48 expectedResult bool 49 }{ 50 { 51 // /var/lib/kubelet is a directory on mount '/' that is shared 52 // This is the most common case. 53 "shared", 54 "/var/lib/kubelet", 55 true, 56 }, 57 { 58 // 8a2a... is a directory on mount /var/lib/docker/devicemapper 59 // that is private. 60 "private", 61 "/var/lib/docker/devicemapper/mnt/8a2a5c19eefb06d6f851dfcb240f8c113427f5b49b19658b5c60168e88267693/", 62 false, 63 }, 64 { 65 // 'directory' is a directory on mount 66 // /var/lib/docker/devicemapper/test/shared that is shared, but one 67 // of its parent is private. 68 "nested-shared", 69 "/var/lib/docker/devicemapper/test/shared/my/test/directory", 70 true, 71 }, 72 { 73 // /var/lib/foo is a mount point and it's shared 74 "shared-mount", 75 "/var/lib/foo", 76 true, 77 }, 78 { 79 // /var/lib/bar is a mount point and it's private 80 "private-mount", 81 "/var/lib/bar", 82 false, 83 }, 84 } 85 for _, test := range tests { 86 ret, err := isShared(test.path, filename) 87 if err != nil { 88 t.Errorf("test %s got unexpected error: %v", test.name, err) 89 } 90 if ret != test.expectedResult { 91 t.Errorf("test %s expected %v, got %v", test.name, test.expectedResult, ret) 92 } 93 } 94 } 95 96 func TestIsSharedFailure(t *testing.T) { 97 errorTests := []struct { 98 name string 99 content string 100 }{ 101 { 102 // the first line is too short 103 name: "too-short-line", 104 content: `62 0 253:0 / / rw,relatime 105 76 62 8:1 / /boot rw,relatime shared:29 - ext4 /dev/sda1 rw,seclabel,data=ordered 106 78 62 0:41 / /tmp rw,nosuid,nodev shared:30 - tmpfs tmpfs rw,seclabel 107 80 62 0:42 / /var/lib/nfs/rpc_pipefs rw,relatime shared:31 - rpc_pipefs sunrpc rw 108 227 62 253:0 /var/lib/docker/devicemapper /var/lib/docker/devicemapper rw,relatime - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered 109 224 62 253:0 /var/lib/docker/devicemapper/test/shared /var/lib/docker/devicemapper/test/shared rw,relatime master:1 shared:44 - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered 110 `, 111 }, 112 { 113 // there is no root mount 114 name: "no-root-mount", 115 content: `76 62 8:1 / /boot rw,relatime shared:29 - ext4 /dev/sda1 rw,seclabel,data=ordered 116 78 62 0:41 / /tmp rw,nosuid,nodev shared:30 - tmpfs tmpfs rw,seclabel 117 80 62 0:42 / /var/lib/nfs/rpc_pipefs rw,relatime shared:31 - rpc_pipefs sunrpc rw 118 227 62 253:0 /var/lib/docker/devicemapper /var/lib/docker/devicemapper rw,relatime - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered 119 224 62 253:0 /var/lib/docker/devicemapper/test/shared /var/lib/docker/devicemapper/test/shared rw,relatime master:1 shared:44 - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered 120 `, 121 }, 122 } 123 for _, test := range errorTests { 124 tempDir, filename, err := writeFile(test.content) 125 if err != nil { 126 t.Fatalf("cannot create temporary file: %v", err) 127 } 128 defer os.RemoveAll(tempDir) 129 130 _, err = isShared("/", filename) 131 if err == nil { 132 t.Errorf("test %q: expected error, got none", test.name) 133 } 134 } 135 } 136 137 func TestGetSELinuxSupport(t *testing.T) { 138 info := 139 `62 0 253:0 / / rw,relatime shared:1 - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered 140 78 62 0:41 / /tmp rw,nosuid,nodev shared:30 - tmpfs tmpfs rw,seclabel 141 83 63 0:44 / /var/lib/bar rw,relatime - tmpfs tmpfs rw 142 227 62 253:0 /var/lib/docker/devicemapper /var/lib/docker/devicemapper rw,relatime - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered 143 150 23 1:58 / /media/nfs_vol rw,relatime shared:89 - nfs4 172.18.4.223:/srv/nfs rw,vers=4.0,rsize=524288,wsize=524288,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=172.18.4.223,local_lock=none,addr=172.18.4.223 144 ` 145 tempDir, filename, err := writeFile(info) 146 if err != nil { 147 t.Fatalf("cannot create temporary file: %v", err) 148 } 149 defer os.RemoveAll(tempDir) 150 151 tests := []struct { 152 name string 153 mountPoint string 154 selinuxEnabled bool 155 expectedResult bool 156 }{ 157 { 158 "ext4 on / with disabled SELinux", 159 "/", 160 false, 161 false, 162 }, 163 { 164 "ext4 on /", 165 "/", 166 true, 167 true, 168 }, 169 { 170 "tmpfs on /var/lib/bar", 171 "/var/lib/bar", 172 true, 173 false, 174 }, 175 { 176 "nfsv4", 177 "/media/nfs_vol", 178 true, 179 false, 180 }, 181 } 182 183 for _, test := range tests { 184 out, err := GetSELinux(test.mountPoint, filename, func() bool { return test.selinuxEnabled }) 185 if err != nil { 186 t.Errorf("Test %s failed with error: %s", test.name, err) 187 } 188 if test.expectedResult != out { 189 t.Errorf("Test %s failed: expected %v, got %v", test.name, test.expectedResult, out) 190 } 191 } 192 } 193 194 func writeFile(content string) (string, string, error) { 195 tempDir, err := os.MkdirTemp("", "mounter_shared_test") 196 if err != nil { 197 return "", "", err 198 } 199 filename := filepath.Join(tempDir, "mountinfo") 200 err = os.WriteFile(filename, []byte(content), 0600) 201 if err != nil { 202 os.RemoveAll(tempDir) 203 return "", "", err 204 } 205 return tempDir, filename, nil 206 } 207 208 func TestGetSELinuxMountContext(t *testing.T) { 209 info := 210 `840 60 8:0 / /var/lib/kubelet/pods/d4f3b306-ad4c-4f7a-8983-b5b228039a8c/volumes/kubernetes.io~iscsi/mypv rw,relatime shared:421 - ext4 /dev/sda rw,context="system_u:object_r:container_file_t:s0:c314,c894" 211 224 62 253:0 /var/lib/docker/devicemapper/test/shared /var/lib/docker/devicemapper/test/shared rw,relatime master:1 shared:44 - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered 212 82 62 0:43 / /var/lib/foo rw,relatime shared:32 - tmpfs tmpfs rw 213 83 63 0:44 / /var/lib/bar rw,relatime - tmpfs tmpfs rw 214 ` 215 tempDir, filename, err := writeFile(info) 216 if err != nil { 217 t.Fatalf("cannot create temporary file: %v", err) 218 } 219 defer os.RemoveAll(tempDir) 220 221 tests := []struct { 222 name string 223 mountPoint string 224 seLinuxEnabled bool 225 expectedContext string 226 }{ 227 { 228 "no context", 229 "/var/lib/foo", 230 true, 231 "", 232 }, 233 { 234 "with context with SELinux", 235 "/var/lib/kubelet/pods/d4f3b306-ad4c-4f7a-8983-b5b228039a8c/volumes/kubernetes.io~iscsi/mypv", 236 true, 237 "system_u:object_r:container_file_t:s0:c314,c894", 238 }, 239 { 240 "with context with no SELinux", 241 "/var/lib/kubelet/pods/d4f3b306-ad4c-4f7a-8983-b5b228039a8c/volumes/kubernetes.io~iscsi/mypv", 242 false, 243 "", 244 }, 245 { 246 "no context with seclabel", 247 "/var/lib/docker/devicemapper/test/shared", 248 true, 249 "", 250 }, 251 } 252 253 for _, test := range tests { 254 out, err := getSELinuxMountContext(test.mountPoint, filename, func() bool { return test.seLinuxEnabled }) 255 if err != nil { 256 t.Errorf("Test %s failed with error: %s", test.name, err) 257 } 258 if test.expectedContext != out { 259 t.Errorf("Test %s failed: expected %v, got %v", test.name, test.expectedContext, out) 260 } 261 } 262 263 }