mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

The selftests build four kernel modules which use copy-pasted Makefile targets. This is a bit messy, and doesn't scale so well when we add more modules, so let's consolidate these rules into a single rule generated for each module name, and move the module sources into a single directory. To avoid parallel builds of the different modules stepping on each other's toes during the 'modpost' phase of the Kbuild 'make modules', the module files should really be a grouped target. However, make only added explicit support for grouped targets in version 4.3, which is newer than the minimum version supported by the kernel. However, make implicitly treats pattern matching rules with multiple targets as a grouped target, so we can work around this by turning the rule into a pattern matching target. We do this by replacing '.ko' with '%ko' in the targets with subst(). Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Acked-by: Viktor Malik <vmalik@redhat.com> Link: https://lore.kernel.org/bpf/20241204-bpf-selftests-mod-compile-v5-1-b96231134a49@redhat.com
160 lines
3.1 KiB
C
160 lines
3.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Copyright (c) 2021 Facebook */
|
|
#include <vmlinux.h>
|
|
#include <bpf/bpf_helpers.h>
|
|
#include "../test_kmods/bpf_testmod_kfunc.h"
|
|
|
|
struct syscall_test_args {
|
|
__u8 data[16];
|
|
size_t size;
|
|
};
|
|
|
|
SEC("?syscall")
|
|
int kfunc_syscall_test_fail(struct syscall_test_args *args)
|
|
{
|
|
bpf_kfunc_call_test_mem_len_pass1(&args->data, sizeof(*args) + 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("?syscall")
|
|
int kfunc_syscall_test_null_fail(struct syscall_test_args *args)
|
|
{
|
|
/* Must be called with args as a NULL pointer
|
|
* we do not check for it to have the verifier consider that
|
|
* the pointer might not be null, and so we can load it.
|
|
*
|
|
* So the following can not be added:
|
|
*
|
|
* if (args)
|
|
* return -22;
|
|
*/
|
|
|
|
bpf_kfunc_call_test_mem_len_pass1(args, sizeof(*args));
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC("?tc")
|
|
int kfunc_call_test_get_mem_fail_rdonly(struct __sk_buff *skb)
|
|
{
|
|
struct prog_test_ref_kfunc *pt;
|
|
unsigned long s = 0;
|
|
int *p = NULL;
|
|
int ret = 0;
|
|
|
|
pt = bpf_kfunc_call_test_acquire(&s);
|
|
if (pt) {
|
|
p = bpf_kfunc_call_test_get_rdonly_mem(pt, 2 * sizeof(int));
|
|
if (p)
|
|
p[0] = 42; /* this is a read-only buffer, so -EACCES */
|
|
else
|
|
ret = -1;
|
|
|
|
bpf_kfunc_call_test_release(pt);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
SEC("?tc")
|
|
int kfunc_call_test_get_mem_fail_use_after_free(struct __sk_buff *skb)
|
|
{
|
|
struct prog_test_ref_kfunc *pt;
|
|
unsigned long s = 0;
|
|
int *p = NULL;
|
|
int ret = 0;
|
|
|
|
pt = bpf_kfunc_call_test_acquire(&s);
|
|
if (pt) {
|
|
p = bpf_kfunc_call_test_get_rdwr_mem(pt, 2 * sizeof(int));
|
|
if (p) {
|
|
p[0] = 42;
|
|
ret = p[1]; /* 108 */
|
|
} else {
|
|
ret = -1;
|
|
}
|
|
|
|
bpf_kfunc_call_test_release(pt);
|
|
}
|
|
if (p)
|
|
ret = p[0]; /* p is not valid anymore */
|
|
|
|
return ret;
|
|
}
|
|
|
|
SEC("?tc")
|
|
int kfunc_call_test_get_mem_fail_oob(struct __sk_buff *skb)
|
|
{
|
|
struct prog_test_ref_kfunc *pt;
|
|
unsigned long s = 0;
|
|
int *p = NULL;
|
|
int ret = 0;
|
|
|
|
pt = bpf_kfunc_call_test_acquire(&s);
|
|
if (pt) {
|
|
p = bpf_kfunc_call_test_get_rdonly_mem(pt, 2 * sizeof(int));
|
|
if (p)
|
|
ret = p[2 * sizeof(int)]; /* oob access, so -EACCES */
|
|
else
|
|
ret = -1;
|
|
|
|
bpf_kfunc_call_test_release(pt);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int not_const_size = 2 * sizeof(int);
|
|
|
|
SEC("?tc")
|
|
int kfunc_call_test_get_mem_fail_not_const(struct __sk_buff *skb)
|
|
{
|
|
struct prog_test_ref_kfunc *pt;
|
|
unsigned long s = 0;
|
|
int *p = NULL;
|
|
int ret = 0;
|
|
|
|
pt = bpf_kfunc_call_test_acquire(&s);
|
|
if (pt) {
|
|
p = bpf_kfunc_call_test_get_rdonly_mem(pt, not_const_size); /* non const size, -EINVAL */
|
|
if (p)
|
|
ret = p[0];
|
|
else
|
|
ret = -1;
|
|
|
|
bpf_kfunc_call_test_release(pt);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
SEC("?tc")
|
|
int kfunc_call_test_mem_acquire_fail(struct __sk_buff *skb)
|
|
{
|
|
struct prog_test_ref_kfunc *pt;
|
|
unsigned long s = 0;
|
|
int *p = NULL;
|
|
int ret = 0;
|
|
|
|
pt = bpf_kfunc_call_test_acquire(&s);
|
|
if (pt) {
|
|
/* we are failing on this one, because we are not acquiring a PTR_TO_BTF_ID (a struct ptr) */
|
|
p = bpf_kfunc_call_test_acq_rdonly_mem(pt, 2 * sizeof(int));
|
|
if (p)
|
|
ret = p[0];
|
|
else
|
|
ret = -1;
|
|
|
|
bpf_kfunc_call_int_mem_release(p);
|
|
|
|
bpf_kfunc_call_test_release(pt);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
SEC("?tc")
|
|
int kfunc_call_test_pointer_arg_type_mismatch(struct __sk_buff *skb)
|
|
{
|
|
bpf_kfunc_call_test_pass_ctx((void *)10);
|
|
return 0;
|
|
}
|
|
|
|
char _license[] SEC("license") = "GPL";
|