Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c) 2020, Oracle and/or its affiliates. */
0003 
0004 #include "btf_ptr.h"
0005 #include <bpf/bpf_helpers.h>
0006 #include <bpf/bpf_tracing.h>
0007 #include <bpf/bpf_core_read.h>
0008 
0009 #include <errno.h>
0010 
0011 long ret = 0;
0012 int num_subtests = 0;
0013 int ran_subtests = 0;
0014 bool skip = false;
0015 
0016 #define STRSIZE         2048
0017 #define EXPECTED_STRSIZE    256
0018 
0019 #if defined(bpf_target_s390)
0020 /* NULL points to a readable struct lowcore on s390, so take the last page */
0021 #define BADPTR          ((void *)0xFFFFFFFFFFFFF000ULL)
0022 #else
0023 #define BADPTR          0
0024 #endif
0025 
0026 #ifndef ARRAY_SIZE
0027 #define ARRAY_SIZE(x)   (sizeof(x) / sizeof((x)[0]))
0028 #endif
0029 
0030 struct {
0031     __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
0032     __uint(max_entries, 1);
0033     __type(key, __u32);
0034     __type(value, char[STRSIZE]);
0035 } strdata SEC(".maps");
0036 
0037 static int __strncmp(const void *m1, const void *m2, size_t len)
0038 {
0039     const unsigned char *s1 = m1;
0040     const unsigned char *s2 = m2;
0041     int i, delta = 0;
0042 
0043     for (i = 0; i < len; i++) {
0044         delta = s1[i] - s2[i];
0045         if (delta || s1[i] == 0 || s2[i] == 0)
0046             break;
0047     }
0048     return delta;
0049 }
0050 
0051 #if __has_builtin(__builtin_btf_type_id)
0052 #define TEST_BTF(_str, _type, _flags, _expected, ...)           \
0053     do {                                \
0054         static const char _expectedval[EXPECTED_STRSIZE] =  \
0055                             _expected;  \
0056         static const char _ptrtype[64] = #_type;        \
0057         __u64 _hflags = _flags | BTF_F_COMPACT;         \
0058         static _type _ptrdata = __VA_ARGS__;            \
0059         static struct btf_ptr _ptr = { };           \
0060         int _cmp;                       \
0061                                     \
0062         ++num_subtests;                     \
0063         if (ret < 0)                        \
0064             break;                      \
0065         ++ran_subtests;                     \
0066         _ptr.ptr = &_ptrdata;                   \
0067         _ptr.type_id = bpf_core_type_id_kernel(_type);      \
0068         if (_ptr.type_id <= 0) {                \
0069             ret = -EINVAL;                  \
0070             break;                      \
0071         }                           \
0072         ret = bpf_snprintf_btf(_str, STRSIZE,           \
0073                        &_ptr, sizeof(_ptr), _hflags);   \
0074         if (ret)                        \
0075             break;                      \
0076         _cmp = __strncmp(_str, _expectedval, EXPECTED_STRSIZE); \
0077         if (_cmp != 0) {                    \
0078             bpf_printk("(%d) got %s", _cmp, _str);      \
0079             bpf_printk("(%d) expected %s", _cmp,        \
0080                    _expectedval);           \
0081             ret = -EBADMSG;                 \
0082             break;                      \
0083         }                           \
0084     } while (0)
0085 #endif
0086 
0087 /* Use where expected data string matches its stringified declaration */
0088 #define TEST_BTF_C(_str, _type, _flags, ...)                \
0089     TEST_BTF(_str, _type, _flags, "(" #_type ")" #__VA_ARGS__,  \
0090          __VA_ARGS__)
0091 
0092 /* TRACE_EVENT(netif_receive_skb,
0093  *  TP_PROTO(struct sk_buff *skb),
0094  */
0095 SEC("tp_btf/netif_receive_skb")
0096 int BPF_PROG(trace_netif_receive_skb, struct sk_buff *skb)
0097 {
0098     static __u64 flags[] = { 0, BTF_F_COMPACT, BTF_F_ZERO, BTF_F_PTR_RAW,
0099                  BTF_F_NONAME, BTF_F_COMPACT | BTF_F_ZERO |
0100                  BTF_F_PTR_RAW | BTF_F_NONAME };
0101     static struct btf_ptr p = { };
0102     __u32 key = 0;
0103     int i, __ret;
0104     char *str;
0105 
0106 #if __has_builtin(__builtin_btf_type_id)
0107     str = bpf_map_lookup_elem(&strdata, &key);
0108     if (!str)
0109         return 0;
0110 
0111     /* Ensure we can write skb string representation */
0112     p.type_id = bpf_core_type_id_kernel(struct sk_buff);
0113     p.ptr = skb;
0114     for (i = 0; i < ARRAY_SIZE(flags); i++) {
0115         ++num_subtests;
0116         ret = bpf_snprintf_btf(str, STRSIZE, &p, sizeof(p), 0);
0117         if (ret < 0)
0118             bpf_printk("returned %d when writing skb", ret);
0119         ++ran_subtests;
0120     }
0121 
0122     /* Check invalid ptr value */
0123     p.ptr = BADPTR;
0124     __ret = bpf_snprintf_btf(str, STRSIZE, &p, sizeof(p), 0);
0125     if (__ret >= 0) {
0126         bpf_printk("printing %llx should generate error, got (%d)",
0127                (unsigned long long)BADPTR, __ret);
0128         ret = -ERANGE;
0129     }
0130 
0131     /* Verify type display for various types. */
0132 
0133     /* simple int */
0134     TEST_BTF_C(str, int, 0, 1234);
0135     TEST_BTF(str, int, BTF_F_NONAME, "1234", 1234);
0136     /* zero value should be printed at toplevel */
0137     TEST_BTF(str, int, 0, "(int)0", 0);
0138     TEST_BTF(str, int, BTF_F_NONAME, "0", 0);
0139     TEST_BTF(str, int, BTF_F_ZERO, "(int)0", 0);
0140     TEST_BTF(str, int, BTF_F_NONAME | BTF_F_ZERO, "0", 0);
0141     TEST_BTF_C(str, int, 0, -4567);
0142     TEST_BTF(str, int, BTF_F_NONAME, "-4567", -4567);
0143 
0144     /* simple char */
0145     TEST_BTF_C(str, char, 0, 100);
0146     TEST_BTF(str, char, BTF_F_NONAME, "100", 100);
0147     /* zero value should be printed at toplevel */
0148     TEST_BTF(str, char, 0, "(char)0", 0);
0149     TEST_BTF(str, char, BTF_F_NONAME, "0", 0);
0150     TEST_BTF(str, char, BTF_F_ZERO, "(char)0", 0);
0151     TEST_BTF(str, char, BTF_F_NONAME | BTF_F_ZERO, "0", 0);
0152 
0153     /* simple typedef */
0154     TEST_BTF_C(str, uint64_t, 0, 100);
0155     TEST_BTF(str, u64, BTF_F_NONAME, "1", 1);
0156     /* zero value should be printed at toplevel */
0157     TEST_BTF(str, u64, 0, "(u64)0", 0);
0158     TEST_BTF(str, u64, BTF_F_NONAME, "0", 0);
0159     TEST_BTF(str, u64, BTF_F_ZERO, "(u64)0", 0);
0160     TEST_BTF(str, u64, BTF_F_NONAME|BTF_F_ZERO, "0", 0);
0161 
0162     /* typedef struct */
0163     TEST_BTF_C(str, atomic_t, 0, {.counter = (int)1,});
0164     TEST_BTF(str, atomic_t, BTF_F_NONAME, "{1,}", {.counter = 1,});
0165     /* typedef with 0 value should be printed at toplevel */
0166     TEST_BTF(str, atomic_t, 0, "(atomic_t){}", {.counter = 0,});
0167     TEST_BTF(str, atomic_t, BTF_F_NONAME, "{}", {.counter = 0,});
0168     TEST_BTF(str, atomic_t, BTF_F_ZERO, "(atomic_t){.counter = (int)0,}",
0169          {.counter = 0,});
0170     TEST_BTF(str, atomic_t, BTF_F_NONAME|BTF_F_ZERO,
0171          "{0,}", {.counter = 0,});
0172 
0173     /* enum where enum value does (and does not) exist */
0174     TEST_BTF_C(str, enum bpf_cmd, 0, BPF_MAP_CREATE);
0175     TEST_BTF(str, enum bpf_cmd, 0, "(enum bpf_cmd)BPF_MAP_CREATE", 0);
0176     TEST_BTF(str, enum bpf_cmd, BTF_F_NONAME, "BPF_MAP_CREATE",
0177          BPF_MAP_CREATE);
0178     TEST_BTF(str, enum bpf_cmd, BTF_F_NONAME|BTF_F_ZERO,
0179          "BPF_MAP_CREATE", 0);
0180 
0181     TEST_BTF(str, enum bpf_cmd, BTF_F_ZERO, "(enum bpf_cmd)BPF_MAP_CREATE",
0182          BPF_MAP_CREATE);
0183     TEST_BTF(str, enum bpf_cmd, BTF_F_NONAME|BTF_F_ZERO,
0184          "BPF_MAP_CREATE", BPF_MAP_CREATE);
0185     TEST_BTF_C(str, enum bpf_cmd, 0, 2000);
0186     TEST_BTF(str, enum bpf_cmd, BTF_F_NONAME, "2000", 2000);
0187 
0188     /* simple struct */
0189     TEST_BTF_C(str, struct btf_enum, 0,
0190            {.name_off = (__u32)3,.val = (__s32)-1,});
0191     TEST_BTF(str, struct btf_enum, BTF_F_NONAME, "{3,-1,}",
0192          { .name_off = 3, .val = -1,});
0193     TEST_BTF(str, struct btf_enum, BTF_F_NONAME, "{-1,}",
0194          { .name_off = 0, .val = -1,});
0195     TEST_BTF(str, struct btf_enum, BTF_F_NONAME|BTF_F_ZERO, "{0,-1,}",
0196          { .name_off = 0, .val = -1,});
0197     /* empty struct should be printed */
0198     TEST_BTF(str, struct btf_enum, 0, "(struct btf_enum){}",
0199          { .name_off = 0, .val = 0,});
0200     TEST_BTF(str, struct btf_enum, BTF_F_NONAME, "{}",
0201          { .name_off = 0, .val = 0,});
0202     TEST_BTF(str, struct btf_enum, BTF_F_ZERO,
0203          "(struct btf_enum){.name_off = (__u32)0,.val = (__s32)0,}",
0204          { .name_off = 0, .val = 0,});
0205 
0206     /* struct with pointers */
0207     TEST_BTF(str, struct list_head, BTF_F_PTR_RAW,
0208          "(struct list_head){.next = (struct list_head *)0x0000000000000001,}",
0209          { .next = (struct list_head *)1 });
0210     /* NULL pointer should not be displayed */
0211     TEST_BTF(str, struct list_head, BTF_F_PTR_RAW,
0212          "(struct list_head){}",
0213          { .next = (struct list_head *)0 });
0214 
0215     /* struct with char array */
0216     TEST_BTF(str, struct bpf_prog_info, 0,
0217          "(struct bpf_prog_info){.name = (char[])['f','o','o',],}",
0218          { .name = "foo",});
0219     TEST_BTF(str, struct bpf_prog_info, BTF_F_NONAME,
0220          "{['f','o','o',],}",
0221          {.name = "foo",});
0222     /* leading null char means do not display string */
0223     TEST_BTF(str, struct bpf_prog_info, 0,
0224          "(struct bpf_prog_info){}",
0225          {.name = {'\0', 'f', 'o', 'o'}});
0226     /* handle non-printable characters */
0227     TEST_BTF(str, struct bpf_prog_info, 0,
0228          "(struct bpf_prog_info){.name = (char[])[1,2,3,],}",
0229          { .name = {1, 2, 3, 0}});
0230 
0231     /* struct with non-char array */
0232     TEST_BTF(str, struct __sk_buff, 0,
0233          "(struct __sk_buff){.cb = (__u32[])[1,2,3,4,5,],}",
0234          { .cb = {1, 2, 3, 4, 5,},});
0235     TEST_BTF(str, struct __sk_buff, BTF_F_NONAME,
0236          "{[1,2,3,4,5,],}",
0237          { .cb = { 1, 2, 3, 4, 5},});
0238     /* For non-char, arrays, show non-zero values only */
0239     TEST_BTF(str, struct __sk_buff, 0,
0240          "(struct __sk_buff){.cb = (__u32[])[1,],}",
0241          { .cb = { 0, 0, 1, 0, 0},});
0242 
0243     /* struct with bitfields */
0244     TEST_BTF_C(str, struct bpf_insn, 0,
0245            {.code = (__u8)1,.dst_reg = (__u8)0x2,.src_reg = (__u8)0x3,.off = (__s16)4,.imm = (__s32)5,});
0246     TEST_BTF(str, struct bpf_insn, BTF_F_NONAME, "{1,0x2,0x3,4,5,}",
0247          {.code = 1, .dst_reg = 0x2, .src_reg = 0x3, .off = 4,
0248           .imm = 5,});
0249 #else
0250     skip = true;
0251 #endif
0252 
0253     return 0;
0254 }
0255 
0256 char _license[] SEC("license") = "GPL";