forked from TrueCloudLab/restic
fs: fallback to low privilege security descriptors on access denied
This commit is contained in:
parent
d46525a51b
commit
7bfe3d99ae
2 changed files with 36 additions and 0 deletions
14
changelog/unreleased/issue-5003
Normal file
14
changelog/unreleased/issue-5003
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
Bugfix: fix metadata errors during backup of removable disks on Windows
|
||||||
|
|
||||||
|
Since restic 0.17.0, backups of removable disks on Windows could report
|
||||||
|
errors with retrieving metadata like shown below.
|
||||||
|
|
||||||
|
```
|
||||||
|
error: incomplete metadata for d:\filename: get named security info failed with: Access is denied.
|
||||||
|
```
|
||||||
|
|
||||||
|
This has now been fixed.
|
||||||
|
|
||||||
|
https://github.com/restic/restic/issues/5003
|
||||||
|
https://github.com/restic/restic/pull/5123
|
||||||
|
https://forum.restic.net/t/backing-up-a-folder-from-a-veracrypt-volume-brings-up-errors-since-restic-v17-0/8444
|
|
@ -54,6 +54,15 @@ func GetSecurityDescriptor(filePath string) (securityDescriptor *[]byte, err err
|
||||||
sd, err = getNamedSecurityInfoLow(filePath)
|
sd, err = getNamedSecurityInfoLow(filePath)
|
||||||
} else {
|
} else {
|
||||||
sd, err = getNamedSecurityInfoHigh(filePath)
|
sd, err = getNamedSecurityInfoHigh(filePath)
|
||||||
|
// Fallback to the low privilege version when receiving an access denied error.
|
||||||
|
// For some reason the ERROR_PRIVILEGE_NOT_HELD error is not returned for removable media
|
||||||
|
// but instead an access denied error is returned. Workaround that by just retrying with
|
||||||
|
// the low privilege version, but don't switch privileges as we cannot distinguish this
|
||||||
|
// case from actual access denied errors.
|
||||||
|
// see https://github.com/restic/restic/issues/5003#issuecomment-2452314191 for details
|
||||||
|
if err != nil && isAccessDeniedError(err) {
|
||||||
|
sd, err = getNamedSecurityInfoLow(filePath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !useLowerPrivileges && isHandlePrivilegeNotHeldError(err) {
|
if !useLowerPrivileges && isHandlePrivilegeNotHeldError(err) {
|
||||||
|
@ -114,6 +123,10 @@ func SetSecurityDescriptor(filePath string, securityDescriptor *[]byte) error {
|
||||||
err = setNamedSecurityInfoLow(filePath, dacl)
|
err = setNamedSecurityInfoLow(filePath, dacl)
|
||||||
} else {
|
} else {
|
||||||
err = setNamedSecurityInfoHigh(filePath, owner, group, dacl, sacl)
|
err = setNamedSecurityInfoHigh(filePath, owner, group, dacl, sacl)
|
||||||
|
// See corresponding fallback in getSecurityDescriptor for an explanation
|
||||||
|
if err != nil && isAccessDeniedError(err) {
|
||||||
|
err = setNamedSecurityInfoLow(filePath, dacl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -174,6 +187,15 @@ func isHandlePrivilegeNotHeldError(err error) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isAccessDeniedError checks if the error is ERROR_ACCESS_DENIED
|
||||||
|
func isAccessDeniedError(err error) bool {
|
||||||
|
if errno, ok := err.(syscall.Errno); ok {
|
||||||
|
// Compare the error code to the expected value
|
||||||
|
return errno == windows.ERROR_ACCESS_DENIED
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// SecurityDescriptorBytesToStruct converts the security descriptor bytes representation
|
// SecurityDescriptorBytesToStruct converts the security descriptor bytes representation
|
||||||
// into a pointer to windows SECURITY_DESCRIPTOR.
|
// into a pointer to windows SECURITY_DESCRIPTOR.
|
||||||
func SecurityDescriptorBytesToStruct(sd []byte) (*windows.SECURITY_DESCRIPTOR, error) {
|
func SecurityDescriptorBytesToStruct(sd []byte) (*windows.SECURITY_DESCRIPTOR, error) {
|
||||||
|
|
Loading…
Reference in a new issue