mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 05:40:42 +00:00 
			
		
		
		
	runc rc95 contains a fix for CVE-2021-30465. runc rc94 provides fixes and improvements. One notable change is cgroup manager's Set now accept Resources rather than Cgroup (see https://github.com/opencontainers/runc/pull/2906). Modify the code accordingly. Also update runc dependencies (as hinted by hack/lint-depdendencies.sh): github.com/cilium/ebpf v0.5.0 github.com/containerd/console v1.0.2 github.com/coreos/go-systemd/v22 v22.3.1 github.com/godbus/dbus/v5 v5.0.4 github.com/moby/sys/mountinfo v0.4.1 golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 github.com/google/go-cmp v0.5.4 github.com/kr/pretty v0.2.1 github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
		
			
				
	
	
		
			261 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			261 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package criu
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 	"os/exec"
 | |
| 	"strconv"
 | |
| 	"syscall"
 | |
| 
 | |
| 	"github.com/checkpoint-restore/go-criu/v5/rpc"
 | |
| 	"google.golang.org/protobuf/proto"
 | |
| )
 | |
| 
 | |
| // Criu struct
 | |
| type Criu struct {
 | |
| 	swrkCmd  *exec.Cmd
 | |
| 	swrkSk   *os.File
 | |
| 	swrkPath string
 | |
| }
 | |
| 
 | |
| // MakeCriu returns the Criu object required for most operations
 | |
| func MakeCriu() *Criu {
 | |
| 	return &Criu{
 | |
| 		swrkPath: "criu",
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // SetCriuPath allows setting the path to the CRIU binary
 | |
| // if it is in a non standard location
 | |
| func (c *Criu) SetCriuPath(path string) {
 | |
| 	c.swrkPath = path
 | |
| }
 | |
| 
 | |
| // Prepare sets up everything for the RPC communication to CRIU
 | |
| func (c *Criu) Prepare() error {
 | |
| 	fds, err := syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_SEQPACKET, 0)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	cln := os.NewFile(uintptr(fds[0]), "criu-xprt-cln")
 | |
| 	syscall.CloseOnExec(fds[0])
 | |
| 	srv := os.NewFile(uintptr(fds[1]), "criu-xprt-srv")
 | |
| 	defer srv.Close()
 | |
| 
 | |
| 	args := []string{"swrk", strconv.Itoa(fds[1])}
 | |
| 	// #nosec G204
 | |
| 	cmd := exec.Command(c.swrkPath, args...)
 | |
| 
 | |
| 	err = cmd.Start()
 | |
| 	if err != nil {
 | |
| 		cln.Close()
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	c.swrkCmd = cmd
 | |
| 	c.swrkSk = cln
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Cleanup cleans up
 | |
| func (c *Criu) Cleanup() {
 | |
| 	if c.swrkCmd != nil {
 | |
| 		c.swrkSk.Close()
 | |
| 		c.swrkSk = nil
 | |
| 		_ = c.swrkCmd.Wait()
 | |
| 		c.swrkCmd = nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (c *Criu) sendAndRecv(reqB []byte) ([]byte, int, error) {
 | |
| 	cln := c.swrkSk
 | |
| 	_, err := cln.Write(reqB)
 | |
| 	if err != nil {
 | |
| 		return nil, 0, err
 | |
| 	}
 | |
| 
 | |
| 	respB := make([]byte, 2*4096)
 | |
| 	n, err := cln.Read(respB)
 | |
| 	if err != nil {
 | |
| 		return nil, 0, err
 | |
| 	}
 | |
| 
 | |
| 	return respB, n, nil
 | |
| }
 | |
| 
 | |
| func (c *Criu) doSwrk(reqType rpc.CriuReqType, opts *rpc.CriuOpts, nfy Notify) error {
 | |
| 	resp, err := c.doSwrkWithResp(reqType, opts, nfy)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	respType := resp.GetType()
 | |
| 	if respType != reqType {
 | |
| 		return errors.New("unexpected responce")
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (c *Criu) doSwrkWithResp(reqType rpc.CriuReqType, opts *rpc.CriuOpts, nfy Notify) (*rpc.CriuResp, error) {
 | |
| 	var resp *rpc.CriuResp
 | |
| 
 | |
| 	req := rpc.CriuReq{
 | |
| 		Type: &reqType,
 | |
| 		Opts: opts,
 | |
| 	}
 | |
| 
 | |
| 	if nfy != nil {
 | |
| 		opts.NotifyScripts = proto.Bool(true)
 | |
| 	}
 | |
| 
 | |
| 	if c.swrkCmd == nil {
 | |
| 		err := c.Prepare()
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		defer c.Cleanup()
 | |
| 	}
 | |
| 
 | |
| 	for {
 | |
| 		reqB, err := proto.Marshal(&req)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		respB, respS, err := c.sendAndRecv(reqB)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		resp = &rpc.CriuResp{}
 | |
| 		err = proto.Unmarshal(respB[:respS], resp)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		if !resp.GetSuccess() {
 | |
| 			return resp, fmt.Errorf("operation failed (msg:%s err:%d)",
 | |
| 				resp.GetCrErrmsg(), resp.GetCrErrno())
 | |
| 		}
 | |
| 
 | |
| 		respType := resp.GetType()
 | |
| 		if respType != rpc.CriuReqType_NOTIFY {
 | |
| 			break
 | |
| 		}
 | |
| 		if nfy == nil {
 | |
| 			return resp, errors.New("unexpected notify")
 | |
| 		}
 | |
| 
 | |
| 		notify := resp.GetNotify()
 | |
| 		switch notify.GetScript() {
 | |
| 		case "pre-dump":
 | |
| 			err = nfy.PreDump()
 | |
| 		case "post-dump":
 | |
| 			err = nfy.PostDump()
 | |
| 		case "pre-restore":
 | |
| 			err = nfy.PreRestore()
 | |
| 		case "post-restore":
 | |
| 			err = nfy.PostRestore(notify.GetPid())
 | |
| 		case "network-lock":
 | |
| 			err = nfy.NetworkLock()
 | |
| 		case "network-unlock":
 | |
| 			err = nfy.NetworkUnlock()
 | |
| 		case "setup-namespaces":
 | |
| 			err = nfy.SetupNamespaces(notify.GetPid())
 | |
| 		case "post-setup-namespaces":
 | |
| 			err = nfy.PostSetupNamespaces()
 | |
| 		case "post-resume":
 | |
| 			err = nfy.PostResume()
 | |
| 		default:
 | |
| 			err = nil
 | |
| 		}
 | |
| 
 | |
| 		if err != nil {
 | |
| 			return resp, err
 | |
| 		}
 | |
| 
 | |
| 		req = rpc.CriuReq{
 | |
| 			Type:          &respType,
 | |
| 			NotifySuccess: proto.Bool(true),
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return resp, nil
 | |
| }
 | |
| 
 | |
| // Dump dumps a process
 | |
| func (c *Criu) Dump(opts *rpc.CriuOpts, nfy Notify) error {
 | |
| 	return c.doSwrk(rpc.CriuReqType_DUMP, opts, nfy)
 | |
| }
 | |
| 
 | |
| // Restore restores a process
 | |
| func (c *Criu) Restore(opts *rpc.CriuOpts, nfy Notify) error {
 | |
| 	return c.doSwrk(rpc.CriuReqType_RESTORE, opts, nfy)
 | |
| }
 | |
| 
 | |
| // PreDump does a pre-dump
 | |
| func (c *Criu) PreDump(opts *rpc.CriuOpts, nfy Notify) error {
 | |
| 	return c.doSwrk(rpc.CriuReqType_PRE_DUMP, opts, nfy)
 | |
| }
 | |
| 
 | |
| // StartPageServer starts the page server
 | |
| func (c *Criu) StartPageServer(opts *rpc.CriuOpts) error {
 | |
| 	return c.doSwrk(rpc.CriuReqType_PAGE_SERVER, opts, nil)
 | |
| }
 | |
| 
 | |
| // StartPageServerChld starts the page server and returns PID and port
 | |
| func (c *Criu) StartPageServerChld(opts *rpc.CriuOpts) (int, int, error) {
 | |
| 	resp, err := c.doSwrkWithResp(rpc.CriuReqType_PAGE_SERVER_CHLD, opts, nil)
 | |
| 	if err != nil {
 | |
| 		return 0, 0, err
 | |
| 	}
 | |
| 
 | |
| 	return int(resp.Ps.GetPid()), int(resp.Ps.GetPort()), nil
 | |
| }
 | |
| 
 | |
| // GetCriuVersion executes the VERSION RPC call and returns the version
 | |
| // as an integer. Major * 10000 + Minor * 100 + SubLevel
 | |
| func (c *Criu) GetCriuVersion() (int, error) {
 | |
| 	resp, err := c.doSwrkWithResp(rpc.CriuReqType_VERSION, nil, nil)
 | |
| 	if err != nil {
 | |
| 		return 0, err
 | |
| 	}
 | |
| 
 | |
| 	if resp.GetType() != rpc.CriuReqType_VERSION {
 | |
| 		return 0, fmt.Errorf("Unexpected CRIU RPC response")
 | |
| 	}
 | |
| 
 | |
| 	version := int(*resp.GetVersion().MajorNumber) * 10000
 | |
| 	version += int(*resp.GetVersion().MinorNumber) * 100
 | |
| 	if resp.GetVersion().Sublevel != nil {
 | |
| 		version += int(*resp.GetVersion().Sublevel)
 | |
| 	}
 | |
| 
 | |
| 	if resp.GetVersion().Gitid != nil {
 | |
| 		// taken from runc: if it is a git release -> increase minor by 1
 | |
| 		version -= (version % 100)
 | |
| 		version += 100
 | |
| 	}
 | |
| 
 | |
| 	return version, nil
 | |
| }
 | |
| 
 | |
| // IsCriuAtLeast checks if the version is at least the same
 | |
| // as the parameter version
 | |
| func (c *Criu) IsCriuAtLeast(version int) (bool, error) {
 | |
| 	criuVersion, err := c.GetCriuVersion()
 | |
| 	if err != nil {
 | |
| 		return false, err
 | |
| 	}
 | |
| 
 | |
| 	if criuVersion >= version {
 | |
| 		return true, nil
 | |
| 	}
 | |
| 
 | |
| 	return false, nil
 | |
| }
 |