1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2021 Facebook */
3 #include <vmlinux.h>
4 #include <bpf/bpf_helpers.h>
5 #include "../bpf_testmod/bpf_testmod_kfunc.h"
6 
7 struct syscall_test_args {
8 	__u8 data[16];
9 	size_t size;
10 };
11 
12 SEC("?syscall")
13 int kfunc_syscall_test_fail(struct syscall_test_args *args)
14 {
15 	bpf_kfunc_call_test_mem_len_pass1(&args->data, sizeof(*args) + 1);
16 
17 	return 0;
18 }
19 
20 SEC("?syscall")
21 int kfunc_syscall_test_null_fail(struct syscall_test_args *args)
22 {
23 	/* Must be called with args as a NULL pointer
24 	 * we do not check for it to have the verifier consider that
25 	 * the pointer might not be null, and so we can load it.
26 	 *
27 	 * So the following can not be added:
28 	 *
29 	 * if (args)
30 	 *      return -22;
31 	 */
32 
33 	bpf_kfunc_call_test_mem_len_pass1(args, sizeof(*args));
34 
35 	return 0;
36 }
37 
38 SEC("?tc")
39 int kfunc_call_test_get_mem_fail_rdonly(struct __sk_buff *skb)
40 {
41 	struct prog_test_ref_kfunc *pt;
42 	unsigned long s = 0;
43 	int *p = NULL;
44 	int ret = 0;
45 
46 	pt = bpf_kfunc_call_test_acquire(&s);
47 	if (pt) {
48 		p = bpf_kfunc_call_test_get_rdonly_mem(pt, 2 * sizeof(int));
49 		if (p)
50 			p[0] = 42; /* this is a read-only buffer, so -EACCES */
51 		else
52 			ret = -1;
53 
54 		bpf_kfunc_call_test_release(pt);
55 	}
56 	return ret;
57 }
58 
59 SEC("?tc")
60 int kfunc_call_test_get_mem_fail_use_after_free(struct __sk_buff *skb)
61 {
62 	struct prog_test_ref_kfunc *pt;
63 	unsigned long s = 0;
64 	int *p = NULL;
65 	int ret = 0;
66 
67 	pt = bpf_kfunc_call_test_acquire(&s);
68 	if (pt) {
69 		p = bpf_kfunc_call_test_get_rdwr_mem(pt, 2 * sizeof(int));
70 		if (p) {
71 			p[0] = 42;
72 			ret = p[1]; /* 108 */
73 		} else {
74 			ret = -1;
75 		}
76 
77 		bpf_kfunc_call_test_release(pt);
78 	}
79 	if (p)
80 		ret = p[0]; /* p is not valid anymore */
81 
82 	return ret;
83 }
84 
85 SEC("?tc")
86 int kfunc_call_test_get_mem_fail_oob(struct __sk_buff *skb)
87 {
88 	struct prog_test_ref_kfunc *pt;
89 	unsigned long s = 0;
90 	int *p = NULL;
91 	int ret = 0;
92 
93 	pt = bpf_kfunc_call_test_acquire(&s);
94 	if (pt) {
95 		p = bpf_kfunc_call_test_get_rdonly_mem(pt, 2 * sizeof(int));
96 		if (p)
97 			ret = p[2 * sizeof(int)]; /* oob access, so -EACCES */
98 		else
99 			ret = -1;
100 
101 		bpf_kfunc_call_test_release(pt);
102 	}
103 	return ret;
104 }
105 
106 int not_const_size = 2 * sizeof(int);
107 
108 SEC("?tc")
109 int kfunc_call_test_get_mem_fail_not_const(struct __sk_buff *skb)
110 {
111 	struct prog_test_ref_kfunc *pt;
112 	unsigned long s = 0;
113 	int *p = NULL;
114 	int ret = 0;
115 
116 	pt = bpf_kfunc_call_test_acquire(&s);
117 	if (pt) {
118 		p = bpf_kfunc_call_test_get_rdonly_mem(pt, not_const_size); /* non const size, -EINVAL */
119 		if (p)
120 			ret = p[0];
121 		else
122 			ret = -1;
123 
124 		bpf_kfunc_call_test_release(pt);
125 	}
126 	return ret;
127 }
128 
129 SEC("?tc")
130 int kfunc_call_test_mem_acquire_fail(struct __sk_buff *skb)
131 {
132 	struct prog_test_ref_kfunc *pt;
133 	unsigned long s = 0;
134 	int *p = NULL;
135 	int ret = 0;
136 
137 	pt = bpf_kfunc_call_test_acquire(&s);
138 	if (pt) {
139 		/* we are failing on this one, because we are not acquiring a PTR_TO_BTF_ID (a struct ptr) */
140 		p = bpf_kfunc_call_test_acq_rdonly_mem(pt, 2 * sizeof(int));
141 		if (p)
142 			ret = p[0];
143 		else
144 			ret = -1;
145 
146 		bpf_kfunc_call_int_mem_release(p);
147 
148 		bpf_kfunc_call_test_release(pt);
149 	}
150 	return ret;
151 }
152 
153 char _license[] SEC("license") = "GPL";
154