diff --git a/go.mod b/go.mod index cf9cc879..877b53ca 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,7 @@ require ( github.com/opencontainers/runc v1.1.2 // indirect github.com/opencontainers/umoci v0.4.8-0.20220412065115-12453f247749 github.com/pkg/errors v0.9.1 + github.com/pkg/xattr v0.4.9 github.com/prometheus/common v0.32.1 // indirect github.com/smartystreets/assertions v1.0.1 // indirect github.com/smartystreets/goconvey v1.6.4 @@ -41,7 +42,7 @@ require ( go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 // indirect golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect - golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 + golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 google.golang.org/genproto v0.0.0-20220303160752-862486edd9cc // indirect gopkg.in/yaml.v2 v2.4.0 diff --git a/go.sum b/go.sum index 4869ac82..f8703476 100644 --- a/go.sum +++ b/go.sum @@ -1247,6 +1247,8 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/xattr v0.4.9 h1:5883YPCtkSd8LFbs13nXplj9g9tlrwoJRjgpgMu1/fE= +github.com/pkg/xattr v0.4.9/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1908,8 +1910,8 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211109184856-51b60fd695b3/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f h1:8w7RhxzTVgUzw/AH/9mUV5q0vMgy40SQRursCcfmkCw= +golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/overlay/pack.go b/overlay/pack.go index 8b4f6f6f..94990c72 100644 --- a/overlay/pack.go +++ b/overlay/pack.go @@ -4,9 +4,11 @@ import ( "context" "fmt" "io" + "io/fs" "io/ioutil" "os" "path" + "path/filepath" "runtime" "strings" "time" @@ -19,6 +21,7 @@ import ( "github.com/opencontainers/umoci/oci/casext" "github.com/opencontainers/umoci/oci/layer" "github.com/pkg/errors" + "github.com/pkg/xattr" "github.com/project-stacker/stacker/lib" "github.com/project-stacker/stacker/log" stackeroci "github.com/project-stacker/stacker/oci" @@ -316,6 +319,44 @@ func ociPutBlob(blob io.ReadCloser, config types.StackerConfig, layerMediaType s return desc, nil } +func stripOverlayAttrs(path string) error { + attrs, err := xattr.LList(path) + if err != nil { + return err + } + const match = ".overlay." + const opaque = match + "opaque" + + dropped := []string{} + for _, attr := range attrs { + if !strings.Contains(attr, match) { + continue + } + if strings.HasSuffix(attr, opaque) { + continue + } + if err := xattr.LRemove(path, attr); err != nil { + return errors.Errorf("%s: failed to remove attr %s: %v", path, attr, err) + } + dropped = append(dropped, attr) + } + + if len(dropped) != 0 { + log.Debugf("%s: dropped overlay attrs: %s", path, strings.Join(dropped, ",")) + } + return nil +} + +func stripOverlayAttrsUnder(dirPath string) error { + return fs.WalkDir(os.DirFS(dirPath), ".", + func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + return stripOverlayAttrs(filepath.Join(dirPath, path)) + }) +} + func generateLayer(config types.StackerConfig, oci casext.Engine, mutators []*mutate.Mutator, name string, layerTypes []types.LayerType) (bool, error) { dir := path.Join(config.RootFSDir, name, "overlay") ents, err := ioutil.ReadDir(dir) @@ -357,6 +398,10 @@ func generateLayer(config types.StackerConfig, oci casext.Engine, mutators []*mu EmptyLayer: false, } + if err := stripOverlayAttrsUnder(dir); err != nil { + return false, err + } + descs := []ispec.Descriptor{} for i, layerType := range layerTypes { mutator := mutators[i]