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
7struct syscall_test_args {
8	__u8 data[16];
9	size_t size;
10};
11
12SEC("?syscall")
13int 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
20SEC("?syscall")
21int 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
38SEC("?tc")
39int 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
59SEC("?tc")
60int 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
85SEC("?tc")
86int 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
106int not_const_size = 2 * sizeof(int);
107
108SEC("?tc")
109int 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
129SEC("?tc")
130int 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
153char _license[] SEC("license") = "GPL";
154