 de6db4038c
			
		
	
	de6db4038c
	
	
	
		
			
			Note that this is the code in containerd that uses runc (as almost a library). Please see the other commit for the update to runc binary itself. Signed-off-by: Davanum Srinivas <davanum@gmail.com>
		
			
				
	
	
		
			172 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package link
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 
 | |
| 	"github.com/cilium/ebpf"
 | |
| )
 | |
| 
 | |
| type cgroupAttachFlags uint32
 | |
| 
 | |
| // cgroup attach flags
 | |
| const (
 | |
| 	flagAllowOverride cgroupAttachFlags = 1 << iota
 | |
| 	flagAllowMulti
 | |
| 	flagReplace
 | |
| )
 | |
| 
 | |
| type CgroupOptions struct {
 | |
| 	// Path to a cgroupv2 folder.
 | |
| 	Path string
 | |
| 	// One of the AttachCgroup* constants
 | |
| 	Attach ebpf.AttachType
 | |
| 	// Program must be of type CGroup*, and the attach type must match Attach.
 | |
| 	Program *ebpf.Program
 | |
| }
 | |
| 
 | |
| // AttachCgroup links a BPF program to a cgroup.
 | |
| func AttachCgroup(opts CgroupOptions) (Link, error) {
 | |
| 	cgroup, err := os.Open(opts.Path)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("can't open cgroup: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	clone, err := opts.Program.Clone()
 | |
| 	if err != nil {
 | |
| 		cgroup.Close()
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	var cg Link
 | |
| 	cg, err = newLinkCgroup(cgroup, opts.Attach, clone)
 | |
| 	if errors.Is(err, ErrNotSupported) {
 | |
| 		cg, err = newProgAttachCgroup(cgroup, opts.Attach, clone, flagAllowMulti)
 | |
| 	}
 | |
| 	if errors.Is(err, ErrNotSupported) {
 | |
| 		cg, err = newProgAttachCgroup(cgroup, opts.Attach, clone, flagAllowOverride)
 | |
| 	}
 | |
| 	if err != nil {
 | |
| 		cgroup.Close()
 | |
| 		clone.Close()
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return cg, nil
 | |
| }
 | |
| 
 | |
| // LoadPinnedCgroup loads a pinned cgroup from a bpffs.
 | |
| func LoadPinnedCgroup(fileName string, opts *ebpf.LoadPinOptions) (Link, error) {
 | |
| 	link, err := LoadPinnedRawLink(fileName, CgroupType, opts)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return &linkCgroup{*link}, nil
 | |
| }
 | |
| 
 | |
| type progAttachCgroup struct {
 | |
| 	cgroup     *os.File
 | |
| 	current    *ebpf.Program
 | |
| 	attachType ebpf.AttachType
 | |
| 	flags      cgroupAttachFlags
 | |
| }
 | |
| 
 | |
| var _ Link = (*progAttachCgroup)(nil)
 | |
| 
 | |
| func (cg *progAttachCgroup) isLink() {}
 | |
| 
 | |
| func newProgAttachCgroup(cgroup *os.File, attach ebpf.AttachType, prog *ebpf.Program, flags cgroupAttachFlags) (*progAttachCgroup, error) {
 | |
| 	if flags&flagAllowMulti > 0 {
 | |
| 		if err := haveProgAttachReplace(); err != nil {
 | |
| 			return nil, fmt.Errorf("can't support multiple programs: %w", err)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	err := RawAttachProgram(RawAttachProgramOptions{
 | |
| 		Target:  int(cgroup.Fd()),
 | |
| 		Program: prog,
 | |
| 		Flags:   uint32(flags),
 | |
| 		Attach:  attach,
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("cgroup: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	return &progAttachCgroup{cgroup, prog, attach, flags}, nil
 | |
| }
 | |
| 
 | |
| func (cg *progAttachCgroup) Close() error {
 | |
| 	defer cg.cgroup.Close()
 | |
| 	defer cg.current.Close()
 | |
| 
 | |
| 	err := RawDetachProgram(RawDetachProgramOptions{
 | |
| 		Target:  int(cg.cgroup.Fd()),
 | |
| 		Program: cg.current,
 | |
| 		Attach:  cg.attachType,
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("close cgroup: %s", err)
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (cg *progAttachCgroup) Update(prog *ebpf.Program) error {
 | |
| 	new, err := prog.Clone()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	args := RawAttachProgramOptions{
 | |
| 		Target:  int(cg.cgroup.Fd()),
 | |
| 		Program: prog,
 | |
| 		Attach:  cg.attachType,
 | |
| 		Flags:   uint32(cg.flags),
 | |
| 	}
 | |
| 
 | |
| 	if cg.flags&flagAllowMulti > 0 {
 | |
| 		// Atomically replacing multiple programs requires at least
 | |
| 		// 5.5 (commit 7dd68b3279f17921 "bpf: Support replacing cgroup-bpf
 | |
| 		// program in MULTI mode")
 | |
| 		args.Flags |= uint32(flagReplace)
 | |
| 		args.Replace = cg.current
 | |
| 	}
 | |
| 
 | |
| 	if err := RawAttachProgram(args); err != nil {
 | |
| 		new.Close()
 | |
| 		return fmt.Errorf("can't update cgroup: %s", err)
 | |
| 	}
 | |
| 
 | |
| 	cg.current.Close()
 | |
| 	cg.current = new
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (cg *progAttachCgroup) Pin(string) error {
 | |
| 	return fmt.Errorf("can't pin cgroup: %w", ErrNotSupported)
 | |
| }
 | |
| 
 | |
| func (cg *progAttachCgroup) Unpin() error {
 | |
| 	return fmt.Errorf("can't pin cgroup: %w", ErrNotSupported)
 | |
| }
 | |
| 
 | |
| type linkCgroup struct {
 | |
| 	RawLink
 | |
| }
 | |
| 
 | |
| var _ Link = (*linkCgroup)(nil)
 | |
| 
 | |
| func newLinkCgroup(cgroup *os.File, attach ebpf.AttachType, prog *ebpf.Program) (*linkCgroup, error) {
 | |
| 	link, err := AttachRawLink(RawLinkOptions{
 | |
| 		Target:  int(cgroup.Fd()),
 | |
| 		Program: prog,
 | |
| 		Attach:  attach,
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return &linkCgroup{*link}, err
 | |
| }
 |