Skip to content

Commit b25edf5

Browse files
authored
Merge pull request #4354 from apostasie/2025-06-fixes
Hardening: internal/filesystem: prevent inode change on failure
2 parents 6fb2b45 + dc7971f commit b25edf5

File tree

2 files changed

+17
-10
lines changed

2 files changed

+17
-10
lines changed

pkg/internal/filesystem/helpers.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ func ensureRecovery(filename string) (err error) {
5454
if err = backupRestore(filename); err != nil {
5555
return err
5656
}
57+
_ = backupRemove(filename)
5758
} else {
5859
// We do not see a backup.
5960
// Do we have a final destination then?
@@ -101,6 +102,10 @@ func backupRestore(path string) error {
101102
return err
102103
}
103104

105+
func backupRemove(path string) error {
106+
return os.Remove(backupLocation(path))
107+
}
108+
104109
// backupExists checks if a backup file exists for file located at `path`.
105110
func backupExists(path string) (bool, error) {
106111
_, err := os.Stat(backupLocation(path))
@@ -190,16 +195,16 @@ func internalCopy(sourcePath, destinationPath string) (err error) {
190195
return err
191196
}
192197

198+
defer func() {
199+
err = errors.Join(err, source.Close())
200+
}()
201+
193202
// Read file length
194203
srcInfo, err := source.Stat()
195204
if err != nil {
196205
return err
197206
}
198207

199-
defer func() {
200-
err = errors.Join(err, source.Close())
201-
}()
202-
203208
return fileWrite(source, srcInfo.Size(), destinationPath, privateFilePermission, srcInfo.ModTime())
204209
}
205210

@@ -220,11 +225,6 @@ func fileWrite(source io.Reader, size int64, destinationPath string, perm os.Fil
220225
if mustClose {
221226
err = errors.Join(err, destination.Close())
222227
}
223-
224-
// Remove destination if we failed anywhere. Ignore removal failures.
225-
if err != nil {
226-
_ = os.Remove(destinationPath)
227-
}
228228
}()
229229

230230
// Copy over

pkg/internal/filesystem/writefile_rollback.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,22 @@ func WriteFileWithRollback(filename string, data []byte, perm os.FileMode) (roll
6161
}
6262
}
6363

64+
// Make sure no leftover backup file is here
65+
// Note: this happens after a successful write. Generally not a problem, except if the file is then deleted,
66+
// then written to again, and that second write would fail.
67+
_ = backupRemove(filename)
68+
6469
// Create the marker. Failure to do so is a hard error.
6570
if err = markerCreate(filename, markerData); err != nil {
6671
return nil, err
6772
}
6873

6974
// If the file exists, we need to back it up.
7075
if markerData == "" {
71-
// Back it up now.
76+
// Back it up now. Remove on failure.
7277
if err = backupSave(filename); err != nil {
78+
_ = backupRemove(filename)
79+
_ = markerRemove(filename)
7380
return nil, err
7481
}
7582
}

0 commit comments

Comments
 (0)