Skip to content

Commit 886ba60

Browse files
committed
Pass containerd's address to shim.SocketAddress()
As a fix for CVE-2020-15257, containerd uses a file-based Unix domain socket instead of an abstract Unix domain socket. Due to the change SocketAddress() now takes the socket address of containerd. Signed-off-by: Kazuyoshi Kato <[email protected]>
1 parent 68365e3 commit 886ba60

File tree

3 files changed

+45
-27
lines changed

3 files changed

+45
-27
lines changed

firecracker-control/local.go

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"os"
2121
"os/exec"
2222
"strconv"
23-
"strings"
2423
"sync"
2524
"syscall"
2625
"time"
@@ -115,15 +114,15 @@ func (s *local) CreateVM(requestCtx context.Context, req *proto.CreateVMRequest)
115114
// We determine if there is already a shim managing a VM with the current VMID by attempting
116115
// to listen on the abstract socket address (which is parameterized by VMID). If we get
117116
// EADDRINUSE, then we assume there is already a shim for the VM and return an AlreadyExists error.
118-
shimSocketAddress, err := fcShim.SocketAddress(requestCtx, id)
117+
shimSocketAddress, err := shim.SocketAddress(requestCtx, s.containerdAddress, id)
119118
if err != nil {
120119
err = errors.Wrap(err, "failed to obtain shim socket address")
121120
s.logger.WithError(err).Error()
122121
return nil, err
123122
}
124123

125124
shimSocket, err := shim.NewSocket(shimSocketAddress)
126-
if isEADDRINUSE(err) {
125+
if shim.SocketEaddrinuse(err) {
127126
return nil, status.Errorf(codes.AlreadyExists, "VM with ID %q already exists (socket: %q)", id, shimSocketAddress)
128127
} else if err != nil {
129128
err = errors.Wrapf(err, "failed to open shim socket at address %q", shimSocketAddress)
@@ -132,7 +131,6 @@ func (s *local) CreateVM(requestCtx context.Context, req *proto.CreateVMRequest)
132131
}
133132

134133
// If we're here, there is no pre-existing shim for this VMID, so we spawn a new one
135-
defer shimSocket.Close()
136134
if err := os.Mkdir(s.config.ShimBaseDir, 0700); err != nil && !os.IsExist(err) {
137135
s.logger.WithError(err).Error()
138136
return nil, errors.Wrapf(err, "failed to make shim base directory: %s", s.config.ShimBaseDir)
@@ -165,7 +163,7 @@ func (s *local) CreateVM(requestCtx context.Context, req *proto.CreateVMRequest)
165163
// containerd does not currently expose the shim server for us to register the fccontrol service with too.
166164
// This is likely addressable through some relatively small upstream contributions; the following is a stop-gap
167165
// solution until that time.
168-
fcSocketAddress, err := fcShim.FCControlSocketAddress(requestCtx, id)
166+
fcSocketAddress, err := fcShim.FCControlSocketAddress(requestCtx, s.containerdAddress, id)
169167
if err != nil {
170168
err = errors.Wrap(err, "failed to obtain shim socket address")
171169
s.logger.WithError(err).Error()
@@ -179,8 +177,6 @@ func (s *local) CreateVM(requestCtx context.Context, req *proto.CreateVMRequest)
179177
return nil, err
180178
}
181179

182-
defer fcSocket.Close()
183-
184180
cmd, err := s.newShim(ns, id, s.containerdAddress, shimSocket, fcSocket)
185181
if err != nil {
186182
return nil, err
@@ -223,14 +219,14 @@ func (s *local) shimFirecrackerClient(requestCtx context.Context, vmID string) (
223219
return nil, errors.Wrap(err, "invalid id")
224220
}
225221

226-
socketAddr, err := fcShim.FCControlSocketAddress(requestCtx, vmID)
222+
socketAddr, err := fcShim.FCControlSocketAddress(requestCtx, s.containerdAddress, vmID)
227223
if err != nil {
228224
err = errors.Wrap(err, "failed to get shim's fccontrol socket address")
229225
s.logger.WithError(err).Error()
230226
return nil, err
231227
}
232228

233-
return fcclient.New("\x00" + socketAddr)
229+
return fcclient.New(socketAddr)
234230
}
235231

236232
// StopVM stops running VM instance by VM ID. This stops the VM, all tasks within the VM and the runtime shim
@@ -289,7 +285,7 @@ func (s *local) ResumeVM(ctx context.Context, req *proto.ResumeVMRequest) (*empt
289285
}
290286

291287
func (s *local) waitForShimToExit(ctx context.Context, vmID string) error {
292-
socketAddr, err := fcShim.SocketAddress(ctx, vmID)
288+
socketAddr, err := shim.SocketAddress(ctx, s.containerdAddress, vmID)
293289
if err != nil {
294290
return err
295291
}
@@ -458,14 +454,18 @@ func (s *local) newShim(ns, vmID, containerdAddress string, shimSocket *net.Unix
458454
}
459455
}
460456

461-
// Close all Unix abstract sockets.
457+
// Close all Unix sockets.
462458
if err := shimSocketFile.Close(); err != nil {
463459
logger.WithError(err).Errorf("failed to close %q", shimSocketFile.Name())
464460
}
465461
if err := fcSocketFile.Close(); err != nil {
466462
logger.WithError(err).Errorf("failed to close %q", fcSocketFile.Name())
467463
}
468464

465+
if err := s.removeSockets(ns, vmID); err != nil {
466+
logger.WithError(err).Errorf("failed to remove sockets")
467+
}
468+
469469
if err := os.RemoveAll(shimDir.RootPath()); err != nil {
470470
logger.WithError(err).Errorf("failed to remove %q", shimDir.RootPath())
471471
}
@@ -480,8 +480,33 @@ func (s *local) newShim(ns, vmID, containerdAddress string, shimSocket *net.Unix
480480
return cmd, nil
481481
}
482482

483-
func isEADDRINUSE(err error) bool {
484-
return err != nil && strings.Contains(err.Error(), "address already in use")
483+
func (s *local) removeSockets(ns string, vmID string) error {
484+
var result *multierror.Error
485+
486+
// This context is only used for passing the namespace.
487+
ctx := namespaces.WithNamespace(context.Background(), ns)
488+
489+
address, err := shim.SocketAddress(ctx, s.containerdAddress, vmID)
490+
if err != nil {
491+
result = multierror.Append(result, err)
492+
} else {
493+
err := shim.RemoveSocket(address)
494+
if err != nil {
495+
result = multierror.Append(result, err)
496+
}
497+
}
498+
499+
address, err = fcShim.FCControlSocketAddress(ctx, s.containerdAddress, vmID)
500+
if err != nil {
501+
result = multierror.Append(result, err)
502+
} else {
503+
err = shim.RemoveSocket(address)
504+
if err != nil {
505+
result = multierror.Append(result, err)
506+
}
507+
}
508+
509+
return result.ErrorOrNil()
485510
}
486511

487512
func setShimOOMScore(shimPid int) error {

internal/shim/shim.go

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,18 @@ package shim
1515

1616
import (
1717
"context"
18-
"path/filepath"
1918

2019
"github.com/containerd/containerd/runtime/v2/shim"
2120
)
2221

23-
// SocketAddress is the abstract unix socket address at which a shim
24-
// with the given namespace and vmID will listen and serve the shim api
25-
func SocketAddress(namespacedCtx context.Context, vmID string) (string, error) {
26-
return shim.SocketAddress(namespacedCtx, vmID)
27-
}
28-
29-
// FCControlSocketAddress is the abstract unix socket address at which a shim
30-
// with the given namespace and vmID will listen and serve the fccontrol api
31-
func FCControlSocketAddress(namespacedCtx context.Context, vmID string) (string, error) {
32-
shimSocketAddr, err := SocketAddress(namespacedCtx, vmID)
22+
// FCControlSocketAddress is a unix socket address at which a shim
23+
// with the given namespace, the containerd socket address, and the vmID will listen and serve
24+
// the fccontrol api
25+
func FCControlSocketAddress(namespacedCtx context.Context, socketPath, vmID string) (string, error) {
26+
shimSocketAddr, err := shim.SocketAddress(namespacedCtx, socketPath, vmID)
3327
if err != nil {
3428
return "", err
3529
}
3630

37-
return filepath.Join(shimSocketAddr, "fccontrol"), nil
31+
return shimSocketAddr + "-fccontrol", nil
3832
}

runtime/service.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ import (
5959
"github.com/firecracker-microvm/firecracker-containerd/eventbridge"
6060
"github.com/firecracker-microvm/firecracker-containerd/internal"
6161
"github.com/firecracker-microvm/firecracker-containerd/internal/bundle"
62-
fcShim "github.com/firecracker-microvm/firecracker-containerd/internal/shim"
6362
"github.com/firecracker-microvm/firecracker-containerd/internal/vm"
6463
"github.com/firecracker-microvm/firecracker-containerd/proto"
6564
drivemount "github.com/firecracker-microvm/firecracker-containerd/proto/service/drivemount/ttrpc"
@@ -393,7 +392,7 @@ func (s *service) StartShim(shimCtx context.Context, containerID, containerdBina
393392
}
394393
log.WithField("vmID", s.vmID).Infof("successfully started shim (git commit: %s).%s", revision, str)
395394

396-
return fcShim.SocketAddress(shimCtx, s.vmID)
395+
return shim.SocketAddress(shimCtx, containerdAddress, s.vmID)
397396
}
398397

399398
func logPanicAndDie(logger *logrus.Entry) {

0 commit comments

Comments
 (0)