Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c) 2022 Facebook */
0003 
0004 #include <string.h>
0005 #include <linux/bpf.h>
0006 #include <bpf/bpf_helpers.h>
0007 #include "bpf_misc.h"
0008 #include "errno.h"
0009 
0010 char _license[] SEC("license") = "GPL";
0011 
0012 int pid, err, val;
0013 
0014 struct sample {
0015     int pid;
0016     int seq;
0017     long value;
0018     char comm[16];
0019 };
0020 
0021 struct {
0022     __uint(type, BPF_MAP_TYPE_RINGBUF);
0023 } ringbuf SEC(".maps");
0024 
0025 struct {
0026     __uint(type, BPF_MAP_TYPE_ARRAY);
0027     __uint(max_entries, 1);
0028     __type(key, __u32);
0029     __type(value, __u32);
0030 } array_map SEC(".maps");
0031 
0032 SEC("tp/syscalls/sys_enter_nanosleep")
0033 int test_read_write(void *ctx)
0034 {
0035     char write_data[64] = "hello there, world!!";
0036     char read_data[64] = {}, buf[64] = {};
0037     struct bpf_dynptr ptr;
0038     int i;
0039 
0040     if (bpf_get_current_pid_tgid() >> 32 != pid)
0041         return 0;
0042 
0043     bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(write_data), 0, &ptr);
0044 
0045     /* Write data into the dynptr */
0046     err = bpf_dynptr_write(&ptr, 0, write_data, sizeof(write_data), 0);
0047 
0048     /* Read the data that was written into the dynptr */
0049     err = err ?: bpf_dynptr_read(read_data, sizeof(read_data), &ptr, 0, 0);
0050 
0051     /* Ensure the data we read matches the data we wrote */
0052     for (i = 0; i < sizeof(read_data); i++) {
0053         if (read_data[i] != write_data[i]) {
0054             err = 1;
0055             break;
0056         }
0057     }
0058 
0059     bpf_ringbuf_discard_dynptr(&ptr, 0);
0060     return 0;
0061 }
0062 
0063 SEC("tp/syscalls/sys_enter_nanosleep")
0064 int test_data_slice(void *ctx)
0065 {
0066     __u32 key = 0, val = 235, *map_val;
0067     struct bpf_dynptr ptr;
0068     __u32 map_val_size;
0069     void *data;
0070 
0071     map_val_size = sizeof(*map_val);
0072 
0073     if (bpf_get_current_pid_tgid() >> 32 != pid)
0074         return 0;
0075 
0076     bpf_map_update_elem(&array_map, &key, &val, 0);
0077 
0078     map_val = bpf_map_lookup_elem(&array_map, &key);
0079     if (!map_val) {
0080         err = 1;
0081         return 0;
0082     }
0083 
0084     bpf_dynptr_from_mem(map_val, map_val_size, 0, &ptr);
0085 
0086     /* Try getting a data slice that is out of range */
0087     data = bpf_dynptr_data(&ptr, map_val_size + 1, 1);
0088     if (data) {
0089         err = 2;
0090         return 0;
0091     }
0092 
0093     /* Try getting more bytes than available */
0094     data = bpf_dynptr_data(&ptr, 0, map_val_size + 1);
0095     if (data) {
0096         err = 3;
0097         return 0;
0098     }
0099 
0100     data = bpf_dynptr_data(&ptr, 0, sizeof(__u32));
0101     if (!data) {
0102         err = 4;
0103         return 0;
0104     }
0105 
0106     *(__u32 *)data = 999;
0107 
0108     err = bpf_probe_read_kernel(&val, sizeof(val), data);
0109     if (err)
0110         return 0;
0111 
0112     if (val != *(int *)data)
0113         err = 5;
0114 
0115     return 0;
0116 }
0117 
0118 static int ringbuf_callback(__u32 index, void *data)
0119 {
0120     struct sample *sample;
0121 
0122     struct bpf_dynptr *ptr = (struct bpf_dynptr *)data;
0123 
0124     sample = bpf_dynptr_data(ptr, 0, sizeof(*sample));
0125     if (!sample)
0126         err = 2;
0127     else
0128         sample->pid += index;
0129 
0130     return 0;
0131 }
0132 
0133 SEC("tp/syscalls/sys_enter_nanosleep")
0134 int test_ringbuf(void *ctx)
0135 {
0136     struct bpf_dynptr ptr;
0137     struct sample *sample;
0138 
0139     if (bpf_get_current_pid_tgid() >> 32 != pid)
0140         return 0;
0141 
0142     val = 100;
0143 
0144     /* check that you can reserve a dynamic size reservation */
0145     err = bpf_ringbuf_reserve_dynptr(&ringbuf, val, 0, &ptr);
0146 
0147     sample = err ? NULL : bpf_dynptr_data(&ptr, 0, sizeof(*sample));
0148     if (!sample) {
0149         err = 1;
0150         goto done;
0151     }
0152 
0153     sample->pid = 10;
0154 
0155     /* Can pass dynptr to callback functions */
0156     bpf_loop(10, ringbuf_callback, &ptr, 0);
0157 
0158     if (sample->pid != 55)
0159         err = 2;
0160 
0161 done:
0162     bpf_ringbuf_discard_dynptr(&ptr, 0);
0163     return 0;
0164 }