183 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */3 4#include <vmlinux.h>5#include <bpf/bpf_helpers.h>6#include <bpf/bpf_tracing.h>7#include <bpf/bpf_core_read.h>8#include "bpf_misc.h"9#include "xdp_metadata.h"10#include "bpf_kfuncs.h"11 12extern struct task_struct *bpf_task_acquire(struct task_struct *p) __ksym __weak;13extern void bpf_task_release(struct task_struct *p) __ksym __weak;14 15__weak int subprog_trusted_task_nullable(struct task_struct *task __arg_trusted __arg_nullable)16{17 if (!task)18 return 0;19 return task->pid + task->tgid;20}21 22__weak int subprog_trusted_task_nullable_extra_layer(struct task_struct *task __arg_trusted __arg_nullable)23{24 return subprog_trusted_task_nullable(task) + subprog_trusted_task_nullable(NULL);25}26 27SEC("?tp_btf/task_newtask")28__success __log_level(2)29__msg("Validating subprog_trusted_task_nullable() func#1...")30__msg(": R1=trusted_ptr_or_null_task_struct(")31int trusted_task_arg_nullable(void *ctx)32{33 struct task_struct *t1 = bpf_get_current_task_btf();34 struct task_struct *t2 = bpf_task_acquire(t1);35 int res = 0;36 37 /* known NULL */38 res += subprog_trusted_task_nullable(NULL);39 40 /* known non-NULL */41 res += subprog_trusted_task_nullable(t1);42 res += subprog_trusted_task_nullable_extra_layer(t1);43 44 /* unknown if NULL or not */45 res += subprog_trusted_task_nullable(t2);46 res += subprog_trusted_task_nullable_extra_layer(t2);47 48 if (t2) {49 /* known non-NULL after explicit NULL check, just in case */50 res += subprog_trusted_task_nullable(t2);51 res += subprog_trusted_task_nullable_extra_layer(t2);52 53 bpf_task_release(t2);54 }55 56 return res;57}58 59__weak int subprog_trusted_task_nonnull(struct task_struct *task __arg_trusted)60{61 return task->pid + task->tgid;62}63 64SEC("?kprobe")65__failure __log_level(2)66__msg("R1 type=scalar expected=ptr_, trusted_ptr_, rcu_ptr_")67__msg("Caller passes invalid args into func#1 ('subprog_trusted_task_nonnull')")68int trusted_task_arg_nonnull_fail1(void *ctx)69{70 return subprog_trusted_task_nonnull(NULL);71}72 73SEC("?tp_btf/task_newtask")74__failure __log_level(2)75__msg("R1 type=ptr_or_null_ expected=ptr_, trusted_ptr_, rcu_ptr_")76__msg("Caller passes invalid args into func#1 ('subprog_trusted_task_nonnull')")77int trusted_task_arg_nonnull_fail2(void *ctx)78{79 struct task_struct *t = bpf_get_current_task_btf();80 struct task_struct *nullable;81 int res;82 83 nullable = bpf_task_acquire(t);84 85 /* should fail, PTR_TO_BTF_ID_OR_NULL */86 res = subprog_trusted_task_nonnull(nullable);87 88 if (nullable)89 bpf_task_release(nullable);90 91 return res;92}93 94SEC("?kprobe")95__success __log_level(2)96__msg("Validating subprog_trusted_task_nonnull() func#1...")97__msg(": R1=trusted_ptr_task_struct(")98int trusted_task_arg_nonnull(void *ctx)99{100 struct task_struct *t = bpf_get_current_task_btf();101 102 return subprog_trusted_task_nonnull(t);103}104 105struct task_struct___local {} __attribute__((preserve_access_index));106 107__weak int subprog_nullable_task_flavor(108 struct task_struct___local *task __arg_trusted __arg_nullable)109{110 char buf[16];111 112 if (!task)113 return 0;114 115 return bpf_copy_from_user_task(&buf, sizeof(buf), NULL, (void *)task, 0);116}117 118SEC("?uprobe.s")119__success __log_level(2)120__msg("Validating subprog_nullable_task_flavor() func#1...")121__msg(": R1=trusted_ptr_or_null_task_struct(")122int flavor_ptr_nullable(void *ctx)123{124 struct task_struct___local *t = (void *)bpf_get_current_task_btf();125 126 return subprog_nullable_task_flavor(t);127}128 129__weak int subprog_nonnull_task_flavor(struct task_struct___local *task __arg_trusted)130{131 char buf[16];132 133 return bpf_copy_from_user_task(&buf, sizeof(buf), NULL, (void *)task, 0);134}135 136SEC("?uprobe.s")137__success __log_level(2)138__msg("Validating subprog_nonnull_task_flavor() func#1...")139__msg(": R1=trusted_ptr_task_struct(")140int flavor_ptr_nonnull(void *ctx)141{142 struct task_struct *t = bpf_get_current_task_btf();143 144 return subprog_nonnull_task_flavor((void *)t);145}146 147__weak int subprog_trusted_destroy(struct task_struct *task __arg_trusted)148{149 bpf_task_release(task); /* should be rejected */150 151 return 0;152}153 154SEC("?tp_btf/task_newtask")155__failure __log_level(2)156__msg("release kernel function bpf_task_release expects refcounted PTR_TO_BTF_ID")157int BPF_PROG(trusted_destroy_fail, struct task_struct *task, u64 clone_flags)158{159 return subprog_trusted_destroy(task);160}161 162__weak int subprog_trusted_acq_rel(struct task_struct *task __arg_trusted)163{164 struct task_struct *owned;165 166 owned = bpf_task_acquire(task);167 if (!owned)168 return 0;169 170 bpf_task_release(owned); /* this one is OK, we acquired it locally */171 172 return 0;173}174 175SEC("?tp_btf/task_newtask")176__success __log_level(2)177int BPF_PROG(trusted_acq_rel, struct task_struct *task, u64 clone_flags)178{179 return subprog_trusted_acq_rel(task);180}181 182char _license[] SEC("license") = "GPL";183