From f4b3a8cea0b2de62db312e55da0427d9be0302e8 Mon Sep 17 00:00:00 2001 From: Michal Rostecki Date: Mon, 6 Mar 2023 15:52:58 +0100 Subject: [PATCH] ebpf: Change error types to `c_long` All helper functions and context methods are returning `c_long` as an error. Before this change, aya-template and book examples were adjusting the error type in `try_*` functionns return type of the program. For example, for XDP programs programs, which return `u32`, the type returned by `try_*` functions, was `Result`. This approach is forcing people to write boilerplate code for casting errors from `c_long` to the expected type, like: ```rust MY_MAP.insert(k, v, 0).map_err(|_| 1u32)?; ``` This change solves that problem by: * Using `Result` as a type for `try_*` functions for SKB-based programs and then replacing errors with `TC_ACT_SHOT` or `0` once in the main program function. * Using `Result` as a type for `try_*` functions in `try_*` funnctions for XDP programs and then replacing errors with `XDP_ABORT`. * Using either `Result` or `Result` as types in `try_*` functions for all other program types where the return value matters (LSM, sysctl etc.) and replacing the error either with `0` or `1` (depending on which number means "block the action" for particular type of program). * Using `Result<(), c_long` for all other program types where the return value doesn't matter (kprobe, uprobe etc.). So errors can be handled without casting, like: ```rust MY_MAP.insert(k, v, 0)?; ``` The other change is fixing return values of cgroup_skb, sockopt and sysctl programs (1 means "allow", 0 means "deny"). Signed-off-by: Michal Rostecki --- {{project-name}}-ebpf/src/main.rs | 213 +++++++++++++++++------------- 1 file changed, 118 insertions(+), 95 deletions(-) diff --git a/{{project-name}}-ebpf/src/main.rs b/{{project-name}}-ebpf/src/main.rs index ad72100..34c5934 100644 --- a/{{project-name}}-ebpf/src/main.rs +++ b/{{project-name}}-ebpf/src/main.rs @@ -1,116 +1,112 @@ #![no_std] #![no_main] + {% case program_type -%} {%- when "kprobe" %} -use aya_bpf::{macros::kprobe, programs::ProbeContext}; +use aya_bpf::{ + cty::c_long, + macros::kprobe, + programs::ProbeContext, +}; use aya_log_ebpf::info; #[kprobe(name = "{{crate_name}}")] -pub fn {{crate_name}}(ctx: ProbeContext) -> u32 { - match try_{{crate_name}}(ctx) { - Ok(ret) => ret, - Err(ret) => ret, - } +pub fn {{crate_name}}(ctx: ProbeContext) { + let _ = try_{{crate_name}}(ctx); } -fn try_{{crate_name}}(ctx: ProbeContext) -> Result { +fn try_{{crate_name}}(ctx: ProbeContext) -> Result<(), c_long> { info!(&ctx, "function {{kprobe}} called"); - Ok(0) + Ok(()) } {%- when "kretprobe" %} -use aya_bpf::{macros::kretprobe, programs::ProbeContext}; +use aya_bpf::{ + cty::c_long, + macros::kretprobe, + programs::ProbeContext, +}; use aya_log_ebpf::info; #[kretprobe(name = "{{crate_name}}")] -pub fn {{crate_name}}(ctx: ProbeContext) -> u32 { - match try_{{crate_name}}(ctx) { - Ok(ret) => ret, - Err(ret) => ret, - } +pub fn {{crate_name}}(ctx: ProbeContext) { + let _ = try_{{crate_name}}(ctx); } -fn try_{{crate_name}}(ctx: ProbeContext) -> Result { +fn try_{{crate_name}}(ctx: ProbeContext) -> Result<(), c_long> { info!(&ctx, "function {{kprobe}} called"); - Ok(0) + Ok(()) } {%- when "fentry" %} use aya_bpf::{ + cty::c_long, macros::fentry, programs::FEntryContext, }; use aya_log_ebpf::info; #[fentry(name="{{crate_name}}")] -pub fn {{crate_name}}(ctx: FEntryContext) -> u32 { - match try_{{crate_name}}(ctx) { - Ok(ret) => ret, - Err(ret) => ret, - } +pub fn {{crate_name}}(ctx: FEntryContext) { + let _ = try_{{crate_name}}(ctx); } -fn try_{{crate_name}}(ctx: FEntryContext) -> Result { +fn try_{{crate_name}}(ctx: FEntryContext) -> Result<(), c_long> { info!(&ctx, "function {{fn_name}} called"); - Ok(0) + Ok(()) } {%- when "fexit" %} use aya_bpf::{ + cty::c_long, macros::fexit, programs::FExitContext, }; use aya_log_ebpf::info; #[fexit(name="{{crate_name}}")] -pub fn {{crate_name}}(ctx: FExitContext) -> u32 { - match try_{{crate_name}}(ctx) { - Ok(ret) => ret, - Err(ret) => ret, - } +pub fn {{crate_name}}(ctx: FExitContext) { + let _ = try_{{crate_name}}(ctx); } -fn try_{{crate_name}}(ctx: FExitContext) -> Result { +fn try_{{crate_name}}(ctx: FExitContext) -> Result<(), c_long> { info!(&ctx, "function {{fn_name}} called"); - Ok(0) + Ok(()) } {%- when "uprobe" %} use aya_bpf::{ + cty::c_long, macros::uprobe, programs::ProbeContext, }; use aya_log_ebpf::info; #[uprobe(name="{{crate_name}}")] -pub fn {{crate_name}}(ctx: ProbeContext) -> u32 { - match try_{{crate_name}}(ctx) { - Ok(ret) => ret, - Err(ret) => ret, - } +pub fn {{crate_name}}(ctx: ProbeContext) { + let _ = try_{{crate_name}}(ctx); } -fn try_{{crate_name}}(ctx: ProbeContext) -> Result { +fn try_{{crate_name}}(ctx: ProbeContext) -> Result<(), c_long> { info!(&ctx, "function {{uprobe_fn_name}} called by {{uprobe_target}}"); - Ok(0) + Ok(()) } {%- when "uretprobe" %} use aya_bpf::{ + cty::c_long, macros::uretprobe, programs::ProbeContext, }; use aya_log_ebpf::info; #[uretprobe(name="{{crate_name}}")] -pub fn {{crate_name}}(ctx: ProbeContext) -> u32 { - match try_{{crate_name}}(ctx) { - Ok(ret) => ret, - Err(ret) => ret, - } +pub fn {{crate_name}}(ctx: ProbeContext) { + let _ = try_{{crate_name}}(ctx); } -fn try_{{crate_name}}(ctx: ProbeContext) -> Result { +fn try_{{crate_name}}(ctx: ProbeContext) -> Result<(), c_long> { info!(&ctx, "function {{uprobe_fn_name}} called by {{uprobe_target}}"); - Ok(0) + Ok(()) } {%- when "sock_ops" %} use aya_bpf::{ + cty::c_long, macros::sock_ops, programs::SockOpsContext, }; @@ -120,16 +116,17 @@ use aya_log_ebpf::info; pub fn {{crate_name}}(ctx: SockOpsContext) -> u32 { match try_{{crate_name}}(ctx) { Ok(ret) => ret, - Err(ret) => ret, + Err(_) => 1, } } -fn try_{{crate_name}}(ctx: SockOpsContext) -> Result { +fn try_{{crate_name}}(ctx: SockOpsContext) -> Result { info!(&ctx, "received TCP connection"); Ok(0) } {%- when "sk_msg" %} use aya_bpf::{ + cty::c_long, macros::{map, sk_msg}, maps::SockHash, programs::SkMsgContext, @@ -145,16 +142,21 @@ static {{sock_map}}: SockHash = SockHash::::with_max_entries(1 pub fn {{crate_name}}(ctx: SkMsgContext) -> u32 { match try_{{crate_name}}(ctx) { Ok(ret) => ret, - Err(ret) => ret, + Err(_) => 1, } } -fn try_{{crate_name}}(ctx: SkMsgContext) -> Result { +fn try_{{crate_name}}(ctx: SkMsgContext) -> Result { info!(&ctx, "received a message on the socket"); Ok(0) } {%- when "xdp" %} -use aya_bpf::{bindings::xdp_action, macros::xdp, programs::XdpContext}; +use aya_bpf::{ + bindings::xdp_action, + cty::c_long, + macros::xdp, + programs::XdpContext, +}; use aya_log_ebpf::info; #[xdp(name = "{{crate_name}}")] @@ -165,28 +167,34 @@ pub fn {{crate_name}}(ctx: XdpContext) -> u32 { } } -fn try_{{crate_name}}(ctx: XdpContext) -> Result { +fn try_{{crate_name}}(ctx: XdpContext) -> Result { info!(&ctx, "received a packet"); Ok(xdp_action::XDP_PASS) } {%- when "classifier" %} -use aya_bpf::{macros::classifier, programs::TcContext}; +use aya_bpf::{ + bindings::{TC_ACT_PIPE, TC_ACT_SHOT}, + cty::c_long, + macros::classifier, + programs::TcContext, +}; use aya_log_ebpf::info; #[classifier(name = "{{crate_name}}")] pub fn {{crate_name}}(ctx: TcContext) -> i32 { match try_{{crate_name}}(ctx) { Ok(ret) => ret, - Err(ret) => ret, + Err(_) => TC_ACT_SHOT, } } -fn try_{{crate_name}}(ctx: TcContext) -> Result { +fn try_{{crate_name}}(ctx: TcContext) -> Result { info!(&ctx, "received a packet"); - Ok(0) + Ok(TC_ACT_PIPE) } {%- when "cgroup_skb" %} use aya_bpf::{ + cty::c_long, macros::cgroup_skb, programs::SkBuffContext, }; @@ -196,35 +204,34 @@ use aya_log_ebpf::info; pub fn {{crate_name}}(ctx: SkBuffContext) -> i32 { match try_{{crate_name}}(ctx) { Ok(ret) => ret, - Err(ret) => ret, + Err(_) => 0, } } -fn try_{{crate_name}}(ctx: SkBuffContext) -> Result { +fn try_{{crate_name}}(ctx: SkBuffContext) -> Result { info!(&ctx, "received a packet"); - Ok(0) + Ok(1) } {%- when "tracepoint" %} use aya_bpf::{ + cty::c_long, macros::tracepoint, programs::TracePointContext, }; use aya_log_ebpf::info; #[tracepoint(name = "{{crate_name}}")] -pub fn {{crate_name}}(ctx: TracePointContext) -> u32 { - match try_{{crate_name}}(ctx) { - Ok(ret) => ret, - Err(ret) => ret, - } +pub fn {{crate_name}}(ctx: TracePointContext) { + let _ = try_{{crate_name}}(ctx); } -fn try_{{crate_name}}(ctx: TracePointContext) -> Result { +fn try_{{crate_name}}(ctx: TracePointContext) -> Result<(), c_long> { info!(&ctx, "tracepoint {{tracepoint_name}} called"); - Ok(0) + Ok(()) } {%- when "lsm" %} use aya_bpf::{ + cty::c_long, macros::lsm, programs::LsmContext, }; @@ -234,45 +241,52 @@ use aya_log_ebpf::info; pub fn {{lsm_hook}}(ctx: LsmContext) -> i32 { match try_{{lsm_hook}}(ctx) { Ok(ret) => ret, - Err(ret) => ret, + Err(ret) => 1, } } -fn try_{{lsm_hook}}(ctx: LsmContext) -> Result { +fn try_{{lsm_hook}}(ctx: LsmContext) -> Result { info!(&ctx, "lsm hook {{lsm_hook}} called"); Ok(0) } {%- when "tp_btf" %} use aya_bpf::{ + cty::c_long, macros::btf_tracepoint, programs::BtfTracePointContext, }; use aya_log_ebpf::info; #[btf_tracepoint(name = "{{tracepoint_name}}")] -pub fn {{tracepoint_name}}(ctx: BtfTracePointContext) -> i32 { - match try_{{tracepoint_name}}(ctx) { - Ok(ret) => ret, - Err(ret) => ret, - } +pub fn {{tracepoint_name}}(ctx: BtfTracePointContext) { + let _ = try_{{tracepoint_name}}(ctx); } -fn try_{{tracepoint_name}}(ctx: BtfTracePointContext) -> Result { +fn try_{{tracepoint_name}}(ctx: BtfTracePointContext) -> Result<(), c_long> { info!(&ctx, "tracepoint {{tracepoint_name}} called"); - Ok(0) + Ok(()) } {%- when "socket_filter" %} use aya_bpf::{ + cty::c_long, macros::socket_filter, programs::SkBuffContext, }; #[socket_filter(name = "{{crate_name}}")] -pub fn {{crate_name}}(_ctx: SkBuffContext) -> i64 { - return 0 +pub fn {{crate_name}}(ctx: SkBuffContext) -> i64 { + match try_{{crate_name}}(ctx) { + Ok(ret) => ret, + Err(_) => 0, + } +} + +fn try_{{crate_name}}(ctx: SkBuffContext) -> Result { + Ok(0) } {%- when "cgroup_sysctl" %} use aya_bpf::{ + cty::c_long, macros::cgroup_sysctl, programs::SysctlContext, }; @@ -282,61 +296,70 @@ use aya_log_ebpf::info; pub fn {{crate_name}}(ctx: SysctlContext) -> i32 { match try_{{crate_name}}(ctx) { Ok(ret) => ret, - Err(ret) => ret, + Err(_) => 0, } } -fn try_{{crate_name}}(ctx: SysctlContext) -> Result { +fn try_{{crate_name}}(ctx: SysctlContext) -> Result { info!(&ctx, "sysctl operation called"); - Ok(0) + Ok(1) } {%- when "cgroup_sockopt" %} -use aya_bpf::{macros::cgroup_sockopt, programs::SockoptContext}; +use aya_bpf::{ + cty::c_long, + macros::cgroup_sockopt, + programs::SockoptContext, +}; use aya_log_ebpf::info; #[cgroup_sockopt({{sockopt_target}}, name = "{{crate_name}}")] pub fn {{crate_name}}(ctx: SockoptContext) -> i32 { match try_{{crate_name}}(ctx) { Ok(ret) => ret, - Err(ret) => ret, + Err(_) => 0, } } -fn try_{{crate_name}}(ctx: SockoptContext) -> Result { +fn try_{{crate_name}}(ctx: SockoptContext) -> Result { info!(&ctx, "{{sockopt_target}} called"); - Ok(0) + Ok(1) } {%- when "raw_tracepoint" %} -use aya_bpf::{macros::raw_tracepoint, programs::RawTracePointContext}; +use aya_bpf::{ + cty::c_long, + macros::raw_tracepoint, + programs::RawTracePointContext, +}; use aya_log_ebpf::info; #[raw_tracepoint(name = "{{crate_name}}")] -pub fn {{crate_name}}(ctx: RawTracePointContext) -> i32 { - match try_{{crate_name}}(ctx) { - Ok(ret) => ret, - Err(ret) => ret, - } +pub fn {{crate_name}}(ctx: RawTracePointContext) { + let _ = try_{{crate_name}}(ctx); } -fn try_{{crate_name}}(ctx: RawTracePointContext) -> Result { +fn try_{{crate_name}}(ctx: RawTracePointContext) -> Result<(), c_long> { info!(&ctx, "tracepoint {{tracepoint_name}} called"); - Ok(0) + Ok(()) } {%- when "perf_event" %} use aya_bpf::{ - helpers::bpf_get_smp_processor_id, macros::perf_event, programs::PerfEventContext, BpfContext, + cty::c_long, + helpers::bpf_get_smp_processor_id, + macros::perf_event, + programs::PerfEventContext, + BpfContext, }; use aya_log_ebpf::info; #[perf_event] pub fn {{crate_name}}(ctx: PerfEventContext) -> u32 { match try_{{crate_name}}(ctx) { - Ok(ret) => ret, - Err(ret) => ret, + Ok(_) => 0, + Err(_) => 1, } } -fn try_{{crate_name}}(ctx: PerfEventContext) -> Result { +fn try_{{crate_name}}(ctx: PerfEventContext) -> Result<(), c_long> { let cpu = unsafe { bpf_get_smp_processor_id() }; match ctx.pid() { 0 => info!( @@ -349,7 +372,7 @@ fn try_{{crate_name}}(ctx: PerfEventContext) -> Result { ), } - Ok(0) + Ok(()) } {%- endcase %}