Skip to content

Commit a631796

Browse files
linxiuleileilei.lin
authored andcommitted
horten the unix socket path for shim
Use sha256 hash to shorten the unix socket path to satisfy the length limitation of abstract socket path This commit also backports the feature storing address path to a file from v2 to keep compatibility Fixes #3032 Signed-off-by: Eric Lin <[email protected]>
1 parent a15b6e2 commit a631796

4 files changed

Lines changed: 112 additions & 3 deletions

File tree

container_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ import (
3232
// Register the typeurl
3333
"github.com/containerd/containerd/cio"
3434
"github.com/containerd/containerd/containers"
35+
"github.com/containerd/containerd/namespaces"
3536
"github.com/containerd/containerd/oci"
37+
"github.com/containerd/containerd/platforms"
3638
_ "github.com/containerd/containerd/runtime"
3739
"github.com/containerd/typeurl"
3840
specs "github.com/opencontainers/runtime-spec/specs-go"
@@ -1528,3 +1530,59 @@ func TestContainerHook(t *testing.T) {
15281530
}
15291531
defer task.Delete(ctx, WithProcessKill)
15301532
}
1533+
1534+
func TestShimSockLength(t *testing.T) {
1535+
t.Parallel()
1536+
1537+
// Max length of namespace should be 76
1538+
namespace := strings.Repeat("n", 76)
1539+
1540+
ctx, cancel := context.WithCancel(context.Background())
1541+
defer cancel()
1542+
1543+
ctx = namespaces.WithNamespace(ctx, namespace)
1544+
1545+
client, err := newClient(t, address)
1546+
if err != nil {
1547+
t.Fatal(err)
1548+
}
1549+
defer client.Close()
1550+
1551+
image, err := client.Pull(ctx, testImage,
1552+
WithPlatformMatcher(platforms.Default()),
1553+
WithPullUnpack,
1554+
)
1555+
if err != nil {
1556+
t.Fatal(err)
1557+
}
1558+
1559+
id := strings.Repeat("c", 64)
1560+
1561+
// We don't have limitation with length of container name,
1562+
// but 64 bytes of sha256 is the common case
1563+
container, err := client.NewContainer(ctx, id,
1564+
WithNewSnapshot(id, image),
1565+
WithNewSpec(oci.WithImageConfig(image), withExitStatus(0)),
1566+
)
1567+
if err != nil {
1568+
t.Fatal(err)
1569+
}
1570+
defer container.Delete(ctx, WithSnapshotCleanup)
1571+
1572+
task, err := container.NewTask(ctx, empty())
1573+
if err != nil {
1574+
t.Fatal(err)
1575+
}
1576+
defer task.Delete(ctx)
1577+
1578+
statusC, err := task.Wait(ctx)
1579+
if err != nil {
1580+
t.Fatal(err)
1581+
}
1582+
1583+
if err := task.Start(ctx); err != nil {
1584+
t.Fatal(err)
1585+
}
1586+
1587+
<-statusC
1588+
}

runtime/v1/linux/bundle.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package linux
2020

2121
import (
2222
"context"
23+
"crypto/sha256"
2324
"fmt"
2425
"io/ioutil"
2526
"os"
@@ -103,7 +104,7 @@ func ShimLocal(c *Config, exchange *exchange.Exchange) ShimOpt {
103104
// ShimConnect is a ShimOpt for connecting to an existing remote shim
104105
func ShimConnect(c *Config, onClose func()) ShimOpt {
105106
return func(b *bundle, ns string, ropts *runctypes.RuncOptions) (shim.Config, client.Opt) {
106-
return b.shimConfig(ns, c, ropts), client.WithConnect(b.shimAddress(ns), onClose)
107+
return b.shimConfig(ns, c, ropts), client.WithConnect(b.decideShimAddress(ns), onClose)
107108
}
108109
}
109110

@@ -127,10 +128,32 @@ func (b *bundle) Delete() error {
127128
return errors.Wrapf(err, "Failed to remove both bundle and workdir locations: %v", err2)
128129
}
129130

130-
func (b *bundle) shimAddress(namespace string) string {
131+
func (b *bundle) legacyShimAddress(namespace string) string {
131132
return filepath.Join(string(filepath.Separator), "containerd-shim", namespace, b.id, "shim.sock")
132133
}
133134

135+
func (b *bundle) shimAddress(namespace string) string {
136+
d := sha256.Sum256([]byte(filepath.Join(namespace, b.id)))
137+
return filepath.Join(string(filepath.Separator), "containerd-shim", fmt.Sprintf("%x.sock", d))
138+
}
139+
140+
func (b *bundle) loadAddress() (string, error) {
141+
addressPath := filepath.Join(b.path, "address")
142+
data, err := ioutil.ReadFile(addressPath)
143+
if err != nil {
144+
return "", err
145+
}
146+
return string(data), nil
147+
}
148+
149+
func (b *bundle) decideShimAddress(namespace string) string {
150+
address, err := b.loadAddress()
151+
if err != nil {
152+
return b.legacyShimAddress(namespace)
153+
}
154+
return address
155+
}
156+
134157
func (b *bundle) shimConfig(namespace string, c *Config, runcOptions *runctypes.RuncOptions) shim.Config {
135158
var (
136159
criuPath string

runtime/v1/shim/client/client.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ package client
2020

2121
import (
2222
"context"
23+
"fmt"
2324
"io"
2425
"net"
2526
"os"
2627
"os/exec"
28+
"path/filepath"
2729
"strings"
2830
"sync"
2931
"syscall"
@@ -107,6 +109,10 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa
107109
"address": address,
108110
"debug": debug,
109111
}).Infof("shim %s started", binary)
112+
113+
if err := writeAddress(filepath.Join(config.Path, "address"), address); err != nil {
114+
return nil, nil, err
115+
}
110116
// set shim in cgroup if it is provided
111117
if cgroup != "" {
112118
if err := setCgroup(cgroup, cmd); err != nil {
@@ -166,6 +172,25 @@ func newCommand(binary, daemonAddress string, debug bool, config shim.Config, so
166172
return cmd, nil
167173
}
168174

175+
// writeAddress writes a address file atomically
176+
func writeAddress(path, address string) error {
177+
path, err := filepath.Abs(path)
178+
if err != nil {
179+
return err
180+
}
181+
tempPath := filepath.Join(filepath.Dir(path), fmt.Sprintf(".%s", filepath.Base(path)))
182+
f, err := os.OpenFile(tempPath, os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC, 0666)
183+
if err != nil {
184+
return err
185+
}
186+
_, err = f.WriteString(address)
187+
f.Close()
188+
if err != nil {
189+
return err
190+
}
191+
return os.Rename(tempPath, path)
192+
}
193+
169194
func newSocket(address string) (*net.UnixListener, error) {
170195
if len(address) > 106 {
171196
return nil, errors.Errorf("%q: unix socket path too long (> 106)", address)

runtime/v2/shim/util_unix.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ package shim
2020

2121
import (
2222
"context"
23+
"crypto/sha256"
24+
"fmt"
2325
"net"
2426
"path/filepath"
2527
"strings"
@@ -50,7 +52,8 @@ func SocketAddress(ctx context.Context, id string) (string, error) {
5052
if err != nil {
5153
return "", err
5254
}
53-
return filepath.Join(string(filepath.Separator), "containerd-shim", ns, id, "shim.sock"), nil
55+
d := sha256.Sum256([]byte(filepath.Join(ns, id)))
56+
return filepath.Join(string(filepath.Separator), "containerd-shim", fmt.Sprintf("%x.sock", d)), nil
5457
}
5558

5659
// AnonDialer returns a dialer for an abstract socket

0 commit comments

Comments
 (0)