diff --git a/pkg/util/fs_util.go b/pkg/util/fs_util.go index 38b25bc518..8eae159540 100644 --- a/pkg/util/fs_util.go +++ b/pkg/util/fs_util.go @@ -216,16 +216,17 @@ func extractFile(dest string, hdr *tar.Header, tr io.Reader) error { if err != nil { return err } - // manually set permissions on file, since the default umask (022) will interfere - if err = os.Chmod(path, mode); err != nil { - return err - } if _, err = io.Copy(currFile, tr); err != nil { return err } if err = currFile.Chown(uid, gid); err != nil { return err } + // manually set permissions on file, since the default umask (022) will interfere + // Must chmod after chown because chown resets the file mode. + if err = currFile.Chmod(mode); err != nil { + return err + } currFile.Close() case tar.TypeDir: logrus.Debugf("creating dir %s", path) diff --git a/pkg/util/fs_util_test.go b/pkg/util/fs_util_test.go index 4f91343f8d..73eab847ba 100644 --- a/pkg/util/fs_util_test.go +++ b/pkg/util/fs_util_test.go @@ -19,6 +19,7 @@ package util import ( "archive/tar" "bytes" + "fmt" "io/ioutil" "os" "path/filepath" @@ -503,6 +504,16 @@ func TestExtractFile(t *testing.T) { filesAreHardlinks("/bin/uncompress", "/bin/gzip"), }, }, + { + name: "file with setuid bit", + contents: []byte("helloworld"), + hdrs: []*tar.Header{fileHeader("./bar", "helloworld", 04644)}, + checkers: []checker{ + fileExists("/bar"), + fileMatches("/bar", []byte("helloworld")), + permissionsMatch("/bar", 0644|os.ModeSetuid), + }, + }, } for _, tc := range tcs {