diff --git a/archive/compression/compression.go b/archive/compression/compression.go index a883e4d58..b82c60a36 100644 --- a/archive/compression/compression.go +++ b/archive/compression/compression.go @@ -24,12 +24,12 @@ import ( "fmt" "io" "os" - "os/exec" "strconv" "sync" "github.com/containerd/containerd/log" "github.com/klauspost/compress/zstd" + exec "golang.org/x/sys/execabs" ) type ( diff --git a/archive/compression/compression_test.go b/archive/compression/compression_test.go index 7f00e9fcd..5b16fcf2d 100644 --- a/archive/compression/compression_test.go +++ b/archive/compression/compression_test.go @@ -24,11 +24,12 @@ import ( "io/ioutil" "math/rand" "os" - "os/exec" "path/filepath" "runtime" "strings" "testing" + + exec "golang.org/x/sys/execabs" ) func TestMain(m *testing.M) { diff --git a/archive/tar_test.go b/archive/tar_test.go index 13879672b..1e0a29ab9 100644 --- a/archive/tar_test.go +++ b/archive/tar_test.go @@ -27,7 +27,6 @@ import ( "io" "io/ioutil" "os" - "os/exec" "path/filepath" "testing" "time" @@ -39,6 +38,7 @@ import ( "github.com/containerd/continuity/fs" "github.com/containerd/continuity/fs/fstest" "github.com/pkg/errors" + exec "golang.org/x/sys/execabs" ) const tarCmd = "tar" diff --git a/cmd/containerd-shim/main_unix.go b/cmd/containerd-shim/main_unix.go index 10c64cdcb..0ba452d35 100644 --- a/cmd/containerd-shim/main_unix.go +++ b/cmd/containerd-shim/main_unix.go @@ -27,7 +27,6 @@ import ( "io" "net" "os" - "os/exec" "os/signal" "runtime" "runtime/debug" @@ -48,6 +47,7 @@ import ( ptypes "github.com/gogo/protobuf/types" "github.com/pkg/errors" "github.com/sirupsen/logrus" + exec "golang.org/x/sys/execabs" "golang.org/x/sys/unix" ) diff --git a/cmd/containerd/command/service_windows.go b/cmd/containerd/command/service_windows.go index d683c1836..a0700ccb7 100644 --- a/cmd/containerd/command/service_windows.go +++ b/cmd/containerd/command/service_windows.go @@ -21,7 +21,6 @@ import ( "io/ioutil" "log" "os" - "os/exec" "path/filepath" "time" "unsafe" @@ -31,6 +30,7 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/urfave/cli" + exec "golang.org/x/sys/execabs" "golang.org/x/sys/windows" "golang.org/x/sys/windows/svc" "golang.org/x/sys/windows/svc/debug" diff --git a/cmd/ctr/commands/content/content.go b/cmd/ctr/commands/content/content.go index 6f61fca38..99ed64ebd 100644 --- a/cmd/ctr/commands/content/content.go +++ b/cmd/ctr/commands/content/content.go @@ -21,7 +21,6 @@ import ( "io" "io/ioutil" "os" - "os/exec" "strings" "text/tabwriter" "time" @@ -35,6 +34,7 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" "github.com/urfave/cli" + exec "golang.org/x/sys/execabs" ) var ( diff --git a/contrib/apparmor/template.go b/contrib/apparmor/template.go index 6e0af2840..f105334d5 100644 --- a/contrib/apparmor/template.go +++ b/contrib/apparmor/template.go @@ -27,13 +27,13 @@ import ( "io" "io/ioutil" "os" - "os/exec" "path" "strconv" "strings" "text/template" "github.com/pkg/errors" + exec "golang.org/x/sys/execabs" ) // NOTE: This code is copied from . diff --git a/contrib/fuzz/container_fuzzer.go b/contrib/fuzz/container_fuzzer.go index 2433db677..4bc292580 100644 --- a/contrib/fuzz/container_fuzzer.go +++ b/contrib/fuzz/container_fuzzer.go @@ -26,17 +26,18 @@ import ( "context" "errors" "fmt" - fuzz "github.com/AdaLogics/go-fuzz-headers" - "github.com/containerd/containerd" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/sys" "io" "io/ioutil" "net/http" "os" - "os/exec" "strings" "time" + + fuzz "github.com/AdaLogics/go-fuzz-headers" + "github.com/containerd/containerd" + "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/sys" + exec "golang.org/x/sys/execabs" ) var ( diff --git a/contrib/nvidia/nvidia.go b/contrib/nvidia/nvidia.go index d08044aa2..a808dd166 100644 --- a/contrib/nvidia/nvidia.go +++ b/contrib/nvidia/nvidia.go @@ -20,13 +20,13 @@ import ( "context" "fmt" "os" - "os/exec" "strconv" "strings" "github.com/containerd/containerd/containers" "github.com/containerd/containerd/oci" specs "github.com/opencontainers/runtime-spec/specs-go" + exec "golang.org/x/sys/execabs" ) // NvidiaCLI is the path to the Nvidia helper binary diff --git a/diff/stream_unix.go b/diff/stream_unix.go index 37d0709b7..fd8adc223 100644 --- a/diff/stream_unix.go +++ b/diff/stream_unix.go @@ -25,12 +25,12 @@ import ( "fmt" "io" "os" - "os/exec" "sync" "github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/types" "github.com/pkg/errors" + exec "golang.org/x/sys/execabs" ) // NewBinaryProcessor returns a binary processor for use with processing content streams diff --git a/diff/stream_windows.go b/diff/stream_windows.go index 1bb96f6e6..8f03d2f4c 100644 --- a/diff/stream_windows.go +++ b/diff/stream_windows.go @@ -23,7 +23,6 @@ import ( "io" "io/ioutil" "os" - "os/exec" "path/filepath" "sync" @@ -32,6 +31,7 @@ import ( "github.com/gogo/protobuf/types" "github.com/pkg/errors" "github.com/sirupsen/logrus" + exec "golang.org/x/sys/execabs" ) const processorPipe = "STREAM_PROCESSOR_PIPE" diff --git a/integration/client/client_test.go b/integration/client/client_test.go index 022669ae1..e93fe1931 100644 --- a/integration/client/client_test.go +++ b/integration/client/client_test.go @@ -24,7 +24,6 @@ import ( "io" "io/ioutil" "os" - "os/exec" "testing" "time" @@ -42,6 +41,7 @@ import ( "github.com/opencontainers/go-digest" "github.com/opencontainers/image-spec/identity" "github.com/sirupsen/logrus" + exec "golang.org/x/sys/execabs" ) var ( diff --git a/integration/client/container_linux_test.go b/integration/client/container_linux_test.go index 5285ebd01..cbdae0908 100644 --- a/integration/client/container_linux_test.go +++ b/integration/client/container_linux_test.go @@ -23,7 +23,6 @@ import ( "io" "io/ioutil" "os" - "os/exec" "path/filepath" "runtime" "strings" @@ -50,6 +49,7 @@ import ( "github.com/containerd/typeurl" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" + exec "golang.org/x/sys/execabs" "golang.org/x/sys/unix" ) diff --git a/integration/client/container_test.go b/integration/client/container_test.go index b32a00f2e..d995a36fd 100644 --- a/integration/client/container_test.go +++ b/integration/client/container_test.go @@ -22,7 +22,6 @@ import ( "io" "io/ioutil" "os" - "os/exec" "path" "runtime" "strings" @@ -33,18 +32,18 @@ import ( . "github.com/containerd/containerd" "github.com/containerd/containerd/cio" "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/oci" "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/plugin" _ "github.com/containerd/containerd/runtime" "github.com/containerd/containerd/runtime/v2/runc/options" - "github.com/containerd/typeurl" - specs "github.com/opencontainers/runtime-spec/specs-go" - - "github.com/containerd/containerd/errdefs" "github.com/containerd/go-runc" + "github.com/containerd/typeurl" gogotypes "github.com/gogo/protobuf/types" + specs "github.com/opencontainers/runtime-spec/specs-go" + exec "golang.org/x/sys/execabs" ) func empty() cio.Creator { diff --git a/integration/client/daemon_config_linux_test.go b/integration/client/daemon_config_linux_test.go index d62e93877..564a9d271 100644 --- a/integration/client/daemon_config_linux_test.go +++ b/integration/client/daemon_config_linux_test.go @@ -23,7 +23,6 @@ import ( "fmt" "io/ioutil" "os" - "os/exec" "path/filepath" "strings" "syscall" @@ -37,6 +36,7 @@ import ( "github.com/containerd/containerd/plugin" "github.com/containerd/containerd/runtime/v2/runc/options" srvconfig "github.com/containerd/containerd/services/server/config" + exec "golang.org/x/sys/execabs" ) // the following nolint is for shutting up gometalinter on non-linux. diff --git a/integration/client/daemon_test.go b/integration/client/daemon_test.go index bf746c286..43f197ac4 100644 --- a/integration/client/daemon_test.go +++ b/integration/client/daemon_test.go @@ -19,12 +19,12 @@ package client import ( "context" "io" - "os/exec" "sync" "syscall" . "github.com/containerd/containerd" "github.com/pkg/errors" + exec "golang.org/x/sys/execabs" ) type daemon struct { diff --git a/integration/image_load_test.go b/integration/image_load_test.go index e8dfcc28b..87a2be266 100644 --- a/integration/image_load_test.go +++ b/integration/image_load_test.go @@ -19,13 +19,13 @@ package integration import ( "io/ioutil" "os" - "os/exec" "path/filepath" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + exec "golang.org/x/sys/execabs" runtime "k8s.io/cri-api/pkg/apis/runtime/v1" ) diff --git a/integration/main_test.go b/integration/main_test.go index 324f31948..94740112e 100644 --- a/integration/main_test.go +++ b/integration/main_test.go @@ -22,7 +22,6 @@ import ( "flag" "fmt" "os" - "os/exec" "path/filepath" "strconv" "strings" @@ -31,19 +30,19 @@ import ( "github.com/containerd/containerd" cri "github.com/containerd/containerd/integration/cri-api/pkg/apis" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/grpc" - runtime "k8s.io/cri-api/pkg/apis/runtime/v1" - "github.com/containerd/containerd/integration/remote" dialer "github.com/containerd/containerd/integration/util" criconfig "github.com/containerd/containerd/pkg/cri/config" "github.com/containerd/containerd/pkg/cri/constants" "github.com/containerd/containerd/pkg/cri/server" "github.com/containerd/containerd/pkg/cri/util" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + exec "golang.org/x/sys/execabs" + "google.golang.org/grpc" + runtime "k8s.io/cri-api/pkg/apis/runtime/v1" ) const ( diff --git a/integration/volume_copy_up_test.go b/integration/volume_copy_up_test.go index 65a49085d..079da9a5c 100644 --- a/integration/volume_copy_up_test.go +++ b/integration/volume_copy_up_test.go @@ -18,13 +18,13 @@ package integration import ( "fmt" - "os/exec" goruntime "runtime" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + exec "golang.org/x/sys/execabs" ) func TestVolumeCopyUp(t *testing.T) { diff --git a/mount/lookup_linux_test.go b/mount/lookup_linux_test.go index a9422ba4c..a60adff7d 100644 --- a/mount/lookup_linux_test.go +++ b/mount/lookup_linux_test.go @@ -20,7 +20,6 @@ import ( "fmt" "io/ioutil" "os" - "os/exec" "path/filepath" "strings" "testing" @@ -29,6 +28,7 @@ import ( // so we use continuity/testutil instead. "github.com/containerd/continuity/testutil" "github.com/containerd/continuity/testutil/loopback" + exec "golang.org/x/sys/execabs" "gotest.tools/v3/assert" ) diff --git a/mount/mount_freebsd.go b/mount/mount_freebsd.go index 8e30f27d0..c7c48568e 100644 --- a/mount/mount_freebsd.go +++ b/mount/mount_freebsd.go @@ -18,10 +18,10 @@ package mount import ( "os" - "os/exec" "time" "github.com/pkg/errors" + exec "golang.org/x/sys/execabs" "golang.org/x/sys/unix" ) diff --git a/mount/mount_linux.go b/mount/mount_linux.go index 31148049a..1c4dafb4a 100644 --- a/mount/mount_linux.go +++ b/mount/mount_linux.go @@ -19,12 +19,12 @@ package mount import ( "fmt" "os" - "os/exec" "path" "strings" "time" "github.com/pkg/errors" + exec "golang.org/x/sys/execabs" "golang.org/x/sys/unix" ) diff --git a/mount/mount_linux_test.go b/mount/mount_linux_test.go index a254a18fa..3641c634f 100644 --- a/mount/mount_linux_test.go +++ b/mount/mount_linux_test.go @@ -20,12 +20,12 @@ import ( "fmt" "io/ioutil" "os" - "os/exec" "path/filepath" "reflect" "testing" "github.com/containerd/continuity/testutil" + exec "golang.org/x/sys/execabs" ) func TestLongestCommonPrefix(t *testing.T) { diff --git a/pkg/process/io.go b/pkg/process/io.go index e54c3e5f6..59c82d3d9 100644 --- a/pkg/process/io.go +++ b/pkg/process/io.go @@ -25,7 +25,6 @@ import ( "io" "net/url" "os" - "os/exec" "path/filepath" "sync" "sync/atomic" @@ -39,6 +38,7 @@ import ( runc "github.com/containerd/go-runc" "github.com/hashicorp/go-multierror" "github.com/pkg/errors" + exec "golang.org/x/sys/execabs" ) const binaryIOProcTermTimeout = 12 * time.Second // Give logger process solid 10 seconds for cleanup diff --git a/pkg/process/io_util.go b/pkg/process/io_util.go index 72bbf9233..e814c114b 100644 --- a/pkg/process/io_util.go +++ b/pkg/process/io_util.go @@ -19,7 +19,8 @@ package process import ( "net/url" "os" - "os/exec" + + exec "golang.org/x/sys/execabs" ) // NewBinaryCmd returns a Cmd to be used to start a logging binary. diff --git a/runtime/v1/shim/client/client.go b/runtime/v1/shim/client/client.go index 3185294b8..82343fc9a 100644 --- a/runtime/v1/shim/client/client.go +++ b/runtime/v1/shim/client/client.go @@ -26,7 +26,6 @@ import ( "io/ioutil" "net" "os" - "os/exec" "path/filepath" "strconv" "strings" @@ -34,12 +33,6 @@ import ( "syscall" "time" - "golang.org/x/sys/unix" - - "github.com/containerd/ttrpc" - "github.com/pkg/errors" - "github.com/sirupsen/logrus" - "github.com/containerd/containerd/events" "github.com/containerd/containerd/log" "github.com/containerd/containerd/pkg/dialer" @@ -47,7 +40,12 @@ import ( "github.com/containerd/containerd/runtime/v1/shim" shimapi "github.com/containerd/containerd/runtime/v1/shim/v1" "github.com/containerd/containerd/sys" + "github.com/containerd/ttrpc" ptypes "github.com/gogo/protobuf/types" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + exec "golang.org/x/sys/execabs" + "golang.org/x/sys/unix" ) var empty = &ptypes.Empty{} diff --git a/runtime/v1/shim/client/client_linux.go b/runtime/v1/shim/client/client_linux.go index d47988b9c..f8e40846a 100644 --- a/runtime/v1/shim/client/client_linux.go +++ b/runtime/v1/shim/client/client_linux.go @@ -17,11 +17,11 @@ package client import ( - "os/exec" "syscall" "github.com/containerd/cgroups" "github.com/pkg/errors" + exec "golang.org/x/sys/execabs" ) func getSysProcAttr() *syscall.SysProcAttr { diff --git a/runtime/v1/shim/client/client_unix.go b/runtime/v1/shim/client/client_unix.go index 2280b991e..5da615146 100644 --- a/runtime/v1/shim/client/client_unix.go +++ b/runtime/v1/shim/client/client_unix.go @@ -20,8 +20,9 @@ package client import ( - "os/exec" "syscall" + + exec "golang.org/x/sys/execabs" ) func getSysProcAttr() *syscall.SysProcAttr { diff --git a/runtime/v2/runc/v1/service.go b/runtime/v2/runc/v1/service.go index 0b3c0f19d..770a83a05 100644 --- a/runtime/v2/runc/v1/service.go +++ b/runtime/v2/runc/v1/service.go @@ -23,7 +23,6 @@ import ( "context" "io/ioutil" "os" - "os/exec" "path/filepath" "sync" "syscall" @@ -50,6 +49,7 @@ import ( ptypes "github.com/gogo/protobuf/types" "github.com/pkg/errors" "github.com/sirupsen/logrus" + exec "golang.org/x/sys/execabs" "golang.org/x/sys/unix" ) diff --git a/runtime/v2/runc/v2/service.go b/runtime/v2/runc/v2/service.go index ac6b00ab7..9ea5e767a 100644 --- a/runtime/v2/runc/v2/service.go +++ b/runtime/v2/runc/v2/service.go @@ -24,7 +24,6 @@ import ( "encoding/json" "io/ioutil" "os" - "os/exec" "path/filepath" "sync" "syscall" @@ -54,6 +53,7 @@ import ( ptypes "github.com/gogo/protobuf/types" "github.com/pkg/errors" "github.com/sirupsen/logrus" + exec "golang.org/x/sys/execabs" "golang.org/x/sys/unix" ) diff --git a/runtime/v2/shim/util.go b/runtime/v2/shim/util.go index 5905c0a0f..58f2e9b3f 100644 --- a/runtime/v2/shim/util.go +++ b/runtime/v2/shim/util.go @@ -23,7 +23,6 @@ import ( "io/ioutil" "net" "os" - "os/exec" "path/filepath" "strings" "sync" @@ -33,6 +32,7 @@ import ( "github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/types" "github.com/pkg/errors" + exec "golang.org/x/sys/execabs" ) var runtimePaths sync.Map @@ -73,12 +73,9 @@ func Command(ctx context.Context, runtime, containerdAddress, containerdTTRPCAdd if cmdPath, lerr = exec.LookPath(name); lerr != nil { if eerr, ok := lerr.(*exec.Error); ok { if eerr.Err == exec.ErrNotFound { - // LookPath only finds current directory matches based on - // the callers current directory but the caller is not - // likely in the same directory as the containerd - // executables. Instead match the calling binaries path - // (containerd) and see if they are side by side. If so - // execute the shim found there. + // Match the calling binaries (containerd) path and see + // if they are side by side. If so, execute the shim + // found there. testPath := filepath.Join(filepath.Dir(self), name) if _, serr := os.Stat(testPath); serr == nil { cmdPath = testPath diff --git a/snapshots/btrfs/btrfs_test.go b/snapshots/btrfs/btrfs_test.go index ecf831c8d..c51443da4 100644 --- a/snapshots/btrfs/btrfs_test.go +++ b/snapshots/btrfs/btrfs_test.go @@ -24,7 +24,6 @@ import ( "context" "io/ioutil" "os" - "os/exec" "path/filepath" "strings" "testing" @@ -37,6 +36,7 @@ import ( "github.com/containerd/containerd/snapshots/testsuite" "github.com/containerd/continuity/testutil/loopback" "github.com/pkg/errors" + exec "golang.org/x/sys/execabs" "golang.org/x/sys/unix" ) diff --git a/snapshots/devmapper/blkdiscard/blkdiscard.go b/snapshots/devmapper/blkdiscard/blkdiscard.go index b6bcd4422..384184afa 100644 --- a/snapshots/devmapper/blkdiscard/blkdiscard.go +++ b/snapshots/devmapper/blkdiscard/blkdiscard.go @@ -19,7 +19,7 @@ package blkdiscard -import "os/exec" +import exec "golang.org/x/sys/execabs" // Version returns the output of "blkdiscard --version" func Version() (string, error) { diff --git a/snapshots/devmapper/dmsetup/dmsetup.go b/snapshots/devmapper/dmsetup/dmsetup.go index a6a920db8..7526984da 100644 --- a/snapshots/devmapper/dmsetup/dmsetup.go +++ b/snapshots/devmapper/dmsetup/dmsetup.go @@ -25,12 +25,12 @@ import ( "fmt" "io" "os" - "os/exec" "strconv" "strings" blkdiscard "github.com/containerd/containerd/snapshots/devmapper/blkdiscard" "github.com/pkg/errors" + exec "golang.org/x/sys/execabs" "golang.org/x/sys/unix" ) diff --git a/snapshots/devmapper/pool_device_test.go b/snapshots/devmapper/pool_device_test.go index d44ed1cc7..e5179b245 100644 --- a/snapshots/devmapper/pool_device_test.go +++ b/snapshots/devmapper/pool_device_test.go @@ -24,7 +24,6 @@ import ( "fmt" "io/ioutil" "os" - "os/exec" "path/filepath" "testing" "time" @@ -34,6 +33,7 @@ import ( "github.com/containerd/containerd/snapshots/devmapper/dmsetup" "github.com/docker/go-units" "github.com/sirupsen/logrus" + exec "golang.org/x/sys/execabs" "gotest.tools/v3/assert" ) diff --git a/snapshots/devmapper/snapshotter.go b/snapshots/devmapper/snapshotter.go index 5670b6b02..35845cad5 100644 --- a/snapshots/devmapper/snapshotter.go +++ b/snapshots/devmapper/snapshotter.go @@ -23,7 +23,6 @@ import ( "context" "fmt" "os" - "os/exec" "path/filepath" "strings" "sync" @@ -37,6 +36,7 @@ import ( "github.com/hashicorp/go-multierror" "github.com/pkg/errors" "github.com/sirupsen/logrus" + exec "golang.org/x/sys/execabs" ) const ( diff --git a/snapshots/overlay/overlayutils/check_test.go b/snapshots/overlay/overlayutils/check_test.go index 34863e774..f3a4d3b0a 100644 --- a/snapshots/overlay/overlayutils/check_test.go +++ b/snapshots/overlay/overlayutils/check_test.go @@ -22,11 +22,11 @@ package overlayutils import ( "io/ioutil" "os" - "os/exec" "testing" "github.com/containerd/containerd/pkg/testutil" "github.com/containerd/continuity/testutil/loopback" + exec "golang.org/x/sys/execabs" ) func testOverlaySupported(t testing.TB, expected bool, mkfs ...string) { diff --git a/sys/oom_linux_test.go b/sys/oom_linux_test.go index 3cea56a75..0c8f90b66 100644 --- a/sys/oom_linux_test.go +++ b/sys/oom_linux_test.go @@ -20,11 +20,11 @@ import ( "errors" "fmt" "os" - "os/exec" "testing" "time" "github.com/containerd/containerd/pkg/userns" + exec "golang.org/x/sys/execabs" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) diff --git a/sys/reaper/reaper_unix.go b/sys/reaper/reaper_unix.go index 41f905f6b..a735e1cbd 100644 --- a/sys/reaper/reaper_unix.go +++ b/sys/reaper/reaper_unix.go @@ -20,12 +20,12 @@ package reaper import ( - "os/exec" "sync" "time" runc "github.com/containerd/go-runc" "github.com/pkg/errors" + exec "golang.org/x/sys/execabs" "golang.org/x/sys/unix" ) diff --git a/vendor/golang.org/x/sys/execabs/execabs.go b/vendor/golang.org/x/sys/execabs/execabs.go new file mode 100644 index 000000000..78192498d --- /dev/null +++ b/vendor/golang.org/x/sys/execabs/execabs.go @@ -0,0 +1,102 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package execabs is a drop-in replacement for os/exec +// that requires PATH lookups to find absolute paths. +// That is, execabs.Command("cmd") runs the same PATH lookup +// as exec.Command("cmd"), but if the result is a path +// which is relative, the Run and Start methods will report +// an error instead of running the executable. +// +// See https://blog.golang.org/path-security for more information +// about when it may be necessary or appropriate to use this package. +package execabs + +import ( + "context" + "fmt" + "os/exec" + "path/filepath" + "reflect" + "unsafe" +) + +// ErrNotFound is the error resulting if a path search failed to find an executable file. +// It is an alias for exec.ErrNotFound. +var ErrNotFound = exec.ErrNotFound + +// Cmd represents an external command being prepared or run. +// It is an alias for exec.Cmd. +type Cmd = exec.Cmd + +// Error is returned by LookPath when it fails to classify a file as an executable. +// It is an alias for exec.Error. +type Error = exec.Error + +// An ExitError reports an unsuccessful exit by a command. +// It is an alias for exec.ExitError. +type ExitError = exec.ExitError + +func relError(file, path string) error { + return fmt.Errorf("%s resolves to executable in current directory (.%c%s)", file, filepath.Separator, path) +} + +// LookPath searches for an executable named file in the directories +// named by the PATH environment variable. If file contains a slash, +// it is tried directly and the PATH is not consulted. The result will be +// an absolute path. +// +// LookPath differs from exec.LookPath in its handling of PATH lookups, +// which are used for file names without slashes. If exec.LookPath's +// PATH lookup would have returned an executable from the current directory, +// LookPath instead returns an error. +func LookPath(file string) (string, error) { + path, err := exec.LookPath(file) + if err != nil { + return "", err + } + if filepath.Base(file) == file && !filepath.IsAbs(path) { + return "", relError(file, path) + } + return path, nil +} + +func fixCmd(name string, cmd *exec.Cmd) { + if filepath.Base(name) == name && !filepath.IsAbs(cmd.Path) { + // exec.Command was called with a bare binary name and + // exec.LookPath returned a path which is not absolute. + // Set cmd.lookPathErr and clear cmd.Path so that it + // cannot be run. + lookPathErr := (*error)(unsafe.Pointer(reflect.ValueOf(cmd).Elem().FieldByName("lookPathErr").Addr().Pointer())) + if *lookPathErr == nil { + *lookPathErr = relError(name, cmd.Path) + } + cmd.Path = "" + } +} + +// CommandContext is like Command but includes a context. +// +// The provided context is used to kill the process (by calling os.Process.Kill) +// if the context becomes done before the command completes on its own. +func CommandContext(ctx context.Context, name string, arg ...string) *exec.Cmd { + cmd := exec.CommandContext(ctx, name, arg...) + fixCmd(name, cmd) + return cmd + +} + +// Command returns the Cmd struct to execute the named program with the given arguments. +// See exec.Command for most details. +// +// Command differs from exec.Command in its handling of PATH lookups, +// which are used when the program name contains no slashes. +// If exec.Command would have returned an exec.Cmd configured to run an +// executable from the current directory, Command instead +// returns an exec.Cmd that will return an error from Start or Run. +func Command(name string, arg ...string) *exec.Cmd { + cmd := exec.Command(name, arg...) + fixCmd(name, cmd) + return cmd +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 31db68dc3..b3f9d8bd5 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -444,6 +444,7 @@ golang.org/x/sync/errgroup golang.org/x/sync/semaphore # golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c ## explicit +golang.org/x/sys/execabs golang.org/x/sys/internal/unsafeheader golang.org/x/sys/plan9 golang.org/x/sys/unix