linux/tools/testing/selftests/bpf/progs/test_core_autosize.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2020 Facebook */
   3
   4#include <linux/bpf.h>
   5#include <stdint.h>
   6#include <bpf/bpf_helpers.h>
   7#include <bpf/bpf_core_read.h>
   8
   9char _license[] SEC("license") = "GPL";
  10
  11/* fields of exactly the same size */
  12struct test_struct___samesize {
  13        void *ptr;
  14        unsigned long long val1;
  15        unsigned int val2;
  16        unsigned short val3;
  17        unsigned char val4;
  18} __attribute((preserve_access_index));
  19
  20/* unsigned fields that have to be downsized by libbpf */
  21struct test_struct___downsize {
  22        void *ptr;
  23        unsigned long val1;
  24        unsigned long val2;
  25        unsigned long val3;
  26        unsigned long val4;
  27        /* total sz: 40 */
  28} __attribute__((preserve_access_index));
  29
  30/* fields with signed integers of wrong size, should be rejected */
  31struct test_struct___signed {
  32        void *ptr;
  33        long val1;
  34        long val2;
  35        long val3;
  36        long val4;
  37} __attribute((preserve_access_index));
  38
  39/* real layout and sizes according to test's (32-bit) BTF */
  40struct test_struct___real {
  41        unsigned int ptr; /* can't use `void *`, it is always 8 byte in BPF target */
  42        unsigned int val2;
  43        unsigned long long val1;
  44        unsigned short val3;
  45        unsigned char val4;
  46        unsigned char _pad;
  47        /* total sz: 20 */
  48};
  49
  50struct test_struct___real input = {
  51        .ptr = 0x01020304,
  52        .val1 = 0x1020304050607080,
  53        .val2 = 0x0a0b0c0d,
  54        .val3 = 0xfeed,
  55        .val4 = 0xb9,
  56        ._pad = 0xff, /* make sure no accidental zeros are present */
  57};
  58
  59unsigned long long ptr_samesized = 0;
  60unsigned long long val1_samesized = 0;
  61unsigned long long val2_samesized = 0;
  62unsigned long long val3_samesized = 0;
  63unsigned long long val4_samesized = 0;
  64struct test_struct___real output_samesized = {};
  65
  66unsigned long long ptr_downsized = 0;
  67unsigned long long val1_downsized = 0;
  68unsigned long long val2_downsized = 0;
  69unsigned long long val3_downsized = 0;
  70unsigned long long val4_downsized = 0;
  71struct test_struct___real output_downsized = {};
  72
  73unsigned long long ptr_probed = 0;
  74unsigned long long val1_probed = 0;
  75unsigned long long val2_probed = 0;
  76unsigned long long val3_probed = 0;
  77unsigned long long val4_probed = 0;
  78
  79unsigned long long ptr_signed = 0;
  80unsigned long long val1_signed = 0;
  81unsigned long long val2_signed = 0;
  82unsigned long long val3_signed = 0;
  83unsigned long long val4_signed = 0;
  84struct test_struct___real output_signed = {};
  85
  86SEC("raw_tp/sys_exit")
  87int handle_samesize(void *ctx)
  88{
  89        struct test_struct___samesize *in = (void *)&input;
  90        struct test_struct___samesize *out = (void *)&output_samesized;
  91
  92        ptr_samesized = (unsigned long long)in->ptr;
  93        val1_samesized = in->val1;
  94        val2_samesized = in->val2;
  95        val3_samesized = in->val3;
  96        val4_samesized = in->val4;
  97
  98        out->ptr = in->ptr;
  99        out->val1 = in->val1;
 100        out->val2 = in->val2;
 101        out->val3 = in->val3;
 102        out->val4 = in->val4;
 103
 104        return 0;
 105}
 106
 107SEC("raw_tp/sys_exit")
 108int handle_downsize(void *ctx)
 109{
 110        struct test_struct___downsize *in = (void *)&input;
 111        struct test_struct___downsize *out = (void *)&output_downsized;
 112
 113        ptr_downsized = (unsigned long long)in->ptr;
 114        val1_downsized = in->val1;
 115        val2_downsized = in->val2;
 116        val3_downsized = in->val3;
 117        val4_downsized = in->val4;
 118
 119        out->ptr = in->ptr;
 120        out->val1 = in->val1;
 121        out->val2 = in->val2;
 122        out->val3 = in->val3;
 123        out->val4 = in->val4;
 124
 125        return 0;
 126}
 127
 128#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 129#define bpf_core_read_int bpf_core_read
 130#else
 131#define bpf_core_read_int(dst, sz, src) ({ \
 132        /* Prevent "subtraction from stack pointer prohibited" */ \
 133        volatile long __off = sizeof(*dst) - (sz); \
 134        bpf_core_read((char *)(dst) + __off, sz, src); \
 135})
 136#endif
 137
 138SEC("raw_tp/sys_enter")
 139int handle_probed(void *ctx)
 140{
 141        struct test_struct___downsize *in = (void *)&input;
 142        __u64 tmp;
 143
 144        tmp = 0;
 145        bpf_core_read_int(&tmp, bpf_core_field_size(in->ptr), &in->ptr);
 146        ptr_probed = tmp;
 147
 148        tmp = 0;
 149        bpf_core_read_int(&tmp, bpf_core_field_size(in->val1), &in->val1);
 150        val1_probed = tmp;
 151
 152        tmp = 0;
 153        bpf_core_read_int(&tmp, bpf_core_field_size(in->val2), &in->val2);
 154        val2_probed = tmp;
 155
 156        tmp = 0;
 157        bpf_core_read_int(&tmp, bpf_core_field_size(in->val3), &in->val3);
 158        val3_probed = tmp;
 159
 160        tmp = 0;
 161        bpf_core_read_int(&tmp, bpf_core_field_size(in->val4), &in->val4);
 162        val4_probed = tmp;
 163
 164        return 0;
 165}
 166
 167SEC("raw_tp/sys_enter")
 168int handle_signed(void *ctx)
 169{
 170        struct test_struct___signed *in = (void *)&input;
 171        struct test_struct___signed *out = (void *)&output_signed;
 172
 173        val2_signed = in->val2;
 174        val3_signed = in->val3;
 175        val4_signed = in->val4;
 176
 177        out->val2= in->val2;
 178        out->val3= in->val3;
 179        out->val4= in->val4;
 180
 181        return 0;
 182}
 183