brintos

brintos / linux-shallow public Read only

0
0
Text · 7.8 KiB · ad88a37 Raw
327 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */3 4#include <vmlinux.h>5#include <bpf/bpf_tracing.h>6#include <bpf/bpf_helpers.h>7 8#include "bpf_misc.h"9#include "task_kfunc_common.h"10 11char _license[] SEC("license") = "GPL";12 13/* Prototype for all of the program trace events below:14 *15 * TRACE_EVENT(task_newtask,16 *         TP_PROTO(struct task_struct *p, u64 clone_flags)17 */18 19static struct __tasks_kfunc_map_value *insert_lookup_task(struct task_struct *task)20{21	int status;22 23	status = tasks_kfunc_map_insert(task);24	if (status)25		return NULL;26 27	return tasks_kfunc_map_value_lookup(task);28}29 30SEC("tp_btf/task_newtask")31__failure __msg("Possibly NULL pointer passed to trusted arg0")32int BPF_PROG(task_kfunc_acquire_untrusted, struct task_struct *task, u64 clone_flags)33{34	struct task_struct *acquired;35	struct __tasks_kfunc_map_value *v;36 37	v = insert_lookup_task(task);38	if (!v)39		return 0;40 41	/* Can't invoke bpf_task_acquire() on an untrusted pointer. */42	acquired = bpf_task_acquire(v->task);43	if (!acquired)44		return 0;45 46	bpf_task_release(acquired);47 48	return 0;49}50 51SEC("tp_btf/task_newtask")52__failure __msg("arg#0 pointer type STRUCT task_struct must point")53int BPF_PROG(task_kfunc_acquire_fp, struct task_struct *task, u64 clone_flags)54{55	struct task_struct *acquired, *stack_task = (struct task_struct *)&clone_flags;56 57	/* Can't invoke bpf_task_acquire() on a random frame pointer. */58	acquired = bpf_task_acquire((struct task_struct *)&stack_task);59	if (!acquired)60		return 0;61 62	bpf_task_release(acquired);63 64	return 0;65}66 67SEC("kretprobe/free_task")68__failure __msg("calling kernel function bpf_task_acquire is not allowed")69int BPF_PROG(task_kfunc_acquire_unsafe_kretprobe, struct task_struct *task, u64 clone_flags)70{71	struct task_struct *acquired;72 73	/* Can't call bpf_task_acquire() or bpf_task_release() in an untrusted prog. */74	acquired = bpf_task_acquire(task);75	if (!acquired)76		return 0;77	bpf_task_release(acquired);78 79	return 0;80}81 82SEC("kretprobe/free_task")83__failure __msg("calling kernel function bpf_task_acquire is not allowed")84int BPF_PROG(task_kfunc_acquire_unsafe_kretprobe_rcu, struct task_struct *task, u64 clone_flags)85{86	struct task_struct *acquired;87 88	bpf_rcu_read_lock();89	if (!task) {90		bpf_rcu_read_unlock();91		return 0;92	}93	/* Can't call bpf_task_acquire() or bpf_task_release() in an untrusted prog. */94	acquired = bpf_task_acquire(task);95	if (acquired)96		bpf_task_release(acquired);97	bpf_rcu_read_unlock();98 99	return 0;100}101 102SEC("tp_btf/task_newtask")103__failure __msg("Possibly NULL pointer passed to trusted arg0")104int BPF_PROG(task_kfunc_acquire_null, struct task_struct *task, u64 clone_flags)105{106	struct task_struct *acquired;107 108	/* Can't invoke bpf_task_acquire() on a NULL pointer. */109	acquired = bpf_task_acquire(NULL);110	if (!acquired)111		return 0;112	bpf_task_release(acquired);113 114	return 0;115}116 117SEC("tp_btf/task_newtask")118__failure __msg("Unreleased reference")119int BPF_PROG(task_kfunc_acquire_unreleased, struct task_struct *task, u64 clone_flags)120{121	struct task_struct *acquired;122 123	acquired = bpf_task_acquire(task);124 125	/* Acquired task is never released. */126	__sink(acquired);127 128	return 0;129}130 131SEC("tp_btf/task_newtask")132__failure __msg("Unreleased reference")133int BPF_PROG(task_kfunc_xchg_unreleased, struct task_struct *task, u64 clone_flags)134{135	struct task_struct *kptr;136	struct __tasks_kfunc_map_value *v;137 138	v = insert_lookup_task(task);139	if (!v)140		return 0;141 142	kptr = bpf_kptr_xchg(&v->task, NULL);143	if (!kptr)144		return 0;145 146	/* Kptr retrieved from map is never released. */147 148	return 0;149}150 151SEC("tp_btf/task_newtask")152__failure __msg("Possibly NULL pointer passed to trusted arg0")153int BPF_PROG(task_kfunc_acquire_release_no_null_check, struct task_struct *task, u64 clone_flags)154{155	struct task_struct *acquired;156 157	acquired = bpf_task_acquire(task);158	/* Can't invoke bpf_task_release() on an acquired task without a NULL check. */159	bpf_task_release(acquired);160 161	return 0;162}163 164SEC("tp_btf/task_newtask")165__failure __msg("Possibly NULL pointer passed to trusted arg0")166int BPF_PROG(task_kfunc_release_untrusted, struct task_struct *task, u64 clone_flags)167{168	struct __tasks_kfunc_map_value *v;169 170	v = insert_lookup_task(task);171	if (!v)172		return 0;173 174	/* Can't invoke bpf_task_release() on an untrusted pointer. */175	bpf_task_release(v->task);176 177	return 0;178}179 180SEC("tp_btf/task_newtask")181__failure __msg("arg#0 pointer type STRUCT task_struct must point")182int BPF_PROG(task_kfunc_release_fp, struct task_struct *task, u64 clone_flags)183{184	struct task_struct *acquired = (struct task_struct *)&clone_flags;185 186	/* Cannot release random frame pointer. */187	bpf_task_release(acquired);188 189	return 0;190}191 192SEC("tp_btf/task_newtask")193__failure __msg("Possibly NULL pointer passed to trusted arg0")194int BPF_PROG(task_kfunc_release_null, struct task_struct *task, u64 clone_flags)195{196	struct __tasks_kfunc_map_value local, *v;197	long status;198	struct task_struct *acquired, *old;199	s32 pid;200 201	status = bpf_probe_read_kernel(&pid, sizeof(pid), &task->pid);202	if (status)203		return 0;204 205	local.task = NULL;206	status = bpf_map_update_elem(&__tasks_kfunc_map, &pid, &local, BPF_NOEXIST);207	if (status)208		return status;209 210	v = bpf_map_lookup_elem(&__tasks_kfunc_map, &pid);211	if (!v)212		return -ENOENT;213 214	acquired = bpf_task_acquire(task);215	if (!acquired)216		return -EEXIST;217 218	old = bpf_kptr_xchg(&v->task, acquired);219 220	/* old cannot be passed to bpf_task_release() without a NULL check. */221	bpf_task_release(old);222 223	return 0;224}225 226SEC("tp_btf/task_newtask")227__failure __msg("release kernel function bpf_task_release expects")228int BPF_PROG(task_kfunc_release_unacquired, struct task_struct *task, u64 clone_flags)229{230	/* Cannot release trusted task pointer which was not acquired. */231	bpf_task_release(task);232 233	return 0;234}235 236SEC("tp_btf/task_newtask")237__failure __msg("Possibly NULL pointer passed to trusted arg0")238int BPF_PROG(task_kfunc_from_pid_no_null_check, struct task_struct *task, u64 clone_flags)239{240	struct task_struct *acquired;241 242	acquired = bpf_task_from_pid(task->pid);243 244	/* Releasing bpf_task_from_pid() lookup without a NULL check. */245	bpf_task_release(acquired);246 247	return 0;248}249 250SEC("lsm/task_free")251__failure __msg("R1 must be a rcu pointer")252int BPF_PROG(task_kfunc_from_lsm_task_free, struct task_struct *task)253{254	struct task_struct *acquired;255 256	/* the argument of lsm task_free hook is untrusted. */257	acquired = bpf_task_acquire(task);258	if (!acquired)259		return 0;260 261	bpf_task_release(acquired);262	return 0;263}264 265SEC("tp_btf/task_newtask")266__failure __msg("access beyond the end of member comm")267int BPF_PROG(task_access_comm1, struct task_struct *task, u64 clone_flags)268{269	bpf_strncmp(task->comm, 17, "foo");270	return 0;271}272 273SEC("tp_btf/task_newtask")274__failure __msg("access beyond the end of member comm")275int BPF_PROG(task_access_comm2, struct task_struct *task, u64 clone_flags)276{277	bpf_strncmp(task->comm + 1, 16, "foo");278	return 0;279}280 281SEC("tp_btf/task_newtask")282__failure __msg("write into memory")283int BPF_PROG(task_access_comm3, struct task_struct *task, u64 clone_flags)284{285	bpf_probe_read_kernel(task->comm, 16, task->comm);286	return 0;287}288 289SEC("fentry/__set_task_comm")290__failure __msg("R1 type=ptr_ expected")291int BPF_PROG(task_access_comm4, struct task_struct *task, const char *buf, bool exec)292{293	/*294	 * task->comm is a legacy ptr_to_btf_id. The verifier cannot guarantee295	 * its safety. Hence it cannot be accessed with normal load insns.296	 */297	bpf_strncmp(task->comm, 16, "foo");298	return 0;299}300 301SEC("tp_btf/task_newtask")302__failure __msg("R1 must be referenced or trusted")303int BPF_PROG(task_kfunc_release_in_map, struct task_struct *task, u64 clone_flags)304{305	struct task_struct *local;306	struct __tasks_kfunc_map_value *v;307 308	if (tasks_kfunc_map_insert(task))309		return 0;310 311	v = tasks_kfunc_map_value_lookup(task);312	if (!v)313		return 0;314 315	bpf_rcu_read_lock();316	local = v->task;317	if (!local) {318		bpf_rcu_read_unlock();319		return 0;320	}321	/* Can't release a kptr that's still stored in a map. */322	bpf_task_release(local);323	bpf_rcu_read_unlock();324 325	return 0;326}327