mirror of
https://github.com/octoleo/restic.git
synced 2024-11-25 14:17:42 +00:00
rclone/sftp: Improve handling of ErrDot errors
Restic now yields a more informative error message when exec.ErrDot occurs.
This commit is contained in:
parent
d6575f53ca
commit
ebe9f2c969
15
changelog/unreleased/issue-3932
Normal file
15
changelog/unreleased/issue-3932
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Enhancement: Improve handling of ErrDot errors in rclone and sftp backends
|
||||||
|
|
||||||
|
Since Go 1.19, restic can no longer implicitly run relative executables which
|
||||||
|
are found in the current directory (e.g. `rclone` if it's found in `.`). This
|
||||||
|
is a security feature of Go to prevent against running unintended and possibly
|
||||||
|
harmful executables.
|
||||||
|
|
||||||
|
The error message for this was just "cannot run executable found relative to
|
||||||
|
current directory". This has now been improved to yield a more specific error
|
||||||
|
message, informing the user how to explicitly allow running the executable
|
||||||
|
using the `-o rclone.program` and `-o sftp.command` extended options with `./`.
|
||||||
|
|
||||||
|
https://github.com/restic/restic/issues/3932
|
||||||
|
https://pkg.go.dev/os/exec#hdr-Executables_in_the_current_directory
|
||||||
|
https://go.dev/blog/path-security
|
@ -633,6 +633,13 @@ initiate a new repository in the path ``bar`` in the remote ``foo``:
|
|||||||
|
|
||||||
Restic takes care of starting and stopping rclone.
|
Restic takes care of starting and stopping rclone.
|
||||||
|
|
||||||
|
.. note:: If you get an error message saying "cannot implicitly run relative
|
||||||
|
executable rclone found in current directory", this means that an
|
||||||
|
rclone executable was found in the current directory. For security
|
||||||
|
reasons restic will not run this implicitly, instead you have to
|
||||||
|
use the ``-o rclone.program=./rclone`` extended option to override
|
||||||
|
this security check and explicitly tell restic to use the executable.
|
||||||
|
|
||||||
As a more concrete example, suppose you have configured a remote named
|
As a more concrete example, suppose you have configured a remote named
|
||||||
``b2prod`` for Backblaze B2 with rclone, with a bucket called ``yggdrasil``.
|
``b2prod`` for Backblaze B2 with rclone, with a bucket called ``yggdrasil``.
|
||||||
You can then use rclone to list files in the bucket like this:
|
You can then use rclone to list files in the bucket like this:
|
||||||
|
20
internal/backend/errdot_119.go
Normal file
20
internal/backend/errdot_119.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//go:build go1.19
|
||||||
|
// +build go1.19
|
||||||
|
|
||||||
|
// This file provides a function to check whether an error from cmd.Start() is
|
||||||
|
// exec.ErrDot which was introduced in Go 1.19.
|
||||||
|
// This function is needed so that we can perform this check only for Go 1.19 and
|
||||||
|
// up, whereas for older versions we use a dummy/stub in the file errdot_old.go.
|
||||||
|
// Once the minimum Go version restic supports is 1.19, remove this file and
|
||||||
|
// replace any calls to it with the corresponding code as per below.
|
||||||
|
|
||||||
|
package backend
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsErrDot(err error) bool {
|
||||||
|
return errors.Is(err, exec.ErrDot)
|
||||||
|
}
|
13
internal/backend/errdot_old.go
Normal file
13
internal/backend/errdot_old.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//go:build !go1.19
|
||||||
|
// +build !go1.19
|
||||||
|
|
||||||
|
// This file provides a stub for IsErrDot() for Go versions below 1.19.
|
||||||
|
// See the corresponding file errdot_119.go for more information.
|
||||||
|
// Once the minimum Go version restic supports is 1.19, remove this file
|
||||||
|
// and perform the actions listed in errdot_119.go.
|
||||||
|
|
||||||
|
package backend
|
||||||
|
|
||||||
|
func IsErrDot(err error) bool {
|
||||||
|
return false
|
||||||
|
}
|
@ -85,6 +85,9 @@ func run(command string, args ...string) (*StdioConn, *sync.WaitGroup, func() er
|
|||||||
err = errW
|
err = errW
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if backend.IsErrDot(err) {
|
||||||
|
return nil, nil, nil, errors.Errorf("cannot implicitly run relative executable %v found in current directory, use -o rclone.program=./<program> to override", cmd.Path)
|
||||||
|
}
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,10 @@ func startClient(cfg Config) (*SFTP, error) {
|
|||||||
|
|
||||||
bg, err := backend.StartForeground(cmd)
|
bg, err := backend.StartForeground(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "cmd.Start")
|
if backend.IsErrDot(err) {
|
||||||
|
return nil, errors.Errorf("cannot implicitly run relative executable %v found in current directory, use -o sftp.command=./<command> to override", cmd.Path)
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait in a different goroutine
|
// wait in a different goroutine
|
||||||
|
Loading…
Reference in New Issue
Block a user