This is an archive of the discontinued LLVM Phabricator instance.

[BPF] Adding __attribute__((bpf_virtual_offsets)) for structs
AbandonedPublicDraft

Authored by eddyz87 on Aug 29 2022, 5:34 PM.

Details

Reviewers
aaron.ballman
Summary

This commit adds a new BPF specific structure attribte
__attribute__((bpf_virtual_offsets)) and passes to deal with it.

This attribute may be attached to a struct or union declaration, where
it notifies the compiler that runtime environment might patch access
to the fields of this type by updating the field offset.

BPF verifier limits access patterns allowed for certain data
types. E.g. struct __sk_buff and struct bpf_sock_ops. For these
types only BASE + static-offset memory loads and stores are allowed.

This is so because offsets of the fields of these structures do not
match real offsets in the running kernel. During BPF program
load/verification loads and stores to the fields of these types are
rewritten so that offsets match real offsets. For this rewrite to
happen static offsets have to be encoded in the instructions.

See kernel/bpf/verifier.c:convert_ctx_access function in the Linux
kernel source tree for details.

Access to the structure fields is translated to the IR as a pair:

  • (load (getelementptr ...)) or
  • (store (getelementptr ...))

During instruction selection phase the following sequence of
instructions:

%x = getelementptr %ptr, %offset
%y = load %x

Is translated as a single load instruction with embedded offset,
e.g. LDW %ptr, %offset, which matches access pattern necessary for
the restricted set of types described above (when %offset is
static).

Multiple optimizer passes might separate these instructions, this
includes:

  • SimplifyCFGPass (sinking)
  • InstCombine (sinking)
  • GVN (hoisting)

The bpf_virtual_offsets attribute marks structures for which the
following transformations happen:

  • at the early IR processing stage:
    • (load (getelementptr ...)) replaced by call to intrinsic llvm.bpf.getelementptr.and.load;
    • (store (getelementptr ...)) replaced by call to intrinsic llvm.bpf.getelementptr.and.store;
  • at the late IR processing stage this modification is undone.

Such handling prevents various optimizer passes from generating
sequences of instructions that would be rejected by BPF verifier.

This addresses the issue reported by the following thread:

https://lore.kernel.org/bpf/CAA-VZPmxh8o8EBcJ=m-DH4ytcxDFmo0JKsm1p1gf40kS0CE3NQ@mail.gmail.com/T/#m4b9ce2ce73b34f34172328f975235fc6f19841b6

Diff Detail

Event Timeline

eddyz87 created this revision.Aug 29 2022, 5:34 PM
Herald added a project: Restricted Project. · View Herald Transcript
eddyz87 updated this revision to Diff 457876.Sep 4 2022, 4:11 PM

Handle GEP chains / proper test cases

eddyz87 abandoned this revision.Sep 28 2022, 6:14 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptSep 28 2022, 6:14 AM