From 95afeb7831dcb2426ad35dbebfb31b9d85c553ac Mon Sep 17 00:00:00 2001 From: Kenfe-Mickael Laventure Date: Mon, 12 Jun 2017 14:43:28 -0700 Subject: [PATCH] containerd-shim: Use abstract namespace for the unix socket Signed-off-by: Kenfe-Mickael Laventure --- cmd/containerd-shim/main_unix.go | 26 ++++++++++++++++++++------ cmd/ctr/shim.go | 27 ++++++++++++++++++--------- linux/bundle.go | 11 +++++++++-- linux/shim/client.go | 25 ++++++++++++++++--------- 4 files changed, 63 insertions(+), 26 deletions(-) diff --git a/cmd/containerd-shim/main_unix.go b/cmd/containerd-shim/main_unix.go index a2b59fb9e..209462f75 100644 --- a/cmd/containerd-shim/main_unix.go +++ b/cmd/containerd-shim/main_unix.go @@ -22,12 +22,12 @@ import ( ) const usage = ` - __ _ __ __ _ - _________ ____ / /_____ _(_)___ ___ _________/ / _____/ /_ (_)___ ___ + __ _ __ __ _ + _________ ____ / /_____ _(_)___ ___ _________/ / _____/ /_ (_)___ ___ / ___/ __ \/ __ \/ __/ __ ` + "`" + `/ / __ \/ _ \/ ___/ __ /_____/ ___/ __ \/ / __ ` + "`" + `__ \ / /__/ /_/ / / / / /_/ /_/ / / / / / __/ / / /_/ /_____(__ ) / / / / / / / / / -\___/\____/_/ /_/\__/\__,_/_/_/ /_/\___/_/ \__,_/ /____/_/ /_/_/_/ /_/ /_/ - +\___/\____/_/ /_/\__/\__,_/_/_/ /_/\___/_/ \__,_/ /____/_/ /_/_/_/ /_/ /_/ + shim for container lifecycle and reconnection ` @@ -45,6 +45,10 @@ func main() { Name: "namespace,n", Usage: "namespace that owns the task", }, + cli.StringFlag{ + Name: "socket,s", + Usage: "abstract socket path to server on", + }, } app.Before = func(context *cli.Context) error { if context.GlobalBool("debug") { @@ -73,7 +77,8 @@ func main() { } logrus.Debug("registering grpc server") shimapi.RegisterShimServer(server, sv) - if err := serve(server, "shim.sock"); err != nil { + socket := context.GlobalString("socket") + if err := serve(server, socket); err != nil { return err } return handleSignals(signals, server) @@ -87,7 +92,16 @@ func main() { // serve serves the grpc API over a unix socket at the provided path // this function does not block func serve(server *grpc.Server, path string) error { - l, err := net.FileListener(os.NewFile(3, "socket")) + var ( + l net.Listener + err error + ) + if path == "" { + l, err = net.FileListener(os.NewFile(3, "socket")) + path = "[inherited from parent]" + } else { + l, err = net.Listen("unix", "\x00"+path) + } if err != nil { return err } diff --git a/cmd/ctr/shim.go b/cmd/ctr/shim.go index 270295f9b..775b61af3 100644 --- a/cmd/ctr/shim.go +++ b/cmd/ctr/shim.go @@ -51,6 +51,12 @@ var fifoFlags = []cli.Flag{ var shimCommand = cli.Command{ Name: "shim", Usage: "interact with a shim directly", + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "socket", + Usage: "socket on which to connect to the shim", + }, + }, Subcommands: []cli.Command{ shimCreateCommand, shimStartCommand, @@ -88,7 +94,7 @@ var shimCreateCommand = cli.Command{ if id == "" { return errors.New("container id must be provided") } - service, err := getShimService() + service, err := getShimService(context) if err != nil { return err } @@ -139,7 +145,7 @@ var shimStartCommand = cli.Command{ Name: "start", Usage: "start a container with a shim", Action: func(context *cli.Context) error { - service, err := getShimService() + service, err := getShimService(context) if err != nil { return err } @@ -152,7 +158,7 @@ var shimDeleteCommand = cli.Command{ Name: "delete", Usage: "delete a container with a shim", Action: func(context *cli.Context) error { - service, err := getShimService() + service, err := getShimService(context) if err != nil { return err } @@ -169,7 +175,7 @@ var shimStateCommand = cli.Command{ Name: "state", Usage: "get the state of all the processes of the shim", Action: func(context *cli.Context) error { - service, err := getShimService() + service, err := getShimService(context) if err != nil { return err } @@ -213,7 +219,7 @@ var shimExecCommand = cli.Command{ }, ), Action: func(context *cli.Context) error { - service, err := getShimService() + service, err := getShimService(context) ctx := gocontext.Background() if err != nil { return err @@ -275,7 +281,7 @@ var shimEventsCommand = cli.Command{ Name: "events", Usage: "get events for a shim", Action: func(context *cli.Context) error { - service, err := getShimService() + service, err := getShimService(context) if err != nil { return err } @@ -293,15 +299,18 @@ var shimEventsCommand = cli.Command{ }, } -func getShimService() (shim.ShimClient, error) { - bindSocket := "shim.sock" +func getShimService(context *cli.Context) (shim.ShimClient, error) { + bindSocket := context.GlobalString("socket") + if bindSocket == "" { + return nil, errors.New("socket path must be specified") + } // reset the logger for grpc to log to dev/null so that it does not mess with our stdio grpclog.SetLogger(log.New(ioutil.Discard, "", log.LstdFlags)) dialOpts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithTimeout(100 * time.Second)} dialOpts = append(dialOpts, grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) { - return net.DialTimeout("unix", bindSocket, timeout) + return net.DialTimeout("unix", "\x00"+bindSocket, timeout) }, )) conn, err := grpc.Dial(fmt.Sprintf("unix://%s", bindSocket), dialOpts...) diff --git a/linux/bundle.go b/linux/bundle.go index 78cb4fcd3..2a92175cd 100644 --- a/linux/bundle.go +++ b/linux/bundle.go @@ -44,12 +44,14 @@ func newBundle(path, namespace, id string, spec []byte) (b *bundle, err error) { defer f.Close() _, err = io.Copy(f, bytes.NewReader(spec)) return &bundle{ + id: id, path: path, namespace: namespace, }, err } type bundle struct { + id string path string namespace string } @@ -61,7 +63,7 @@ func (b *bundle) NewShim(ctx context.Context, binary string, remote bool) (*clie opt = client.WithLocal } return client.New(ctx, client.Config{ - Address: filepath.Join(b.path, "shim.sock"), + Address: b.shimAddress(), Path: b.path, Namespace: b.namespace, }, opt) @@ -74,7 +76,7 @@ func (b *bundle) Connect(ctx context.Context, remote bool) (*client.Client, erro opt = client.WithLocal } return client.New(ctx, client.Config{ - Address: filepath.Join(b.path, "shim.sock"), + Address: b.shimAddress(), Path: b.path, Namespace: b.namespace, }, opt) @@ -89,3 +91,8 @@ func (b *bundle) Spec() ([]byte, error) { func (b *bundle) Delete() error { return os.RemoveAll(b.path) } + +func (b *bundle) shimAddress() string { + return filepath.Join(string(filepath.Separator), "containerd-shim", b.namespace, b.id, "shim.sock") + +} diff --git a/linux/shim/client.go b/linux/shim/client.go index 2abaf6010..2b762c068 100644 --- a/linux/shim/client.go +++ b/linux/shim/client.go @@ -34,11 +34,14 @@ func WithStart(binary string) ClientOpt { if err != nil { return nil, nil, err } - // close our side of the socket, do not close the listener as it will - // remove the socket from disk defer socket.Close() + f, err := socket.File() + if err != nil { + return nil, nil, errors.Wrapf(err, "failed to get fd for socket %s", config.Address) + } + defer f.Close() - cmd := newCommand(binary, config, socket) + cmd := newCommand(binary, config, f) if err := reaper.Default.Start(cmd); err != nil { return nil, nil, errors.Wrapf(err, "failed to start shim") } @@ -73,12 +76,16 @@ func newCommand(binary string, config Config, socket *os.File) *exec.Cmd { return cmd } -func newSocket(config Config) (*os.File, error) { - l, err := sys.CreateUnixSocket(config.Address) - if err != nil { - return nil, err +func newSocket(config Config) (*net.UnixListener, error) { + if len(config.Address) > 106 { + return nil, errors.Errorf("%q: unix socket path too long (limit 106)", config.Address) } - return l.(*net.UnixListener).File() + l, err := net.Listen("unix", "\x00"+config.Address) + if err != nil { + return nil, errors.Wrapf(err, "failed to listen to abstract unix socket %q", config.Address) + } + + return l.(*net.UnixListener), nil } func connect(address string) (*grpc.ClientConn, error) { @@ -98,7 +105,7 @@ func connect(address string) (*grpc.ClientConn, error) { func dialer(address string, timeout time.Duration) (net.Conn, error) { address = strings.TrimPrefix(address, "unix://") - return net.DialTimeout("unix", address, timeout) + return net.DialTimeout("unix", "\x00"+address, timeout) } func dialAddress(address string) string {