mirror of https://github.com/restic/restic.git
vss: fix potential crash (not reachable in restic) (#3045)
HasSufficientPrivilegesForVSS() now returns an error
This commit is contained in:
parent
a06f5c28c0
commit
916b2d303b
|
@ -556,8 +556,8 @@ func runBackup(opts BackupOptions, gopts GlobalOptions, term *termstatus.Termina
|
|||
|
||||
var targetFS fs.FS = fs.Local{}
|
||||
if runtime.GOOS == "windows" && opts.UseFsSnapshot {
|
||||
if !fs.HasSufficientPrivilegesForVSS() {
|
||||
return errors.Fatal("user doesn't have sufficient privileges to use VSS snapshots\n")
|
||||
if err = fs.HasSufficientPrivilegesForVSS(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
errorHandler := func(item string, err error) error {
|
||||
|
|
|
@ -286,7 +286,7 @@ func TestBackup(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestBackupWithFilesystemSnapshots(t *testing.T) {
|
||||
if runtime.GOOS == "windows" && fs.HasSufficientPrivilegesForVSS() {
|
||||
if runtime.GOOS == "windows" && fs.HasSufficientPrivilegesForVSS() == nil {
|
||||
testBackup(t, true)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ type VssSnapshot struct {
|
|||
}
|
||||
|
||||
// HasSufficientPrivilegesForVSS returns true if the user is allowed to use VSS.
|
||||
func HasSufficientPrivilegesForVSS() bool {
|
||||
return false
|
||||
func HasSufficientPrivilegesForVSS() error {
|
||||
return errors.New("VSS snapshots are only supported on windows")
|
||||
}
|
||||
|
||||
// NewVssSnapshot creates a new vss snapshot. If creating the snapshots doesn't
|
||||
|
|
|
@ -686,10 +686,10 @@ func (p *VssSnapshot) GetSnapshotDeviceObject() string {
|
|||
}
|
||||
|
||||
// initializeCOMInterface initialize an instance of the VSS COM api
|
||||
func initializeVssCOMInterface() (*ole.IUnknown, uintptr, error) {
|
||||
func initializeVssCOMInterface() (*ole.IUnknown, error) {
|
||||
vssInstance, err := loadIVssBackupComponentsConstructor()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ensure COM is initialized before use
|
||||
|
@ -697,22 +697,33 @@ func initializeVssCOMInterface() (*ole.IUnknown, uintptr, error) {
|
|||
|
||||
var oleIUnknown *ole.IUnknown
|
||||
result, _, _ := vssInstance.Call(uintptr(unsafe.Pointer(&oleIUnknown)))
|
||||
hresult := HRESULT(result)
|
||||
|
||||
return oleIUnknown, result, nil
|
||||
switch hresult {
|
||||
case S_OK:
|
||||
case E_ACCESSDENIED:
|
||||
return oleIUnknown, newVssError(
|
||||
"The caller does not have sufficient backup privileges or is not an administrator",
|
||||
hresult)
|
||||
default:
|
||||
return oleIUnknown, newVssError("Failed to create VSS instance", hresult)
|
||||
}
|
||||
|
||||
if oleIUnknown == nil {
|
||||
return nil, newVssError("Failed to initialize COM interface", hresult)
|
||||
}
|
||||
|
||||
return oleIUnknown, nil
|
||||
}
|
||||
|
||||
// HasSufficientPrivilegesForVSS returns true if the user is allowed to use VSS.
|
||||
func HasSufficientPrivilegesForVSS() bool {
|
||||
oleIUnknown, result, err := initializeVssCOMInterface()
|
||||
// HasSufficientPrivilegesForVSS returns nil if the user is allowed to use VSS.
|
||||
func HasSufficientPrivilegesForVSS() error {
|
||||
oleIUnknown, err := initializeVssCOMInterface()
|
||||
if oleIUnknown != nil {
|
||||
oleIUnknown.Release()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return !(HRESULT(result) == E_ACCESSDENIED)
|
||||
return err
|
||||
}
|
||||
|
||||
// NewVssSnapshot creates a new vss snapshot. If creating the snapshots doesn't
|
||||
|
@ -734,24 +745,12 @@ func NewVssSnapshot(
|
|||
|
||||
timeoutInMillis := uint32(timeoutInSeconds * 1000)
|
||||
|
||||
oleIUnknown, result, err := initializeVssCOMInterface()
|
||||
if err != nil {
|
||||
if oleIUnknown != nil {
|
||||
oleIUnknown.Release()
|
||||
}
|
||||
return VssSnapshot{}, err
|
||||
oleIUnknown, err := initializeVssCOMInterface()
|
||||
if oleIUnknown != nil {
|
||||
defer oleIUnknown.Release()
|
||||
}
|
||||
defer oleIUnknown.Release()
|
||||
|
||||
switch HRESULT(result) {
|
||||
case S_OK:
|
||||
case E_ACCESSDENIED:
|
||||
return VssSnapshot{}, newVssTextError(fmt.Sprintf("%s (%#x) The caller does not have "+
|
||||
"sufficient backup privileges or is not an administrator.", HRESULT(result).Str(),
|
||||
result))
|
||||
default:
|
||||
return VssSnapshot{}, newVssTextError(fmt.Sprintf("Failed to create VSS instance: %s (%#x)",
|
||||
HRESULT(result).Str(), result))
|
||||
if err != nil {
|
||||
return VssSnapshot{}, err
|
||||
}
|
||||
|
||||
comInterface, err := queryInterface(oleIUnknown, UUID_IVSS)
|
||||
|
|
Loading…
Reference in New Issue