forked from TrueCloudLab/restic
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
6 changed files with 62 additions and 1 deletions
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.
|
||||
|
||||
.. 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
|
||||
``b2prod`` for Backblaze B2 with rclone, with a bucket called ``yggdrasil``.
|
||||
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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,10 @@ func startClient(cfg Config) (*SFTP, error) {
|
|||
|
||||
bg, err := backend.StartForeground(cmd)
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue