prog.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. package ebpf
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "math"
  8. "path/filepath"
  9. "runtime"
  10. "strings"
  11. "time"
  12. "unsafe"
  13. "github.com/cilium/ebpf/asm"
  14. "github.com/cilium/ebpf/btf"
  15. "github.com/cilium/ebpf/internal"
  16. "github.com/cilium/ebpf/internal/sys"
  17. "github.com/cilium/ebpf/internal/unix"
  18. )
  19. // ErrNotSupported is returned whenever the kernel doesn't support a feature.
  20. var ErrNotSupported = internal.ErrNotSupported
  21. // ProgramID represents the unique ID of an eBPF program.
  22. type ProgramID uint32
  23. const (
  24. // Number of bytes to pad the output buffer for BPF_PROG_TEST_RUN.
  25. // This is currently the maximum of spare space allocated for SKB
  26. // and XDP programs, and equal to XDP_PACKET_HEADROOM + NET_IP_ALIGN.
  27. outputPad = 256 + 2
  28. )
  29. // DefaultVerifierLogSize is the default number of bytes allocated for the
  30. // verifier log.
  31. const DefaultVerifierLogSize = 64 * 1024
  32. // maxVerifierLogSize is the maximum size of verifier log buffer the kernel
  33. // will accept before returning EINVAL.
  34. const maxVerifierLogSize = math.MaxUint32 >> 2
  35. // ProgramOptions control loading a program into the kernel.
  36. type ProgramOptions struct {
  37. // Bitmap controlling the detail emitted by the kernel's eBPF verifier log.
  38. // LogLevel-type values can be ORed together to request specific kinds of
  39. // verifier output. See the documentation on [ebpf.LogLevel] for details.
  40. //
  41. // opts.LogLevel = (ebpf.LogLevelBranch | ebpf.LogLevelStats)
  42. //
  43. // If left to its default value, the program will first be loaded without
  44. // verifier output enabled. Upon error, the program load will be repeated
  45. // with LogLevelBranch and the given (or default) LogSize value.
  46. //
  47. // Setting this to a non-zero value will unconditionally enable the verifier
  48. // log, populating the [ebpf.Program.VerifierLog] field on successful loads
  49. // and including detailed verifier errors if the program is rejected. This
  50. // will always allocate an output buffer, but will result in only a single
  51. // attempt at loading the program.
  52. LogLevel LogLevel
  53. // Controls the output buffer size for the verifier log, in bytes. See the
  54. // documentation on ProgramOptions.LogLevel for details about how this value
  55. // is used.
  56. //
  57. // If this value is set too low to fit the verifier log, the resulting
  58. // [ebpf.VerifierError]'s Truncated flag will be true, and the error string
  59. // will also contain a hint to that effect.
  60. //
  61. // Defaults to DefaultVerifierLogSize.
  62. LogSize int
  63. // Disables the verifier log completely, regardless of other options.
  64. LogDisabled bool
  65. // Type information used for CO-RE relocations.
  66. //
  67. // This is useful in environments where the kernel BTF is not available
  68. // (containers) or where it is in a non-standard location. Defaults to
  69. // use the kernel BTF from a well-known location if nil.
  70. KernelTypes *btf.Spec
  71. }
  72. // ProgramSpec defines a Program.
  73. type ProgramSpec struct {
  74. // Name is passed to the kernel as a debug aid. Must only contain
  75. // alpha numeric and '_' characters.
  76. Name string
  77. // Type determines at which hook in the kernel a program will run.
  78. Type ProgramType
  79. // AttachType of the program, needed to differentiate allowed context
  80. // accesses in some newer program types like CGroupSockAddr.
  81. //
  82. // Available on kernels 4.17 and later.
  83. AttachType AttachType
  84. // Name of a kernel data structure or function to attach to. Its
  85. // interpretation depends on Type and AttachType.
  86. AttachTo string
  87. // The program to attach to. Must be provided manually.
  88. AttachTarget *Program
  89. // The name of the ELF section this program originated from.
  90. SectionName string
  91. Instructions asm.Instructions
  92. // Flags is passed to the kernel and specifies additional program
  93. // load attributes.
  94. Flags uint32
  95. // License of the program. Some helpers are only available if
  96. // the license is deemed compatible with the GPL.
  97. //
  98. // See https://www.kernel.org/doc/html/latest/process/license-rules.html#id1
  99. License string
  100. // Version used by Kprobe programs.
  101. //
  102. // Deprecated on kernels 5.0 and later. Leave empty to let the library
  103. // detect this value automatically.
  104. KernelVersion uint32
  105. // The byte order this program was compiled for, may be nil.
  106. ByteOrder binary.ByteOrder
  107. }
  108. // Copy returns a copy of the spec.
  109. func (ps *ProgramSpec) Copy() *ProgramSpec {
  110. if ps == nil {
  111. return nil
  112. }
  113. cpy := *ps
  114. cpy.Instructions = make(asm.Instructions, len(ps.Instructions))
  115. copy(cpy.Instructions, ps.Instructions)
  116. return &cpy
  117. }
  118. // Tag calculates the kernel tag for a series of instructions.
  119. //
  120. // Use asm.Instructions.Tag if you need to calculate for non-native endianness.
  121. func (ps *ProgramSpec) Tag() (string, error) {
  122. return ps.Instructions.Tag(internal.NativeEndian)
  123. }
  124. // VerifierError is returned by [NewProgram] and [NewProgramWithOptions] if a
  125. // program is rejected by the verifier.
  126. //
  127. // Use [errors.As] to access the error.
  128. type VerifierError = internal.VerifierError
  129. // Program represents BPF program loaded into the kernel.
  130. //
  131. // It is not safe to close a Program which is used by other goroutines.
  132. type Program struct {
  133. // Contains the output of the kernel verifier if enabled,
  134. // otherwise it is empty.
  135. VerifierLog string
  136. fd *sys.FD
  137. name string
  138. pinnedPath string
  139. typ ProgramType
  140. }
  141. // NewProgram creates a new Program.
  142. //
  143. // See [NewProgramWithOptions] for details.
  144. //
  145. // Returns a [VerifierError] containing the full verifier log if the program is
  146. // rejected by the kernel.
  147. func NewProgram(spec *ProgramSpec) (*Program, error) {
  148. return NewProgramWithOptions(spec, ProgramOptions{})
  149. }
  150. // NewProgramWithOptions creates a new Program.
  151. //
  152. // Loading a program for the first time will perform
  153. // feature detection by loading small, temporary programs.
  154. //
  155. // Returns a [VerifierError] containing the full verifier log if the program is
  156. // rejected by the kernel.
  157. func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, error) {
  158. if spec == nil {
  159. return nil, errors.New("can't load a program from a nil spec")
  160. }
  161. prog, err := newProgramWithOptions(spec, opts)
  162. if errors.Is(err, asm.ErrUnsatisfiedMapReference) {
  163. return nil, fmt.Errorf("cannot load program without loading its whole collection: %w", err)
  164. }
  165. return prog, err
  166. }
  167. func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, error) {
  168. if len(spec.Instructions) == 0 {
  169. return nil, errors.New("instructions cannot be empty")
  170. }
  171. if spec.Type == UnspecifiedProgram {
  172. return nil, errors.New("can't load program of unspecified type")
  173. }
  174. if spec.ByteOrder != nil && spec.ByteOrder != internal.NativeEndian {
  175. return nil, fmt.Errorf("can't load %s program on %s", spec.ByteOrder, internal.NativeEndian)
  176. }
  177. if opts.LogSize < 0 {
  178. return nil, errors.New("ProgramOptions.LogSize must be a positive value; disable verifier logs using ProgramOptions.LogDisabled")
  179. }
  180. // Kernels before 5.0 (6c4fc209fcf9 "bpf: remove useless version check for prog load")
  181. // require the version field to be set to the value of the KERNEL_VERSION
  182. // macro for kprobe-type programs.
  183. // Overwrite Kprobe program version if set to zero or the magic version constant.
  184. kv := spec.KernelVersion
  185. if spec.Type == Kprobe && (kv == 0 || kv == internal.MagicKernelVersion) {
  186. v, err := internal.KernelVersion()
  187. if err != nil {
  188. return nil, fmt.Errorf("detecting kernel version: %w", err)
  189. }
  190. kv = v.Kernel()
  191. }
  192. attr := &sys.ProgLoadAttr{
  193. ProgType: sys.ProgType(spec.Type),
  194. ProgFlags: spec.Flags,
  195. ExpectedAttachType: sys.AttachType(spec.AttachType),
  196. License: sys.NewStringPointer(spec.License),
  197. KernVersion: kv,
  198. }
  199. if haveObjName() == nil {
  200. attr.ProgName = sys.NewObjName(spec.Name)
  201. }
  202. insns := make(asm.Instructions, len(spec.Instructions))
  203. copy(insns, spec.Instructions)
  204. handle, fib, lib, err := btf.MarshalExtInfos(insns)
  205. if err != nil && !errors.Is(err, btf.ErrNotSupported) {
  206. return nil, fmt.Errorf("load ext_infos: %w", err)
  207. }
  208. if handle != nil {
  209. defer handle.Close()
  210. attr.ProgBtfFd = uint32(handle.FD())
  211. attr.FuncInfoRecSize = btf.FuncInfoSize
  212. attr.FuncInfoCnt = uint32(len(fib)) / btf.FuncInfoSize
  213. attr.FuncInfo = sys.NewSlicePointer(fib)
  214. attr.LineInfoRecSize = btf.LineInfoSize
  215. attr.LineInfoCnt = uint32(len(lib)) / btf.LineInfoSize
  216. attr.LineInfo = sys.NewSlicePointer(lib)
  217. }
  218. if err := applyRelocations(insns, opts.KernelTypes, spec.ByteOrder); err != nil {
  219. return nil, fmt.Errorf("apply CO-RE relocations: %w", err)
  220. }
  221. kconfig, err := resolveKconfigReferences(insns)
  222. if err != nil {
  223. return nil, fmt.Errorf("resolve .kconfig: %w", err)
  224. }
  225. defer kconfig.Close()
  226. if err := fixupAndValidate(insns); err != nil {
  227. return nil, err
  228. }
  229. handles, err := fixupKfuncs(insns)
  230. if err != nil {
  231. return nil, fmt.Errorf("fixing up kfuncs: %w", err)
  232. }
  233. defer handles.close()
  234. if len(handles) > 0 {
  235. fdArray := handles.fdArray()
  236. attr.FdArray = sys.NewPointer(unsafe.Pointer(&fdArray[0]))
  237. }
  238. buf := bytes.NewBuffer(make([]byte, 0, insns.Size()))
  239. err = insns.Marshal(buf, internal.NativeEndian)
  240. if err != nil {
  241. return nil, err
  242. }
  243. bytecode := buf.Bytes()
  244. attr.Insns = sys.NewSlicePointer(bytecode)
  245. attr.InsnCnt = uint32(len(bytecode) / asm.InstructionSize)
  246. if spec.AttachTarget != nil {
  247. targetID, err := findTargetInProgram(spec.AttachTarget, spec.AttachTo, spec.Type, spec.AttachType)
  248. if err != nil {
  249. return nil, fmt.Errorf("attach %s/%s: %w", spec.Type, spec.AttachType, err)
  250. }
  251. attr.AttachBtfId = targetID
  252. attr.AttachBtfObjFd = uint32(spec.AttachTarget.FD())
  253. defer runtime.KeepAlive(spec.AttachTarget)
  254. } else if spec.AttachTo != "" {
  255. module, targetID, err := findProgramTargetInKernel(spec.AttachTo, spec.Type, spec.AttachType)
  256. if err != nil && !errors.Is(err, errUnrecognizedAttachType) {
  257. // We ignore errUnrecognizedAttachType since AttachTo may be non-empty
  258. // for programs that don't attach anywhere.
  259. return nil, fmt.Errorf("attach %s/%s: %w", spec.Type, spec.AttachType, err)
  260. }
  261. attr.AttachBtfId = targetID
  262. if module != nil {
  263. attr.AttachBtfObjFd = uint32(module.FD())
  264. defer module.Close()
  265. }
  266. }
  267. if opts.LogSize == 0 {
  268. opts.LogSize = DefaultVerifierLogSize
  269. }
  270. // The caller requested a specific verifier log level. Set up the log buffer.
  271. var logBuf []byte
  272. if !opts.LogDisabled && opts.LogLevel != 0 {
  273. logBuf = make([]byte, opts.LogSize)
  274. attr.LogLevel = opts.LogLevel
  275. attr.LogSize = uint32(len(logBuf))
  276. attr.LogBuf = sys.NewSlicePointer(logBuf)
  277. }
  278. fd, err := sys.ProgLoad(attr)
  279. if err == nil {
  280. return &Program{unix.ByteSliceToString(logBuf), fd, spec.Name, "", spec.Type}, nil
  281. }
  282. // An error occurred loading the program, but the caller did not explicitly
  283. // enable the verifier log. Re-run with branch-level verifier logs enabled to
  284. // obtain more info. Preserve the original error to return it to the caller.
  285. // An undersized log buffer will result in ENOSPC regardless of the underlying
  286. // cause.
  287. var err2 error
  288. if !opts.LogDisabled && opts.LogLevel == 0 {
  289. logBuf = make([]byte, opts.LogSize)
  290. attr.LogLevel = LogLevelBranch
  291. attr.LogSize = uint32(len(logBuf))
  292. attr.LogBuf = sys.NewSlicePointer(logBuf)
  293. _, err2 = sys.ProgLoad(attr)
  294. }
  295. switch {
  296. case errors.Is(err, unix.EPERM):
  297. if len(logBuf) > 0 && logBuf[0] == 0 {
  298. // EPERM due to RLIMIT_MEMLOCK happens before the verifier, so we can
  299. // check that the log is empty to reduce false positives.
  300. return nil, fmt.Errorf("load program: %w (MEMLOCK may be too low, consider rlimit.RemoveMemlock)", err)
  301. }
  302. fallthrough
  303. case errors.Is(err, unix.EINVAL):
  304. if hasFunctionReferences(spec.Instructions) {
  305. if err := haveBPFToBPFCalls(); err != nil {
  306. return nil, fmt.Errorf("load program: %w", err)
  307. }
  308. }
  309. if opts.LogSize > maxVerifierLogSize {
  310. return nil, fmt.Errorf("load program: %w (ProgramOptions.LogSize exceeds maximum value of %d)", err, maxVerifierLogSize)
  311. }
  312. }
  313. truncated := errors.Is(err, unix.ENOSPC) || errors.Is(err2, unix.ENOSPC)
  314. return nil, internal.ErrorWithLog("load program", err, logBuf, truncated)
  315. }
  316. // NewProgramFromFD creates a program from a raw fd.
  317. //
  318. // You should not use fd after calling this function.
  319. //
  320. // Requires at least Linux 4.10.
  321. func NewProgramFromFD(fd int) (*Program, error) {
  322. f, err := sys.NewFD(fd)
  323. if err != nil {
  324. return nil, err
  325. }
  326. return newProgramFromFD(f)
  327. }
  328. // NewProgramFromID returns the program for a given id.
  329. //
  330. // Returns ErrNotExist, if there is no eBPF program with the given id.
  331. func NewProgramFromID(id ProgramID) (*Program, error) {
  332. fd, err := sys.ProgGetFdById(&sys.ProgGetFdByIdAttr{
  333. Id: uint32(id),
  334. })
  335. if err != nil {
  336. return nil, fmt.Errorf("get program by id: %w", err)
  337. }
  338. return newProgramFromFD(fd)
  339. }
  340. func newProgramFromFD(fd *sys.FD) (*Program, error) {
  341. info, err := newProgramInfoFromFd(fd)
  342. if err != nil {
  343. fd.Close()
  344. return nil, fmt.Errorf("discover program type: %w", err)
  345. }
  346. return &Program{"", fd, info.Name, "", info.Type}, nil
  347. }
  348. func (p *Program) String() string {
  349. if p.name != "" {
  350. return fmt.Sprintf("%s(%s)#%v", p.typ, p.name, p.fd)
  351. }
  352. return fmt.Sprintf("%s(%v)", p.typ, p.fd)
  353. }
  354. // Type returns the underlying type of the program.
  355. func (p *Program) Type() ProgramType {
  356. return p.typ
  357. }
  358. // Info returns metadata about the program.
  359. //
  360. // Requires at least 4.10.
  361. func (p *Program) Info() (*ProgramInfo, error) {
  362. return newProgramInfoFromFd(p.fd)
  363. }
  364. // Handle returns a reference to the program's type information in the kernel.
  365. //
  366. // Returns ErrNotSupported if the kernel has no BTF support, or if there is no
  367. // BTF associated with the program.
  368. func (p *Program) Handle() (*btf.Handle, error) {
  369. info, err := p.Info()
  370. if err != nil {
  371. return nil, err
  372. }
  373. id, ok := info.BTFID()
  374. if !ok {
  375. return nil, fmt.Errorf("program %s: retrieve BTF ID: %w", p, ErrNotSupported)
  376. }
  377. return btf.NewHandleFromID(id)
  378. }
  379. // FD gets the file descriptor of the Program.
  380. //
  381. // It is invalid to call this function after Close has been called.
  382. func (p *Program) FD() int {
  383. return p.fd.Int()
  384. }
  385. // Clone creates a duplicate of the Program.
  386. //
  387. // Closing the duplicate does not affect the original, and vice versa.
  388. //
  389. // Cloning a nil Program returns nil.
  390. func (p *Program) Clone() (*Program, error) {
  391. if p == nil {
  392. return nil, nil
  393. }
  394. dup, err := p.fd.Dup()
  395. if err != nil {
  396. return nil, fmt.Errorf("can't clone program: %w", err)
  397. }
  398. return &Program{p.VerifierLog, dup, p.name, "", p.typ}, nil
  399. }
  400. // Pin persists the Program on the BPF virtual file system past the lifetime of
  401. // the process that created it
  402. //
  403. // Calling Pin on a previously pinned program will overwrite the path, except when
  404. // the new path already exists. Re-pinning across filesystems is not supported.
  405. //
  406. // This requires bpffs to be mounted above fileName.
  407. // See https://docs.cilium.io/en/stable/network/kubernetes/configuration/#mounting-bpffs-with-systemd
  408. func (p *Program) Pin(fileName string) error {
  409. if err := internal.Pin(p.pinnedPath, fileName, p.fd); err != nil {
  410. return err
  411. }
  412. p.pinnedPath = fileName
  413. return nil
  414. }
  415. // Unpin removes the persisted state for the Program from the BPF virtual filesystem.
  416. //
  417. // Failed calls to Unpin will not alter the state returned by IsPinned.
  418. //
  419. // Unpinning an unpinned Program returns nil.
  420. func (p *Program) Unpin() error {
  421. if err := internal.Unpin(p.pinnedPath); err != nil {
  422. return err
  423. }
  424. p.pinnedPath = ""
  425. return nil
  426. }
  427. // IsPinned returns true if the Program has a non-empty pinned path.
  428. func (p *Program) IsPinned() bool {
  429. return p.pinnedPath != ""
  430. }
  431. // Close the Program's underlying file descriptor, which could unload
  432. // the program from the kernel if it is not pinned or attached to a
  433. // kernel hook.
  434. func (p *Program) Close() error {
  435. if p == nil {
  436. return nil
  437. }
  438. return p.fd.Close()
  439. }
  440. // Various options for Run'ing a Program
  441. type RunOptions struct {
  442. // Program's data input. Required field.
  443. //
  444. // The kernel expects at least 14 bytes input for an ethernet header for
  445. // XDP and SKB programs.
  446. Data []byte
  447. // Program's data after Program has run. Caller must allocate. Optional field.
  448. DataOut []byte
  449. // Program's context input. Optional field.
  450. Context interface{}
  451. // Program's context after Program has run. Must be a pointer or slice. Optional field.
  452. ContextOut interface{}
  453. // Minimum number of times to run Program. Optional field. Defaults to 1.
  454. //
  455. // The program may be executed more often than this due to interruptions, e.g.
  456. // when runtime.AllThreadsSyscall is invoked.
  457. Repeat uint32
  458. // Optional flags.
  459. Flags uint32
  460. // CPU to run Program on. Optional field.
  461. // Note not all program types support this field.
  462. CPU uint32
  463. // Called whenever the syscall is interrupted, and should be set to testing.B.ResetTimer
  464. // or similar. Typically used during benchmarking. Optional field.
  465. //
  466. // Deprecated: use [testing.B.ReportMetric] with unit "ns/op" instead.
  467. Reset func()
  468. }
  469. // Test runs the Program in the kernel with the given input and returns the
  470. // value returned by the eBPF program. outLen may be zero.
  471. //
  472. // Note: the kernel expects at least 14 bytes input for an ethernet header for
  473. // XDP and SKB programs.
  474. //
  475. // This function requires at least Linux 4.12.
  476. func (p *Program) Test(in []byte) (uint32, []byte, error) {
  477. // Older kernels ignore the dataSizeOut argument when copying to user space.
  478. // Combined with things like bpf_xdp_adjust_head() we don't really know what the final
  479. // size will be. Hence we allocate an output buffer which we hope will always be large
  480. // enough, and panic if the kernel wrote past the end of the allocation.
  481. // See https://patchwork.ozlabs.org/cover/1006822/
  482. var out []byte
  483. if len(in) > 0 {
  484. out = make([]byte, len(in)+outputPad)
  485. }
  486. opts := RunOptions{
  487. Data: in,
  488. DataOut: out,
  489. Repeat: 1,
  490. }
  491. ret, _, err := p.run(&opts)
  492. if err != nil {
  493. return ret, nil, fmt.Errorf("test program: %w", err)
  494. }
  495. return ret, opts.DataOut, nil
  496. }
  497. // Run runs the Program in kernel with given RunOptions.
  498. //
  499. // Note: the same restrictions from Test apply.
  500. func (p *Program) Run(opts *RunOptions) (uint32, error) {
  501. ret, _, err := p.run(opts)
  502. if err != nil {
  503. return ret, fmt.Errorf("run program: %w", err)
  504. }
  505. return ret, nil
  506. }
  507. // Benchmark runs the Program with the given input for a number of times
  508. // and returns the time taken per iteration.
  509. //
  510. // Returns the result of the last execution of the program and the time per
  511. // run or an error. reset is called whenever the benchmark syscall is
  512. // interrupted, and should be set to testing.B.ResetTimer or similar.
  513. //
  514. // This function requires at least Linux 4.12.
  515. func (p *Program) Benchmark(in []byte, repeat int, reset func()) (uint32, time.Duration, error) {
  516. if uint(repeat) > math.MaxUint32 {
  517. return 0, 0, fmt.Errorf("repeat is too high")
  518. }
  519. opts := RunOptions{
  520. Data: in,
  521. Repeat: uint32(repeat),
  522. Reset: reset,
  523. }
  524. ret, total, err := p.run(&opts)
  525. if err != nil {
  526. return ret, total, fmt.Errorf("benchmark program: %w", err)
  527. }
  528. return ret, total, nil
  529. }
  530. var haveProgRun = internal.NewFeatureTest("BPF_PROG_RUN", "4.12", func() error {
  531. prog, err := NewProgram(&ProgramSpec{
  532. // SocketFilter does not require privileges on newer kernels.
  533. Type: SocketFilter,
  534. Instructions: asm.Instructions{
  535. asm.LoadImm(asm.R0, 0, asm.DWord),
  536. asm.Return(),
  537. },
  538. License: "MIT",
  539. })
  540. if err != nil {
  541. // This may be because we lack sufficient permissions, etc.
  542. return err
  543. }
  544. defer prog.Close()
  545. in := internal.EmptyBPFContext
  546. attr := sys.ProgRunAttr{
  547. ProgFd: uint32(prog.FD()),
  548. DataSizeIn: uint32(len(in)),
  549. DataIn: sys.NewSlicePointer(in),
  550. }
  551. err = sys.ProgRun(&attr)
  552. switch {
  553. case errors.Is(err, unix.EINVAL):
  554. // Check for EINVAL specifically, rather than err != nil since we
  555. // otherwise misdetect due to insufficient permissions.
  556. return internal.ErrNotSupported
  557. case errors.Is(err, unix.EINTR):
  558. // We know that PROG_TEST_RUN is supported if we get EINTR.
  559. return nil
  560. case errors.Is(err, sys.ENOTSUPP):
  561. // The first PROG_TEST_RUN patches shipped in 4.12 didn't include
  562. // a test runner for SocketFilter. ENOTSUPP means PROG_TEST_RUN is
  563. // supported, but not for the program type used in the probe.
  564. return nil
  565. }
  566. return err
  567. })
  568. func (p *Program) run(opts *RunOptions) (uint32, time.Duration, error) {
  569. if uint(len(opts.Data)) > math.MaxUint32 {
  570. return 0, 0, fmt.Errorf("input is too long")
  571. }
  572. if err := haveProgRun(); err != nil {
  573. return 0, 0, err
  574. }
  575. var ctxBytes []byte
  576. if opts.Context != nil {
  577. ctx := new(bytes.Buffer)
  578. if err := binary.Write(ctx, internal.NativeEndian, opts.Context); err != nil {
  579. return 0, 0, fmt.Errorf("cannot serialize context: %v", err)
  580. }
  581. ctxBytes = ctx.Bytes()
  582. }
  583. var ctxOut []byte
  584. if opts.ContextOut != nil {
  585. ctxOut = make([]byte, binary.Size(opts.ContextOut))
  586. }
  587. attr := sys.ProgRunAttr{
  588. ProgFd: p.fd.Uint(),
  589. DataSizeIn: uint32(len(opts.Data)),
  590. DataSizeOut: uint32(len(opts.DataOut)),
  591. DataIn: sys.NewSlicePointer(opts.Data),
  592. DataOut: sys.NewSlicePointer(opts.DataOut),
  593. Repeat: uint32(opts.Repeat),
  594. CtxSizeIn: uint32(len(ctxBytes)),
  595. CtxSizeOut: uint32(len(ctxOut)),
  596. CtxIn: sys.NewSlicePointer(ctxBytes),
  597. CtxOut: sys.NewSlicePointer(ctxOut),
  598. Flags: opts.Flags,
  599. Cpu: opts.CPU,
  600. }
  601. if attr.Repeat == 0 {
  602. attr.Repeat = 1
  603. }
  604. retry:
  605. for {
  606. err := sys.ProgRun(&attr)
  607. if err == nil {
  608. break retry
  609. }
  610. if errors.Is(err, unix.EINTR) {
  611. if attr.Repeat == 1 {
  612. // Older kernels check whether enough repetitions have been
  613. // executed only after checking for pending signals.
  614. //
  615. // run signal? done? run ...
  616. //
  617. // As a result we can get EINTR for repeat==1 even though
  618. // the program was run exactly once. Treat this as a
  619. // successful run instead.
  620. //
  621. // Since commit 607b9cc92bd7 ("bpf: Consolidate shared test timing code")
  622. // the conditions are reversed:
  623. // run done? signal? ...
  624. break retry
  625. }
  626. if opts.Reset != nil {
  627. opts.Reset()
  628. }
  629. continue retry
  630. }
  631. if errors.Is(err, sys.ENOTSUPP) {
  632. return 0, 0, fmt.Errorf("kernel doesn't support running %s: %w", p.Type(), ErrNotSupported)
  633. }
  634. return 0, 0, err
  635. }
  636. if opts.DataOut != nil {
  637. if int(attr.DataSizeOut) > cap(opts.DataOut) {
  638. // Houston, we have a problem. The program created more data than we allocated,
  639. // and the kernel wrote past the end of our buffer.
  640. panic("kernel wrote past end of output buffer")
  641. }
  642. opts.DataOut = opts.DataOut[:int(attr.DataSizeOut)]
  643. }
  644. if len(ctxOut) != 0 {
  645. b := bytes.NewReader(ctxOut)
  646. if err := binary.Read(b, internal.NativeEndian, opts.ContextOut); err != nil {
  647. return 0, 0, fmt.Errorf("failed to decode ContextOut: %v", err)
  648. }
  649. }
  650. total := time.Duration(attr.Duration) * time.Nanosecond
  651. return attr.Retval, total, nil
  652. }
  653. func unmarshalProgram(buf []byte) (*Program, error) {
  654. if len(buf) != 4 {
  655. return nil, errors.New("program id requires 4 byte value")
  656. }
  657. // Looking up an entry in a nested map or prog array returns an id,
  658. // not an fd.
  659. id := internal.NativeEndian.Uint32(buf)
  660. return NewProgramFromID(ProgramID(id))
  661. }
  662. func marshalProgram(p *Program, length int) ([]byte, error) {
  663. if length != 4 {
  664. return nil, fmt.Errorf("can't marshal program to %d bytes", length)
  665. }
  666. buf := make([]byte, 4)
  667. internal.NativeEndian.PutUint32(buf, p.fd.Uint())
  668. return buf, nil
  669. }
  670. // LoadPinnedProgram loads a Program from a BPF file.
  671. //
  672. // Requires at least Linux 4.11.
  673. func LoadPinnedProgram(fileName string, opts *LoadPinOptions) (*Program, error) {
  674. fd, err := sys.ObjGet(&sys.ObjGetAttr{
  675. Pathname: sys.NewStringPointer(fileName),
  676. FileFlags: opts.Marshal(),
  677. })
  678. if err != nil {
  679. return nil, err
  680. }
  681. info, err := newProgramInfoFromFd(fd)
  682. if err != nil {
  683. _ = fd.Close()
  684. return nil, fmt.Errorf("info for %s: %w", fileName, err)
  685. }
  686. var progName string
  687. if haveObjName() == nil {
  688. progName = info.Name
  689. } else {
  690. progName = filepath.Base(fileName)
  691. }
  692. return &Program{"", fd, progName, fileName, info.Type}, nil
  693. }
  694. // SanitizeName replaces all invalid characters in name with replacement.
  695. // Passing a negative value for replacement will delete characters instead
  696. // of replacing them. Use this to automatically generate valid names for maps
  697. // and programs at runtime.
  698. //
  699. // The set of allowed characters depends on the running kernel version.
  700. // Dots are only allowed as of kernel 5.2.
  701. func SanitizeName(name string, replacement rune) string {
  702. return strings.Map(func(char rune) rune {
  703. if invalidBPFObjNameChar(char) {
  704. return replacement
  705. }
  706. return char
  707. }, name)
  708. }
  709. // ProgramGetNextID returns the ID of the next eBPF program.
  710. //
  711. // Returns ErrNotExist, if there is no next eBPF program.
  712. func ProgramGetNextID(startID ProgramID) (ProgramID, error) {
  713. attr := &sys.ProgGetNextIdAttr{Id: uint32(startID)}
  714. return ProgramID(attr.NextId), sys.ProgGetNextId(attr)
  715. }
  716. // BindMap binds map to the program and is only released once program is released.
  717. //
  718. // This may be used in cases where metadata should be associated with the program
  719. // which otherwise does not contain any references to the map.
  720. func (p *Program) BindMap(m *Map) error {
  721. attr := &sys.ProgBindMapAttr{
  722. ProgFd: uint32(p.FD()),
  723. MapFd: uint32(m.FD()),
  724. }
  725. return sys.ProgBindMap(attr)
  726. }
  727. var errUnrecognizedAttachType = errors.New("unrecognized attach type")
  728. // find an attach target type in the kernel.
  729. //
  730. // name, progType and attachType determine which type we need to attach to.
  731. //
  732. // The attach target may be in a loaded kernel module.
  733. // In that case the returned handle will be non-nil.
  734. // The caller is responsible for closing the handle.
  735. //
  736. // Returns errUnrecognizedAttachType if the combination of progType and attachType
  737. // is not recognised.
  738. func findProgramTargetInKernel(name string, progType ProgramType, attachType AttachType) (*btf.Handle, btf.TypeID, error) {
  739. type match struct {
  740. p ProgramType
  741. a AttachType
  742. }
  743. var (
  744. typeName, featureName string
  745. target btf.Type
  746. )
  747. switch (match{progType, attachType}) {
  748. case match{LSM, AttachLSMMac}:
  749. typeName = "bpf_lsm_" + name
  750. featureName = name + " LSM hook"
  751. target = (*btf.Func)(nil)
  752. case match{Tracing, AttachTraceIter}:
  753. typeName = "bpf_iter_" + name
  754. featureName = name + " iterator"
  755. target = (*btf.Func)(nil)
  756. case match{Tracing, AttachTraceFEntry}:
  757. typeName = name
  758. featureName = fmt.Sprintf("fentry %s", name)
  759. target = (*btf.Func)(nil)
  760. case match{Tracing, AttachTraceFExit}:
  761. typeName = name
  762. featureName = fmt.Sprintf("fexit %s", name)
  763. target = (*btf.Func)(nil)
  764. case match{Tracing, AttachModifyReturn}:
  765. typeName = name
  766. featureName = fmt.Sprintf("fmod_ret %s", name)
  767. target = (*btf.Func)(nil)
  768. case match{Tracing, AttachTraceRawTp}:
  769. typeName = fmt.Sprintf("btf_trace_%s", name)
  770. featureName = fmt.Sprintf("raw_tp %s", name)
  771. target = (*btf.Typedef)(nil)
  772. default:
  773. return nil, 0, errUnrecognizedAttachType
  774. }
  775. spec, err := btf.LoadKernelSpec()
  776. if err != nil {
  777. return nil, 0, fmt.Errorf("load kernel spec: %w", err)
  778. }
  779. spec, module, err := findTargetInKernel(spec, typeName, &target)
  780. if errors.Is(err, btf.ErrNotFound) {
  781. return nil, 0, &internal.UnsupportedFeatureError{Name: featureName}
  782. }
  783. // See cilium/ebpf#894. Until we can disambiguate between equally-named kernel
  784. // symbols, we should explicitly refuse program loads. They will not reliably
  785. // do what the caller intended.
  786. if errors.Is(err, btf.ErrMultipleMatches) {
  787. return nil, 0, fmt.Errorf("attaching to ambiguous kernel symbol is not supported: %w", err)
  788. }
  789. if err != nil {
  790. return nil, 0, fmt.Errorf("find target for %s: %w", featureName, err)
  791. }
  792. id, err := spec.TypeID(target)
  793. return module, id, err
  794. }
  795. // findTargetInKernel attempts to find a named type in the current kernel.
  796. //
  797. // target will point at the found type after a successful call. Searches both
  798. // vmlinux and any loaded modules.
  799. //
  800. // Returns a non-nil handle if the type was found in a module, or btf.ErrNotFound
  801. // if the type wasn't found at all.
  802. func findTargetInKernel(kernelSpec *btf.Spec, typeName string, target *btf.Type) (*btf.Spec, *btf.Handle, error) {
  803. err := kernelSpec.TypeByName(typeName, target)
  804. if errors.Is(err, btf.ErrNotFound) {
  805. spec, module, err := findTargetInModule(kernelSpec, typeName, target)
  806. if err != nil {
  807. return nil, nil, fmt.Errorf("find target in modules: %w", err)
  808. }
  809. return spec, module, nil
  810. }
  811. if err != nil {
  812. return nil, nil, fmt.Errorf("find target in vmlinux: %w", err)
  813. }
  814. return kernelSpec, nil, err
  815. }
  816. // findTargetInModule attempts to find a named type in any loaded module.
  817. //
  818. // base must contain the kernel's types and is used to parse kmod BTF. Modules
  819. // are searched in the order they were loaded.
  820. //
  821. // Returns btf.ErrNotFound if the target can't be found in any module.
  822. func findTargetInModule(base *btf.Spec, typeName string, target *btf.Type) (*btf.Spec, *btf.Handle, error) {
  823. it := new(btf.HandleIterator)
  824. defer it.Handle.Close()
  825. for it.Next() {
  826. info, err := it.Handle.Info()
  827. if err != nil {
  828. return nil, nil, fmt.Errorf("get info for BTF ID %d: %w", it.ID, err)
  829. }
  830. if !info.IsModule() {
  831. continue
  832. }
  833. spec, err := it.Handle.Spec(base)
  834. if err != nil {
  835. return nil, nil, fmt.Errorf("parse types for module %s: %w", info.Name, err)
  836. }
  837. err = spec.TypeByName(typeName, target)
  838. if errors.Is(err, btf.ErrNotFound) {
  839. continue
  840. }
  841. if err != nil {
  842. return nil, nil, fmt.Errorf("lookup type in module %s: %w", info.Name, err)
  843. }
  844. return spec, it.Take(), nil
  845. }
  846. if err := it.Err(); err != nil {
  847. return nil, nil, fmt.Errorf("iterate modules: %w", err)
  848. }
  849. return nil, nil, btf.ErrNotFound
  850. }
  851. // find an attach target type in a program.
  852. //
  853. // Returns errUnrecognizedAttachType.
  854. func findTargetInProgram(prog *Program, name string, progType ProgramType, attachType AttachType) (btf.TypeID, error) {
  855. type match struct {
  856. p ProgramType
  857. a AttachType
  858. }
  859. var typeName string
  860. switch (match{progType, attachType}) {
  861. case match{Extension, AttachNone}:
  862. typeName = name
  863. default:
  864. return 0, errUnrecognizedAttachType
  865. }
  866. btfHandle, err := prog.Handle()
  867. if err != nil {
  868. return 0, fmt.Errorf("load target BTF: %w", err)
  869. }
  870. defer btfHandle.Close()
  871. spec, err := btfHandle.Spec(nil)
  872. if err != nil {
  873. return 0, err
  874. }
  875. var targetFunc *btf.Func
  876. err = spec.TypeByName(typeName, &targetFunc)
  877. if err != nil {
  878. return 0, fmt.Errorf("find target %s: %w", typeName, err)
  879. }
  880. return spec.TypeID(targetFunc)
  881. }