github.com/opencontainers/umoci@v0.4.8-0.20240508124516-656e4836fb0d/oci/layer/tar_extract_linux_test.go (about) 1 //go:build linux 2 // +build linux 3 4 /* 5 * umoci: Umoci Modifies Open Containers' Images 6 * Copyright (C) 2020 Cisco Inc. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package layer 22 23 import ( 24 "archive/tar" 25 "io/ioutil" 26 "os" 27 "path/filepath" 28 "testing" 29 30 "github.com/opencontainers/umoci/pkg/system" 31 "golang.org/x/sys/unix" 32 ) 33 34 func canMknod(dir string) (bool, error) { 35 testNode := filepath.Join(dir, "test") 36 err := system.Mknod(testNode, unix.S_IFCHR|0666, unix.Mkdev(0, 0)) 37 if err != nil { 38 if os.IsPermission(err) { 39 return false, nil 40 } 41 42 return false, err 43 } 44 return true, os.Remove(testNode) 45 } 46 47 func TestUnpackEntryOverlayFSWhiteout(t *testing.T) { 48 dir, err := ioutil.TempDir("", "umoci-TestOverlayFSWhiteout") 49 if err != nil { 50 t.Fatal(err) 51 } 52 defer os.RemoveAll(dir) 53 54 mknodOk, err := canMknod(dir) 55 if err != nil { 56 t.Fatalf("couldn't mknod in dir: %v", err) 57 } 58 59 if !mknodOk { 60 t.Skip("skipping overlayfs test on kernel < 5.8") 61 } 62 63 headers := []pseudoHdr{ 64 {"file", "", tar.TypeReg, false}, 65 {whPrefix + "file", "", tar.TypeReg, false}, 66 } 67 68 canSetTrustedXattrs := os.Geteuid() == 0 69 70 if canSetTrustedXattrs { 71 headers = append(headers, []pseudoHdr{ 72 {"dir", "", tar.TypeDir, false}, 73 {"dir/fileindir", "dir", tar.TypeReg, false}, 74 {"dir/" + whOpaque, "dir", tar.TypeReg, false}, 75 }...) 76 } 77 78 unpackOptions := UnpackOptions{ 79 MapOptions: MapOptions{ 80 Rootless: os.Geteuid() != 0, 81 }, 82 WhiteoutMode: OverlayFSWhiteout, 83 } 84 85 te := NewTarExtractor(unpackOptions) 86 87 for _, ph := range headers { 88 hdr, rdr := fromPseudoHdr(ph) 89 if err := te.UnpackEntry(dir, hdr, rdr); err != nil { 90 t.Errorf("UnpackEntry %s failed: %v", hdr.Name, err) 91 } 92 } 93 94 fi, err := os.Stat(filepath.Join(dir, "file")) 95 if err != nil { 96 t.Fatalf("failed to stat `file`: %v", err) 97 } 98 99 whiteout, err := isOverlayWhiteout(fi) 100 if err != nil { 101 t.Fatalf("failed to check overlay whiteout: %v", err) 102 } 103 if !whiteout { 104 t.Fatalf("extract didn't make overlay whiteout") 105 } 106 107 if canSetTrustedXattrs { 108 value := make([]byte, 10) 109 n, err := unix.Getxattr(filepath.Join(dir, "dir"), "trusted.overlay.opaque", value) 110 if err != nil { 111 t.Fatalf("failed to get overlay opaque attr: %v", err) 112 } 113 114 if string(value[:n]) != "y" { 115 t.Fatalf("bad opaque xattr: %v", string(value[:n])) 116 } 117 } 118 }