Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
8char _license[] SEC("license") = "GPL";
9
10struct sample {
11 int pid;
12 int seq;
13 long value;
14 char comm[16];
15};
16
17struct {
18 __uint(type, BPF_MAP_TYPE_USER_RINGBUF);
19} user_ringbuf SEC(".maps");
20
21static long
22bad_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 */
35SEC("?raw_tp/sys_nanosleep")
36int 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
43static long
44bad_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 */
57SEC("?raw_tp/sys_nanosleep")
58int 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
65static long
66write_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 */
76SEC("?raw_tp/sys_nanosleep")
77int 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
84static long
85null_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 */
95SEC("?raw_tp/sys_nanosleep")
96int 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
103static long
104null_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 */
116SEC("?raw_tp/sys_nanosleep")
117int 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
124static long
125try_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 */
135SEC("?raw_tp/sys_nanosleep")
136int 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
143static long
144try_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 */
154SEC("?raw_tp/sys_nanosleep")
155int 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
162static long
163invalid_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 */
171SEC("?raw_tp/sys_nanosleep")
172int 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}