mbox series

[bpf-next,00/10] Support BTF_KIND_TYPE_TAG for btf_type_tag attributes

Message ID 20211110051940.367472-1-yhs@fb.com (mailing list archive)
Headers show
Series Support BTF_KIND_TYPE_TAG for btf_type_tag attributes | expand

Message

Yonghong Song Nov. 10, 2021, 5:19 a.m. UTC
LLVM patches ([1] for clang, [2] and [3] for BPF backend)
added support for btf_type_tag attributes. This patch
added support for the kernel.

The main motivation for btf_type_tag is to bring kernel
annotations __user, __rcu etc. to btf. With such information
available in btf, bpf verifier can detect mis-usages
and reject the program. For example, for __user tagged pointer,
developers can then use proper helper like bpf_probe_read_kernel()
etc. to read the data.

BTF_KIND_TYPE_TAG may also useful for other tracing
facility where instead of to require user to specify
kernel/user address type, the kernel can detect it
by itself with btf.

Patch 1 added support in kernel, Patch 2 for libbpf and Patch 3
for bpftool. Patches 4-9 are for bpf selftests and Patch 10
updated docs/bpf/btf.rst file with new btf kind.

  [1] https://reviews.llvm.org/D111199
  [2] https://reviews.llvm.org/D113222
  [3] https://reviews.llvm.org/D113496

Yonghong Song (10):
  bpf: Support BTF_KIND_TYPE_TAG for btf_type_tag attributes
  libbpf: Support BTF_KIND_TYPE_TAG
  bpftool: Support BTF_KIND_TYPE_TAG
  selftests/bpf: Test libbpf API function btf__add_type_tag()
  selftests/bpf: Add BTF_KIND_TYPE_TAG unit tests
  selftests/bpf: Test BTF_KIND_DECL_TAG for deduplication
  selftests/bpf: Rename progs/tag.c to progs/btf_decl_tag.c
  selftests/bpf: Add a C test for btf_type_tag
  selftests/bpf: Clarify llvm dependency with btf_tag selftest
  docs/bpf: Update documentation for BTF_KIND_TYPE_TAG support

 Documentation/bpf/btf.rst                     | 13 +++-
 include/uapi/linux/btf.h                      |  3 +-
 kernel/bpf/btf.c                              | 14 +++-
 tools/bpf/bpftool/btf.c                       |  2 +
 tools/include/uapi/linux/btf.h                |  3 +-
 tools/lib/bpf/btf.c                           | 23 +++++++
 tools/lib/bpf/btf.h                           |  9 ++-
 tools/lib/bpf/btf_dump.c                      |  9 +++
 tools/lib/bpf/libbpf.c                        | 31 ++++++++-
 tools/lib/bpf/libbpf.map                      |  1 +
 tools/lib/bpf/libbpf_internal.h               |  2 +
 tools/testing/selftests/bpf/README.rst        |  9 +--
 tools/testing/selftests/bpf/btf_helpers.c     |  4 +-
 tools/testing/selftests/bpf/prog_tests/btf.c  | 64 ++++++++++++++++--
 .../selftests/bpf/prog_tests/btf_tag.c        | 44 ++++++++++--
 .../selftests/bpf/prog_tests/btf_write.c      | 67 +++++++++++--------
 .../bpf/progs/{tag.c => btf_decl_tag.c}       |  0
 .../selftests/bpf/progs/btf_type_tag.c        | 29 ++++++++
 tools/testing/selftests/bpf/test_btf.h        |  3 +
 19 files changed, 281 insertions(+), 49 deletions(-)
 rename tools/testing/selftests/bpf/progs/{tag.c => btf_decl_tag.c} (100%)
 create mode 100644 tools/testing/selftests/bpf/progs/btf_type_tag.c

Comments

Alexei Starovoitov Nov. 10, 2021, 5:28 a.m. UTC | #1
On Tue, Nov 09, 2021 at 09:19:40PM -0800, Yonghong Song wrote:
> LLVM patches ([1] for clang, [2] and [3] for BPF backend)
> added support for btf_type_tag attributes. This patch
> added support for the kernel.
> 
> The main motivation for btf_type_tag is to bring kernel
> annotations __user, __rcu etc. to btf. With such information
> available in btf, bpf verifier can detect mis-usages
> and reject the program. For example, for __user tagged pointer,
> developers can then use proper helper like bpf_probe_read_kernel()
> etc. to read the data.

+#define __tag1 __attribute__((btf_type_tag("tag1")))
+#define __tag2 __attribute__((btf_type_tag("tag2")))
+
+struct btf_type_tag_test {
+       int __tag1 * __tag1 __tag2 *p;
+} g;

Can we build the kernel with the latest clang and get __user in BTF ?
Yonghong Song Nov. 10, 2021, 6:26 a.m. UTC | #2
On 11/9/21 9:28 PM, Alexei Starovoitov wrote:
> On Tue, Nov 09, 2021 at 09:19:40PM -0800, Yonghong Song wrote:
>> LLVM patches ([1] for clang, [2] and [3] for BPF backend)
>> added support for btf_type_tag attributes. This patch
>> added support for the kernel.
>>
>> The main motivation for btf_type_tag is to bring kernel
>> annotations __user, __rcu etc. to btf. With such information
>> available in btf, bpf verifier can detect mis-usages
>> and reject the program. For example, for __user tagged pointer,
>> developers can then use proper helper like bpf_probe_read_kernel()
>> etc. to read the data.
> 
> +#define __tag1 __attribute__((btf_type_tag("tag1")))
> +#define __tag2 __attribute__((btf_type_tag("tag2")))
> +
> +struct btf_type_tag_test {
> +       int __tag1 * __tag1 __tag2 *p;
> +} g;
> 
> Can we build the kernel with the latest clang and get __user in BTF ?

Not yet. The following are the steps:
   1. land this patch set in the kernel
   2. sync to libbpf repo.
   3. pahole sync with libbpf repo, and pahole convert btf_type_tag
      in llvm to BTF
   4. another kernel patch to define __user as
      __attribute__((btf_type_tag("user")))
and then we will get __user in vmlinux BTF.
Alexei Starovoitov Nov. 10, 2021, 4:40 p.m. UTC | #3
On Tue, Nov 9, 2021 at 10:26 PM Yonghong Song <yhs@fb.com> wrote:
>
>
>
> On 11/9/21 9:28 PM, Alexei Starovoitov wrote:
> > On Tue, Nov 09, 2021 at 09:19:40PM -0800, Yonghong Song wrote:
> >> LLVM patches ([1] for clang, [2] and [3] for BPF backend)
> >> added support for btf_type_tag attributes. This patch
> >> added support for the kernel.
> >>
> >> The main motivation for btf_type_tag is to bring kernel
> >> annotations __user, __rcu etc. to btf. With such information
> >> available in btf, bpf verifier can detect mis-usages
> >> and reject the program. For example, for __user tagged pointer,
> >> developers can then use proper helper like bpf_probe_read_kernel()
> >> etc. to read the data.
> >
> > +#define __tag1 __attribute__((btf_type_tag("tag1")))
> > +#define __tag2 __attribute__((btf_type_tag("tag2")))
> > +
> > +struct btf_type_tag_test {
> > +       int __tag1 * __tag1 __tag2 *p;
> > +} g;
> >
> > Can we build the kernel with the latest clang and get __user in BTF ?
>
> Not yet. The following are the steps:
>    1. land this patch set in the kernel
>    2. sync to libbpf repo.
>    3. pahole sync with libbpf repo, and pahole convert btf_type_tag
>       in llvm to BTF
>    4. another kernel patch to define __user as
>       __attribute__((btf_type_tag("user")))
> and then we will get __user in vmlinux BTF.

Makes sense. I was wondering whether clang can handle
the whole kernel source code with
#define __user __attribute__((btf_type_tag("user")))
Steps 1,2,3 are necessary to make use of it,
but step 4 can be tried out already?
Yonghong Song Nov. 10, 2021, 5:04 p.m. UTC | #4
On 11/10/21 8:40 AM, Alexei Starovoitov wrote:
> On Tue, Nov 9, 2021 at 10:26 PM Yonghong Song <yhs@fb.com> wrote:
>>
>>
>>
>> On 11/9/21 9:28 PM, Alexei Starovoitov wrote:
>>> On Tue, Nov 09, 2021 at 09:19:40PM -0800, Yonghong Song wrote:
>>>> LLVM patches ([1] for clang, [2] and [3] for BPF backend)
>>>> added support for btf_type_tag attributes. This patch
>>>> added support for the kernel.
>>>>
>>>> The main motivation for btf_type_tag is to bring kernel
>>>> annotations __user, __rcu etc. to btf. With such information
>>>> available in btf, bpf verifier can detect mis-usages
>>>> and reject the program. For example, for __user tagged pointer,
>>>> developers can then use proper helper like bpf_probe_read_kernel()
>>>> etc. to read the data.
>>>
>>> +#define __tag1 __attribute__((btf_type_tag("tag1")))
>>> +#define __tag2 __attribute__((btf_type_tag("tag2")))
>>> +
>>> +struct btf_type_tag_test {
>>> +       int __tag1 * __tag1 __tag2 *p;
>>> +} g;
>>>
>>> Can we build the kernel with the latest clang and get __user in BTF ?
>>
>> Not yet. The following are the steps:
>>     1. land this patch set in the kernel
>>     2. sync to libbpf repo.
>>     3. pahole sync with libbpf repo, and pahole convert btf_type_tag
>>        in llvm to BTF
>>     4. another kernel patch to define __user as
>>        __attribute__((btf_type_tag("user")))
>> and then we will get __user in vmlinux BTF.
> 
> Makes sense. I was wondering whether clang can handle
> the whole kernel source code with
> #define __user __attribute__((btf_type_tag("user")))
> Steps 1,2,3 are necessary to make use of it,
> but step 4 can be tried out already?

Yes, you try clang -> vmlinux dwarf part of step 4 with
the following kernel hack:

diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index 05ceb2e92b0e..30e199c30a53 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -32,7 +32,7 @@ static inline void __chk_io_ptr(const volatile void 
__iomem *ptr) { }
  # ifdef STRUCTLEAK_PLUGIN
  #  define __user       __attribute__((user))
  # else
-#  define __user
+#  define __user       __attribute__((btf_type_tag("user")))
  # endif
  # define __iomem
  # define __percpu
[yhs@devbig309.ftw3 ~/work/bpf-next]
Alexei Starovoitov Nov. 11, 2021, 1:47 a.m. UTC | #5
On Wed, Nov 10, 2021 at 9:04 AM Yonghong Song <yhs@fb.com> wrote:
>
>
>
> On 11/10/21 8:40 AM, Alexei Starovoitov wrote:
> > On Tue, Nov 9, 2021 at 10:26 PM Yonghong Song <yhs@fb.com> wrote:
> >>
> >>
> >>
> >> On 11/9/21 9:28 PM, Alexei Starovoitov wrote:
> >>> On Tue, Nov 09, 2021 at 09:19:40PM -0800, Yonghong Song wrote:
> >>>> LLVM patches ([1] for clang, [2] and [3] for BPF backend)
> >>>> added support for btf_type_tag attributes. This patch
> >>>> added support for the kernel.
> >>>>
> >>>> The main motivation for btf_type_tag is to bring kernel
> >>>> annotations __user, __rcu etc. to btf. With such information
> >>>> available in btf, bpf verifier can detect mis-usages
> >>>> and reject the program. For example, for __user tagged pointer,
> >>>> developers can then use proper helper like bpf_probe_read_kernel()
> >>>> etc. to read the data.
> >>>
> >>> +#define __tag1 __attribute__((btf_type_tag("tag1")))
> >>> +#define __tag2 __attribute__((btf_type_tag("tag2")))
> >>> +
> >>> +struct btf_type_tag_test {
> >>> +       int __tag1 * __tag1 __tag2 *p;
> >>> +} g;
> >>>
> >>> Can we build the kernel with the latest clang and get __user in BTF ?
> >>
> >> Not yet. The following are the steps:
> >>     1. land this patch set in the kernel
> >>     2. sync to libbpf repo.
> >>     3. pahole sync with libbpf repo, and pahole convert btf_type_tag
> >>        in llvm to BTF
> >>     4. another kernel patch to define __user as
> >>        __attribute__((btf_type_tag("user")))
> >> and then we will get __user in vmlinux BTF.
> >
> > Makes sense. I was wondering whether clang can handle
> > the whole kernel source code with
> > #define __user __attribute__((btf_type_tag("user")))
> > Steps 1,2,3 are necessary to make use of it,
> > but step 4 can be tried out already?
>
> Yes, you try clang -> vmlinux dwarf part of step 4 with
> the following kernel hack:
>
> diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
> index 05ceb2e92b0e..30e199c30a53 100644
> --- a/include/linux/compiler_types.h
> +++ b/include/linux/compiler_types.h
> @@ -32,7 +32,7 @@ static inline void __chk_io_ptr(const volatile void
> __iomem *ptr) { }
>   # ifdef STRUCTLEAK_PLUGIN
>   #  define __user       __attribute__((user))
>   # else
> -#  define __user
> +#  define __user       __attribute__((btf_type_tag("user")))
>   # endif
>   # define __iomem
>   # define __percpu

I've tried the latest LLVM with the above diff and it seems to work!

$ llvm-dwarfdump kernel/bpf/built-in.a |grep -3 btf_type_tag|head
0x00003ace:   DW_TAG_pointer_type

0x00003acf:     DW_TAG_LLVM_annotation
                  DW_AT_name    ("btf_type_tag")
                  DW_AT_const_value    ("user")


Nice!
Didn't notice any warnings. Great.