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  }