Skip to content

Commit e25e64b

Browse files
kolyshkinclaude
andcommitted
deps: bump to go-criu v8.3.0
go-criu v8.3.0 switches to protobuf-go-lite, which helps to remove google.golang.org/protobuf dependency from here, reducing the runc binary size from ~16M to ~14M. The only missing piece is proto.String, proto.Bool, proto.Int32 etc. helpers that return a pointer to a given variable. Those are replaced by a generic mkPtr, which in turn is to be replaced by the new builtin once Go < 1.26 is no longer supported. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
1 parent da3d022 commit e25e64b

151 files changed

Lines changed: 12933 additions & 36419 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/opencontainers/runc
33
go 1.25.0
44

55
require (
6-
github.com/checkpoint-restore/go-criu/v8 v8.2.0
6+
github.com/checkpoint-restore/go-criu/v8 v8.2.1-0.20260612135546-b8967dc8885e
77
github.com/containerd/console v1.0.5
88
github.com/coreos/go-systemd/v22 v22.7.0
99
github.com/cyphar/filepath-securejoin v0.6.1
@@ -25,10 +25,10 @@ require (
2525
github.com/vishvananda/netns v0.0.5
2626
golang.org/x/net v0.56.0
2727
golang.org/x/sys v0.46.0
28-
google.golang.org/protobuf v1.36.11
2928
)
3029

3130
require (
3231
cyphar.com/go-pathrs v0.2.4 // indirect
32+
github.com/aperturerobotics/protobuf-go-lite v0.14.0 // indirect
3333
github.com/cilium/ebpf v0.17.3 // indirect
3434
)

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
cyphar.com/go-pathrs v0.2.4 h1:iD/mge36swa1UFKdINkr1Frkpp6wZsy3YYEildj9cLY=
22
cyphar.com/go-pathrs v0.2.4/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc=
3-
github.com/checkpoint-restore/go-criu/v8 v8.2.0 h1:dsgMgj/eJtZNKn3qn/+Ri0b4bd0uo6o2zt1yd8Nj2NI=
4-
github.com/checkpoint-restore/go-criu/v8 v8.2.0/go.mod h1:HVKJ1dK+bowJcFI1MtdL2ECIuY+/AtRMHzD9Lqa4uA4=
3+
github.com/aperturerobotics/protobuf-go-lite v0.14.0 h1:6YhovtoUZtXgXLHZ2VV2GCYUzFfi8UN6172Vl2flNlE=
4+
github.com/aperturerobotics/protobuf-go-lite v0.14.0/go.mod h1:lGH3s5ArCTXKI4wJdlNpaybUtwSjfAG0vdWjxOfMcF8=
5+
github.com/checkpoint-restore/go-criu/v8 v8.2.1-0.20260612135546-b8967dc8885e h1:2CLmsg9n9Gph1crSmLUYKgE0Y+u72TcPKQwqcs4fsBA=
6+
github.com/checkpoint-restore/go-criu/v8 v8.2.1-0.20260612135546-b8967dc8885e/go.mod h1:33d6FwGJGwnzKVvaO0SxlN0tPSuArKU9X/inD/L7/qA=
57
github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg=
68
github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk=
79
github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc=
@@ -75,7 +77,5 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
7577
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
7678
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
7779
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
78-
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
79-
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
8080
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
8181
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

libcontainer/criu_linux.go

Lines changed: 73 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222
securejoin "github.com/cyphar/filepath-securejoin"
2323
"github.com/sirupsen/logrus"
2424
"golang.org/x/sys/unix"
25-
"google.golang.org/protobuf/proto"
2625

2726
"github.com/opencontainers/cgroups"
2827
"github.com/opencontainers/runc/internal/cmsg"
@@ -110,14 +109,17 @@ func (c *Container) checkCriuVersion(minVersion int) error {
110109

111110
const descriptorsFilename = "descriptors.json"
112111

112+
// TODO: replace with new(v) once Go < 1.26 is not supported.
113+
func mkPtr[T any](v T) *T { return &v }
114+
113115
func (c *Container) addCriuDumpMount(req *criurpc.CriuReq, m *configs.Mount) {
114116
mountDest := strings.TrimPrefix(m.Destination, c.config.Rootfs)
115117
if dest, err := securejoin.SecureJoin(c.config.Rootfs, mountDest); err == nil {
116118
mountDest = dest[len(c.config.Rootfs):]
117119
}
118120
extMnt := &criurpc.ExtMountMap{
119-
Key: proto.String(mountDest),
120-
Val: proto.String(mountDest),
121+
Key: mkPtr(mountDest),
122+
Val: mkPtr(mountDest),
121123
}
122124
req.Opts.ExtMnt = append(req.Opts.ExtMnt, extMnt)
123125
}
@@ -136,8 +138,8 @@ func (c *Container) addMaskPaths(req *criurpc.CriuReq) error {
136138
}
137139

138140
extMnt := &criurpc.ExtMountMap{
139-
Key: proto.String(path),
140-
Val: proto.String("/dev/null"),
141+
Key: mkPtr(path),
142+
Val: mkPtr("/dev/null"),
141143
}
142144
req.Opts.ExtMnt = append(req.Opts.ExtMnt, extMnt)
143145
}
@@ -157,15 +159,15 @@ func (c *Container) handleCriuConfigurationFile(rpcOpts *criurpc.CriuOpts) {
157159
// configuration file. If the file does not exist, CRIU
158160
// will just ignore it.
159161
if configFile != "" {
160-
rpcOpts.ConfigFile = proto.String(configFile)
162+
rpcOpts.ConfigFile = mkPtr(configFile)
161163
}
162164
// If 'org.criu.config' exists and is set to an empty
163165
// string, a runc specific CRIU configuration file will
164166
// be not set at all.
165167
} else {
166168
// If the mentioned annotation has not been found, specify
167169
// a default CRIU configuration file.
168-
rpcOpts.ConfigFile = proto.String("/etc/criu/runc.conf")
170+
rpcOpts.ConfigFile = mkPtr("/etc/criu/runc.conf")
169171
}
170172
}
171173

@@ -252,8 +254,8 @@ func (c *Container) handleRestoringNamespaces(rpcOpts *criurpc.CriuOpts, extraFi
252254
// CRIU will issue a warning for NEWUSER:
253255
// criu/namespaces.c: 'join-ns with user-namespace is not fully tested and dangerous'
254256
rpcOpts.JoinNs = append(rpcOpts.JoinNs, &criurpc.JoinNamespace{
255-
Ns: proto.String(configs.NsName(ns.Type)),
256-
NsFile: proto.String(nsPath),
257+
Ns: mkPtr(configs.NsName(ns.Type)),
258+
NsFile: mkPtr(nsPath),
257259
})
258260
}
259261
}
@@ -280,10 +282,10 @@ func (c *Container) handleRestoringExternalNamespaces(rpcOpts *criurpc.CriuOpts,
280282
return fmt.Errorf("Requested network namespace %v does not exist", nsPath)
281283
}
282284
inheritFd := &criurpc.InheritFd{
283-
Key: proto.String(criuNsToKey(t)),
285+
Key: mkPtr(criuNsToKey(t)),
284286
// The offset of four is necessary because 0, 1, 2 and 3 are
285287
// already used by stdin, stdout, stderr, 'criu swrk' socket.
286-
Fd: proto.Int32(int32(4 + len(*extraFiles))),
288+
Fd: mkPtr(int32(4 + len(*extraFiles))),
287289
}
288290
rpcOpts.InheritFd = append(rpcOpts.InheritFd, inheritFd)
289291
// All open FDs need to be transferred to CRIU via extraFiles
@@ -331,25 +333,25 @@ func (c *Container) Checkpoint(criuOpts *CriuOpts) error {
331333
defer imageDir.Close()
332334

333335
rpcOpts := criurpc.CriuOpts{
334-
ImagesDirFd: proto.Int32(int32(imageDir.Fd())),
335-
LogLevel: proto.Int32(4),
336-
LogFile: proto.String(logFile),
337-
Root: proto.String(c.config.Rootfs),
338-
ManageCgroups: proto.Bool(true), // Obsoleted by ManageCgroupsMode.
336+
ImagesDirFd: mkPtr(int32(imageDir.Fd())),
337+
LogLevel: mkPtr(int32(4)),
338+
LogFile: mkPtr(logFile),
339+
Root: mkPtr(c.config.Rootfs),
340+
ManageCgroups: mkPtr(true), // Obsoleted by ManageCgroupsMode.
339341
ManageCgroupsMode: &cgMode,
340-
NotifyScripts: proto.Bool(true),
341-
Pid: proto.Int32(int32(c.initProcess.pid())),
342-
ShellJob: proto.Bool(criuOpts.ShellJob),
343-
LeaveRunning: proto.Bool(criuOpts.LeaveRunning),
344-
TcpEstablished: proto.Bool(criuOpts.TcpEstablished),
345-
TcpSkipInFlight: proto.Bool(criuOpts.TcpSkipInFlight),
346-
LinkRemap: proto.Bool(criuOpts.LinkRemap),
347-
ExtUnixSk: proto.Bool(criuOpts.ExternalUnixConnections),
348-
FileLocks: proto.Bool(criuOpts.FileLocks),
349-
EmptyNs: proto.Uint32(criuOpts.EmptyNs),
350-
OrphanPtsMaster: proto.Bool(true),
351-
AutoDedup: proto.Bool(criuOpts.AutoDedup),
352-
LazyPages: proto.Bool(criuOpts.LazyPages),
342+
NotifyScripts: mkPtr(true),
343+
Pid: mkPtr(int32(c.initProcess.pid())),
344+
ShellJob: mkPtr(criuOpts.ShellJob),
345+
LeaveRunning: mkPtr(criuOpts.LeaveRunning),
346+
TcpEstablished: mkPtr(criuOpts.TcpEstablished),
347+
TcpSkipInFlight: mkPtr(criuOpts.TcpSkipInFlight),
348+
LinkRemap: mkPtr(criuOpts.LinkRemap),
349+
ExtUnixSk: mkPtr(criuOpts.ExternalUnixConnections),
350+
FileLocks: mkPtr(criuOpts.FileLocks),
351+
EmptyNs: mkPtr(criuOpts.EmptyNs),
352+
OrphanPtsMaster: mkPtr(true),
353+
AutoDedup: mkPtr(criuOpts.AutoDedup),
354+
LazyPages: mkPtr(criuOpts.LazyPages),
353355
}
354356

355357
// if criuOpts.WorkDirectory is not set, criu default is used.
@@ -362,7 +364,7 @@ func (c *Container) Checkpoint(criuOpts *CriuOpts) error {
362364
return err
363365
}
364366
defer workDir.Close()
365-
rpcOpts.WorkDirFd = proto.Int32(int32(workDir.Fd()))
367+
rpcOpts.WorkDirFd = mkPtr(int32(workDir.Fd()))
366368
logDir = criuOpts.WorkDirectory
367369
}
368370

@@ -388,28 +390,28 @@ func (c *Container) Checkpoint(criuOpts *CriuOpts) error {
388390
// Note cgroup v2 freezer is only supported since CRIU release 3.14.
389391
if !cgroups.IsCgroup2UnifiedMode() || c.checkCriuVersion(31400) == nil {
390392
if fcg := c.cgroupManager.Path("freezer"); fcg != "" {
391-
rpcOpts.FreezeCgroup = proto.String(fcg)
393+
rpcOpts.FreezeCgroup = mkPtr(fcg)
392394
}
393395
}
394396

395397
// append optional criu opts, e.g., page-server and port
396398
if criuOpts.PageServer.Address != "" && criuOpts.PageServer.Port != 0 {
397399
rpcOpts.Ps = &criurpc.CriuPageServerInfo{
398-
Address: proto.String(criuOpts.PageServer.Address),
399-
Port: proto.Int32(criuOpts.PageServer.Port),
400+
Address: mkPtr(criuOpts.PageServer.Address),
401+
Port: mkPtr(criuOpts.PageServer.Port),
400402
}
401403
}
402404

403405
// pre-dump may need parentImage param to complete iterative migration
404406
if criuOpts.ParentImage != "" {
405-
rpcOpts.ParentImg = proto.String(criuOpts.ParentImage)
406-
rpcOpts.TrackMem = proto.Bool(true)
407+
rpcOpts.ParentImg = mkPtr(criuOpts.ParentImage)
408+
rpcOpts.TrackMem = mkPtr(true)
407409
}
408410

409411
var t criurpc.CriuReqType
410412
if criuOpts.PreDump {
411413
feat := criurpc.CriuFeatures{
412-
MemTrack: proto.Bool(true),
414+
MemTrack: mkPtr(true),
413415
}
414416

415417
if err := c.checkCriuFeatures(criuOpts, &feat); err != nil {
@@ -424,7 +426,7 @@ func (c *Container) Checkpoint(criuOpts *CriuOpts) error {
424426
if criuOpts.LazyPages {
425427
// lazy migration requested; check if criu supports it
426428
feat := criurpc.CriuFeatures{
427-
LazyPages: proto.Bool(true),
429+
LazyPages: mkPtr(true),
428430
}
429431
if err := c.checkCriuFeatures(criuOpts, &feat); err != nil {
430432
return err
@@ -444,7 +446,7 @@ func (c *Container) Checkpoint(criuOpts *CriuOpts) error {
444446
if c.checkCriuVersion(31500) != nil {
445447
// For criu 3.15+, use notifications (see case "status-ready"
446448
// in criuNotifications). Otherwise, rely on criu status fd.
447-
rpcOpts.StatusFd = proto.Int32(int32(fd))
449+
rpcOpts.StatusFd = mkPtr(int32(fd))
448450
}
449451
}
450452
}
@@ -512,8 +514,8 @@ func (c *Container) addCriuRestoreMount(req *criurpc.CriuReq, m *configs.Mount)
512514
mountDest = dest[len(c.config.Rootfs):]
513515
}
514516
extMnt := &criurpc.ExtMountMap{
515-
Key: proto.String(mountDest),
516-
Val: proto.String(m.Source),
517+
Key: mkPtr(mountDest),
518+
Val: mkPtr(m.Source),
517519
}
518520
req.Opts.ExtMnt = append(req.Opts.ExtMnt, extMnt)
519521
}
@@ -523,17 +525,17 @@ func (c *Container) restoreNetwork(req *criurpc.CriuReq, criuOpts *CriuOpts) {
523525
switch iface.Type {
524526
case "veth":
525527
veth := new(criurpc.CriuVethPair)
526-
veth.IfOut = proto.String(iface.HostInterfaceName)
527-
veth.IfIn = proto.String(iface.Name)
528+
veth.IfOut = mkPtr(iface.HostInterfaceName)
529+
veth.IfIn = mkPtr(iface.Name)
528530
req.Opts.Veths = append(req.Opts.Veths, veth)
529531
case "loopback":
530532
// Do nothing
531533
}
532534
}
533535
for _, i := range criuOpts.VethPairs {
534536
veth := new(criurpc.CriuVethPair)
535-
veth.IfOut = proto.String(i.HostInterfaceName)
536-
veth.IfIn = proto.String(i.ContainerInterfaceName)
537+
veth.IfOut = mkPtr(i.HostInterfaceName)
538+
veth.IfIn = mkPtr(i.ContainerInterfaceName)
537539
req.Opts.Veths = append(req.Opts.Veths, veth)
538540
}
539541
}
@@ -687,23 +689,23 @@ func (c *Container) Restore(process *Process, criuOpts *CriuOpts) error {
687689
req := &criurpc.CriuReq{
688690
Type: &t,
689691
Opts: &criurpc.CriuOpts{
690-
ImagesDirFd: proto.Int32(int32(imageDir.Fd())),
691-
EvasiveDevices: proto.Bool(true),
692-
LogLevel: proto.Int32(4),
693-
LogFile: proto.String(logFile),
694-
RstSibling: proto.Bool(true),
695-
Root: proto.String(root),
696-
ManageCgroups: proto.Bool(true), // Obsoleted by ManageCgroupsMode.
692+
ImagesDirFd: mkPtr(int32(imageDir.Fd())),
693+
EvasiveDevices: mkPtr(true),
694+
LogLevel: mkPtr(int32(4)),
695+
LogFile: mkPtr(logFile),
696+
RstSibling: mkPtr(true),
697+
Root: mkPtr(root),
698+
ManageCgroups: mkPtr(true), // Obsoleted by ManageCgroupsMode.
697699
ManageCgroupsMode: &cgMode,
698-
NotifyScripts: proto.Bool(true),
699-
ShellJob: proto.Bool(criuOpts.ShellJob),
700-
ExtUnixSk: proto.Bool(criuOpts.ExternalUnixConnections),
701-
TcpEstablished: proto.Bool(criuOpts.TcpEstablished),
702-
FileLocks: proto.Bool(criuOpts.FileLocks),
703-
EmptyNs: proto.Uint32(criuOpts.EmptyNs),
704-
OrphanPtsMaster: proto.Bool(true),
705-
AutoDedup: proto.Bool(criuOpts.AutoDedup),
706-
LazyPages: proto.Bool(criuOpts.LazyPages),
700+
NotifyScripts: mkPtr(true),
701+
ShellJob: mkPtr(criuOpts.ShellJob),
702+
ExtUnixSk: mkPtr(criuOpts.ExternalUnixConnections),
703+
TcpEstablished: mkPtr(criuOpts.TcpEstablished),
704+
FileLocks: mkPtr(criuOpts.FileLocks),
705+
EmptyNs: mkPtr(criuOpts.EmptyNs),
706+
OrphanPtsMaster: mkPtr(true),
707+
AutoDedup: mkPtr(criuOpts.AutoDedup),
708+
LazyPages: mkPtr(criuOpts.LazyPages),
707709
},
708710
}
709711

@@ -713,13 +715,13 @@ func (c *Container) Restore(process *Process, criuOpts *CriuOpts) error {
713715
if err := c.checkCriuVersion(31600); err != nil {
714716
return errors.New("--lsm-profile requires at least CRIU 3.16")
715717
}
716-
req.Opts.LsmProfile = proto.String(criuOpts.LsmProfile)
718+
req.Opts.LsmProfile = mkPtr(criuOpts.LsmProfile)
717719
}
718720
if criuOpts.LsmMountContext != "" {
719721
if err := c.checkCriuVersion(31600); err != nil {
720722
return errors.New("--lsm-mount-context requires at least CRIU 3.16")
721723
}
722-
req.Opts.LsmMountContext = proto.String(criuOpts.LsmMountContext)
724+
req.Opts.LsmMountContext = mkPtr(criuOpts.LsmMountContext)
723725
}
724726

725727
if criuOpts.WorkDirectory != "" {
@@ -733,7 +735,7 @@ func (c *Container) Restore(process *Process, criuOpts *CriuOpts) error {
733735
return err
734736
}
735737
defer workDir.Close()
736-
req.Opts.WorkDirFd = proto.Int32(int32(workDir.Fd()))
738+
req.Opts.WorkDirFd = mkPtr(int32(workDir.Fd()))
737739
logDir = criuOpts.WorkDirectory
738740
}
739741
c.handleCriuConfigurationFile(req.Opts)
@@ -796,8 +798,8 @@ func (c *Container) Restore(process *Process, criuOpts *CriuOpts) error {
796798
for i := range fds {
797799
if s := fds[i]; strings.Contains(s, "pipe:") {
798800
inheritFd := new(criurpc.InheritFd)
799-
inheritFd.Key = proto.String(s)
800-
inheritFd.Fd = proto.Int32(int32(i))
801+
inheritFd.Key = mkPtr(s)
802+
inheritFd.Fd = mkPtr(int32(i))
801803
req.Opts.InheritFd = append(req.Opts.InheritFd, inheritFd)
802804
}
803805
}
@@ -889,8 +891,8 @@ func (c *Container) criuApplyCgroups(pid int, req *criurpc.CriuReq) error {
889891

890892
for c, p := range cgroupsPaths {
891893
cgroupRoot := &criurpc.CgroupRoot{
892-
Ctrl: proto.String(c),
893-
Path: proto.String(p),
894+
Ctrl: mkPtr(c),
895+
Path: mkPtr(p),
894896
}
895897
req.Opts.CgRoot = append(req.Opts.CgRoot, cgroupRoot)
896898
}
@@ -984,7 +986,7 @@ func (c *Container) criuSwrk(process *Process, req *criurpc.CriuReq, opts *CriuO
984986
}
985987
}
986988
}
987-
data, err := proto.Marshal(req)
989+
data, err := req.MarshalVT()
988990
if err != nil {
989991
return err
990992
}
@@ -1017,7 +1019,7 @@ func (c *Container) criuSwrk(process *Process, req *criurpc.CriuReq, opts *CriuO
10171019
}
10181020

10191021
resp := new(criurpc.CriuResp)
1020-
err = proto.Unmarshal(buf[:n], resp)
1022+
err = resp.UnmarshalVT(buf[:n])
10211023
if err != nil {
10221024
return err
10231025
}
@@ -1036,9 +1038,9 @@ func (c *Container) criuSwrk(process *Process, req *criurpc.CriuReq, opts *CriuO
10361038
}
10371039
req = &criurpc.CriuReq{
10381040
Type: &t,
1039-
NotifySuccess: proto.Bool(true),
1041+
NotifySuccess: mkPtr(true),
10401042
}
1041-
data, err = proto.Marshal(req)
1043+
data, err = req.MarshalVT()
10421044
if err != nil {
10431045
return err
10441046
}

update.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/urfave/cli/v3"
1919
)
2020

21+
// TODO: replace with new(v) once Go < 1.26 is not supported.
2122
func mkPtr[T any](v T) *T { return &v }
2223

2324
var updateCommand = &cli.Command{

vendor/github.com/aperturerobotics/protobuf-go-lite/.gitattributes

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/aperturerobotics/protobuf-go-lite/.gitignore

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)