Merge pull request #5019 from MichaelEischer/fix-windows-sd-race

backup: Fix spurious "A Required Privilege Is Not Held by the Client" error
This commit is contained in:
Michael Eischer 2024-08-29 16:59:06 +02:00 committed by GitHub
commit a0f2dfbc19
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 22 additions and 12 deletions

View file

@ -0,0 +1,12 @@
Bugfix: Fix spurious "A Required Privilege Is Not Held by the Client" error
On Windows, creating a backup could sometimes print the following error
```
error: nodeFromFileInfo [...]: get named security info failed with: a required privilege is not held by the client.
```
This has been fixed.
https://github.com/restic/restic/issues/5004
https://github.com/restic/restic/pull/5019

View file

@ -48,19 +48,18 @@ func GetSecurityDescriptor(filePath string) (securityDescriptor *[]byte, err err
var sd *windows.SECURITY_DESCRIPTOR var sd *windows.SECURITY_DESCRIPTOR
if lowerPrivileges.Load() { // store original value to avoid unrelated changes in the error check
useLowerPrivileges := lowerPrivileges.Load()
if useLowerPrivileges {
sd, err = getNamedSecurityInfoLow(filePath) sd, err = getNamedSecurityInfoLow(filePath)
} else { } else {
sd, err = getNamedSecurityInfoHigh(filePath) sd, err = getNamedSecurityInfoHigh(filePath)
} }
if err != nil { if err != nil {
if !lowerPrivileges.Load() && isHandlePrivilegeNotHeldError(err) { if !useLowerPrivileges && isHandlePrivilegeNotHeldError(err) {
// If ERROR_PRIVILEGE_NOT_HELD is encountered, fallback to backups/restores using lower non-admin privileges. // If ERROR_PRIVILEGE_NOT_HELD is encountered, fallback to backups/restores using lower non-admin privileges.
lowerPrivileges.Store(true) lowerPrivileges.Store(true)
sd, err = getNamedSecurityInfoLow(filePath) return GetSecurityDescriptor(filePath)
if err != nil {
return nil, fmt.Errorf("get low-level named security info failed with: %w", err)
}
} else if errors.Is(err, windows.ERROR_NOT_SUPPORTED) { } else if errors.Is(err, windows.ERROR_NOT_SUPPORTED) {
return nil, nil return nil, nil
} else { } else {
@ -109,20 +108,19 @@ func SetSecurityDescriptor(filePath string, securityDescriptor *[]byte) error {
sacl = nil sacl = nil
} }
if lowerPrivileges.Load() { // store original value to avoid unrelated changes in the error check
useLowerPrivileges := lowerPrivileges.Load()
if useLowerPrivileges {
err = setNamedSecurityInfoLow(filePath, dacl) err = setNamedSecurityInfoLow(filePath, dacl)
} else { } else {
err = setNamedSecurityInfoHigh(filePath, owner, group, dacl, sacl) err = setNamedSecurityInfoHigh(filePath, owner, group, dacl, sacl)
} }
if err != nil { if err != nil {
if !lowerPrivileges.Load() && isHandlePrivilegeNotHeldError(err) { if !useLowerPrivileges && isHandlePrivilegeNotHeldError(err) {
// If ERROR_PRIVILEGE_NOT_HELD is encountered, fallback to backups/restores using lower non-admin privileges. // If ERROR_PRIVILEGE_NOT_HELD is encountered, fallback to backups/restores using lower non-admin privileges.
lowerPrivileges.Store(true) lowerPrivileges.Store(true)
err = setNamedSecurityInfoLow(filePath, dacl) return SetSecurityDescriptor(filePath, securityDescriptor)
if err != nil {
return fmt.Errorf("set low-level named security info failed with: %w", err)
}
} else { } else {
return fmt.Errorf("set named security info failed with: %w", err) return fmt.Errorf("set named security info failed with: %w", err)
} }