1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */ 3 4 #include <linux/bpf.h> 5 #include <bpf/bpf_helpers.h> 6 #include "bpf_misc.h" 7 8 char _license[] SEC("license") = "GPL"; 9 10 struct sample { 11 int pid; 12 int seq; 13 long value; 14 char comm[16]; 15 }; 16 17 struct { 18 __uint(type, BPF_MAP_TYPE_USER_RINGBUF); 19 } user_ringbuf SEC(".maps"); 20 21 static long 22 bad_access1(struct bpf_dynptr *dynptr, void *context) 23 { 24 const struct sample *sample; 25 26 sample = bpf_dynptr_data(dynptr - 1, 0, sizeof(*sample)); 27 bpf_printk("Was able to pass bad pointer %lx\n", (__u64)dynptr - 1); 28 29 return 0; 30 } 31 32 /* A callback that accesses a dynptr in a bpf_user_ringbuf_drain callback should 33 * not be able to read before the pointer. 34 */ 35 SEC("?raw_tp/sys_nanosleep") 36 int user_ringbuf_callback_bad_access1(void *ctx) 37 { 38 bpf_user_ringbuf_drain(&user_ringbuf, bad_access1, NULL, 0); 39 40 return 0; 41 } 42 43 static long 44 bad_access2(struct bpf_dynptr *dynptr, void *context) 45 { 46 const struct sample *sample; 47 48 sample = bpf_dynptr_data(dynptr + 1, 0, sizeof(*sample)); 49 bpf_printk("Was able to pass bad pointer %lx\n", (__u64)dynptr + 1); 50 51 return 0; 52 } 53 54 /* A callback that accesses a dynptr in a bpf_user_ringbuf_drain callback should 55 * not be able to read past the end of the pointer. 56 */ 57 SEC("?raw_tp/sys_nanosleep") 58 int user_ringbuf_callback_bad_access2(void *ctx) 59 { 60 bpf_user_ringbuf_drain(&user_ringbuf, bad_access2, NULL, 0); 61 62 return 0; 63 } 64 65 static long 66 write_forbidden(struct bpf_dynptr *dynptr, void *context) 67 { 68 *((long *)dynptr) = 0; 69 70 return 0; 71 } 72 73 /* A callback that accesses a dynptr in a bpf_user_ringbuf_drain callback should 74 * not be able to write to that pointer. 75 */ 76 SEC("?raw_tp/sys_nanosleep") 77 int user_ringbuf_callback_write_forbidden(void *ctx) 78 { 79 bpf_user_ringbuf_drain(&user_ringbuf, write_forbidden, NULL, 0); 80 81 return 0; 82 } 83 84 static long 85 null_context_write(struct bpf_dynptr *dynptr, void *context) 86 { 87 *((__u64 *)context) = 0; 88 89 return 0; 90 } 91 92 /* A callback that accesses a dynptr in a bpf_user_ringbuf_drain callback should 93 * not be able to write to that pointer. 94 */ 95 SEC("?raw_tp/sys_nanosleep") 96 int user_ringbuf_callback_null_context_write(void *ctx) 97 { 98 bpf_user_ringbuf_drain(&user_ringbuf, null_context_write, NULL, 0); 99 100 return 0; 101 } 102 103 static long 104 null_context_read(struct bpf_dynptr *dynptr, void *context) 105 { 106 __u64 id = *((__u64 *)context); 107 108 bpf_printk("Read id %lu\n", id); 109 110 return 0; 111 } 112 113 /* A callback that accesses a dynptr in a bpf_user_ringbuf_drain callback should 114 * not be able to write to that pointer. 115 */ 116 SEC("?raw_tp/sys_nanosleep") 117 int user_ringbuf_callback_null_context_read(void *ctx) 118 { 119 bpf_user_ringbuf_drain(&user_ringbuf, null_context_read, NULL, 0); 120 121 return 0; 122 } 123 124 static long 125 try_discard_dynptr(struct bpf_dynptr *dynptr, void *context) 126 { 127 bpf_ringbuf_discard_dynptr(dynptr, 0); 128 129 return 0; 130 } 131 132 /* A callback that accesses a dynptr in a bpf_user_ringbuf_drain callback should 133 * not be able to read past the end of the pointer. 134 */ 135 SEC("?raw_tp/sys_nanosleep") 136 int user_ringbuf_callback_discard_dynptr(void *ctx) 137 { 138 bpf_user_ringbuf_drain(&user_ringbuf, try_discard_dynptr, NULL, 0); 139 140 return 0; 141 } 142 143 static long 144 try_submit_dynptr(struct bpf_dynptr *dynptr, void *context) 145 { 146 bpf_ringbuf_submit_dynptr(dynptr, 0); 147 148 return 0; 149 } 150 151 /* A callback that accesses a dynptr in a bpf_user_ringbuf_drain callback should 152 * not be able to read past the end of the pointer. 153 */ 154 SEC("?raw_tp/sys_nanosleep") 155 int user_ringbuf_callback_submit_dynptr(void *ctx) 156 { 157 bpf_user_ringbuf_drain(&user_ringbuf, try_submit_dynptr, NULL, 0); 158 159 return 0; 160 } 161 162 static long 163 invalid_drain_callback_return(struct bpf_dynptr *dynptr, void *context) 164 { 165 return 2; 166 } 167 168 /* A callback that accesses a dynptr in a bpf_user_ringbuf_drain callback should 169 * not be able to write to that pointer. 170 */ 171 SEC("?raw_tp/sys_nanosleep") 172 int user_ringbuf_callback_invalid_return(void *ctx) 173 { 174 bpf_user_ringbuf_drain(&user_ringbuf, invalid_drain_callback_return, NULL, 0); 175 176 return 0; 177 } 178