v2, util: Take the full binary path when starting the shimv2 process

The current code simply ignores the full binary path when starting the
shimv2 process, and instead fallbacks to a binary in the path, and this
is problematic (and confusing) for those using CRI-O, which has this
bits vendored.

The reason it's problematic with CRI-O is because the user can simply
set the full binary path and, instead of having that executed, CRI-O
will simply fail to create the container unless that binary is part of
the path, which may not be case in a few different scenarios (testing
being the most common one).

Fixes: #5006

Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
This commit is contained in:
Fabiano Fidêncio 2021-02-05 13:20:54 +01:00
parent 5f2d02adc5
commit d80dbdae68

View File

@ -64,21 +64,28 @@ func Command(ctx context.Context, runtime, containerdAddress, containerdTTRPCAdd
cmdPath = cmdPathI.(string) cmdPath = cmdPathI.(string)
} else { } else {
var lerr error var lerr error
if cmdPath, lerr = exec.LookPath(name); lerr != nil { binaryPath := BinaryPath(runtime)
if eerr, ok := lerr.(*exec.Error); ok { if _, serr := os.Stat(binaryPath); serr == nil {
if eerr.Err == exec.ErrNotFound { cmdPath = binaryPath
// 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 if cmdPath == "" {
// executables. Instead match the calling binaries path if cmdPath, lerr = exec.LookPath(name); err != nil {
// (containerd) and see if they are side by side. If so if eerr, ok := lerr.(*exec.Error); ok {
// execute the shim found there. if eerr.Err == exec.ErrNotFound {
testPath := filepath.Join(filepath.Dir(self), name) // LookPath only finds current directory matches based on
if _, serr := os.Stat(testPath); serr == nil { // the callers current directory but the caller is not
cmdPath = testPath // likely in the same directory as the containerd
} // executables. Instead match the calling binaries path
if cmdPath == "" { // (containerd) and see if they are side by side. If so
return nil, errors.Wrapf(os.ErrNotExist, "runtime %q binary not installed %q", runtime, name) // execute the shim found there.
testPath := filepath.Join(filepath.Dir(self), name)
if _, serr := os.Stat(testPath); serr == nil {
cmdPath = testPath
}
if cmdPath == "" {
return nil, errors.Wrapf(os.ErrNotExist, "runtime %q binary not installed %q", runtime, name)
}
} }
} }
} }
@ -123,6 +130,20 @@ func BinaryName(runtime string) string {
return fmt.Sprintf(shimBinaryFormat, parts[len(parts)-2], parts[len(parts)-1]) return fmt.Sprintf(shimBinaryFormat, parts[len(parts)-2], parts[len(parts)-1])
} }
// BinaryPath returns the full path for the shim binary from the runtime name,
// empty string returns means runtime name is invalid
func BinaryPath(runtime string) string {
dir := filepath.Dir(runtime)
binary := BinaryName(runtime)
path, err := filepath.Abs(filepath.Join(dir, binary))
if err != nil {
return ""
}
return path
}
// Connect to the provided address // Connect to the provided address
func Connect(address string, d func(string, time.Duration) (net.Conn, error)) (net.Conn, error) { func Connect(address string, d func(string, time.Duration) (net.Conn, error)) (net.Conn, error) {
return d(address, 100*time.Second) return d(address, 100*time.Second)