github.com/cilium/cilium@v1.16.2/bpf/lib/policy_log.h (about) 1 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 /* Copyright Authors of Cilium */ 3 4 /* 5 * Policy verdict notification via perf event ring buffer. 6 * 7 * API: 8 * void send_policy_verdict_notify(ctx, remote_label, dst_port, proto, dir, 9 * is_ipv6, verdict, match_type) 10 * 11 * If POLICY_VERDICT_NOTIFY is not defined, the API will be a non-op. 12 */ 13 #pragma once 14 15 #include "common.h" 16 17 #ifdef POLICY_VERDICT_NOTIFY 18 19 #ifndef POLICY_VERDICT_LOG_FILTER 20 DEFINE_U32(POLICY_VERDICT_LOG_FILTER, 0xffff); 21 #define POLICY_VERDICT_LOG_FILTER fetch_u32(POLICY_VERDICT_LOG_FILTER) 22 #endif 23 24 struct policy_verdict_notify { 25 NOTIFY_CAPTURE_HDR 26 __u32 remote_label; 27 __s32 verdict; 28 __u16 dst_port; 29 __u8 proto; 30 __u8 dir:2, 31 ipv6:1, 32 match_type:3, 33 audited:1, 34 pad0:1; 35 __u8 auth_type; 36 __u8 pad1; /* align with 64 bits */ 37 __u16 pad2; /* align with 64 bits */ 38 }; 39 40 static __always_inline bool policy_verdict_filter_allow(__u32 filter, __u8 dir) 41 { 42 /* Make dir being volatile to avoid compiler optimizing out 43 * filter (thinking it to be zero). 44 */ 45 volatile __u8 d = dir; 46 47 return ((filter & d) > 0); 48 } 49 50 static __always_inline void 51 send_policy_verdict_notify(struct __ctx_buff *ctx, __u32 remote_label, __u16 dst_port, 52 __u8 proto, __u8 dir, __u8 is_ipv6, int verdict, __u16 proxy_port, 53 __u8 match_type, __u8 is_audited, __u8 auth_type) 54 { 55 __u64 ctx_len = ctx_full_len(ctx); 56 __u64 cap_len = min_t(__u64, TRACE_PAYLOAD_LEN, ctx_len); 57 struct policy_verdict_notify msg; 58 59 #if defined(IS_BPF_HOST) 60 /* When this function is called in the context of bpf_host (e.g. by 61 * host firewall) POLICY_VERDICT_LOG_FILTER is always set to 0, 62 * preventing any policy verdict notification, as the logic to set it 63 * is only wired up to endpoints. 64 * 65 * Insead of tweaking POLICY_VERDICT_LOG_FILTER and reloading bpf_host 66 * based on whether host firewall policies are present or not, just 67 * always enable policy verdicts notifications, and filter out the ones 68 * for default allow policies, to prevent a flood of notifications for 69 * traffic allowed by default. 70 */ 71 if (match_type == POLICY_MATCH_ALL && verdict == CTX_ACT_OK) 72 return; 73 #else 74 if (!policy_verdict_filter_allow(POLICY_VERDICT_LOG_FILTER, dir)) 75 return; 76 #endif 77 78 if (verdict == 0) 79 verdict = (int)proxy_port; 80 81 msg = (typeof(msg)) { 82 __notify_common_hdr(CILIUM_NOTIFY_POLICY_VERDICT, 0), 83 __notify_pktcap_hdr(ctx_len, (__u16)cap_len), 84 .remote_label = remote_label, 85 .verdict = verdict, 86 .dst_port = bpf_ntohs(dst_port), 87 .match_type = match_type, 88 .proto = proto, 89 .dir = dir, 90 .ipv6 = is_ipv6, 91 .audited = is_audited, 92 .auth_type = auth_type, 93 }; 94 95 ctx_event_output(ctx, &EVENTS_MAP, 96 (cap_len << 32) | BPF_F_CURRENT_CPU, 97 &msg, sizeof(msg)); 98 } 99 #else 100 static __always_inline void 101 send_policy_verdict_notify(struct __ctx_buff *ctx __maybe_unused, 102 __u32 remote_label __maybe_unused, __u16 dst_port __maybe_unused, 103 __u8 proto __maybe_unused, __u8 dir __maybe_unused, 104 __u8 is_ipv6 __maybe_unused, int verdict __maybe_unused, 105 __u16 proxy_port __maybe_unused, 106 __u8 match_type __maybe_unused, __u8 is_audited __maybe_unused, 107 __u8 auth_type __maybe_unused) 108 { 109 } 110 #endif /* POLICY_VERDICT_NOTIFY */