third_party/gvisor: remove old cgroups import

We don't want to use the old cgroups/v1 import, remove it.
Most code using it is no longer in use as it has been replaced by
containerd shim code, so just delete that.
Adjust the rest to work with cgroups/v3.

As K8s 1.32 drops its dependency on cgroups/v1 Gazelle mangles the deps
if we leave it in.

Change-Id: Ic95fce7a17acbddf70a1b5b2a0978b9246a17c58
Reviewed-on: https://review.monogon.dev/c/monogon/+/3720
Tested-by: Jenkins CI
Reviewed-by: Tim Windelschmidt <tim@monogon.tech>
diff --git a/third_party/go/patches/gvisor-containerd-compat.patch b/third_party/go/patches/gvisor-containerd-compat.patch
index f643674..f7b1d7f 100644
--- a/third_party/go/patches/gvisor-containerd-compat.patch
+++ b/third_party/go/patches/gvisor-containerd-compat.patch
@@ -1,4 +1,4 @@
-From 611642fc8162a1bb66f1cf7ef7950e18a7e5ffda Mon Sep 17 00:00:00 2001
+From a16338e9841ca5776cf4757726166924c9c02062 Mon Sep 17 00:00:00 2001
 From: Lorenz Brun <lorenz@brun.one>
 Date: Tue, 19 Nov 2024 17:29:26 +0100
 Subject: [PATCH] containerd v2 upgrade
@@ -14,14 +14,16 @@
  pkg/shim/proc/io.go             |    2 +-
  pkg/shim/proc/types.go          |    4 +-
  pkg/shim/runsc/debug.go         |    2 +-
- pkg/shim/runsc/epoll.go         |    4 +-
- pkg/shim/runsc/oom_v2.go        |    4 +-
- pkg/shim/runsc/service.go       |  183 ++---
+ pkg/shim/runsc/epoll.go         |  134 ----
+ pkg/shim/runsc/oom_v2.go        |  115 ---
+ pkg/shim/runsc/service.go       |  205 ++---
  pkg/shim/runsc/state.go         |    8 +-
  pkg/shim/runsccmd/runsc.go      |    2 +-
  pkg/shim/service.go             |  432 +++++++----
  shim/cli/cli.go                 |   33 +-
- 17 files changed, 583 insertions(+), 1482 deletions(-)
+ 17 files changed, 590 insertions(+), 1738 deletions(-)
+ delete mode 100644 pkg/shim/runsc/epoll.go
+ delete mode 100644 pkg/shim/runsc/oom_v2.go
 
 diff --git a/go.mod b/go.mod
 index 2533dbfa1..fd8d4b0bd 100644
@@ -1786,37 +1788,268 @@
  
  var once sync.Once
 diff --git a/pkg/shim/runsc/epoll.go b/pkg/shim/runsc/epoll.go
-index e9eb10e05..db7c3455c 100644
+deleted file mode 100644
+index e9eb10e05..000000000
 --- a/pkg/shim/runsc/epoll.go
-+++ b/pkg/shim/runsc/epoll.go
-@@ -24,8 +24,8 @@ import (
- 	"sync"
- 
- 	"github.com/containerd/cgroups"
++++ /dev/null
+@@ -1,134 +0,0 @@
+-// Copyright 2018 The containerd Authors.
+-// Copyright 2018 The gVisor Authors.
+-//
+-// Licensed under the Apache License, Version 2.0 (the "License");
+-// you may not use this file except in compliance with the License.
+-// You may obtain a copy of the License at
+-//
+-//     https://www.apache.org/licenses/LICENSE-2.0
+-//
+-// Unless required by applicable law or agreed to in writing, software
+-// distributed under the License is distributed on an "AS IS" BASIS,
+-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-// See the License for the specific language governing permissions and
+-// limitations under the License.
+-
+-//go:build linux
+-// +build linux
+-
+-package runsc
+-
+-import (
+-	"context"
+-	"fmt"
+-	"sync"
+-
+-	"github.com/containerd/cgroups"
 -	"github.com/containerd/containerd/events"
 -	"github.com/containerd/containerd/runtime"
-+	"github.com/containerd/containerd/v2/core/events"
-+	"github.com/containerd/containerd/v2/core/runtime"
- 	"golang.org/x/sys/unix"
- )
- 
+-	"golang.org/x/sys/unix"
+-)
+-
+-func newOOMEpoller(publisher events.Publisher) (*epoller, error) {
+-	fd, err := unix.EpollCreate1(unix.EPOLL_CLOEXEC)
+-	if err != nil {
+-		return nil, err
+-	}
+-	return &epoller{
+-		fd:        fd,
+-		publisher: publisher,
+-		set:       make(map[uintptr]*item),
+-	}, nil
+-}
+-
+-type epoller struct {
+-	mu sync.Mutex
+-
+-	fd        int
+-	publisher events.Publisher
+-	set       map[uintptr]*item
+-}
+-
+-type item struct {
+-	id string
+-	cg cgroups.Cgroup
+-}
+-
+-func (e *epoller) Close() error {
+-	return unix.Close(e.fd)
+-}
+-
+-func (e *epoller) run(ctx context.Context) {
+-	var events [128]unix.EpollEvent
+-	for {
+-		select {
+-		case <-ctx.Done():
+-			e.Close()
+-			return
+-		default:
+-			n, err := unix.EpollWait(e.fd, events[:], -1)
+-			if err != nil {
+-				if err == unix.EINTR || err == unix.EAGAIN {
+-					continue
+-				}
+-				// Should not happen.
+-				panic(fmt.Errorf("cgroups: epoll wait: %w", err))
+-			}
+-			for i := 0; i < n; i++ {
+-				e.process(ctx, uintptr(events[i].Fd))
+-			}
+-		}
+-	}
+-}
+-
+-func (e *epoller) add(id string, cgx any) error {
+-	e.mu.Lock()
+-	defer e.mu.Unlock()
+-	cg, ok := cgx.(cgroups.Cgroup)
+-	if !ok {
+-		return fmt.Errorf("expected cgroups.Cgroup, got: %T", cgx)
+-	}
+-	fd, err := cg.OOMEventFD()
+-	if err != nil {
+-		return err
+-	}
+-	e.set[fd] = &item{
+-		id: id,
+-		cg: cg,
+-	}
+-	event := unix.EpollEvent{
+-		Fd:     int32(fd),
+-		Events: unix.EPOLLHUP | unix.EPOLLIN | unix.EPOLLERR,
+-	}
+-	return unix.EpollCtl(e.fd, unix.EPOLL_CTL_ADD, int(fd), &event)
+-}
+-
+-func (e *epoller) process(ctx context.Context, fd uintptr) {
+-	flush(fd)
+-	e.mu.Lock()
+-	i, ok := e.set[fd]
+-	if !ok {
+-		e.mu.Unlock()
+-		return
+-	}
+-	e.mu.Unlock()
+-	if i.cg.State() == cgroups.Deleted {
+-		e.mu.Lock()
+-		delete(e.set, fd)
+-		e.mu.Unlock()
+-		unix.Close(int(fd))
+-		return
+-	}
+-	if err := e.publisher.Publish(ctx, runtime.TaskOOMEventTopic, &TaskOOM{
+-		ContainerID: i.id,
+-	}); err != nil {
+-		// Should not happen.
+-		panic(fmt.Errorf("publish OOM event: %w", err))
+-	}
+-}
+-
+-func flush(fd uintptr) error {
+-	var buf [8]byte
+-	_, err := unix.Read(int(fd), buf[:])
+-	return err
+-}
 diff --git a/pkg/shim/runsc/oom_v2.go b/pkg/shim/runsc/oom_v2.go
-index 89b7bed2e..7b23ee81a 100644
+deleted file mode 100644
+index 89b7bed2e..000000000
 --- a/pkg/shim/runsc/oom_v2.go
-+++ b/pkg/shim/runsc/oom_v2.go
-@@ -23,8 +23,8 @@ import (
- 	"fmt"
- 
- 	cgroupsv2 "github.com/containerd/cgroups/v2"
++++ /dev/null
+@@ -1,115 +0,0 @@
+-// Copyright The containerd Authors.
+-// Copyright 2021 The gVisor Authors.
+-//
+-// Licensed under the Apache License, Version 2.0 (the "License");
+-// you may not use this file except in compliance with the License.
+-// You may obtain a copy of the License at
+-//
+-//     https://www.apache.org/licenses/LICENSE-2.0
+-//
+-// Unless required by applicable law or agreed to in writing, software
+-// distributed under the License is distributed on an "AS IS" BASIS,
+-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-// See the License for the specific language governing permissions and
+-// limitations under the License.
+-
+-//go:build linux
+-// +build linux
+-
+-package runsc
+-
+-import (
+-	"context"
+-	"fmt"
+-
+-	cgroupsv2 "github.com/containerd/cgroups/v2"
 -	"github.com/containerd/containerd/runtime"
 -	"github.com/containerd/containerd/runtime/v2/shim"
-+	"github.com/containerd/containerd/v2/core/runtime"
-+	"github.com/containerd/containerd/v2/pkg/shim"
- 	"github.com/sirupsen/logrus"
- )
- 
+-	"github.com/sirupsen/logrus"
+-)
+-
+-// newOOMv2Epoller returns an implementation that listens to OOM events
+-// from a container's cgroups v2.  This is copied from containerd to avoid
+-// having to upgrade containerd package just to get it
+-func newOOMv2Poller(publisher shim.Publisher) (oomPoller, error) {
+-	return &watcherV2{
+-		itemCh:    make(chan itemV2),
+-		publisher: publisher,
+-	}, nil
+-}
+-
+-// watcher implementation for handling OOM events from a container's cgroup
+-type watcherV2 struct {
+-	itemCh    chan itemV2
+-	publisher shim.Publisher
+-}
+-
+-type itemV2 struct {
+-	id  string
+-	ev  cgroupsv2.Event
+-	err error
+-}
+-
+-// Close closes the watcher
+-func (w *watcherV2) Close() error {
+-	return nil
+-}
+-
+-// Run the loop
+-func (w *watcherV2) run(ctx context.Context) {
+-	lastOOMMap := make(map[string]uint64) // key: id, value: ev.OOM
+-	for {
+-		select {
+-		case <-ctx.Done():
+-			w.Close()
+-			return
+-		case i := <-w.itemCh:
+-			if i.err != nil {
+-				logrus.WithError(i.err).Debugf("Error listening for OOM, id: %q", i.id)
+-				delete(lastOOMMap, i.id)
+-				continue
+-			}
+-			logrus.Debugf("Received OOM event, id: %q, event: %+v", i.id, i.ev)
+-			lastOOM := lastOOMMap[i.id]
+-			if i.ev.OOMKill > lastOOM {
+-				if err := w.publisher.Publish(ctx, runtime.TaskOOMEventTopic, &TaskOOM{
+-					ContainerID: i.id,
+-				}); err != nil {
+-					logrus.WithError(err).Error("Publish OOM event")
+-				}
+-			}
+-			if i.ev.OOMKill > 0 {
+-				lastOOMMap[i.id] = i.ev.OOMKill
+-			}
+-		}
+-	}
+-}
+-
+-// Add cgroups.Cgroup to the epoll monitor
+-func (w *watcherV2) add(id string, cgx any) error {
+-	cg, ok := cgx.(*cgroupsv2.Manager)
+-	if !ok {
+-		return fmt.Errorf("expected *cgroupsv2.Manager, got: %T", cgx)
+-	}
+-	// NOTE: containerd/cgroups/v2 does not support closing eventCh routine
+-	// currently. The routine shuts down when an error happens, mostly when the
+-	// cgroup is deleted.
+-	eventCh, errCh := cg.EventChan()
+-	go func() {
+-		for {
+-			i := itemV2{id: id}
+-			select {
+-			case ev := <-eventCh:
+-				i.ev = ev
+-				w.itemCh <- i
+-			case err := <-errCh:
+-				i.err = err
+-				w.itemCh <- i
+-				// we no longer get any event/err when we got an err
+-				logrus.WithError(err).Warn("error from eventChan")
+-				return
+-			}
+-		}
+-	}()
+-	return nil
+-}
 diff --git a/pkg/shim/runsc/service.go b/pkg/shim/runsc/service.go
-index e5c88018f..f0a9cb4f0 100644
+index e5c88018f..2bfb0733e 100644
 --- a/pkg/shim/runsc/service.go
 +++ b/pkg/shim/runsc/service.go
 @@ -23,33 +23,39 @@ import (
@@ -1827,10 +2060,11 @@
  
  	"github.com/BurntSushi/toml"
 -	"github.com/containerd/cgroups"
- 	cgroupsstats "github.com/containerd/cgroups/stats/v1"
+-	cgroupsstats "github.com/containerd/cgroups/stats/v1"
 -	cgroupsv2 "github.com/containerd/cgroups/v2"
 +	"github.com/containerd/cgroups/v3"
 +	cgroupsv1 "github.com/containerd/cgroups/v3/cgroup1"
++	cgroups1stats "github.com/containerd/cgroups/v3/cgroup1/stats"
 +	cgroupsv2 "github.com/containerd/cgroups/v3/cgroup2"
  	"github.com/containerd/console"
  	"github.com/containerd/containerd/api/events"
@@ -2202,7 +2436,63 @@
  	if err != nil {
  		log.L.Debugf("Stats error, id: %s: %v", r.ID, err)
  		return nil, err
-@@ -706,7 +667,7 @@ func (s *runscService) Stats(ctx context.Context, r *taskAPI.StatsRequest) (*tas
+@@ -660,53 +621,53 @@ func (s *runscService) Stats(ctx context.Context, r *taskAPI.StatsRequest) (*tas
+ 	// as runc.
+ 	//
+ 	// [0]: https://github.com/google/gvisor/blob/277a0d5a1fbe8272d4729c01ee4c6e374d047ebc/runsc/boot/events.go#L61-L81
+-	metrics := &cgroupsstats.Metrics{
+-		CPU: &cgroupsstats.CPUStat{
+-			Usage: &cgroupsstats.CPUUsage{
++	metrics := &cgroups1stats.Metrics{
++		CPU: &cgroups1stats.CPUStat{
++			Usage: &cgroups1stats.CPUUsage{
+ 				Total:  stats.Cpu.Usage.Total,
+ 				Kernel: stats.Cpu.Usage.Kernel,
+ 				User:   stats.Cpu.Usage.User,
+ 				PerCPU: stats.Cpu.Usage.Percpu,
+ 			},
+-			Throttling: &cgroupsstats.Throttle{
++			Throttling: &cgroups1stats.Throttle{
+ 				Periods:          stats.Cpu.Throttling.Periods,
+ 				ThrottledPeriods: stats.Cpu.Throttling.ThrottledPeriods,
+ 				ThrottledTime:    stats.Cpu.Throttling.ThrottledTime,
+ 			},
+ 		},
+-		Memory: &cgroupsstats.MemoryStat{
++		Memory: &cgroups1stats.MemoryStat{
+ 			Cache: stats.Memory.Cache,
+-			Usage: &cgroupsstats.MemoryEntry{
++			Usage: &cgroups1stats.MemoryEntry{
+ 				Limit:   stats.Memory.Usage.Limit,
+ 				Usage:   stats.Memory.Usage.Usage,
+ 				Max:     stats.Memory.Usage.Max,
+ 				Failcnt: stats.Memory.Usage.Failcnt,
+ 			},
+-			Swap: &cgroupsstats.MemoryEntry{
++			Swap: &cgroups1stats.MemoryEntry{
+ 				Limit:   stats.Memory.Swap.Limit,
+ 				Usage:   stats.Memory.Swap.Usage,
+ 				Max:     stats.Memory.Swap.Max,
+ 				Failcnt: stats.Memory.Swap.Failcnt,
+ 			},
+-			Kernel: &cgroupsstats.MemoryEntry{
++			Kernel: &cgroups1stats.MemoryEntry{
+ 				Limit:   stats.Memory.Kernel.Limit,
+ 				Usage:   stats.Memory.Kernel.Usage,
+ 				Max:     stats.Memory.Kernel.Max,
+ 				Failcnt: stats.Memory.Kernel.Failcnt,
+ 			},
+-			KernelTCP: &cgroupsstats.MemoryEntry{
++			KernelTCP: &cgroups1stats.MemoryEntry{
+ 				Limit:   stats.Memory.KernelTCP.Limit,
+ 				Usage:   stats.Memory.KernelTCP.Usage,
+ 				Max:     stats.Memory.KernelTCP.Max,
+ 				Failcnt: stats.Memory.KernelTCP.Failcnt,
+ 			},
+ 		},
+-		Pids: &cgroupsstats.PidsStat{
++		Pids: &cgroups1stats.PidsStat{
+ 			Current: stats.Pids.Current,
  			Limit:   stats.Pids.Limit,
  		},
  	}
@@ -2960,5 +3250,5 @@
 +	containerdshim.Run(context.Background(), shim.NewManager("io.containerd.runsc.v1"))
  }
 -- 
-2.44.1
+2.47.0