From 300236c59b2e0412b4f761bf14716d0b36ab7182 Mon Sep 17 00:00:00 2001 From: Zang Li Date: Thu, 5 Mar 2020 01:34:12 +0000 Subject: [PATCH] Add the datapath filtering for policy verdict logs. Generate policy verdict logs only if the endpoint does have a network policy enforced on the direction of the traffic. Signed-off-by: Zang Li --- bpf/lib/policy_log.h | 18 +++++++++++++ bpf/lxc_config.h | 3 +++ pkg/datapath/config.go | 3 +++ pkg/datapath/linux/config/config.go | 1 + pkg/datapath/loader/template.go | 14 +++++++--- pkg/endpoint/bpf.go | 14 ++++++++++ pkg/endpoint/cache.go | 42 ++++++++++++++++------------- pkg/monitor/datapath_policy.go | 2 +- pkg/testutils/endpoint.go | 1 + 9 files changed, 76 insertions(+), 22 deletions(-) diff --git a/bpf/lib/policy_log.h b/bpf/lib/policy_log.h index 878dca029293..711bdfabf4a0 100644 --- a/bpf/lib/policy_log.h +++ b/bpf/lib/policy_log.h @@ -15,6 +15,12 @@ #include "common.h" #ifdef POLICY_VERDICT_NOTIFY + +#ifndef POLICY_VERDICT_LOG_FILTER +DEFINE_U32(POLICY_VERDICT_LOG_FILTER, 0xffff); +#define POLICY_VERDICT_LOG_FILTER fetch_u32(POLICY_VERDICT_LOG_FILTER) +#endif + struct policy_verdict_notify { NOTIFY_CAPTURE_HDR __u32 remote_label; @@ -28,11 +34,23 @@ struct policy_verdict_notify { __u32 pad1; // align with 64 bits }; +static __always_inline bool policy_verdict_filter_allow(__u32 filter, __u8 dir) +{ + // Make dir being volatile to avoid compiler optimizing out filter (thinking + // it to be zero). + volatile __u8 d = dir; + return ((filter & d) > 0); +} + static __always_inline void send_policy_verdict_notify(struct __ctx_buff *ctx, __u32 remote_label, __u16 dst_port, __u8 proto, __u8 dir, __u8 is_ipv6, int verdict, __u8 match_type) { + if (!policy_verdict_filter_allow(POLICY_VERDICT_LOG_FILTER, dir)) { + return; + } + __u64 ctx_len = (__u64)ctx_full_len(ctx); __u64 cap_len = min((__u64)TRACE_PAYLOAD_LEN, (__u64)ctx_len); __u32 hash = get_hash_recalc(ctx); diff --git a/bpf/lxc_config.h b/bpf/lxc_config.h index ebcef5268185..c7d08b1be404 100644 --- a/bpf/lxc_config.h +++ b/bpf/lxc_config.h @@ -17,6 +17,9 @@ DEFINE_U32(SECLABEL, 0xfffff); DEFINE_U32(SECLABEL_NB, 0xfffff); #define SECLABEL_NB fetch_u32(SECLABEL_NB) +DEFINE_U32(POLICY_VERDICT_LOG_FILTER, 0xffff); +#define POLICY_VERDICT_LOG_FILTER fetch_u32(POLICY_VERDICT_LOG_FILTER) + #define POLICY_MAP test_cilium_policy_65535 #ifndef SKIP_DEBUG diff --git a/pkg/datapath/config.go b/pkg/datapath/config.go index 3d0b2abd526b..4dba8ab34132 100644 --- a/pkg/datapath/config.go +++ b/pkg/datapath/config.go @@ -74,6 +74,9 @@ type EndpointConfiguration interface { // per endpoint route installed in the host's routing table to point to // the endpoint's interface RequireEndpointRoute() bool + + // GetPolicyVerdictLogFilter returns the PolicyVerdictLogFilter for the endpoint + GetPolicyVerdictLogFilter() uint32 } // ConfigWriter is anything which writes the configuration for various datapath diff --git a/pkg/datapath/linux/config/config.go b/pkg/datapath/linux/config/config.go index 94757a09f07f..28580c0fb075 100644 --- a/pkg/datapath/linux/config/config.go +++ b/pkg/datapath/linux/config/config.go @@ -366,6 +366,7 @@ func (h *HeaderfileWriter) writeStaticData(fw io.Writer, e datapath.EndpointConf secID := e.GetIdentity().Uint32() fmt.Fprintf(fw, defineUint32("SECLABEL", secID)) fmt.Fprintf(fw, defineUint32("SECLABEL_NB", byteorder.HostToNetwork(secID).(uint32))) + fmt.Fprintf(fw, defineUint32("POLICY_VERDICT_LOG_FILTER", e.GetPolicyVerdictLogFilter())) epID := uint16(e.GetID()) fmt.Fprintf(fw, "#define POLICY_MAP %s\n", bpf.LocalMapName(policymap.MapName, epID)) diff --git a/pkg/datapath/loader/template.go b/pkg/datapath/loader/template.go index 9c1df8e90bc9..c08f9b124fb5 100644 --- a/pkg/datapath/loader/template.go +++ b/pkg/datapath/loader/template.go @@ -32,8 +32,9 @@ import ( const ( CallsMapName = "cilium_calls_" - templateSecurityID = identity.ReservedIdentityWorld - templateLxcID = uint16(65535) + templateSecurityID = identity.ReservedIdentityWorld + templateLxcID = uint16(65535) + templatePolicyVerdictFilter = uint32(0xffff) ) var ( @@ -117,6 +118,13 @@ func (t *templateCfg) IPv6Address() addressing.CiliumIPv6 { return addressing.CiliumIPv6(templateIPv6) } +// GetPolicyVerdictLogFilter returns an uint32 filter to ensure +// that the filter is non-zero as per the requirements +// described in the structure definition. +func (t *templateCfg) GetPolicyVerdictLogFilter() uint32 { + return templatePolicyVerdictFilter +} + // wrap takes an endpoint configuration and optional stats tracker and wraps // it inside a templateCfg which hides static data from callers that wish to // generate header files based on the configuration, substituting it for @@ -205,7 +213,7 @@ func elfVariableSubstitutions(ep datapath.Endpoint) map[string]uint32 { identity := ep.GetIdentity().Uint32() result["SECLABEL"] = identity result["SECLABEL_NB"] = byteorder.HostToNetwork(identity).(uint32) - + result["POLICY_VERDICT_LOG_FILTER"] = ep.GetPolicyVerdictLogFilter() return result } diff --git a/pkg/endpoint/bpf.go b/pkg/endpoint/bpf.go index e635930473bc..07b3e672c429 100644 --- a/pkg/endpoint/bpf.go +++ b/pkg/endpoint/bpf.go @@ -1303,6 +1303,20 @@ func (e *Endpoint) RequireEndpointRoute() bool { return e.DatapathConfiguration.InstallEndpointRoute } +// GetPolicyVerdictLogFilter returns the PolicyVerdictLogFilter that would control +// the creation of policy verdict logs. Value of VerdictLogFilter needs to be +// consistent with how it is used in policy_verdict_filter_allow() in bpf/lib/policy_log.h +func (e *Endpoint) GetPolicyVerdictLogFilter() uint32 { + var filter uint32 = 0 + if e.desiredPolicy.IngressPolicyEnabled { + filter = (filter | 0x1) + } + if e.desiredPolicy.EgressPolicyEnabled { + filter = (filter | 0x2) + } + return filter +} + type linkCheckerFunc func(string) error // ValidateConnectorPlumbing checks whether the endpoint is correctly plumbed diff --git a/pkg/endpoint/cache.go b/pkg/endpoint/cache.go index f7ea8263f14b..0251cae55622 100644 --- a/pkg/endpoint/cache.go +++ b/pkg/endpoint/cache.go @@ -50,6 +50,7 @@ type epInfoCache struct { requireEgressProg bool requireRouting bool requireEndpointRoute bool + policyVerdictLogFilter uint32 cidr4PrefixLengths, cidr6PrefixLengths []int options *option.IntOptions lxcMAC mac.MAC @@ -71,24 +72,25 @@ func (e *Endpoint) createEpInfoCache(epdir string) *epInfoCache { ep := &epInfoCache{ revision: e.nextPolicyRevision, - epdir: epdir, - id: e.GetID(), - ifName: e.ifName, - ipvlan: e.HasIpvlanDataPath(), - identity: e.GetIdentity(), - mac: e.GetNodeMAC(), - ipv4: e.IPv4Address(), - ipv6: e.IPv6Address(), - conntrackLocal: e.ConntrackLocalLocked(), - requireARPPassthrough: e.RequireARPPassthrough(), - requireEgressProg: e.RequireEgressProg(), - requireRouting: e.RequireRouting(), - requireEndpointRoute: e.RequireEndpointRoute(), - cidr4PrefixLengths: cidr4, - cidr6PrefixLengths: cidr6, - options: e.Options.DeepCopy(), - lxcMAC: e.mac, - ifIndex: e.ifIndex, + epdir: epdir, + id: e.GetID(), + ifName: e.ifName, + ipvlan: e.HasIpvlanDataPath(), + identity: e.GetIdentity(), + mac: e.GetNodeMAC(), + ipv4: e.IPv4Address(), + ipv6: e.IPv6Address(), + conntrackLocal: e.ConntrackLocalLocked(), + requireARPPassthrough: e.RequireARPPassthrough(), + requireEgressProg: e.RequireEgressProg(), + requireRouting: e.RequireRouting(), + requireEndpointRoute: e.RequireEndpointRoute(), + policyVerdictLogFilter: e.GetPolicyVerdictLogFilter(), + cidr4PrefixLengths: cidr4, + cidr6PrefixLengths: cidr6, + options: e.Options.DeepCopy(), + lxcMAC: e.mac, + ifIndex: e.ifIndex, endpoint: e, } @@ -187,3 +189,7 @@ func (ep *epInfoCache) RequireRouting() bool { func (ep *epInfoCache) RequireEndpointRoute() bool { return ep.requireEndpointRoute } + +func (ep *epInfoCache) GetPolicyVerdictLogFilter() uint32 { + return ep.policyVerdictLogFilter +} diff --git a/pkg/monitor/datapath_policy.go b/pkg/monitor/datapath_policy.go index e57012976209..83576dcd8580 100644 --- a/pkg/monitor/datapath_policy.go +++ b/pkg/monitor/datapath_policy.go @@ -96,7 +96,7 @@ type PolicyVerdictNotify struct { DstPort uint16 Proto uint8 Flags uint8 - Pad2 uint32 + Pad1 uint32 // data } diff --git a/pkg/testutils/endpoint.go b/pkg/testutils/endpoint.go index 4482b0253da3..a4ce92beb79a 100644 --- a/pkg/testutils/endpoint.go +++ b/pkg/testutils/endpoint.go @@ -55,6 +55,7 @@ func (e *TestEndpoint) RequireARPPassthrough() bool { return false } func (e *TestEndpoint) RequireEgressProg() bool { return false } func (e *TestEndpoint) RequireRouting() bool { return false } func (e *TestEndpoint) RequireEndpointRoute() bool { return false } +func (e *TestEndpoint) GetPolicyVerdictLogFilter() uint32 { return 0xffff } func (e *TestEndpoint) GetCIDRPrefixLengths() ([]int, []int) { return nil, nil } func (e *TestEndpoint) GetID() uint64 { return e.Id } func (e *TestEndpoint) StringID() string { return "42" }