mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 14:53:58 -04:00
Add a selftest to verify that the verifier correctly identifies refcounted arguments in struct_ops programs, even when they are not the first argument. This ensures that the restriction on tail calls for programs with __ref arguments is properly enforced regardless of which argument they appear in. This test verifies the fix for check_struct_ops_btf_id() proposed by Keisuke Nishimura [0], which corrected a bug where only the first argument was checked for the refcounted flag. The test includes: - An update to bpf_testmod to add 'test_refcounted_multi', an operator with three arguments where the third is tagged with "__ref". - A BPF program 'test_refcounted_multi' that attempts a tail call. - A test runner that asserts the verifier rejects the program with "program with __ref argument cannot tail call". [0]: https://lore.kernel.org/bpf/20260320130219.63711-1-keisuke.nishimura@inria.fr/ Signed-off-by: Varun R Mallya <varunrmallya@gmail.com> Link: https://lore.kernel.org/r/20260321214038.80479-1-varunrmallya@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
36 lines
953 B
C
36 lines
953 B
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Copyright (c) 2026 Varun R Mallya */
|
|
|
|
#include <vmlinux.h>
|
|
#include <bpf/bpf_helpers.h>
|
|
#include <bpf/bpf_tracing.h>
|
|
#include "../test_kmods/bpf_testmod.h"
|
|
#include "bpf_misc.h"
|
|
|
|
char _license[] SEC("license") = "GPL";
|
|
|
|
struct {
|
|
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
|
|
__uint(max_entries, 1);
|
|
__uint(key_size, sizeof(__u32));
|
|
__uint(value_size, sizeof(__u32));
|
|
} prog_array SEC(".maps");
|
|
|
|
SEC("struct_ops/test_refcounted_multi")
|
|
__failure __msg("program with __ref argument cannot tail call")
|
|
int test_refcounted_multi(unsigned long long *ctx)
|
|
{
|
|
/* ctx[2] is used because the refcounted variable is the third argument */
|
|
struct task_struct *refcounted_task = (struct task_struct *)ctx[2];
|
|
|
|
bpf_task_release(refcounted_task);
|
|
bpf_tail_call(ctx, &prog_array, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
SEC(".struct_ops.link")
|
|
struct bpf_testmod_ops testmod_ref_acquire = {
|
|
.test_refcounted_multi = (void *)test_refcounted_multi,
|
|
};
|