Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5df0e3139 |
@@ -313,7 +313,8 @@ func alreadyPresent(dest, localPath string, entry *mfer.MFFilePath) bool {
|
||||
}
|
||||
|
||||
// A recorded mode of 0 means none was recorded.
|
||||
if entry.GetMode() != 0 && info.Mode().Perm() != os.FileMode(entry.GetMode()) {
|
||||
if entry.GetMode() != 0 &&
|
||||
info.Mode().Perm() != os.FileMode(entry.GetMode()).Perm() {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -884,10 +885,11 @@ func saveResponse(
|
||||
return err
|
||||
}
|
||||
|
||||
// A recorded mode of 0 means none was recorded. Any other is set as
|
||||
// it is, whatever the umask: fetchManifest refused modes above 0777.
|
||||
// A recorded mode of 0 means none was recorded. Of any other, only the
|
||||
// permission bits are set, whatever the umask, so setuid, setgid and
|
||||
// sticky never are, whichever caller passed the entry.
|
||||
if entry.GetMode() != 0 {
|
||||
err = out.Chmod(os.FileMode(entry.GetMode()))
|
||||
err = out.Chmod(os.FileMode(entry.GetMode()).Perm())
|
||||
if err != nil {
|
||||
_ = out.Close()
|
||||
_ = os.Remove(filepath.Join(dest, tmpPath))
|
||||
|
||||
@@ -1389,9 +1389,10 @@ func TestFetchSetsRecordedMode(t *testing.T) {
|
||||
[]string{"/" + defaultManifestName, "/" + testFileTxt}, requested)
|
||||
}
|
||||
|
||||
// TestFetchRefusesModeOutsidePermissionBits fetches a manifest that
|
||||
// records a mode with the setuid bit. fetch must refuse it before it
|
||||
// creates the destination or requests any file.
|
||||
// TestFetchRefusesModeOutsidePermissionBits fetches manifests that record
|
||||
// a mode with the setuid bit, once as Unix writes it (04755) and once as
|
||||
// Go keeps it in os.FileMode. fetch must refuse both before it creates the
|
||||
// destination or requests any file.
|
||||
func TestFetchRefusesModeOutsidePermissionBits(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -1399,6 +1400,50 @@ func TestFetchRefusesModeOutsidePermissionBits(t *testing.T) {
|
||||
|
||||
assertFetchRefused(t, manifestWithMode(t, testFileTxt, files[testFileTxt], 0o4755),
|
||||
files, "manifest lists a mode outside 0777: file.txt (04755)")
|
||||
|
||||
assertFetchRefused(t,
|
||||
manifestWithMode(t, testFileTxt, files[testFileTxt],
|
||||
uint32(os.ModeSetuid|0o755)),
|
||||
files, "manifest lists a mode outside 0777: file.txt (040000755)")
|
||||
}
|
||||
|
||||
// TestDownloadFileSetsOnlyPermissionBits downloads a file whose entry
|
||||
// records mode 0755 together with setuid, setgid or sticky, as Go keeps
|
||||
// them in os.FileMode. fetchManifest would refuse such an entry; called
|
||||
// directly, downloadFile must still set only the permission bits.
|
||||
func TestDownloadFileSetsOnlyPermissionBits(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
content := []byte("#!/bin/sh\n")
|
||||
|
||||
digest := sha256.Sum256(content)
|
||||
hash, err := multihash.Encode(digest[:], multihash.SHA2_256)
|
||||
require.NoError(t, err)
|
||||
|
||||
server := httptest.NewServer(
|
||||
http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
_, _ = w.Write(content)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
for _, special := range []os.FileMode{os.ModeSetuid, os.ModeSetgid, os.ModeSticky} {
|
||||
entry := &mfer.MFFilePath{
|
||||
Path: testFileTxt,
|
||||
Size: int64(len(content)),
|
||||
Hashes: []*mfer.MFFileChecksum{{MultiHash: hash}},
|
||||
Mode: uint32(special | 0o755),
|
||||
}
|
||||
|
||||
dest := t.TempDir()
|
||||
|
||||
err := downloadFile(context.Background(), testClient(),
|
||||
server.URL+"/"+testFileTxt, dest, testFileTxt, entry, nil)
|
||||
require.NoError(t, err, special)
|
||||
|
||||
info, err := os.Stat(filepath.Join(dest, testFileTxt))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, os.FileMode(0o755), info.Mode(), special)
|
||||
}
|
||||
}
|
||||
|
||||
// manifestWithMode returns a manifest listing one file, path, with content
|
||||
|
||||
Reference in New Issue
Block a user