1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include "bpf_misc.h"
char _license[] SEC("license") = "GPL";
static long stack[256];
/*
* KPROBE contexts
*/
__weak int kprobe_typedef_ctx_subprog(bpf_user_pt_regs_t *ctx)
{
return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
}
SEC("?kprobe")
__success
int kprobe_typedef_ctx(void *ctx)
{
return kprobe_typedef_ctx_subprog(ctx);
}
/* s390x defines:
*
* typedef user_pt_regs bpf_user_pt_regs_t;
* typedef struct { ... } user_pt_regs;
*
* And so "canonical" underlying struct type is anonymous.
* So on s390x only valid ways to have PTR_TO_CTX argument in global subprogs
* are:
* - bpf_user_pt_regs_t *ctx (typedef);
* - struct bpf_user_pt_regs_t *ctx (backwards compatible struct hack);
* - void *ctx __arg_ctx (arg:ctx tag)
*
* Other architectures also allow using underlying struct types (e.g.,
* `struct pt_regs *ctx` for x86-64)
*/
#ifndef bpf_target_s390
#define pt_regs_struct_t typeof(*(__PT_REGS_CAST((struct pt_regs *)NULL)))
__weak int kprobe_struct_ctx_subprog(pt_regs_struct_t *ctx)
{
return bpf_get_stack((void *)ctx, &stack, sizeof(stack), 0);
}
SEC("?kprobe")
__success
int kprobe_resolved_ctx(void *ctx)
{
return kprobe_struct_ctx_subprog(ctx);
}
#endif
/* this is current hack to make this work on old kernels */
struct bpf_user_pt_regs_t {};
__weak int kprobe_workaround_ctx_subprog(struct bpf_user_pt_regs_t *ctx)
{
return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
}
SEC("?kprobe")
__success
int kprobe_workaround_ctx(void *ctx)
{
return kprobe_workaround_ctx_subprog(ctx);
}
/*
* RAW_TRACEPOINT contexts
*/
__weak int raw_tp_ctx_subprog(struct bpf_raw_tracepoint_args *ctx)
{
return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
}
SEC("?raw_tp")
__success
int raw_tp_ctx(void *ctx)
{
return raw_tp_ctx_subprog(ctx);
}
/*
* RAW_TRACEPOINT_WRITABLE contexts
*/
__weak int raw_tp_writable_ctx_subprog(struct bpf_raw_tracepoint_args *ctx)
{
return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
}
SEC("?raw_tp")
__success
int raw_tp_writable_ctx(void *ctx)
{
return raw_tp_writable_ctx_subprog(ctx);
}
/*
* PERF_EVENT contexts
*/
__weak int perf_event_ctx_subprog(struct bpf_perf_event_data *ctx)
{
return bpf_get_stack(ctx, &stack, sizeof(stack), 0);
}
SEC("?perf_event")
__success
int perf_event_ctx(void *ctx)
{
return perf_event_ctx_subprog(ctx);
}
/* this global subprog can be now called from many types of entry progs, each
* with different context type
*/
__weak int subprog_ctx_tag(void *ctx __arg_ctx)
{
return bpf_get_stack(ctx, stack, sizeof(stack), 0);
}
struct my_struct { int x; };
__weak int subprog_multi_ctx_tags(void *ctx1 __arg_ctx,
struct my_struct *mem,
void *ctx2 __arg_ctx)
{
if (!mem)
return 0;
return bpf_get_stack(ctx1, stack, sizeof(stack), 0) +
mem->x +
bpf_get_stack(ctx2, stack, sizeof(stack), 0);
}
SEC("?raw_tp")
__success __log_level(2)
int arg_tag_ctx_raw_tp(void *ctx)
{
struct my_struct x = { .x = 123 };
return subprog_ctx_tag(ctx) + subprog_multi_ctx_tags(ctx, &x, ctx);
}
SEC("?perf_event")
__success __log_level(2)
int arg_tag_ctx_perf(void *ctx)
{
struct my_struct x = { .x = 123 };
return subprog_ctx_tag(ctx) + subprog_multi_ctx_tags(ctx, &x, ctx);
}
SEC("?kprobe")
__success __log_level(2)
int arg_tag_ctx_kprobe(void *ctx)
{
struct my_struct x = { .x = 123 };
return subprog_ctx_tag(ctx) + subprog_multi_ctx_tags(ctx, &x, ctx);
}
|