Upgrade containerd/cgroups to remove github.com/cilium/ebpf's fuzzer
The fuzzer is broken and it breaks OSS-Fuzz according to #7288. Signed-off-by: Kazuyoshi Kato <katokazu@amazon.com>
This commit is contained in:
205
vendor/github.com/cilium/ebpf/link/uprobe.go
generated
vendored
205
vendor/github.com/cilium/ebpf/link/uprobe.go
generated
vendored
@@ -6,7 +6,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
@@ -16,16 +16,23 @@ import (
|
||||
var (
|
||||
uprobeEventsPath = filepath.Join(tracefsPath, "uprobe_events")
|
||||
|
||||
// rgxUprobeSymbol is used to strip invalid characters from the uprobe symbol
|
||||
// as they are not allowed to be used as the EVENT token in tracefs.
|
||||
rgxUprobeSymbol = regexp.MustCompile("[^a-zA-Z0-9]+")
|
||||
|
||||
uprobeRetprobeBit = struct {
|
||||
once sync.Once
|
||||
value uint64
|
||||
err error
|
||||
}{}
|
||||
|
||||
uprobeRefCtrOffsetPMUPath = "/sys/bus/event_source/devices/uprobe/format/ref_ctr_offset"
|
||||
// elixir.bootlin.com/linux/v5.15-rc7/source/kernel/events/core.c#L9799
|
||||
uprobeRefCtrOffsetShift = 32
|
||||
haveRefCtrOffsetPMU = internal.FeatureTest("RefCtrOffsetPMU", "4.20", func() error {
|
||||
_, err := os.Stat(uprobeRefCtrOffsetPMUPath)
|
||||
if err != nil {
|
||||
return internal.ErrNotSupported
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// ErrNoSymbol indicates that the given symbol was not found
|
||||
// in the ELF symbols table.
|
||||
ErrNoSymbol = errors.New("not found")
|
||||
@@ -35,24 +42,46 @@ var (
|
||||
type Executable struct {
|
||||
// Path of the executable on the filesystem.
|
||||
path string
|
||||
// Parsed ELF symbols and dynamic symbols offsets.
|
||||
offsets map[string]uint64
|
||||
// Parsed ELF and dynamic symbols' addresses.
|
||||
addresses map[string]uint64
|
||||
}
|
||||
|
||||
// UprobeOptions defines additional parameters that will be used
|
||||
// when loading Uprobes.
|
||||
type UprobeOptions struct {
|
||||
// Symbol offset. Must be provided in case of external symbols (shared libs).
|
||||
// If set, overrides the offset eventually parsed from the executable.
|
||||
// Symbol address. Must be provided in case of external symbols (shared libs).
|
||||
// If set, overrides the address eventually parsed from the executable.
|
||||
Address uint64
|
||||
// The offset relative to given symbol. Useful when tracing an arbitrary point
|
||||
// inside the frame of given symbol.
|
||||
//
|
||||
// Note: this field changed from being an absolute offset to being relative
|
||||
// to Address.
|
||||
Offset uint64
|
||||
// Only set the uprobe on the given process ID. Useful when tracing
|
||||
// shared library calls or programs that have many running instances.
|
||||
PID int
|
||||
// Automatically manage SDT reference counts (semaphores).
|
||||
//
|
||||
// If this field is set, the Kernel will increment/decrement the
|
||||
// semaphore located in the process memory at the provided address on
|
||||
// probe attach/detach.
|
||||
//
|
||||
// See also:
|
||||
// sourceware.org/systemtap/wiki/UserSpaceProbeImplementation (Semaphore Handling)
|
||||
// github.com/torvalds/linux/commit/1cc33161a83d
|
||||
// github.com/torvalds/linux/commit/a6ca88b241d5
|
||||
RefCtrOffset uint64
|
||||
// Arbitrary value that can be fetched from an eBPF program
|
||||
// via `bpf_get_attach_cookie()`.
|
||||
//
|
||||
// Needs kernel 5.15+.
|
||||
Cookie uint64
|
||||
}
|
||||
|
||||
// To open a new Executable, use:
|
||||
//
|
||||
// OpenExecutable("/bin/bash")
|
||||
// OpenExecutable("/bin/bash")
|
||||
//
|
||||
// The returned value can then be used to open Uprobe(s).
|
||||
func OpenExecutable(path string) (*Executable, error) {
|
||||
@@ -77,8 +106,8 @@ func OpenExecutable(path string) (*Executable, error) {
|
||||
}
|
||||
|
||||
ex := Executable{
|
||||
path: path,
|
||||
offsets: make(map[string]uint64),
|
||||
path: path,
|
||||
addresses: make(map[string]uint64),
|
||||
}
|
||||
|
||||
if err := ex.load(se); err != nil {
|
||||
@@ -107,7 +136,7 @@ func (ex *Executable) load(f *internal.SafeELFFile) error {
|
||||
continue
|
||||
}
|
||||
|
||||
off := s.Value
|
||||
address := s.Value
|
||||
|
||||
// Loop over ELF segments.
|
||||
for _, prog := range f.Progs {
|
||||
@@ -123,32 +152,42 @@ func (ex *Executable) load(f *internal.SafeELFFile) error {
|
||||
// fn symbol offset = fn symbol VA - .text VA + .text offset
|
||||
//
|
||||
// stackoverflow.com/a/40249502
|
||||
off = s.Value - prog.Vaddr + prog.Off
|
||||
address = s.Value - prog.Vaddr + prog.Off
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
ex.offsets[s.Name] = off
|
||||
ex.addresses[s.Name] = address
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ex *Executable) offset(symbol string) (uint64, error) {
|
||||
if off, ok := ex.offsets[symbol]; ok {
|
||||
// Symbols with location 0 from section undef are shared library calls and
|
||||
// are relocated before the binary is executed. Dynamic linking is not
|
||||
// implemented by the library, so mark this as unsupported for now.
|
||||
//
|
||||
// Since only offset values are stored and not elf.Symbol, if the value is 0,
|
||||
// assume it's an external symbol.
|
||||
if off == 0 {
|
||||
return 0, fmt.Errorf("cannot resolve %s library call '%s', "+
|
||||
"consider providing the offset via options: %w", ex.path, symbol, ErrNotSupported)
|
||||
}
|
||||
return off, nil
|
||||
// address calculates the address of a symbol in the executable.
|
||||
//
|
||||
// opts must not be nil.
|
||||
func (ex *Executable) address(symbol string, opts *UprobeOptions) (uint64, error) {
|
||||
if opts.Address > 0 {
|
||||
return opts.Address + opts.Offset, nil
|
||||
}
|
||||
return 0, fmt.Errorf("symbol %s: %w", symbol, ErrNoSymbol)
|
||||
|
||||
address, ok := ex.addresses[symbol]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("symbol %s: %w", symbol, ErrNoSymbol)
|
||||
}
|
||||
|
||||
// Symbols with location 0 from section undef are shared library calls and
|
||||
// are relocated before the binary is executed. Dynamic linking is not
|
||||
// implemented by the library, so mark this as unsupported for now.
|
||||
//
|
||||
// Since only offset values are stored and not elf.Symbol, if the value is 0,
|
||||
// assume it's an external symbol.
|
||||
if address == 0 {
|
||||
return 0, fmt.Errorf("cannot resolve %s library call '%s': %w "+
|
||||
"(consider providing UprobeOptions.Address)", ex.path, symbol, ErrNotSupported)
|
||||
}
|
||||
|
||||
return address + opts.Offset, nil
|
||||
}
|
||||
|
||||
// Uprobe attaches the given eBPF program to a perf event that fires when the
|
||||
@@ -161,7 +200,9 @@ func (ex *Executable) offset(symbol string) (uint64, error) {
|
||||
// When using symbols which belongs to shared libraries,
|
||||
// an offset must be provided via options:
|
||||
//
|
||||
// up, err := ex.Uprobe("main", prog, &UprobeOptions{Offset: 0x123})
|
||||
// up, err := ex.Uprobe("main", prog, &UprobeOptions{Offset: 0x123})
|
||||
//
|
||||
// Note: Setting the Offset field in the options supersedes the symbol's offset.
|
||||
//
|
||||
// Losing the reference to the resulting Link (up) will close the Uprobe
|
||||
// and prevent further execution of prog. The Link must be Closed during
|
||||
@@ -175,13 +216,13 @@ func (ex *Executable) Uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = u.attach(prog)
|
||||
lnk, err := attachPerfEvent(u, prog)
|
||||
if err != nil {
|
||||
u.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u, nil
|
||||
return lnk, nil
|
||||
}
|
||||
|
||||
// Uretprobe attaches the given eBPF program to a perf event that fires right
|
||||
@@ -193,7 +234,9 @@ func (ex *Executable) Uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
|
||||
// When using symbols which belongs to shared libraries,
|
||||
// an offset must be provided via options:
|
||||
//
|
||||
// up, err := ex.Uretprobe("main", prog, &UprobeOptions{Offset: 0x123})
|
||||
// up, err := ex.Uretprobe("main", prog, &UprobeOptions{Offset: 0x123})
|
||||
//
|
||||
// Note: Setting the Offset field in the options supersedes the symbol's offset.
|
||||
//
|
||||
// Losing the reference to the resulting Link (up) will close the Uprobe
|
||||
// and prevent further execution of prog. The Link must be Closed during
|
||||
@@ -207,13 +250,13 @@ func (ex *Executable) Uretprobe(symbol string, prog *ebpf.Program, opts *UprobeO
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = u.attach(prog)
|
||||
lnk, err := attachPerfEvent(u, prog)
|
||||
if err != nil {
|
||||
u.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return u, nil
|
||||
return lnk, nil
|
||||
}
|
||||
|
||||
// uprobe opens a perf event for the given binary/symbol and attaches prog to it.
|
||||
@@ -225,25 +268,38 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
|
||||
if prog.Type() != ebpf.Kprobe {
|
||||
return nil, fmt.Errorf("eBPF program type %s is not Kprobe: %w", prog.Type(), errInvalidInput)
|
||||
}
|
||||
|
||||
var offset uint64
|
||||
if opts != nil && opts.Offset != 0 {
|
||||
offset = opts.Offset
|
||||
} else {
|
||||
off, err := ex.offset(symbol)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
offset = off
|
||||
if opts == nil {
|
||||
opts = &UprobeOptions{}
|
||||
}
|
||||
|
||||
pid := perfAllThreads
|
||||
if opts != nil && opts.PID != 0 {
|
||||
pid = opts.PID
|
||||
offset, err := ex.address(symbol, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pid := opts.PID
|
||||
if pid == 0 {
|
||||
pid = perfAllThreads
|
||||
}
|
||||
|
||||
if opts.RefCtrOffset != 0 {
|
||||
if err := haveRefCtrOffsetPMU(); err != nil {
|
||||
return nil, fmt.Errorf("uprobe ref_ctr_offset: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
args := probeArgs{
|
||||
symbol: symbol,
|
||||
path: ex.path,
|
||||
offset: offset,
|
||||
pid: pid,
|
||||
refCtrOffset: opts.RefCtrOffset,
|
||||
ret: ret,
|
||||
cookie: opts.Cookie,
|
||||
}
|
||||
|
||||
// Use uprobe PMU if the kernel has it available.
|
||||
tp, err := pmuUprobe(symbol, ex.path, offset, pid, ret)
|
||||
tp, err := pmuUprobe(args)
|
||||
if err == nil {
|
||||
return tp, nil
|
||||
}
|
||||
@@ -252,7 +308,8 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
|
||||
}
|
||||
|
||||
// Use tracefs if uprobe PMU is missing.
|
||||
tp, err = tracefsUprobe(uprobeSanitizedSymbol(symbol), ex.path, offset, pid, ret)
|
||||
args.symbol = sanitizeSymbol(symbol)
|
||||
tp, err = tracefsUprobe(args)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating trace event '%s:%s' in tracefs: %w", ex.path, symbol, err)
|
||||
}
|
||||
@@ -261,23 +318,51 @@ func (ex *Executable) uprobe(symbol string, prog *ebpf.Program, opts *UprobeOpti
|
||||
}
|
||||
|
||||
// pmuUprobe opens a perf event based on the uprobe PMU.
|
||||
func pmuUprobe(symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
|
||||
return pmuProbe(uprobeType, symbol, path, offset, pid, ret)
|
||||
func pmuUprobe(args probeArgs) (*perfEvent, error) {
|
||||
return pmuProbe(uprobeType, args)
|
||||
}
|
||||
|
||||
// tracefsUprobe creates a Uprobe tracefs entry.
|
||||
func tracefsUprobe(symbol, path string, offset uint64, pid int, ret bool) (*perfEvent, error) {
|
||||
return tracefsProbe(uprobeType, symbol, path, offset, pid, ret)
|
||||
func tracefsUprobe(args probeArgs) (*perfEvent, error) {
|
||||
return tracefsProbe(uprobeType, args)
|
||||
}
|
||||
|
||||
// uprobeSanitizedSymbol replaces every invalid characted for the tracefs api with an underscore.
|
||||
func uprobeSanitizedSymbol(symbol string) string {
|
||||
return rgxUprobeSymbol.ReplaceAllString(symbol, "_")
|
||||
// sanitizeSymbol replaces every invalid character for the tracefs api with an underscore.
|
||||
// It is equivalent to calling regexp.MustCompile("[^a-zA-Z0-9]+").ReplaceAllString("_").
|
||||
func sanitizeSymbol(s string) string {
|
||||
var b strings.Builder
|
||||
b.Grow(len(s))
|
||||
var skip bool
|
||||
for _, c := range []byte(s) {
|
||||
switch {
|
||||
case c >= 'a' && c <= 'z',
|
||||
c >= 'A' && c <= 'Z',
|
||||
c >= '0' && c <= '9':
|
||||
skip = false
|
||||
b.WriteByte(c)
|
||||
|
||||
default:
|
||||
if !skip {
|
||||
b.WriteByte('_')
|
||||
skip = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// uprobePathOffset creates the PATH:OFFSET token for the tracefs api.
|
||||
func uprobePathOffset(path string, offset uint64) string {
|
||||
return fmt.Sprintf("%s:%#x", path, offset)
|
||||
// uprobeToken creates the PATH:OFFSET(REF_CTR_OFFSET) token for the tracefs api.
|
||||
func uprobeToken(args probeArgs) string {
|
||||
po := fmt.Sprintf("%s:%#x", args.path, args.offset)
|
||||
|
||||
if args.refCtrOffset != 0 {
|
||||
// This is not documented in Documentation/trace/uprobetracer.txt.
|
||||
// elixir.bootlin.com/linux/v5.15-rc7/source/kernel/trace/trace.c#L5564
|
||||
po += fmt.Sprintf("(%#x)", args.refCtrOffset)
|
||||
}
|
||||
|
||||
return po
|
||||
}
|
||||
|
||||
func uretprobeBit() (uint64, error) {
|
||||
|
||||
Reference in New Issue
Block a user