Skip to content

[CWS] introduce network filter action #39066

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/cloud-workload-security/backend_linux.md
Original file line number Diff line number Diff line change
Expand Up @@ -1633,6 +1633,9 @@ Workload Protection events for Linux systems have the following JSON schema:
},
"tls": {
"$ref": "#/$defs/TLSContext"
},
"dropped": {
"type": "boolean"
}
},
"additionalProperties": false,
Expand Down Expand Up @@ -4599,6 +4602,9 @@ Workload Protection events for Linux systems have the following JSON schema:
},
"tls": {
"$ref": "#/$defs/TLSContext"
},
"dropped": {
"type": "boolean"
}
},
"additionalProperties": false,
Expand Down
3 changes: 3 additions & 0 deletions docs/cloud-workload-security/backend_linux.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1622,6 +1622,9 @@
},
"tls": {
"$ref": "#/$defs/TLSContext"
},
"dropped": {
"type": "boolean"
}
},
"additionalProperties": false,
Expand Down
7 changes: 6 additions & 1 deletion pkg/security/ebpf/c/include/constants/custom.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,13 @@ enum TC_TAIL_CALL_KEYS {
DNS_RESPONSE
};

// see probes/rawpacket/pcap.go
#define RAW_PACKET_MAX_TAIL_CALL 5

enum TC_RAWPACKET_KEYS {
RAW_PACKET_FILTER,
// reserved keys for raw packet filter tail calls
RAW_PACKET_DROP_ACTION = RAW_PACKET_FILTER + RAW_PACKET_MAX_TAIL_CALL + 1, // + 1 for the sender program
};

#define DNS_MAX_LENGTH 256
Expand Down Expand Up @@ -260,7 +264,8 @@ enum link_target_dentry_origin {
};

enum global_rate_limiter_type {
RAW_PACKET_LIMITER = 0,
RAW_PACKET_FILTER_LIMITER = 0,
RAW_PACKET_ACTION_LIMITER,
};

#define TAIL_CALL_FNC_NAME(name, ...) tail_call_##name(__VA_ARGS__)
Expand Down
3 changes: 2 additions & 1 deletion pkg/security/ebpf/c/include/constants/enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,15 @@ enum event_type
EVENT_ON_DEMAND,
EVENT_LOGIN_UID_WRITE,
EVENT_CGROUP_WRITE,
EVENT_RAW_PACKET,
EVENT_RAW_PACKET_FILTER,
EVENT_NETWORK_FLOW_MONITOR,
EVENT_STAT,
EVENT_SYSCTL,
EVENT_SETRLIMIT,
EVENT_SETSOCKOPT,
EVENT_FSMOUNT,
EVENT_OPEN_TREE,
EVENT_RAW_PACKET_ACTION,
EVENT_MAX, // has to be the last one

EVENT_ALL = 0xffffffff // used as a mask for all the events
Expand Down
2 changes: 1 addition & 1 deletion pkg/security/ebpf/c/include/events_definition.h
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ struct raw_packet_event_t {
struct container_context_t container;
struct network_device_context_t device;

int len;
u32 len;
char data[256];
};

Expand Down
1 change: 0 additions & 1 deletion pkg/security/ebpf/c/include/hooks/cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ int __attribute__((always_inline)) dr_cgroup_write_callback(void *ctx) {
return 0;
}


TAIL_CALL_FNC(dr_cgroup_write_callback, ctx_t *ctx) {
return dr_cgroup_write_callback(ctx);
}
Expand Down
31 changes: 22 additions & 9 deletions pkg/security/ebpf/c/include/hooks/network/raw.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,8 @@
#include "helpers/network/raw.h"
#include "perf_ring.h"

TAIL_CALL_CLASSIFIER_FNC(raw_packet_sender, struct __sk_buff *skb) {
u64 rate = 10;
LOAD_CONSTANT("raw_packet_limiter_rate", rate);

if (!global_limiter_allow(RAW_PACKET_LIMITER, rate, 1)) {
return TC_ACT_UNSPEC;
}

__attribute__((always_inline)) int send_raw_packet_event(struct __sk_buff *skb, u32 event_type, u32 action) {
struct packet_t *pkt = get_packet();
if (pkt == NULL) {
// should never happen
Expand Down Expand Up @@ -50,9 +44,28 @@ TAIL_CALL_CLASSIFIER_FNC(raw_packet_sender, struct __sk_buff *skb) {
len = sizeof(evt->data);
}

send_event_with_size_ptr(skb, EVENT_RAW_PACKET, evt, offsetof(struct raw_packet_event_t, data) + len);
send_event_with_size_ptr(skb, event_type, evt, offsetof(struct raw_packet_event_t, data) + len);

return action;
}

TAIL_CALL_CLASSIFIER_FNC(raw_packet_sender, struct __sk_buff *skb) {
u64 rate = 10;
LOAD_CONSTANT("raw_packet_limiter_rate", rate);

if (!global_limiter_allow(RAW_PACKET_FILTER_LIMITER, rate, 1)) {
return TC_ACT_UNSPEC;
}

return send_raw_packet_event(skb, EVENT_RAW_PACKET_FILTER, TC_ACT_UNSPEC);
}

TAIL_CALL_CLASSIFIER_FNC(raw_packet_drop_action_cb, struct __sk_buff *skb) {
if (!global_limiter_allow(RAW_PACKET_ACTION_LIMITER, 1, 1)) {
return TC_ACT_SHOT;
}

return TC_ACT_UNSPEC;
return send_raw_packet_event(skb, EVENT_RAW_PACKET_ACTION, TC_ACT_SHOT);
}

#endif
15 changes: 12 additions & 3 deletions pkg/security/ebpf/c/include/hooks/network/tc.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ int classifier_egress(struct __sk_buff *skb) {
return route_pkt(skb, pkt, EGRESS);
};

__attribute__((always_inline)) int prepare_raw_packet_event(struct __sk_buff *skb) {
__attribute__((always_inline)) int prepare_raw_packet_event(struct __sk_buff *skb, struct packet_t *pkt) {
struct raw_packet_event_t *evt = get_raw_packet_event();
if (evt == NULL) {
// should never happen
return TC_ACT_UNSPEC;
}

evt->process.pid = pkt->pid;

bpf_skb_pull_data(skb, 0);

u32 len = *(u32 *)(skb + offsetof(struct __sk_buff, len));
Expand Down Expand Up @@ -90,7 +92,7 @@ int classifier_raw_packet_ingress(struct __sk_buff *skb) {
return TC_ACT_UNSPEC;
}

if (prepare_raw_packet_event(skb) != TC_ACT_UNSPEC) {
if (prepare_raw_packet_event(skb, pkt) != TC_ACT_UNSPEC) {
return TC_ACT_UNSPEC;
}

Expand All @@ -112,13 +114,20 @@ int classifier_raw_packet_egress(struct __sk_buff *skb) {
resolve_pid(pkt);

if (!is_raw_packet_allowed(pkt)) {
// call the drop action any way
bpf_tail_call_compat(skb, &raw_packet_classifier_router, RAW_PACKET_DROP_ACTION);

return TC_ACT_UNSPEC;
}

if (prepare_raw_packet_event(skb) != TC_ACT_UNSPEC) {
if (prepare_raw_packet_event(skb, pkt) != TC_ACT_UNSPEC) {
return TC_ACT_UNSPEC;
}

// call the drop action
bpf_tail_call_compat(skb, &raw_packet_classifier_router, RAW_PACKET_DROP_ACTION);

// call regular filter
bpf_tail_call_compat(skb, &raw_packet_classifier_router, RAW_PACKET_FILTER);

return TC_ACT_UNSPEC;
Expand Down
26 changes: 26 additions & 0 deletions pkg/security/ebpf/c/include/tests/raw_packet_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,32 @@ int raw_packet_tail_calls(struct __sk_buff *skb) {
return 1;
}

SEC("test/raw_packet_drop_action")
int raw_packet_drop_action(struct __sk_buff *skb) {
struct raw_packet_event_t *evt = get_raw_packet_event();
evt->process.pid = 123;

// assert_not_null(evt, "unable to get raw packet event")
assert_not_null(evt, "unable to get raw packet event")

// tcp dst port 5555 and tcp[tcpflags] == tcp-syn
unsigned char data[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x10,
0x00, 0x30, 0xf4, 0xa2, 0x40, 0x00, 0x40, 0x06,
0x48, 0x13, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00,
0x00, 0x01, 0xa2, 0x36, 0x15, 0xb3, 0x1c, 0x5b,
0x89, 0x33, 0x00, 0x00, 0x00, 0x00, 0x70, 0x02,
0xff, 0xd7, 0xfe, 0x24, 0x00, 0x00, 0x02, 0x04,
0xff, 0xd7, 0x01, 0x03, 0x03, 0x07
};
baloum_memcpy(evt->data, data, sizeof(data));

bpf_tail_call_compat(skb, &raw_packet_classifier_router, RAW_PACKET_DROP_ACTION);

return 1;
}

SEC("test/raw_packet_bpfdoor_magic_number")
int raw_packet_bpfdoor_magic_number(struct __sk_buff *skb) {
struct raw_packet_event_t *evt = get_raw_packet_event();
Expand Down
15 changes: 10 additions & 5 deletions pkg/security/ebpf/probes/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ const (
)

const (
// RawPacketFilterMaxTailCall defines the maximum of tail calls
RawPacketFilterMaxTailCall = 5
// RawPacketMaxTailCall defines the maximum of tail calls, see constants/custom.h
RawPacketMaxTailCall = 5
)

const (
Expand All @@ -92,9 +92,14 @@ const (
const (
// TCRawPacketFilterKey is the key to the raw packet filter program
// reserve 5 tail calls for the filtering
TCRawPacketFilterKey uint32 = iota
// TCRawPacketParserSenderKey is the key to the raw packet sender program
TCRawPacketParserSenderKey = TCRawPacketFilterKey + RawPacketFilterMaxTailCall // reserved key for filter tail calls
TCRawPacketFilterKey uint32 = 0
// TCRawPacketSenderKey is the key to the raw packet sender program
TCRawPacketSenderKey = TCRawPacketFilterKey + RawPacketMaxTailCall

// TCRawPacketDropActionKey is the key to the raw packet drop action program
TCRawPacketDropActionKey = TCRawPacketSenderKey + 1
// TCRawPacketDropActionShotKey is the key to the raw packet drop action program
TCRawPacketDropActionShotKey = TCRawPacketDropActionKey + RawPacketMaxTailCall
)

const (
Expand Down
60 changes: 58 additions & 2 deletions pkg/security/ebpf/probes/rawpacket/bpffilter.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,66 @@ package rawpacket

import (
"github.com/DataDog/datadog-agent/pkg/security/secl/compiler/eval"
"github.com/DataDog/datadog-agent/pkg/security/secl/model"
)

// TCAct is the type of the tc action
type TCAct int

const (
// TCActOk will terminate the packet processing pipeline and allows the packet to proceed
TCActOk TCAct = 0
// TCActShot will terminate the packet processing pipeline and drop the packet
TCActShot TCAct = 2
// TCActUnspec will continue packet processing
TCActUnspec TCAct = -1
)

// Policy defines the policy for a raw packet filter
type Policy int

const (
// PolicyAllow allows the packet to pass
PolicyAllow Policy = iota
// PolicyDrop drops the packet
PolicyDrop
)

// ToTCAct converts a policy to a TCAct
func (p Policy) ToTCAct() TCAct {
switch p {
case PolicyDrop:
return TCActShot
default:
return TCActUnspec
}
}

// String returns the string representation of the policy
func (p Policy) String() string {
switch p {
case PolicyDrop:
return "drop"
default:
return "allow"
}
}

// Parse parses a string and sets the policy
func (p *Policy) Parse(str string) {
switch str {
case "drop":
*p = PolicyDrop
default:
*p = PolicyAllow
}
}

// Filter defines a raw packet filter
type Filter struct {
RuleID eval.RuleID
BPFFilter string
RuleID eval.RuleID
BPFFilter string
Policy Policy
Pid uint32
CGroupPathKey model.PathKey
}
Loading