Allow safe custom restore targets

This commit is contained in:
Mikei386
2026-06-21 16:22:43 +02:00
parent 7dd0685a5a
commit cc6d370c05
9 changed files with 37 additions and 14 deletions
+14 -5
View File
@@ -16,11 +16,7 @@ func ValidateRestoreTarget(target, restoreRoot string, inPlace, confirmed bool)
return "", errors.New("validation: protected system restore target")
}
if !inPlace {
root := filepath.Clean(restoreRoot)
if clean != root && !strings.HasPrefix(clean, root+string(os.PathSeparator)) {
return "", errors.New("validation: staging restore must remain below restoreRoot")
}
if err := rejectSymlinks(root, clean); err != nil {
if err := validateStagingRestoreTarget(clean, restoreRoot); err != nil {
return "", err
}
} else if !confirmed {
@@ -35,6 +31,19 @@ func ValidateRestoreTarget(target, restoreRoot string, inPlace, confirmed bool)
return clean, nil
}
func validateStagingRestoreTarget(target, restoreRoot string) error {
allowedRoots := []string{filepath.Clean(restoreRoot), "/mnt/user", "/mnt/disks", "/mnt/remotes"}
for _, root := range allowedRoots {
if root == "." || root == "" {
continue
}
if target == root || strings.HasPrefix(target, root+string(os.PathSeparator)) {
return rejectSymlinks(root, target)
}
}
return errors.New("validation: staging restore target must be below restoreRoot, /mnt/user, /mnt/disks, or /mnt/remotes")
}
func rejectSymlinks(root, target string) error {
relative, err := filepath.Rel(root, target)
if err != nil {
+6
View File
@@ -12,6 +12,12 @@ func TestValidateRestoreTarget(t *testing.T) {
if got, err := ValidateRestoreTarget(target, root, false, false); err != nil || got != target {
t.Fatalf("staging target rejected: %q %v", got, err)
}
if got, err := ValidateRestoreTarget("/mnt/user/Transfer", root, false, false); err != nil || got != "/mnt/user/Transfer" {
t.Fatalf("user share restore target rejected: %q %v", got, err)
}
if _, err := ValidateRestoreTarget("/home/root/restore", root, false, false); err == nil {
t.Fatal("staging target outside allowed restore roots accepted")
}
if _, err := ValidateRestoreTarget("/etc", root, true, true); err == nil {
t.Fatal("protected target accepted")
}