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 9 char _license[] SEC("license") = "GPL"; 10 11 /* fields of exactly the same size */ 12 struct 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 */ 21 struct 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 */ 31 struct 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 */ 40 struct 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 50 struct 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 59 unsigned long long ptr_samesized = 0; 60 unsigned long long val1_samesized = 0; 61 unsigned long long val2_samesized = 0; 62 unsigned long long val3_samesized = 0; 63 unsigned long long val4_samesized = 0; 64 struct test_struct___real output_samesized = {}; 65 66 unsigned long long ptr_downsized = 0; 67 unsigned long long val1_downsized = 0; 68 unsigned long long val2_downsized = 0; 69 unsigned long long val3_downsized = 0; 70 unsigned long long val4_downsized = 0; 71 struct test_struct___real output_downsized = {}; 72 73 unsigned long long ptr_probed = 0; 74 unsigned long long val1_probed = 0; 75 unsigned long long val2_probed = 0; 76 unsigned long long val3_probed = 0; 77 unsigned long long val4_probed = 0; 78 79 unsigned long long ptr_signed = 0; 80 unsigned long long val1_signed = 0; 81 unsigned long long val2_signed = 0; 82 unsigned long long val3_signed = 0; 83 unsigned long long val4_signed = 0; 84 struct test_struct___real output_signed = {}; 85 86 SEC("raw_tp/sys_exit") 87 int 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 107 SEC("raw_tp/sys_exit") 108 int 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 138 SEC("raw_tp/sys_enter") 139 int 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 167 SEC("raw_tp/sys_enter") 168 int 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