diff --git a/copier/copier.go b/copier/copier.go index d9f531acc..94c76b4e7 100644 --- a/copier/copier.go +++ b/copier/copier.go @@ -344,6 +344,9 @@ type PutOptions struct { ChmodDirs *os.FileMode // set permissions on newly-created directories ChownFiles *idtools.IDPair // set ownership of newly-created files ChmodFiles *os.FileMode // set permissions on newly-created files + StripSetuidBit bool // strip the setuid bit off of items being written + StripSetgidBit bool // strip the setgid bit off of items being written + StripStickyBit bool // strip the sticky bit off of items being written StripXattrs bool // don't bother trying to set extended attributes of items being copied IgnoreXattrErrors bool // ignore any errors encountered when attempting to set extended attributes IgnoreDevices bool // ignore items which are character or block devices @@ -1649,6 +1652,15 @@ func copierHandlerPut(bulkReader io.Reader, req request, idMappings *idtools.IDM return err } // figure out what the permissions should be + if req.PutOptions.StripSetuidBit && hdr.Mode&cISUID == cISUID { + hdr.Mode &^= cISUID + } + if req.PutOptions.StripSetgidBit && hdr.Mode&cISGID == cISGID { + hdr.Mode &^= cISGID + } + if req.PutOptions.StripStickyBit && hdr.Mode&cISVTX == cISVTX { + hdr.Mode &^= cISVTX + } if hdr.Typeflag == tar.TypeDir { if req.PutOptions.ChmodDirs != nil { hdr.Mode = int64(*req.PutOptions.ChmodDirs) diff --git a/copier/copier_test.go b/copier/copier_test.go index 857369980..f8430d745 100644 --- a/copier/copier_test.go +++ b/copier/copier_test.go @@ -579,6 +579,36 @@ func testPut(t *testing.T) { }) } } + + for _, stripSetuidBit := range []bool{false, true} { + for _, stripSetgidBit := range []bool{false, true} { + for _, stripStickyBit := range []bool{false, true} { + t.Run(fmt.Sprintf("stripSetuidBit=%v,stripSetgidBit=%v,stripStickyBit=%v", stripSetuidBit, stripSetgidBit, stripStickyBit), func(t *testing.T) { + mode := int64(0o700) | cISUID | cISGID | cISVTX + archive := makeArchiveSlice([]tar.Header{ + {Name: "test", Typeflag: tar.TypeReg, Size: 0, Mode: mode, ModTime: testDate}, + }) + tmp, err := ioutil.TempDir("", "copier-test-") + require.NoErrorf(t, err, "error creating temporary directory") + defer os.RemoveAll(tmp) + putOptions := PutOptions{ + UIDMap: uidMap, + GIDMap: gidMap, + StripSetuidBit: stripSetuidBit, + StripSetgidBit: stripSetgidBit, + StripStickyBit: stripStickyBit, + } + err = Put(tmp, tmp, putOptions, bytes.NewReader(archive)) + require.Nilf(t, err, "unexpected error writing sample file", err) + st, err := os.Stat(filepath.Join(tmp, "test")) + require.Nilf(t, err, "unexpected error checking permissions of file", err) + assert.Equalf(t, stripSetuidBit, st.Mode()&os.ModeSetuid == 0, "setuid bit was not set/stripped correctly") + assert.Equalf(t, stripSetgidBit, st.Mode()&os.ModeSetgid == 0, "setgid bit was not set/stripped correctly") + assert.Equalf(t, stripStickyBit, st.Mode()&os.ModeSticky == 0, "sticky bit was not set/stripped correctly") + }) + } + } + } } func isExpectedError(err error, inSubdir bool, name string, expectedErrors []expectedError) bool {