brintos

brintos / linux-shallow public Read only

0
0
Text · 4.9 KiB · b40b525 Raw
225 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */3 4#include <vmlinux.h>5#include <bpf/bpf_tracing.h>6#include <bpf/bpf_helpers.h>7#include "bpf_misc.h"8 9#include "cpumask_common.h"10 11char _license[] SEC("license") = "GPL";12 13struct kptr_nested_array_2 {14	struct bpf_cpumask __kptr * mask;15};16 17struct kptr_nested_array_1 {18	/* Make btf_parse_fields() in map_create() return -E2BIG */19	struct kptr_nested_array_2 d_2[CPUMASK_KPTR_FIELDS_MAX + 1];20};21 22struct kptr_nested_array {23	struct kptr_nested_array_1 d_1;24};25 26private(MASK_NESTED) static struct kptr_nested_array global_mask_nested_arr;27 28/* Prototype for all of the program trace events below:29 *30 * TRACE_EVENT(task_newtask,31 *         TP_PROTO(struct task_struct *p, u64 clone_flags)32 */33 34SEC("tp_btf/task_newtask")35__failure __msg("Unreleased reference")36int BPF_PROG(test_alloc_no_release, struct task_struct *task, u64 clone_flags)37{38	struct bpf_cpumask *cpumask;39 40	cpumask = create_cpumask();41	__sink(cpumask);42 43	/* cpumask is never released. */44	return 0;45}46 47SEC("tp_btf/task_newtask")48__failure __msg("NULL pointer passed to trusted arg0")49int BPF_PROG(test_alloc_double_release, struct task_struct *task, u64 clone_flags)50{51	struct bpf_cpumask *cpumask;52 53	cpumask = create_cpumask();54 55	/* cpumask is released twice. */56	bpf_cpumask_release(cpumask);57	bpf_cpumask_release(cpumask);58 59	return 0;60}61 62SEC("tp_btf/task_newtask")63__failure __msg("must be referenced")64int BPF_PROG(test_acquire_wrong_cpumask, struct task_struct *task, u64 clone_flags)65{66	struct bpf_cpumask *cpumask;67 68	/* Can't acquire a non-struct bpf_cpumask. */69	cpumask = bpf_cpumask_acquire((struct bpf_cpumask *)task->cpus_ptr);70	__sink(cpumask);71 72	return 0;73}74 75SEC("tp_btf/task_newtask")76__failure __msg("bpf_cpumask_set_cpu args#1 expected pointer to STRUCT bpf_cpumask")77int BPF_PROG(test_mutate_cpumask, struct task_struct *task, u64 clone_flags)78{79	/* Can't set the CPU of a non-struct bpf_cpumask. */80	bpf_cpumask_set_cpu(0, (struct bpf_cpumask *)task->cpus_ptr);81 82	return 0;83}84 85SEC("tp_btf/task_newtask")86__failure __msg("Unreleased reference")87int BPF_PROG(test_insert_remove_no_release, struct task_struct *task, u64 clone_flags)88{89	struct bpf_cpumask *cpumask;90	struct __cpumask_map_value *v;91 92	cpumask = create_cpumask();93	if (!cpumask)94		return 0;95 96	if (cpumask_map_insert(cpumask))97		return 0;98 99	v = cpumask_map_value_lookup();100	if (!v)101		return 0;102 103	cpumask = bpf_kptr_xchg(&v->cpumask, NULL);104 105	/* cpumask is never released. */106	return 0;107}108 109SEC("tp_btf/task_newtask")110__failure __msg("NULL pointer passed to trusted arg0")111int BPF_PROG(test_cpumask_null, struct task_struct *task, u64 clone_flags)112{113  /* NULL passed to KF_TRUSTED_ARGS kfunc. */114	bpf_cpumask_empty(NULL);115 116	return 0;117}118 119SEC("tp_btf/task_newtask")120__failure __msg("R2 must be a rcu pointer")121int BPF_PROG(test_global_mask_out_of_rcu, struct task_struct *task, u64 clone_flags)122{123	struct bpf_cpumask *local, *prev;124 125	local = create_cpumask();126	if (!local)127		return 0;128 129	prev = bpf_kptr_xchg(&global_mask, local);130	if (prev) {131		bpf_cpumask_release(prev);132		err = 3;133		return 0;134	}135 136	bpf_rcu_read_lock();137	local = global_mask;138	if (!local) {139		err = 4;140		bpf_rcu_read_unlock();141		return 0;142	}143 144	bpf_rcu_read_unlock();145 146	/* RCU region is exited before calling KF_RCU kfunc. */147 148	bpf_cpumask_test_cpu(0, (const struct cpumask *)local);149 150	return 0;151}152 153SEC("tp_btf/task_newtask")154__failure __msg("NULL pointer passed to trusted arg1")155int BPF_PROG(test_global_mask_no_null_check, struct task_struct *task, u64 clone_flags)156{157	struct bpf_cpumask *local, *prev;158 159	local = create_cpumask();160	if (!local)161		return 0;162 163	prev = bpf_kptr_xchg(&global_mask, local);164	if (prev) {165		bpf_cpumask_release(prev);166		err = 3;167		return 0;168	}169 170	bpf_rcu_read_lock();171	local = global_mask;172 173	/* No NULL check is performed on global cpumask kptr. */174	bpf_cpumask_test_cpu(0, (const struct cpumask *)local);175 176	bpf_rcu_read_unlock();177 178	return 0;179}180 181SEC("tp_btf/task_newtask")182__failure __msg("Possibly NULL pointer passed to helper arg2")183int BPF_PROG(test_global_mask_rcu_no_null_check, struct task_struct *task, u64 clone_flags)184{185	struct bpf_cpumask *prev, *curr;186 187	curr = bpf_cpumask_create();188	if (!curr)189		return 0;190 191	prev = bpf_kptr_xchg(&global_mask, curr);192	if (prev)193		bpf_cpumask_release(prev);194 195	bpf_rcu_read_lock();196	curr = global_mask;197	/* PTR_TO_BTF_ID | PTR_MAYBE_NULL | MEM_RCU passed to bpf_kptr_xchg() */198	prev = bpf_kptr_xchg(&global_mask, curr);199	bpf_rcu_read_unlock();200	if (prev)201		bpf_cpumask_release(prev);202 203	return 0;204}205 206SEC("tp_btf/task_newtask")207__failure __msg("has no valid kptr")208int BPF_PROG(test_invalid_nested_array, struct task_struct *task, u64 clone_flags)209{210	struct bpf_cpumask *local, *prev;211 212	local = create_cpumask();213	if (!local)214		return 0;215 216	prev = bpf_kptr_xchg(&global_mask_nested_arr.d_1.d_2[CPUMASK_KPTR_FIELDS_MAX].mask, local);217	if (prev) {218		bpf_cpumask_release(prev);219		err = 3;220		return 0;221	}222 223	return 0;224}225