|
1 | 1 | #include <stdbool.h>
|
2 | 2 | #include <linux/bpf.h>
|
| 3 | +#include <linux/errno.h> |
3 | 4 | #include <linux/if_ether.h>
|
4 | 5 | #include <linux/pkt_cls.h>
|
5 | 6 |
|
@@ -122,6 +123,124 @@ int ing_cls_dynptr_slice_rdwr(struct __sk_buff *ctx)
|
122 | 123 | return TC_ACT_UNSPEC; /* pass */
|
123 | 124 | }
|
124 | 125 |
|
| 126 | +/* Read skb metadata in chunks from various offsets in different ways. */ |
| 127 | +SEC("tc") |
| 128 | +int ing_cls_dynptr_offset_rd(struct __sk_buff *ctx) |
| 129 | +{ |
| 130 | + struct bpf_dynptr meta; |
| 131 | + const __u32 chunk_len = META_SIZE / 4; |
| 132 | + const __u32 zero = 0; |
| 133 | + __u8 *dst, *src; |
| 134 | + |
| 135 | + dst = bpf_map_lookup_elem(&test_result, &zero); |
| 136 | + if (!dst) |
| 137 | + return TC_ACT_SHOT; |
| 138 | + |
| 139 | + /* 1. Regular read */ |
| 140 | + bpf_dynptr_from_skb_meta(ctx, 0, &meta); |
| 141 | + bpf_dynptr_read(dst, chunk_len, &meta, 0, 0); |
| 142 | + dst += chunk_len; |
| 143 | + |
| 144 | + /* 2. Read from an offset-adjusted dynptr */ |
| 145 | + bpf_dynptr_adjust(&meta, chunk_len, bpf_dynptr_size(&meta)); |
| 146 | + bpf_dynptr_read(dst, chunk_len, &meta, 0, 0); |
| 147 | + dst += chunk_len; |
| 148 | + |
| 149 | + /* 3. Read at an offset */ |
| 150 | + bpf_dynptr_read(dst, chunk_len, &meta, chunk_len, 0); |
| 151 | + dst += chunk_len; |
| 152 | + |
| 153 | + /* 4. Read from a slice starting at an offset */ |
| 154 | + src = bpf_dynptr_slice(&meta, 2 * chunk_len, NULL, chunk_len); |
| 155 | + if (!src) |
| 156 | + return TC_ACT_SHOT; |
| 157 | + __builtin_memcpy(dst, src, chunk_len); |
| 158 | + |
| 159 | + return TC_ACT_SHOT; |
| 160 | +} |
| 161 | + |
| 162 | +/* Write skb metadata in chunks at various offsets in different ways. */ |
| 163 | +SEC("tc") |
| 164 | +int ing_cls_dynptr_offset_wr(struct __sk_buff *ctx) |
| 165 | +{ |
| 166 | + const __u32 chunk_len = META_SIZE / 4; |
| 167 | + __u8 payload[META_SIZE]; |
| 168 | + struct bpf_dynptr meta; |
| 169 | + __u8 *dst, *src; |
| 170 | + |
| 171 | + bpf_skb_load_bytes(ctx, sizeof(struct ethhdr), payload, sizeof(payload)); |
| 172 | + src = payload; |
| 173 | + |
| 174 | + /* 1. Regular write */ |
| 175 | + bpf_dynptr_from_skb_meta(ctx, 0, &meta); |
| 176 | + bpf_dynptr_write(&meta, 0, src, chunk_len, 0); |
| 177 | + src += chunk_len; |
| 178 | + |
| 179 | + /* 2. Write to an offset-adjusted dynptr */ |
| 180 | + bpf_dynptr_adjust(&meta, chunk_len, bpf_dynptr_size(&meta)); |
| 181 | + bpf_dynptr_write(&meta, 0, src, chunk_len, 0); |
| 182 | + src += chunk_len; |
| 183 | + |
| 184 | + /* 3. Write at an offset */ |
| 185 | + bpf_dynptr_write(&meta, chunk_len, src, chunk_len, 0); |
| 186 | + src += chunk_len; |
| 187 | + |
| 188 | + /* 4. Write to a slice starting at an offset */ |
| 189 | + dst = bpf_dynptr_slice_rdwr(&meta, 2 * chunk_len, NULL, chunk_len); |
| 190 | + if (!dst) |
| 191 | + return TC_ACT_SHOT; |
| 192 | + __builtin_memcpy(dst, src, chunk_len); |
| 193 | + |
| 194 | + return TC_ACT_UNSPEC; /* pass */ |
| 195 | +} |
| 196 | + |
| 197 | +/* Pass an OOB offset to dynptr read, write, adjust, slice. */ |
| 198 | +SEC("tc") |
| 199 | +int ing_cls_dynptr_offset_oob(struct __sk_buff *ctx) |
| 200 | +{ |
| 201 | + struct bpf_dynptr meta; |
| 202 | + __u8 md, *p; |
| 203 | + int err; |
| 204 | + |
| 205 | + err = bpf_dynptr_from_skb_meta(ctx, 0, &meta); |
| 206 | + if (err) |
| 207 | + goto fail; |
| 208 | + |
| 209 | + /* read offset OOB */ |
| 210 | + err = bpf_dynptr_read(&md, sizeof(md), &meta, META_SIZE, 0); |
| 211 | + if (err != -E2BIG) |
| 212 | + goto fail; |
| 213 | + |
| 214 | + /* write offset OOB */ |
| 215 | + err = bpf_dynptr_write(&meta, META_SIZE, &md, sizeof(md), 0); |
| 216 | + if (err != -E2BIG) |
| 217 | + goto fail; |
| 218 | + |
| 219 | + /* adjust end offset OOB */ |
| 220 | + err = bpf_dynptr_adjust(&meta, 0, META_SIZE + 1); |
| 221 | + if (err != -ERANGE) |
| 222 | + goto fail; |
| 223 | + |
| 224 | + /* adjust start offset OOB */ |
| 225 | + err = bpf_dynptr_adjust(&meta, META_SIZE + 1, META_SIZE + 1); |
| 226 | + if (err != -ERANGE) |
| 227 | + goto fail; |
| 228 | + |
| 229 | + /* slice offset OOB */ |
| 230 | + p = bpf_dynptr_slice(&meta, META_SIZE, NULL, sizeof(*p)); |
| 231 | + if (p) |
| 232 | + goto fail; |
| 233 | + |
| 234 | + /* slice rdwr offset OOB */ |
| 235 | + p = bpf_dynptr_slice_rdwr(&meta, META_SIZE, NULL, sizeof(*p)); |
| 236 | + if (p) |
| 237 | + goto fail; |
| 238 | + |
| 239 | + return TC_ACT_UNSPEC; |
| 240 | +fail: |
| 241 | + return TC_ACT_SHOT; |
| 242 | +} |
| 243 | + |
125 | 244 | /* Reserve and clear space for metadata but don't populate it */
|
126 | 245 | SEC("xdp")
|
127 | 246 | int ing_xdp_zalloc_meta(struct xdp_md *ctx)
|
|
0 commit comments