mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 13:23:02 -04:00
Merge branch 'generate-bpf_func_proto-for-kfunc'
Amery Hung says: ==================== Generate bpf_func_proto for kfunc Hi, This is the second of three patch sets to unify kfunc and helper argument verification. It: 1) further aligns the kfunc and helper argument checks, 2) makes kfunc argument type classification depend solely on BTF, and 3) generates a bpf_func_proto for each kfunc. With classification now a pure function of the kfunc's BTF, it is computed once at add-call time and cached in the generated bpf_func_proto, rather than re-derived on every verification of the call. Along the way it also fixes a few issues. The next patch set will align the argument register compatibility checks and route helper and kfunc argument verification through a single shared function. [1/3] https://lore.kernel.org/bpf/20260715064047.1793790-1-ameryhung@gmail.com/ Changelog v2 -> v3: - Drop a patch that introduces SCALAR_MAYBE_ZERO (Eduard) - Drop patch make helper handle mem+size at mem arg, and instead make kfunc also handle mem+size at size - patch 5: New patch replacing temporary mark_ptr_not_null_reg hack with refine_ptr_not_null_reg (Eduard) - patch 8: Only allow global subprog to read poisoned stack slots (Eduard) - patch 11: Test a precision gap when passing NULL to nullable-mem + size arg (Eduard) - patch 15: Reorganize BTF_ID, MEM, MEM+SIZE classification for clarity (Eduard) - patch 18: Emded bpf_func_proto in bpf_kfunc_desc and dynamically resize bpf_kfunc_desc_tab; Record saved_dst_prog_type early in bpf_prog_load to avoid introducing a fallback logic in resolve_prog_type (Eduard) Link: https://lore.kernel.org/bpf/20260724190813.1458271-1-ameryhung@gmail.com/ v1 -> v2: - patch 2: use reg_arg_name() for the map-mismatch message; derive the object register correctly on both helper and kfunc paths - patch 3: reject non-CONST_PTR_TO_MAP regs (base_type check) to fix map-value type confusion - patch 15: also reject referenced regs with unsafe modifiers (e.g. MEM_PERCPU) - patch 17: reject non-SCALAR_VALUE for KF_ARG_MEM_SIZE ==================== Link: https://patch.msgid.link/20260801074633.1595644-1-ameryhung@gmail.com Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
This commit is contained in:
@@ -250,6 +250,34 @@ Or::
|
||||
...
|
||||
}
|
||||
|
||||
2.3.7 __const_map and __map Annotations
|
||||
---------------------------------------
|
||||
|
||||
These annotations are used for ``struct bpf_map *`` arguments and distinguish a
|
||||
verifier-known map from an opaque one.
|
||||
|
||||
``__const_map`` indicates a map must be known at the verification time, i.e. a
|
||||
concrete map fd the BPF program references directly.
|
||||
|
||||
An example is given below::
|
||||
|
||||
__bpf_kfunc int bpf_wq_init(struct bpf_wq *wq, void *p__const_map,
|
||||
unsigned int flags)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
``__map`` indicates an opaque ``struct bpf_map *`` that may be resolved
|
||||
at run time. The argument may take either a map fd or a ``PTR_TO_BTF_ID``
|
||||
``struct bpf_map`` pointer.
|
||||
|
||||
An example is given below::
|
||||
|
||||
__bpf_kfunc void *bpf_arena_alloc_pages(void *p__map, ...)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
.. _BPF_kfunc_nodef:
|
||||
|
||||
2.4 Using an existing kernel function
|
||||
@@ -411,7 +439,7 @@ Example declaration:
|
||||
.. code-block:: c
|
||||
|
||||
__bpf_kfunc int bpf_task_work_schedule_signal(struct task_struct *task, struct bpf_task_work *tw,
|
||||
void *map__map, bpf_task_work_callback_t callback,
|
||||
void *map__const_map, bpf_task_work_callback_t callback,
|
||||
struct bpf_prog_aux *aux) { ... }
|
||||
|
||||
Example usage in BPF program:
|
||||
|
||||
@@ -888,8 +888,8 @@ enum bpf_arg_type {
|
||||
ARG_PTR_TO_MEM, /* pointer to valid memory (stack, packet, map value) */
|
||||
ARG_PTR_TO_ARENA,
|
||||
|
||||
ARG_CONST_SIZE, /* number of bytes accessed from memory */
|
||||
ARG_CONST_SIZE_OR_ZERO, /* number of bytes accessed from memory or 0 */
|
||||
ARG_MEM_SIZE, /* number of bytes accessed from memory */
|
||||
ARG_MEM_SIZE_OR_ZERO, /* number of bytes accessed from memory or 0 */
|
||||
|
||||
ARG_PTR_TO_CTX, /* pointer to context */
|
||||
ARG_ANYTHING, /* any (initialized) argument is ok */
|
||||
@@ -960,6 +960,21 @@ enum bpf_return_type {
|
||||
};
|
||||
static_assert(__BPF_RET_TYPE_MAX <= BPF_BASE_TYPE_LIMIT);
|
||||
|
||||
/* The longest tracepoint has 12 args.
|
||||
* See include/trace/bpf_probe.h
|
||||
*
|
||||
* Also reuse this macro for maximum number of arguments a BPF function
|
||||
* or a kfunc can have. Args 1-5 are passed in registers, args 6-12 via
|
||||
* stack arg slots. The JIT may map some stack arg slots to registers based
|
||||
* on the native calling convention (e.g., arg 6 to R9 on x86-64).
|
||||
*/
|
||||
#define MAX_BPF_FUNC_ARGS 12
|
||||
|
||||
/* The maximum number of arguments passed through registers
|
||||
* a single function may have.
|
||||
*/
|
||||
#define MAX_BPF_FUNC_REG_ARGS 5
|
||||
|
||||
/* eBPF function prototype used by verifier to allow BPF_CALLs from eBPF programs
|
||||
* to in-kernel helper functions and for adjusting imm32 field in BPF_CALL
|
||||
* instructions after verifying
|
||||
@@ -984,7 +999,7 @@ struct bpf_func_proto {
|
||||
enum bpf_arg_type arg4_type;
|
||||
enum bpf_arg_type arg5_type;
|
||||
};
|
||||
enum bpf_arg_type arg_type[5];
|
||||
enum bpf_arg_type arg_type[MAX_BPF_FUNC_ARGS];
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
@@ -994,7 +1009,7 @@ struct bpf_func_proto {
|
||||
u32 *arg4_btf_id;
|
||||
u32 *arg5_btf_id;
|
||||
};
|
||||
u32 *arg_btf_id[5];
|
||||
u32 *arg_btf_id[MAX_BPF_FUNC_ARGS];
|
||||
struct {
|
||||
size_t arg1_size;
|
||||
size_t arg2_size;
|
||||
@@ -1002,7 +1017,7 @@ struct bpf_func_proto {
|
||||
size_t arg4_size;
|
||||
size_t arg5_size;
|
||||
};
|
||||
size_t arg_size[5];
|
||||
size_t arg_size[MAX_BPF_FUNC_ARGS];
|
||||
};
|
||||
int *ret_btf_id; /* return value btf_id */
|
||||
bool (*allowed)(const struct bpf_prog *prog);
|
||||
@@ -1192,21 +1207,6 @@ struct bpf_prog_offload {
|
||||
u32 jited_len;
|
||||
};
|
||||
|
||||
/* The longest tracepoint has 12 args.
|
||||
* See include/trace/bpf_probe.h
|
||||
*
|
||||
* Also reuse this macro for maximum number of arguments a BPF function
|
||||
* or a kfunc can have. Args 1-5 are passed in registers, args 6-12 via
|
||||
* stack arg slots. The JIT may map some stack arg slots to registers based
|
||||
* on the native calling convention (e.g., arg 6 to R9 on x86-64).
|
||||
*/
|
||||
#define MAX_BPF_FUNC_ARGS 12
|
||||
|
||||
/* The maximum number of arguments passed through registers
|
||||
* a single function may have.
|
||||
*/
|
||||
#define MAX_BPF_FUNC_REG_ARGS 5
|
||||
|
||||
/* The argument is a structure or a union. */
|
||||
#define BTF_FMODEL_STRUCT_ARG BIT(0)
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* ensures that umax_value + (int)off + (int)size cannot overflow a u64.
|
||||
*/
|
||||
#define BPF_MAX_VAR_OFF (1 << 29)
|
||||
/* Maximum variable size permitted for ARG_CONST_SIZE[_OR_ZERO]. This ensures
|
||||
/* Maximum variable size permitted for ARG_MEM_SIZE[_OR_ZERO]. This ensures
|
||||
* that converting umax_value to int cannot overflow.
|
||||
*/
|
||||
#define BPF_MAX_VAR_SIZ (1 << 29)
|
||||
@@ -1302,7 +1302,6 @@ static inline u32 type_flag(u32 type)
|
||||
return type & ~BPF_BASE_TYPE_MASK;
|
||||
}
|
||||
|
||||
/* only use after check_attach_btf_id() */
|
||||
static inline enum bpf_prog_type resolve_prog_type(const struct bpf_prog *prog)
|
||||
{
|
||||
return (prog->type == BPF_PROG_TYPE_EXT && prog->aux->saved_dst_prog_type) ?
|
||||
@@ -1479,10 +1478,17 @@ struct ret_mem_desc {
|
||||
bool found;
|
||||
};
|
||||
|
||||
/* A constant scalar argument; Populated by process_const_arg() */
|
||||
struct arg_constant_desc {
|
||||
u64 value;
|
||||
bool found;
|
||||
};
|
||||
|
||||
struct bpf_call_arg_meta {
|
||||
/* Common */
|
||||
struct btf *btf;
|
||||
u32 func_id;
|
||||
const struct bpf_func_proto *fn;
|
||||
u8 release_regno;
|
||||
u32 ret_btf_id;
|
||||
u32 subprogno;
|
||||
@@ -1496,10 +1502,7 @@ struct bpf_call_arg_meta {
|
||||
u32 kfunc_flags;
|
||||
const struct btf_type *func_proto;
|
||||
const char *func_name;
|
||||
struct {
|
||||
u64 value;
|
||||
bool found;
|
||||
} arg_constant;
|
||||
struct arg_constant_desc arg_constant;
|
||||
|
||||
/* arg_{btf,btf_id,owning_ref} are used by kfunc-specific handling,
|
||||
* generally to pass info about user-defined local kptr types to later
|
||||
@@ -1614,6 +1617,7 @@ enum bpf_reg_arg_type {
|
||||
|
||||
struct bpf_kfunc_desc {
|
||||
struct btf_func_model func_model;
|
||||
struct bpf_func_proto proto;
|
||||
u32 func_id;
|
||||
s32 imm;
|
||||
u16 offset;
|
||||
@@ -1621,13 +1625,15 @@ struct bpf_kfunc_desc {
|
||||
};
|
||||
|
||||
struct bpf_kfunc_desc_tab {
|
||||
u32 nr_descs;
|
||||
/* Sorted by func_id (BTF ID) and offset (fd_array offset) during
|
||||
* verification. JITs do lookups by bpf_insn, where func_id may not be
|
||||
* available, therefore at the end of verification do_misc_fixups()
|
||||
* sorts this by imm and offset.
|
||||
*
|
||||
* Grown one entry at a time by bpf_add_kfunc_call().
|
||||
*/
|
||||
struct bpf_kfunc_desc descs[MAX_KFUNC_DESCS];
|
||||
u32 nr_descs;
|
||||
struct bpf_kfunc_desc descs[];
|
||||
};
|
||||
|
||||
/* Functions exported from verifier.c, used by fixups.c */
|
||||
|
||||
@@ -636,7 +636,7 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
|
||||
* r5 += 1
|
||||
* ...
|
||||
* call bpf_perf_event_output#25
|
||||
* where .arg5_type = ARG_CONST_SIZE_OR_ZERO
|
||||
* where .arg5_type = ARG_MEM_SIZE_OR_ZERO
|
||||
*
|
||||
* and this case:
|
||||
* r6 = 1
|
||||
|
||||
@@ -186,7 +186,7 @@ static const struct bpf_func_proto bpf_ima_inode_hash_proto = {
|
||||
.arg1_type = ARG_PTR_TO_BTF_ID,
|
||||
.arg1_btf_id = &bpf_ima_inode_hash_btf_ids[0],
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
.allowed = bpf_ima_inode_hash_allowed,
|
||||
};
|
||||
|
||||
@@ -205,7 +205,7 @@ static const struct bpf_func_proto bpf_ima_file_hash_proto = {
|
||||
.arg1_type = ARG_PTR_TO_BTF_ID,
|
||||
.arg1_btf_id = &bpf_ima_file_hash_btf_ids[0],
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
.allowed = bpf_ima_inode_hash_allowed,
|
||||
};
|
||||
|
||||
|
||||
@@ -8709,7 +8709,7 @@ const struct bpf_func_proto bpf_btf_find_by_name_kind_proto = {
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg2_type = ARG_CONST_SIZE,
|
||||
.arg2_type = ARG_MEM_SIZE,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -2305,7 +2305,7 @@ static const struct bpf_func_proto bpf_sysctl_get_name_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_WRITE,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -2347,7 +2347,7 @@ static const struct bpf_func_proto bpf_sysctl_get_current_value_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_3(bpf_sysctl_get_new_value, struct bpf_sysctl_kern *, ctx, char *, buf,
|
||||
@@ -2367,7 +2367,7 @@ static const struct bpf_func_proto bpf_sysctl_get_new_value_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_3(bpf_sysctl_set_new_value, struct bpf_sysctl_kern *, ctx,
|
||||
@@ -2393,7 +2393,7 @@ static const struct bpf_func_proto bpf_sysctl_set_new_value_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
static const struct bpf_func_proto *
|
||||
|
||||
@@ -278,7 +278,7 @@ const struct bpf_func_proto bpf_get_current_comm_proto = {
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg2_type = ARG_CONST_SIZE,
|
||||
.arg2_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_QUEUED_SPINLOCKS) || defined(CONFIG_BPF_ARCH_SPINLOCK)
|
||||
@@ -539,7 +539,7 @@ const struct bpf_func_proto bpf_strtol_proto = {
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg2_type = ARG_CONST_SIZE,
|
||||
.arg2_type = ARG_MEM_SIZE,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED,
|
||||
.arg4_size = sizeof(s64),
|
||||
@@ -567,7 +567,7 @@ const struct bpf_func_proto bpf_strtoul_proto = {
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg2_type = ARG_CONST_SIZE,
|
||||
.arg2_type = ARG_MEM_SIZE,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED,
|
||||
.arg4_size = sizeof(u64),
|
||||
@@ -583,7 +583,7 @@ static const struct bpf_func_proto bpf_strncmp_proto = {
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg2_type = ARG_CONST_SIZE,
|
||||
.arg2_type = ARG_MEM_SIZE,
|
||||
.arg3_type = ARG_PTR_TO_CONST_STR,
|
||||
};
|
||||
|
||||
@@ -627,7 +627,7 @@ const struct bpf_func_proto bpf_get_ns_current_pid_tgid_proto = {
|
||||
.arg1_type = ARG_ANYTHING,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
static const struct bpf_func_proto bpf_get_raw_smp_processor_id_proto = {
|
||||
@@ -653,7 +653,7 @@ const struct bpf_func_proto bpf_event_output_data_proto = {
|
||||
.arg2_type = ARG_CONST_MAP_PTR,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg5_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
BPF_CALL_3(bpf_copy_from_user, void *, dst, u32, size,
|
||||
@@ -675,7 +675,7 @@ const struct bpf_func_proto bpf_copy_from_user_proto = {
|
||||
.might_sleep = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -706,7 +706,7 @@ const struct bpf_func_proto bpf_copy_from_user_task_proto = {
|
||||
.might_sleep = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_BTF_ID,
|
||||
.arg4_btf_id = &btf_tracing_ids[BTF_TRACING_TYPE_TASK],
|
||||
@@ -1093,10 +1093,10 @@ const struct bpf_func_proto bpf_snprintf_proto = {
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_MEM_OR_NULL | MEM_WRITE,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_PTR_TO_CONST_STR,
|
||||
.arg4_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg5_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
static void *map_key_from_value(struct bpf_map *map, void *value, u32 *arr_idx)
|
||||
@@ -1888,7 +1888,7 @@ static const struct bpf_func_proto bpf_dynptr_from_mem_proto = {
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL | MEM_UNINIT | MEM_WRITE,
|
||||
};
|
||||
@@ -1943,7 +1943,7 @@ static const struct bpf_func_proto bpf_dynptr_read_proto = {
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_PTR_TO_DYNPTR,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
@@ -2004,7 +2004,7 @@ static const struct bpf_func_proto bpf_dynptr_write_proto = {
|
||||
.arg1_type = ARG_PTR_TO_DYNPTR,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg4_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -3404,10 +3404,10 @@ __bpf_kfunc void bpf_throw(u64 cookie)
|
||||
WARN(1, "A call to BPF exception callback should never return\n");
|
||||
}
|
||||
|
||||
__bpf_kfunc int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags)
|
||||
__bpf_kfunc int bpf_wq_init(struct bpf_wq *wq, void *p__const_map, unsigned int flags)
|
||||
{
|
||||
struct bpf_async_kern *async = (struct bpf_async_kern *)wq;
|
||||
struct bpf_map *map = p__map;
|
||||
struct bpf_map *map = p__const_map;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct bpf_async_kern) > sizeof(struct bpf_wq));
|
||||
BUILD_BUG_ON(__alignof__(struct bpf_async_kern) != __alignof__(struct bpf_wq));
|
||||
@@ -4643,17 +4643,17 @@ static int bpf_task_work_schedule(struct task_struct *task, struct bpf_task_work
|
||||
* mode
|
||||
* @task: Task struct for which callback should be scheduled
|
||||
* @tw: Pointer to struct bpf_task_work in BPF map value for internal bookkeeping
|
||||
* @map__map: bpf_map that embeds struct bpf_task_work in the values
|
||||
* @map__const_map: bpf_map that embeds struct bpf_task_work in the values
|
||||
* @callback: pointer to BPF subprogram to call
|
||||
* @aux: pointer to bpf_prog_aux of the caller BPF program, implicitly set by the verifier
|
||||
*
|
||||
* Return: 0 if task work has been scheduled successfully, negative error code otherwise
|
||||
*/
|
||||
__bpf_kfunc int bpf_task_work_schedule_signal(struct task_struct *task, struct bpf_task_work *tw,
|
||||
void *map__map, bpf_task_work_callback_t callback,
|
||||
void *map__const_map, bpf_task_work_callback_t callback,
|
||||
struct bpf_prog_aux *aux)
|
||||
{
|
||||
return bpf_task_work_schedule(task, tw, map__map, callback, aux, TWA_SIGNAL);
|
||||
return bpf_task_work_schedule(task, tw, map__const_map, callback, aux, TWA_SIGNAL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4661,17 +4661,17 @@ __bpf_kfunc int bpf_task_work_schedule_signal(struct task_struct *task, struct b
|
||||
* mode
|
||||
* @task: Task struct for which callback should be scheduled
|
||||
* @tw: Pointer to struct bpf_task_work in BPF map value for internal bookkeeping
|
||||
* @map__map: bpf_map that embeds struct bpf_task_work in the values
|
||||
* @map__const_map: bpf_map that embeds struct bpf_task_work in the values
|
||||
* @callback: pointer to BPF subprogram to call
|
||||
* @aux: pointer to bpf_prog_aux of the caller BPF program, implicitly set by the verifier
|
||||
*
|
||||
* Return: 0 if task work has been scheduled successfully, negative error code otherwise
|
||||
*/
|
||||
__bpf_kfunc int bpf_task_work_schedule_resume(struct task_struct *task, struct bpf_task_work *tw,
|
||||
void *map__map, bpf_task_work_callback_t callback,
|
||||
void *map__const_map, bpf_task_work_callback_t callback,
|
||||
struct bpf_prog_aux *aux)
|
||||
{
|
||||
return bpf_task_work_schedule(task, tw, map__map, callback, aux, TWA_RESUME);
|
||||
return bpf_task_work_schedule(task, tw, map__const_map, callback, aux, TWA_RESUME);
|
||||
}
|
||||
|
||||
static int make_file_dynptr(struct file *file, u32 flags, bool may_sleep,
|
||||
|
||||
@@ -634,7 +634,7 @@ const struct bpf_func_proto bpf_ringbuf_output_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_CONST_MAP_PTR,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
|
||||
@@ -781,7 +781,7 @@ const struct bpf_func_proto bpf_get_stack_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -797,7 +797,7 @@ const struct bpf_func_proto bpf_get_stack_sleepable_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -831,7 +831,7 @@ const struct bpf_func_proto bpf_get_task_stack_proto = {
|
||||
.arg1_type = ARG_PTR_TO_BTF_ID,
|
||||
.arg1_btf_id = &btf_tracing_ids[BTF_TRACING_TYPE_TASK],
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -848,7 +848,7 @@ const struct bpf_func_proto bpf_get_task_stack_sleepable_proto = {
|
||||
.arg1_type = ARG_PTR_TO_BTF_ID,
|
||||
.arg1_btf_id = &btf_tracing_ids[BTF_TRACING_TYPE_TASK],
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -911,7 +911,7 @@ const struct bpf_func_proto bpf_get_stack_proto_pe = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
|
||||
@@ -3043,6 +3043,10 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, struct bpf_log_at
|
||||
prog->aux->attach_btf = attach_btf;
|
||||
prog->aux->attach_btf_id = multi_func ? bpf_multi_func_btf_id[0] : attr->attach_btf_id;
|
||||
prog->aux->dst_prog = dst_prog;
|
||||
if (dst_prog) {
|
||||
prog->aux->saved_dst_prog_type = dst_prog->type;
|
||||
prog->aux->saved_dst_attach_type = dst_prog->expected_attach_type;
|
||||
}
|
||||
prog->aux->dev_bound = !!attr->prog_ifindex;
|
||||
prog->aux->xdp_has_frags = attr->prog_flags & BPF_F_XDP_HAS_FRAGS;
|
||||
|
||||
@@ -6559,7 +6563,7 @@ static const struct bpf_func_proto bpf_sys_bpf_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_ANYTHING,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
const struct bpf_func_proto * __weak
|
||||
@@ -6606,7 +6610,7 @@ static const struct bpf_func_proto bpf_kallsyms_lookup_name_proto = {
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED,
|
||||
.arg4_size = sizeof(u64),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -221,7 +221,7 @@ const struct bpf_func_proto bpf_probe_read_user_proto = {
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -258,7 +258,7 @@ const struct bpf_func_proto bpf_probe_read_user_str_proto = {
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -273,7 +273,7 @@ const struct bpf_func_proto bpf_probe_read_kernel_proto = {
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -308,7 +308,7 @@ const struct bpf_func_proto bpf_probe_read_kernel_str_proto = {
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -328,7 +328,7 @@ static const struct bpf_func_proto bpf_probe_read_compat_proto = {
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -347,7 +347,7 @@ static const struct bpf_func_proto bpf_probe_read_compat_str_proto = {
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
};
|
||||
#endif /* CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE */
|
||||
@@ -383,7 +383,7 @@ static const struct bpf_func_proto bpf_probe_write_user_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_ANYTHING,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
#define MAX_TRACE_PRINTK_VARARGS 3
|
||||
@@ -418,7 +418,7 @@ static const struct bpf_func_proto bpf_trace_printk_proto = {
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg2_type = ARG_CONST_SIZE,
|
||||
.arg2_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
static void __set_printk_clr_event(struct work_struct *work)
|
||||
@@ -474,9 +474,9 @@ static const struct bpf_func_proto bpf_trace_vprintk_proto = {
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg2_type = ARG_CONST_SIZE,
|
||||
.arg2_type = ARG_MEM_SIZE,
|
||||
.arg3_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
|
||||
.arg4_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
const struct bpf_func_proto *bpf_get_trace_vprintk_proto(void)
|
||||
@@ -518,9 +518,9 @@ static const struct bpf_func_proto bpf_seq_printf_proto = {
|
||||
.arg1_type = ARG_PTR_TO_BTF_ID,
|
||||
.arg1_btf_id = &btf_seq_file_ids[0],
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
.arg4_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg5_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
BPF_CALL_3(bpf_seq_write, struct seq_file *, m, const void *, data, u32, len)
|
||||
@@ -535,7 +535,7 @@ static const struct bpf_func_proto bpf_seq_write_proto = {
|
||||
.arg1_type = ARG_PTR_TO_BTF_ID,
|
||||
.arg1_btf_id = &btf_seq_file_ids[0],
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
BPF_CALL_4(bpf_seq_printf_btf, struct seq_file *, m, struct btf_ptr *, ptr,
|
||||
@@ -559,7 +559,7 @@ static const struct bpf_func_proto bpf_seq_printf_btf_proto = {
|
||||
.arg1_type = ARG_PTR_TO_BTF_ID,
|
||||
.arg1_btf_id = &btf_seq_file_ids[0],
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -633,7 +633,7 @@ static const struct bpf_func_proto bpf_perf_event_read_value_proto = {
|
||||
.arg1_type = ARG_CONST_MAP_PTR,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
const struct bpf_func_proto *bpf_get_perf_event_read_value_proto(void)
|
||||
@@ -730,7 +730,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto = {
|
||||
.arg2_type = ARG_CONST_MAP_PTR,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg5_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(int, bpf_event_output_nest_level);
|
||||
@@ -996,7 +996,7 @@ static const struct bpf_func_proto bpf_d_path_proto = {
|
||||
.arg1_type = ARG_PTR_TO_BTF_ID,
|
||||
.arg1_btf_id = &bpf_d_path_btf_ids[0],
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_WRITE,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.allowed = bpf_d_path_allowed,
|
||||
};
|
||||
|
||||
@@ -1053,9 +1053,9 @@ const struct bpf_func_proto bpf_snprintf_btf_proto = {
|
||||
.gpl_only = false,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_MEM | MEM_WRITE,
|
||||
.arg2_type = ARG_CONST_SIZE,
|
||||
.arg2_type = ARG_MEM_SIZE,
|
||||
.arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_MEM_SIZE,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -1218,7 +1218,7 @@ const struct bpf_func_proto bpf_get_branch_snapshot_proto = {
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
BPF_CALL_3(get_func_arg, void *, ctx, u32, n, u64 *, value)
|
||||
@@ -1421,7 +1421,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto_tp = {
|
||||
.arg2_type = ARG_CONST_MAP_PTR,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg5_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
BPF_CALL_3(bpf_get_stackid_tp, void *, tp_buff, struct bpf_map *, map,
|
||||
@@ -1462,7 +1462,7 @@ static const struct bpf_func_proto bpf_get_stack_proto_tp = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -1524,12 +1524,12 @@ BPF_CALL_3(bpf_perf_prog_read_value, struct bpf_perf_event_data_kern *, ctx,
|
||||
}
|
||||
|
||||
static const struct bpf_func_proto bpf_perf_prog_read_value_proto = {
|
||||
.func = bpf_perf_prog_read_value,
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.func = bpf_perf_prog_read_value,
|
||||
.gpl_only = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_4(bpf_read_branch_records, struct bpf_perf_event_data_kern *, ctx,
|
||||
@@ -1566,7 +1566,7 @@ static const struct bpf_func_proto bpf_read_branch_records_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM_OR_NULL | MEM_WRITE,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -1646,7 +1646,7 @@ static const struct bpf_func_proto bpf_perf_event_output_proto_raw_tp = {
|
||||
.arg2_type = ARG_CONST_MAP_PTR,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg5_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
extern const struct bpf_func_proto bpf_skb_output_proto;
|
||||
@@ -1701,7 +1701,7 @@ static const struct bpf_func_proto bpf_get_stack_proto_raw_tp = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
|
||||
@@ -1747,7 +1747,7 @@ static const struct bpf_func_proto bpf_skb_store_bytes_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_MEM_SIZE,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -1784,7 +1784,7 @@ static const struct bpf_func_proto bpf_skb_load_bytes_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
int __bpf_skb_load_bytes(const struct sk_buff *skb, u32 offset, void *to, u32 len)
|
||||
@@ -1823,7 +1823,7 @@ static const struct bpf_func_proto bpf_flow_dissector_load_bytes_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_skb_load_bytes_relative, const struct sk_buff *, skb,
|
||||
@@ -1867,7 +1867,7 @@ static const struct bpf_func_proto bpf_skb_load_bytes_relative_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_MEM_SIZE,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -2063,9 +2063,9 @@ static const struct bpf_func_proto bpf_csum_diff_proto = {
|
||||
.pkt_access = true,
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
|
||||
.arg2_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg2_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
|
||||
.arg4_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -2626,7 +2626,7 @@ static const struct bpf_func_proto bpf_redirect_neigh_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_ANYTHING,
|
||||
.arg2_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -4199,7 +4199,7 @@ static const struct bpf_func_proto bpf_xdp_load_bytes_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
int __bpf_xdp_load_bytes(struct xdp_buff *xdp, u32 offset, void *buf, u32 len)
|
||||
@@ -4231,7 +4231,7 @@ static const struct bpf_func_proto bpf_xdp_store_bytes_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
int __bpf_xdp_store_bytes(struct xdp_buff *xdp, u32 offset, void *buf, u32 len)
|
||||
@@ -4794,7 +4794,7 @@ static const struct bpf_func_proto bpf_skb_event_output_proto = {
|
||||
.arg2_type = ARG_CONST_MAP_PTR,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg5_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
BTF_ID_LIST_SINGLE(bpf_skb_output_btf_ids, struct, sk_buff)
|
||||
@@ -4808,7 +4808,7 @@ const struct bpf_func_proto bpf_skb_output_proto = {
|
||||
.arg2_type = ARG_CONST_MAP_PTR,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg5_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
static unsigned short bpf_tunnel_key_af(u64 flags)
|
||||
@@ -4891,7 +4891,7 @@ static const struct bpf_func_proto bpf_skb_get_tunnel_key_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -4926,7 +4926,7 @@ static const struct bpf_func_proto bpf_skb_get_tunnel_opt_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
static struct metadata_dst __percpu *md_dst;
|
||||
@@ -5008,7 +5008,7 @@ static const struct bpf_func_proto bpf_skb_set_tunnel_key_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -5036,7 +5036,7 @@ static const struct bpf_func_proto bpf_skb_set_tunnel_opt_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
static const struct bpf_func_proto *
|
||||
@@ -5208,7 +5208,7 @@ static const struct bpf_func_proto bpf_xdp_event_output_proto = {
|
||||
.arg2_type = ARG_CONST_MAP_PTR,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg5_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
BTF_ID_LIST_SINGLE(bpf_xdp_output_btf_ids, struct, xdp_buff)
|
||||
@@ -5222,7 +5222,7 @@ const struct bpf_func_proto bpf_xdp_output_proto = {
|
||||
.arg2_type = ARG_CONST_MAP_PTR,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg5_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
BPF_CALL_1(bpf_get_socket_cookie, struct sk_buff *, skb)
|
||||
@@ -5769,7 +5769,7 @@ const struct bpf_func_proto bpf_sk_setsockopt_proto = {
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_sk_getsockopt, struct sock *, sk, int, level,
|
||||
@@ -5786,7 +5786,7 @@ const struct bpf_func_proto bpf_sk_getsockopt_proto = {
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_sk_setsockopt_nodelay, struct sock *, sk, int, level,
|
||||
@@ -5810,7 +5810,7 @@ const struct bpf_func_proto bpf_sk_setsockopt_nodelay_proto = {
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_unlocked_sk_setsockopt, struct sock *, sk, int, level,
|
||||
@@ -5827,7 +5827,7 @@ const struct bpf_func_proto bpf_unlocked_sk_setsockopt_proto = {
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_unlocked_sk_getsockopt, struct sock *, sk, int, level,
|
||||
@@ -5844,7 +5844,7 @@ const struct bpf_func_proto bpf_unlocked_sk_getsockopt_proto = {
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_sock_addr_setsockopt, struct bpf_sock_addr_kern *, ctx,
|
||||
@@ -5861,7 +5861,7 @@ static const struct bpf_func_proto bpf_sock_addr_setsockopt_proto = {
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_sock_addr_getsockopt, struct bpf_sock_addr_kern *, ctx,
|
||||
@@ -5878,7 +5878,7 @@ static const struct bpf_func_proto bpf_sock_addr_getsockopt_proto = {
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
static int sk_bpf_set_get_bypass_prot_mem(struct sock *sk,
|
||||
@@ -5923,7 +5923,7 @@ static const struct bpf_func_proto bpf_sock_create_setsockopt_proto = {
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_sock_create_getsockopt, struct sock *, sk, int, level,
|
||||
@@ -5949,7 +5949,7 @@ static const struct bpf_func_proto bpf_sock_create_getsockopt_proto = {
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_sock_ops_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
|
||||
@@ -5975,7 +5975,7 @@ static const struct bpf_func_proto bpf_sock_ops_setsockopt_proto = {
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
static int bpf_sock_ops_get_syn(struct bpf_sock_ops_kern *bpf_sock,
|
||||
@@ -6085,7 +6085,7 @@ static const struct bpf_func_proto bpf_sock_ops_getsockopt_proto = {
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_ANYTHING,
|
||||
.arg4_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_2(bpf_sock_ops_cb_flags_set, struct bpf_sock_ops_kern *, bpf_sock,
|
||||
@@ -6152,7 +6152,7 @@ static const struct bpf_func_proto bpf_bind_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_XFRM
|
||||
@@ -6205,7 +6205,7 @@ static const struct bpf_func_proto bpf_skb_get_xfrm_state_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_MEM_SIZE,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
#endif
|
||||
@@ -6612,7 +6612,7 @@ static const struct bpf_func_proto bpf_xdp_fib_lookup_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_WRITE,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -6672,7 +6672,7 @@ static const struct bpf_func_proto bpf_skb_fib_lookup_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_WRITE,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -6870,7 +6870,7 @@ static const struct bpf_func_proto bpf_lwt_in_push_encap_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg4_type = ARG_CONST_SIZE
|
||||
.arg4_type = ARG_MEM_SIZE
|
||||
};
|
||||
|
||||
static const struct bpf_func_proto bpf_lwt_xmit_push_encap_proto = {
|
||||
@@ -6880,7 +6880,7 @@ static const struct bpf_func_proto bpf_lwt_xmit_push_encap_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg4_type = ARG_CONST_SIZE
|
||||
.arg4_type = ARG_MEM_SIZE
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)
|
||||
@@ -6924,7 +6924,7 @@ static const struct bpf_func_proto bpf_lwt_seg6_store_bytes_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg4_type = ARG_CONST_SIZE
|
||||
.arg4_type = ARG_MEM_SIZE
|
||||
};
|
||||
|
||||
static void bpf_update_srh_state(struct sk_buff *skb)
|
||||
@@ -7013,7 +7013,7 @@ static const struct bpf_func_proto bpf_lwt_seg6_action_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg4_type = ARG_CONST_SIZE
|
||||
.arg4_type = ARG_MEM_SIZE
|
||||
};
|
||||
|
||||
BPF_CALL_3(bpf_lwt_seg6_adjust_srh, struct sk_buff *, skb, u32, offset,
|
||||
@@ -7254,7 +7254,7 @@ static const struct bpf_func_proto bpf_skc_lookup_tcp_proto = {
|
||||
.ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
@@ -7273,7 +7273,7 @@ static const struct bpf_func_proto bpf_sk_lookup_tcp_proto = {
|
||||
.ret_type = RET_PTR_TO_SOCKET_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
@@ -7292,7 +7292,7 @@ static const struct bpf_func_proto bpf_sk_lookup_udp_proto = {
|
||||
.ret_type = RET_PTR_TO_SOCKET_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
@@ -7316,7 +7316,7 @@ static const struct bpf_func_proto bpf_tc_skc_lookup_tcp_proto = {
|
||||
.ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
@@ -7340,7 +7340,7 @@ static const struct bpf_func_proto bpf_tc_sk_lookup_tcp_proto = {
|
||||
.ret_type = RET_PTR_TO_SOCKET_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
@@ -7364,7 +7364,7 @@ static const struct bpf_func_proto bpf_tc_sk_lookup_udp_proto = {
|
||||
.ret_type = RET_PTR_TO_SOCKET_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
@@ -7402,7 +7402,7 @@ static const struct bpf_func_proto bpf_xdp_sk_lookup_udp_proto = {
|
||||
.ret_type = RET_PTR_TO_SOCKET_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
@@ -7426,7 +7426,7 @@ static const struct bpf_func_proto bpf_xdp_skc_lookup_tcp_proto = {
|
||||
.ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
@@ -7450,7 +7450,7 @@ static const struct bpf_func_proto bpf_xdp_sk_lookup_tcp_proto = {
|
||||
.ret_type = RET_PTR_TO_SOCKET_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
@@ -7470,7 +7470,7 @@ static const struct bpf_func_proto bpf_sock_addr_skc_lookup_tcp_proto = {
|
||||
.ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
@@ -7489,7 +7489,7 @@ static const struct bpf_func_proto bpf_sock_addr_sk_lookup_tcp_proto = {
|
||||
.ret_type = RET_PTR_TO_SOCKET_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
@@ -7508,7 +7508,7 @@ static const struct bpf_func_proto bpf_sock_addr_sk_lookup_udp_proto = {
|
||||
.ret_type = RET_PTR_TO_SOCKET_OR_NULL,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
@@ -7828,9 +7828,9 @@ static const struct bpf_func_proto bpf_tcp_check_syncookie_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_5(bpf_tcp_gen_syncookie, struct sock *, sk, void *, iph, u32, iph_len,
|
||||
@@ -7897,9 +7897,9 @@ static const struct bpf_func_proto bpf_tcp_gen_syncookie_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg5_type = ARG_CONST_SIZE,
|
||||
.arg5_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_3(bpf_sk_assign, struct sk_buff *, skb, struct sock *, sk, u64, flags)
|
||||
@@ -8053,7 +8053,7 @@ static const struct bpf_func_proto bpf_sock_ops_load_hdr_opt_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_WRITE,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -8131,7 +8131,7 @@ static const struct bpf_func_proto bpf_sock_ops_store_hdr_opt_proto = {
|
||||
.ret_type = RET_INTEGER,
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE,
|
||||
.arg3_type = ARG_MEM_SIZE,
|
||||
.arg4_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
@@ -8226,7 +8226,7 @@ static const struct bpf_func_proto bpf_tcp_raw_gen_syncookie_ipv4_proto = {
|
||||
.arg1_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_RDONLY,
|
||||
.arg1_size = sizeof(struct iphdr),
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
BPF_CALL_3(bpf_tcp_raw_gen_syncookie_ipv6, struct ipv6hdr *, iph,
|
||||
@@ -8258,7 +8258,7 @@ static const struct bpf_func_proto bpf_tcp_raw_gen_syncookie_ipv6_proto = {
|
||||
.arg1_type = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_RDONLY,
|
||||
.arg1_size = sizeof(struct ipv6hdr),
|
||||
.arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY,
|
||||
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
|
||||
.arg3_type = ARG_MEM_SIZE_OR_ZERO,
|
||||
};
|
||||
|
||||
BPF_CALL_2(bpf_tcp_raw_check_syncookie_ipv4, struct iphdr *, iph,
|
||||
@@ -11731,7 +11731,7 @@ static const struct bpf_func_proto sk_reuseport_load_bytes_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_MEM_SIZE,
|
||||
};
|
||||
|
||||
BPF_CALL_5(sk_reuseport_load_bytes_relative,
|
||||
@@ -11749,7 +11749,7 @@ static const struct bpf_func_proto sk_reuseport_load_bytes_relative_proto = {
|
||||
.arg1_type = ARG_PTR_TO_CTX,
|
||||
.arg2_type = ARG_ANYTHING,
|
||||
.arg3_type = ARG_PTR_TO_UNINIT_MEM,
|
||||
.arg4_type = ARG_CONST_SIZE,
|
||||
.arg4_type = ARG_MEM_SIZE,
|
||||
.arg5_type = ARG_ANYTHING,
|
||||
};
|
||||
|
||||
|
||||
@@ -61,12 +61,14 @@
|
||||
#include "verifier_loops1.skel.h"
|
||||
#include "verifier_lwt.skel.h"
|
||||
#include "verifier_map_in_map.skel.h"
|
||||
#include "verifier_map_lookup_refine.skel.h"
|
||||
#include "verifier_map_ptr.skel.h"
|
||||
#include "verifier_map_ptr_mixing.skel.h"
|
||||
#include "verifier_map_ret_val.skel.h"
|
||||
#include "verifier_masking.skel.h"
|
||||
#include "verifier_may_goto_1.skel.h"
|
||||
#include "verifier_may_goto_2.skel.h"
|
||||
#include "verifier_mem_size_reg.skel.h"
|
||||
#include "verifier_meta_access.skel.h"
|
||||
#include "verifier_movsx.skel.h"
|
||||
#include "verifier_mtu.skel.h"
|
||||
@@ -215,12 +217,14 @@ void test_verifier_liveness_exp(void) { RUN(verifier_liveness_exp); }
|
||||
void test_verifier_loops1(void) { RUN(verifier_loops1); }
|
||||
void test_verifier_lwt(void) { RUN(verifier_lwt); }
|
||||
void test_verifier_map_in_map(void) { RUN(verifier_map_in_map); }
|
||||
void test_verifier_map_lookup_refine(void) { RUN(verifier_map_lookup_refine); }
|
||||
void test_verifier_map_ptr(void) { RUN(verifier_map_ptr); }
|
||||
void test_verifier_map_ptr_mixing(void) { RUN(verifier_map_ptr_mixing); }
|
||||
void test_verifier_map_ret_val(void) { RUN(verifier_map_ret_val); }
|
||||
void test_verifier_masking(void) { RUN(verifier_masking); }
|
||||
void test_verifier_may_goto_1(void) { RUN(verifier_may_goto_1); }
|
||||
void test_verifier_may_goto_2(void) { RUN(verifier_may_goto_2); }
|
||||
void test_verifier_mem_size_reg(void) { RUN(verifier_mem_size_reg); }
|
||||
void test_verifier_meta_access(void) { RUN(verifier_meta_access); }
|
||||
void test_verifier_movsx(void) { RUN(verifier_movsx); }
|
||||
void test_verifier_mul(void) { RUN(verifier_mul); }
|
||||
|
||||
@@ -64,7 +64,7 @@ int BPF_PROG(cgrp_kfunc_acquire_no_null_check, struct cgroup *cgrp, const char *
|
||||
}
|
||||
|
||||
SEC("tp_btf/cgroup_mkdir")
|
||||
__failure __msg("R1 pointer type STRUCT cgroup must point")
|
||||
__failure __msg("R1 is fp expected STRUCT cgroup")
|
||||
int BPF_PROG(cgrp_kfunc_acquire_fp, struct cgroup *cgrp, const char *path)
|
||||
{
|
||||
struct cgroup *acquired, *stack_cgrp = (struct cgroup *)&path;
|
||||
|
||||
@@ -1589,7 +1589,7 @@ int xdp_invalid_ctx(void *ctx)
|
||||
__u32 hdr_size = sizeof(struct ethhdr);
|
||||
/* Can't pass in variable-sized len to bpf_dynptr_slice */
|
||||
SEC("?tc")
|
||||
__failure __msg("unbounded memory access")
|
||||
__failure __msg("must be a known constant")
|
||||
int dynptr_slice_var_len1(struct __sk_buff *skb)
|
||||
{
|
||||
struct bpf_dynptr ptr;
|
||||
|
||||
@@ -137,7 +137,7 @@ int helper_param_not_ok(void *ctx)
|
||||
|
||||
p = bpf_rdonly_cast(0, 0);
|
||||
/*
|
||||
* Any helper with ARG_CONST_SIZE_OR_ZERO constraint will do,
|
||||
* Any helper with ARG_MEM_SIZE_OR_ZERO constraint will do,
|
||||
* the most permissive constraint
|
||||
*/
|
||||
bpf_copy_from_user(p, 0, (void *)42);
|
||||
|
||||
@@ -50,7 +50,7 @@ int BPF_PROG(task_kfunc_acquire_untrusted, struct task_struct *task, u64 clone_f
|
||||
}
|
||||
|
||||
SEC("tp_btf/task_newtask")
|
||||
__failure __msg("R1 pointer type STRUCT task_struct must point")
|
||||
__failure __msg("R1 is fp expected STRUCT task_struct")
|
||||
int BPF_PROG(task_kfunc_acquire_fp, struct task_struct *task, u64 clone_flags)
|
||||
{
|
||||
struct task_struct *acquired, *stack_task = (struct task_struct *)&clone_flags;
|
||||
|
||||
@@ -1195,7 +1195,7 @@ l0_%=: r1 = r6; \
|
||||
r3 += -8; \
|
||||
r5 = 0; \
|
||||
/* The 4th argument of bpf_skb_store_bytes is defined as \
|
||||
* ARG_CONST_SIZE, so 0 is not allowed. The 'r4 != 0' \
|
||||
* ARG_MEM_SIZE, so 0 is not allowed. The 'r4 != 0' \
|
||||
* is providing us this exclusion of zero from initial \
|
||||
* [0, 7] range. \
|
||||
*/ \
|
||||
|
||||
@@ -85,7 +85,7 @@ __naked void stack_bitwise_and_zero_included(void)
|
||||
r2 += -64; \
|
||||
r4 = 0; \
|
||||
/* Call bpf_ringbuf_output(), it is one of a few helper functions with\
|
||||
* ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.\
|
||||
* ARG_MEM_SIZE_OR_ZERO parameter allowed in unpriv mode.\
|
||||
* For unpriv this should signal an error, because memory at &fp[-64] is\
|
||||
* not initialized. \
|
||||
*/ \
|
||||
@@ -278,7 +278,7 @@ __naked void stack_jmp_no_min_check(void)
|
||||
r2 += -64; \
|
||||
r4 = 0; \
|
||||
/* Call bpf_ringbuf_output(), it is one of a few helper functions with\
|
||||
* ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.\
|
||||
* ARG_MEM_SIZE_OR_ZERO parameter allowed in unpriv mode.\
|
||||
* For unpriv this should signal an error, because memory at &fp[-64] is\
|
||||
* not initialized. \
|
||||
*/ \
|
||||
@@ -778,7 +778,7 @@ __naked void variable_memory_8_bytes_leak(void)
|
||||
r3 += 1; \
|
||||
r4 = 0; \
|
||||
/* Call bpf_ringbuf_output(), it is one of a few helper functions with\
|
||||
* ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode.\
|
||||
* ARG_MEM_SIZE_OR_ZERO parameter allowed in unpriv mode.\
|
||||
* For unpriv this should signal an error, because memory region [1, 64]\
|
||||
* at &fp[-64] is not fully initialized. \
|
||||
*/ \
|
||||
|
||||
@@ -91,7 +91,7 @@ l0_%=: exit; \
|
||||
|
||||
/* Call a function taking a pointer and a size which doesn't allow the size to
|
||||
* be zero (i.e. bpf_trace_printk() declares the second argument to be
|
||||
* ARG_CONST_SIZE, not ARG_CONST_SIZE_OR_ZERO). We attempt to pass zero for the
|
||||
* ARG_MEM_SIZE, not ARG_MEM_SIZE_OR_ZERO). We attempt to pass zero for the
|
||||
* size and expect to fail.
|
||||
*/
|
||||
SEC("tracepoint")
|
||||
|
||||
@@ -154,7 +154,7 @@ l0_%=: r0 = 0; \
|
||||
|
||||
SEC("socket")
|
||||
__description("forgot null checking on the inner map pointer")
|
||||
__failure __msg("R1 type=map_value_or_null expected=map_ptr")
|
||||
__failure __msg("R1 type=map_ptr_or_null expected=map_ptr")
|
||||
__failure_unpriv
|
||||
__naked void on_the_inner_map_pointer(void)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <vmlinux.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include "bpf_misc.h"
|
||||
#include "bpf_kfuncs.h"
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
struct inner_map {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(max_entries, 1);
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
} inner_map SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
|
||||
__uint(max_entries, 1);
|
||||
__type(key, int);
|
||||
__array(values, struct inner_map);
|
||||
} outer_map SEC(".maps") = {
|
||||
.values = { [0] = &inner_map },
|
||||
};
|
||||
|
||||
SEC("?tc")
|
||||
__failure __msg("type=map_ptr_or_null expected=fp")
|
||||
int mapofmaps_value_as_kfunc_mem_buf(struct __sk_buff *skb)
|
||||
{
|
||||
struct bpf_dynptr dptr;
|
||||
__u32 key = 0;
|
||||
void *inner;
|
||||
char *p;
|
||||
|
||||
inner = bpf_map_lookup_elem(&outer_map, &key);
|
||||
/* intentionally NOT NULL-checked: type is map_ptr_or_null */
|
||||
|
||||
bpf_dynptr_from_skb(skb, 0, &dptr);
|
||||
/* arg3 is mem+size */
|
||||
p = bpf_dynptr_slice(&dptr, 0, inner, 4);
|
||||
if (p)
|
||||
return p[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("?tc")
|
||||
__failure __msg("type=map_ptr_or_null expected=fp")
|
||||
int mapofmaps_value_as_helper_mem_buf(struct __sk_buff *skb)
|
||||
{
|
||||
__u32 key = 0;
|
||||
void *inner;
|
||||
|
||||
inner = bpf_map_lookup_elem(&outer_map, &key);
|
||||
/* intentionally NOT NULL-checked: type is map_ptr_or_null */
|
||||
|
||||
/* arg1 is mem+size */
|
||||
return bpf_csum_diff(inner, 4, NULL, 0, 0) + skb->len;
|
||||
}
|
||||
|
||||
SEC("?tc")
|
||||
__failure __msg("type=map_ptr_or_null expected=fp")
|
||||
int mapofmaps_value_as_helper_fixed_mem(struct __sk_buff *skb)
|
||||
{
|
||||
char th[sizeof(struct tcphdr)] = {};
|
||||
__u32 key = 0;
|
||||
void *inner;
|
||||
|
||||
inner = bpf_map_lookup_elem(&outer_map, &key);
|
||||
/* intentionally NOT NULL-checked: type is map_ptr_or_null */
|
||||
|
||||
/* arg1 is fixed-sized mem */
|
||||
return bpf_tcp_raw_check_syncookie_ipv4(inner, (void *)th);
|
||||
}
|
||||
28
tools/testing/selftests/bpf/progs/verifier_mem_size_reg.c
Normal file
28
tools/testing/selftests/bpf/progs/verifier_mem_size_reg.c
Normal file
@@ -0,0 +1,28 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <vmlinux.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include "bpf_misc.h"
|
||||
#include "bpf_kfuncs.h"
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
/*
|
||||
* The __szk size of a kfunc memory/size pair must be marked precise even when
|
||||
* the nullable buffer is passed as NULL.
|
||||
*/
|
||||
SEC("?tc")
|
||||
__success __log_level(2)
|
||||
__msg("mark_precise: frame0: regs=r4 stack= before")
|
||||
int dynptr_slice_null_buf_size_precise(struct __sk_buff *skb)
|
||||
{
|
||||
struct bpf_dynptr dptr;
|
||||
char *p;
|
||||
|
||||
bpf_dynptr_from_skb(skb, 0, &dptr);
|
||||
|
||||
p = bpf_dynptr_slice(&dptr, 0, NULL, 8);
|
||||
if (p)
|
||||
return p[0];
|
||||
return 0;
|
||||
}
|
||||
@@ -28,7 +28,7 @@ int BPF_PROG(get_task_exe_file_kfunc_null)
|
||||
}
|
||||
|
||||
SEC("lsm.s/inode_getxattr")
|
||||
__failure __msg("R1 pointer type STRUCT task_struct must point to scalar, or struct with scalar")
|
||||
__failure __msg("R1 is fp expected STRUCT task_struct")
|
||||
int BPF_PROG(get_task_exe_file_kfunc_fp)
|
||||
{
|
||||
u64 x;
|
||||
@@ -98,7 +98,7 @@ int BPF_PROG(path_d_path_kfunc_null)
|
||||
}
|
||||
|
||||
SEC("lsm.s/task_alloc")
|
||||
__failure __msg("R1 must be referenced or trusted")
|
||||
__failure __msg("dereference of modified untrusted_ptr_")
|
||||
int BPF_PROG(path_d_path_kfunc_untrusted_from_argument, struct task_struct *task)
|
||||
{
|
||||
struct path *root;
|
||||
@@ -112,7 +112,7 @@ int BPF_PROG(path_d_path_kfunc_untrusted_from_argument, struct task_struct *task
|
||||
}
|
||||
|
||||
SEC("lsm.s/file_open")
|
||||
__failure __msg("R1 must be referenced or trusted")
|
||||
__failure __msg("dereference of modified untrusted_ptr_")
|
||||
int BPF_PROG(path_d_path_kfunc_untrusted_from_current)
|
||||
{
|
||||
struct path *pwd;
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
},
|
||||
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||
.result = REJECT,
|
||||
.errstr = "R1 pointer type STRUCT prog_test_fail1 must point to scalar",
|
||||
.errstr = "R1 is fp expected STRUCT prog_test_fail1",
|
||||
.fixup_kfunc_btf_id = {
|
||||
{ "bpf_kfunc_call_test_fail1", 2 },
|
||||
},
|
||||
@@ -46,7 +46,7 @@
|
||||
},
|
||||
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||
.result = REJECT,
|
||||
.errstr = "max struct nesting depth exceeded\nR1 pointer type STRUCT prog_test_fail2",
|
||||
.errstr = "max struct nesting depth exceeded\nR1 is fp expected STRUCT prog_test_fail2",
|
||||
.fixup_kfunc_btf_id = {
|
||||
{ "bpf_kfunc_call_test_fail2", 2 },
|
||||
},
|
||||
@@ -61,7 +61,7 @@
|
||||
},
|
||||
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
|
||||
.result = REJECT,
|
||||
.errstr = "R1 pointer type STRUCT prog_test_fail3 must point to scalar",
|
||||
.errstr = "R1 is fp expected STRUCT prog_test_fail3",
|
||||
.fixup_kfunc_btf_id = {
|
||||
{ "bpf_kfunc_call_test_fail3", 2 },
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user