fix(windows): protect existing lifecycle child first

This commit is contained in:
2026-08-18 14:11:41 +02:00
parent ada3f9fc7f
commit afb0e21200
+25 -8
View File
@@ -50,14 +50,31 @@ type Transaction struct {
// Acquire obtains the shared lock used by backup, restore, Pi lifecycle and product updates.
func Acquire(installation config.Installation) (*Lock, error) {
directory := installation.ControlDirectory()
// The lifecycle directory is also the restore staging parent. Protect both the shared
// .tht directory and this installation's child before any lock or staging artifact is
// created; chmod alone does not install an owner-only DACL on Windows.
if err := ensurePrivateLifecycleDirectory(filepath.Dir(directory)); err != nil {
return nil, fmt.Errorf("protect lifecycle control parent: %w", err)
}
if err := ensurePrivateLifecycleDirectory(directory); err != nil {
return nil, fmt.Errorf("protect lifecycle control directory: %w", err)
parent := filepath.Dir(directory)
// The lifecycle directory is also the restore staging parent. An existing Windows child
// must be protected before its parent: replacing the parent's inheritable ACL first can
// remove the child's inherited owner authority before the child receives its protected DACL.
// For a new installation the parent must instead exist before safe child creation.
controlInfo, controlErr := os.Lstat(directory)
if controlErr == nil {
if !controlInfo.IsDir() || controlInfo.Mode()&os.ModeSymlink != 0 {
return nil, errors.New("lifecycle control directory is not a regular directory")
}
if err := ensurePrivateLifecycleDirectory(directory); err != nil {
return nil, fmt.Errorf("protect lifecycle control directory: %w", err)
}
if err := ensurePrivateLifecycleDirectory(parent); err != nil {
return nil, fmt.Errorf("protect lifecycle control parent: %w", err)
}
} else if errors.Is(controlErr, os.ErrNotExist) {
if err := ensurePrivateLifecycleDirectory(parent); err != nil {
return nil, fmt.Errorf("protect lifecycle control parent: %w", err)
}
if err := ensurePrivateLifecycleDirectory(directory); err != nil {
return nil, fmt.Errorf("protect lifecycle control directory: %w", err)
}
} else {
return nil, errors.New("lifecycle control directory is unavailable")
}
info, err := os.Lstat(directory)
if err != nil || !info.IsDir() || info.Mode()&os.ModeSymlink != 0 {