Skip to content

Commit 5d0f5f9

Browse files
committed
adding dns preset
Signed-off-by: Shreyas220 <[email protected]> removing unused files Signed-off-by: Shreyas220 <[email protected]>
1 parent f50e70d commit 5d0f5f9

17 files changed

+834
-9
lines changed

KubeArmor/BPF/dnskprobe.bpf.c

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
//go:build ignore
2+
#include "shared.h"
3+
#include <bpf/bpf_helpers.h>
4+
#include <bpf/bpf_core_read.h>
5+
#include <bpf/bpf_tracing.h>
6+
#include <bpf/bpf_endian.h>
7+
8+
char LICENSE[] SEC("license") = "Dual BSD/GPL";
9+
10+
#define AF_INET 2
11+
#define ETH_P_IP 0x0800
12+
13+
static __always_inline u32 get_pid_ns_id(struct nsproxy *ns)
14+
{
15+
// Use BPF_CORE_READ to safely access kernel space memory
16+
struct pid_namespace *pidns = BPF_CORE_READ(ns, pid_ns_for_children);
17+
return BPF_CORE_READ(pidns, ns.inum);
18+
}
19+
20+
static __always_inline u32 get_task_pid_ns_id(struct task_struct *task)
21+
{
22+
return get_pid_ns_id(BPF_CORE_READ(task,nsproxy));
23+
}
24+
25+
static __always_inline u32 get_mnt_ns_id(struct nsproxy *ns)
26+
{
27+
// Use BPF_CORE_READ to safely access kernel space memory
28+
struct mnt_namespace *mntns = BPF_CORE_READ(ns, mnt_ns);
29+
return BPF_CORE_READ(mntns, ns.inum);
30+
}
31+
32+
static __always_inline u32 get_task_mnt_ns_id(struct task_struct *task)
33+
{
34+
return get_mnt_ns_id(BPF_CORE_READ(task,nsproxy));
35+
}
36+
37+
struct outer_key {
38+
u32 pid_ns;
39+
u32 mnt_ns;
40+
};
41+
42+
struct pid_maps{
43+
__uint(type, BPF_MAP_TYPE_HASH);
44+
__uint(max_entries, 256);
45+
__uint(key_size, sizeof(struct outer_key));
46+
__uint(value_size, sizeof(u32));
47+
__uint(pinning, LIBBPF_PIN_BY_NAME);
48+
} ;
49+
50+
struct pid_maps dns_container_maps SEC(".maps");
51+
52+
struct socket_print_key {
53+
__u32 remote_port;
54+
__u32 local_port;
55+
};
56+
57+
struct {
58+
__uint(type, BPF_MAP_TYPE_HASH);
59+
__uint(key_size, sizeof(struct socket_print_key));
60+
__uint(value_size, sizeof(struct __sk_buff));
61+
__uint(max_entries, 128);
62+
} socket_print SEC(".maps");
63+
64+
#define ETH_P_IP 0x0800
65+
66+
SEC("kprobe/udp_sendmsg")
67+
int BPF_KPROBE(ig_udp_sendmsg, struct sock *sk , struct msghdr *msg ,size_t len)
68+
{
69+
struct outer_key key;
70+
u32 *value;
71+
72+
struct task_struct *t = (struct task_struct *)bpf_get_current_task();
73+
74+
key.pid_ns = get_task_pid_ns_id(t);
75+
key.mnt_ns = get_task_mnt_ns_id(t);
76+
77+
value = bpf_map_lookup_elem(&dns_container_maps, &key);
78+
if (!value) {
79+
return 0;
80+
}
81+
bpf_printk("Kprobe container found pid %u and mnt %u", key.pid_ns, key.mnt_ns);
82+
83+
struct sock_common skcom;
84+
85+
bpf_probe_read(&skcom, sizeof(skcom), &sk->__sk_common);
86+
87+
u16 sport = skcom.skc_num;
88+
u16 dport = skcom.skc_dport;
89+
90+
// Processing only packets on port 53.
91+
// 13568 = ntohs(53);
92+
if (sport == 13568 || dport == 13568) {
93+
u32 saddr = skcom.skc_rcv_saddr;
94+
u32 daddr = skcom.skc_daddr;
95+
struct sockets_key socket_key = {0};
96+
BPF_CORE_READ_INTO(&socket_key.netns, sk, __sk_common.skc_net.net,ns.inum);
97+
socket_key.sport = sport;
98+
socket_key.dport = bpf_ntohs(dport);
99+
socket_key.saddr = bpf_ntohs(saddr);
100+
socket_key.daddr = bpf_ntohs(daddr);
101+
102+
struct socket_value socket_value;
103+
104+
socket_value.pid_tgid = bpf_get_current_pid_tgid();
105+
socket_value.uid_gid = bpf_get_current_uid_gid();
106+
bpf_get_current_comm(&socket_value.task, sizeof(socket_value.task));
107+
108+
bpf_map_update_elem(&dns_shared_map, &socket_key, &socket_value, BPF_ANY);
109+
110+
}
111+
112+
return 0;
113+
}

KubeArmor/BPF/dnssocket.bpf.c

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
//go:build ignore
2+
#include "shared.h"
3+
#include <bpf/bpf_helpers.h>
4+
#include <bpf/bpf_core_read.h>
5+
#include <bpf/bpf_tracing.h>
6+
#include <bpf/bpf_endian.h>
7+
8+
char LICENSE[] SEC("license") = "Dual BSD/GPL";
9+
10+
#define ETH_P_IP 0x0800 /* Internet Protocol packet */
11+
#define ETH_HLEN 14
12+
#define PACKET_HOST 0
13+
#define MAX_BUF_SIZE 300
14+
#define DNS_TYPE_A 1 // https://datatracker.ietf.org/doc/html/rfc1035#section-3.2.2
15+
#define MAX_DNS_NAME 255
16+
17+
struct event_t {
18+
__u32 netns;
19+
__u32 saddr_v4;
20+
__u32 daddr_v4;
21+
__u32 af;
22+
__u16 sport;
23+
__u16 dport;
24+
__u32 dns_length;
25+
__u64 pid;
26+
__u64 ppid;
27+
__u8 task[TASK_COMM_LEN];
28+
__u16 payload[MAX_BUF_SIZE];
29+
};
30+
31+
32+
struct {
33+
__uint(type, BPF_MAP_TYPE_RINGBUF);
34+
__uint(max_entries, 1 << 24);
35+
} socket_events SEC(".maps");
36+
37+
# define DNS_OFF (ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))
38+
39+
static volatile const __u32 current_netns ;
40+
41+
SEC("socket")
42+
int simple_socket_handler(struct __sk_buff *skb){
43+
44+
__u32 h_proto;
45+
__u8 protoc;
46+
__u8 name[MAX_DNS_NAME];
47+
__u16 sport, dport, l4_off, dns_off, id;
48+
//Check if the protocol is Ipv4
49+
bpf_skb_load_bytes(skb, offsetof(struct ethhdr, h_proto), &h_proto, sizeof(h_proto));
50+
51+
if (bpf_ntohs(h_proto) == ETH_P_IP){
52+
bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct iphdr, protocol),&protoc, sizeof(protoc));
53+
54+
if (protoc == IPPROTO_UDP){
55+
__u8 ihl_byte;
56+
bpf_skb_load_bytes(skb, ETH_HLEN, &ihl_byte,sizeof(ihl_byte));
57+
struct iphdr *iph = (struct iphdr *)&ihl_byte;
58+
__u8 ip_header_len = iph->ihl * 4;
59+
l4_off = ETH_HLEN + ip_header_len;
60+
61+
int off = l4_off;
62+
63+
if (skb->pkt_type == PACKET_HOST)
64+
off += offsetof(struct udphdr, dest);
65+
else
66+
off += offsetof(struct udphdr, source);
67+
68+
bpf_skb_load_bytes(skb, l4_off + offsetof(struct udphdr, dest),&dport, sizeof(dport));
69+
bpf_skb_load_bytes(skb, l4_off + offsetof(struct udphdr, source),&sport, sizeof(sport));
70+
71+
if (bpf_ntohs(sport) == 53 || bpf_ntohs(dport) == 53 || bpf_ntohs(sport) == 5353 || bpf_ntohs(dport) == 5353 ) {
72+
bpf_printk("currentns is %u",current_netns);
73+
struct sockets_key socket_key = {0,0,0,0};
74+
long err;
75+
__u8 packet_present = 0;
76+
77+
__u32 port;
78+
err = bpf_skb_load_bytes(skb, off, &port , sizeof(port));
79+
if (err < 0)
80+
return 0;
81+
82+
struct event_t *event;
83+
event = bpf_ringbuf_reserve(&socket_events, sizeof(struct event_t), 0);
84+
if (!event) {
85+
return 0;
86+
}
87+
88+
__u16 udp_total_length;
89+
bpf_skb_load_bytes(skb, l4_off + offsetof(struct udphdr, len), &udp_total_length, sizeof(udp_total_length));
90+
91+
__u32 dns_length = bpf_ntohs(udp_total_length) - sizeof(struct udphdr);
92+
event->dns_length = bpf_ntohs(dns_length);
93+
94+
u32 len_payload = 0;
95+
for (len_payload = 0; len_payload < 328; len_payload++) {
96+
if (len_payload == dns_length-1){
97+
break;
98+
}
99+
}
100+
len_payload = len_payload+1;
101+
102+
err = bpf_skb_load_bytes(skb, DNS_OFF, event->payload, len_payload);
103+
if (err != 0) {
104+
bpf_ringbuf_discard(event, 0);
105+
return 0;
106+
}
107+
108+
bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct iphdr, saddr),&event->saddr_v4, sizeof(event->saddr_v4));
109+
bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct iphdr, daddr),&event->daddr_v4, sizeof(event->daddr_v4));
110+
111+
socket_key.netns = current_netns;
112+
socket_key.saddr = bpf_ntohs(event->saddr_v4);
113+
socket_key.daddr = bpf_ntohs(event->daddr_v4);
114+
socket_key.sport = bpf_ntohs(sport);
115+
socket_key.dport = bpf_ntohs(dport);
116+
117+
struct socket_value *skb_val;
118+
skb_val = bpf_map_lookup_elem(&dns_shared_map, &socket_key);
119+
if (skb_val != NULL){
120+
event->pid = skb_val->uid_gid;
121+
event->ppid = skb_val->pid_tgid;
122+
packet_present = (uint32_t)1;
123+
}
124+
125+
event->sport = bpf_ntohs(sport);
126+
event->dport = bpf_ntohs(dport);
127+
event->netns = current_netns;
128+
129+
bpf_ringbuf_submit(event, 0);
130+
}
131+
}
132+
}
133+
return 0;
134+
}

KubeArmor/BPF/shared.h

+24
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,30 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL";
2525

2626
enum file_hook_type { dpath = 0, dfileread, dfilewrite };
2727

28+
struct sockets_key {
29+
__u32 netns;
30+
__u32 saddr;
31+
__u32 daddr;
32+
__u16 sport;
33+
__u16 dport;
34+
35+
};
36+
37+
struct socket_value {
38+
__u8 task[TASK_COMM_LEN];
39+
__u64 pid_tgid;
40+
__u64 uid_gid;
41+
};
42+
43+
struct {
44+
__uint(type, BPF_MAP_TYPE_HASH);
45+
__uint(key_size, sizeof(struct sockets_key));
46+
__uint(value_size, sizeof(struct socket_value));
47+
__uint(max_entries, 128);
48+
__uint(pinning, LIBBPF_PIN_BY_NAME);
49+
} dns_shared_map SEC(".maps");
50+
51+
2852
enum deny_by_default {
2953
dproc = 101,
3054
dfile,

KubeArmor/core/containerdHandler.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ func (ch *ContainerdHandler) GetContainerInfo(ctx context.Context, containerID s
192192
}
193193

194194
pid := strconv.Itoa(int(taskRes.Processes[0].Pid))
195+
container.Pid = int(taskRes.Processes[0].Pid)
195196

196197
if data, err := os.Readlink("/proc/" + pid + "/ns/pid"); err == nil {
197198
if _, err := fmt.Sscanf(data, "pid:[%d]\n", &container.PidNS); err != nil {
@@ -458,7 +459,7 @@ func (dm *KubeArmorDaemon) UpdateContainerdContainer(ctx context.Context, contai
458459
if dm.SystemMonitor != nil && cfg.GlobalCfg.Policy {
459460
// update NsMap
460461
dm.SystemMonitor.AddContainerIDToNsMap(containerID, container.NamespaceName, container.PidNS, container.MntNS)
461-
dm.RuntimeEnforcer.RegisterContainer(containerID, container.PidNS, container.MntNS)
462+
dm.RuntimeEnforcer.RegisterContainer(containerID, container)
462463

463464
if len(endPoint.SecurityPolicies) > 0 { // struct can be empty or no policies registered for the endPoint yet
464465
dm.Logger.UpdateSecurityPolicies("ADDED", endPoint)

KubeArmor/core/crioHandler.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ func (ch *CrioHandler) GetContainerInfo(ctx context.Context, containerID string,
128128
container.Privileged = containerInfo.Privileged
129129

130130
pid := strconv.Itoa(containerInfo.Pid)
131+
container.Pid = containerInfo.Pid
131132

132133
if data, err := os.Readlink("/proc/" + pid + "/ns/pid"); err == nil {
133134
if _, err := fmt.Sscanf(data, "pid:[%d]\n", &container.PidNS); err != nil {
@@ -267,7 +268,7 @@ func (dm *KubeArmorDaemon) UpdateCrioContainer(ctx context.Context, containerID,
267268
if dm.SystemMonitor != nil && cfg.GlobalCfg.Policy {
268269
// update NsMap
269270
dm.SystemMonitor.AddContainerIDToNsMap(containerID, container.NamespaceName, container.PidNS, container.MntNS)
270-
dm.RuntimeEnforcer.RegisterContainer(containerID, container.PidNS, container.MntNS)
271+
dm.RuntimeEnforcer.RegisterContainer(containerID, container)
271272

272273
if len(endpoint.SecurityPolicies) > 0 { // struct can be empty or no policies registered for the endpoint yet
273274
dm.Logger.UpdateSecurityPolicies("ADDED", endpoint)

KubeArmor/core/dockerHandler.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ func (dh *DockerHandler) GetContainerInfo(containerID string, OwnerInfo map[stri
143143
// == //
144144

145145
pid := strconv.Itoa(inspect.State.Pid)
146-
146+
container.Pid = inspect.State.Pid
147147
if data, err := os.Readlink("/proc/" + pid + "/ns/pid"); err == nil {
148148
if _, err := fmt.Sscanf(data, "pid:[%d]\n", &container.PidNS); err != nil {
149149
kg.Warnf("Unable to get PidNS (%s, %s, %s)", containerID, pid, err.Error())
@@ -423,7 +423,7 @@ func (dm *KubeArmorDaemon) GetAlreadyDeployedDockerContainers() {
423423
if dm.SystemMonitor != nil && cfg.GlobalCfg.Policy {
424424
// update NsMap
425425
dm.SystemMonitor.AddContainerIDToNsMap(container.ContainerID, container.NamespaceName, container.PidNS, container.MntNS)
426-
dm.RuntimeEnforcer.RegisterContainer(container.ContainerID, container.PidNS, container.MntNS)
426+
dm.RuntimeEnforcer.RegisterContainer(container.ContainerID, container)
427427

428428
if len(endPoint.SecurityPolicies) > 0 { // struct can be empty or no policies registered for the endpoint yet
429429
dm.Logger.UpdateSecurityPolicies("ADDED", endPoint)
@@ -602,7 +602,7 @@ func (dm *KubeArmorDaemon) UpdateDockerContainer(containerID, action string) {
602602
if dm.SystemMonitor != nil && cfg.GlobalCfg.Policy {
603603
// update NsMap
604604
dm.SystemMonitor.AddContainerIDToNsMap(containerID, container.NamespaceName, container.PidNS, container.MntNS)
605-
dm.RuntimeEnforcer.RegisterContainer(containerID, container.PidNS, container.MntNS)
605+
dm.RuntimeEnforcer.RegisterContainer(containerID, container)
606606

607607
if len(endPoint.SecurityPolicies) > 0 { // struct can be empty or no policies registered for the endpoint yet
608608
dm.Logger.UpdateSecurityPolicies("ADDED", endPoint)

KubeArmor/enforcer/runtimeEnforcer.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
cle "github.com/cilium/ebpf"
1414

15+
"github.com/kubearmor/KubeArmor/KubeArmor/presets/dns"
1516
probe "github.com/kubearmor/KubeArmor/KubeArmor/utils/bpflsmprobe"
1617

1718
kl "github.com/kubearmor/KubeArmor/KubeArmor/common"
@@ -38,6 +39,9 @@ type RuntimeEnforcer struct {
3839

3940
// LSM - SELinux
4041
seLinuxEnforcer *SELinuxEnforcer
42+
43+
//DNS
44+
dns *dns.Dnspreset
4145
}
4246

4347
// selectLsm Function
@@ -176,15 +180,22 @@ probeBPFLSM:
176180
}
177181

178182
// RegisterContainer registers container identifiers to BPFEnforcer Map
179-
func (re *RuntimeEnforcer) RegisterContainer(containerID string, pidns, mntns uint32) {
183+
func (re *RuntimeEnforcer) RegisterContainer(containerId string, container tp.Container) {
180184
// skip if runtime enforcer is not active
181185
if re == nil {
182186
return
183187
}
184188

185189
if re.EnforcerType == "BPFLSM" {
186-
re.bpfEnforcer.AddContainerIDToMap(containerID, pidns, mntns)
190+
re.bpfEnforcer.AddContainerIDToMap(containerId, container.PidNS, container.MntNS)
191+
}
192+
193+
//if preset available
194+
//add containerid to dns map placeholder until we have a check for preset
195+
if re.EnforcerType == "DNS" {
196+
re.dns.RegisterContainer(container)
187197
}
198+
188199
}
189200

190201
// UnregisterContainer removes container identifiers from BPFEnforcer Map
@@ -235,6 +246,11 @@ func (re *RuntimeEnforcer) UpdateSecurityPolicies(endPoint tp.EndPoint) {
235246
} else if re.EnforcerType == "AppArmor" {
236247
re.appArmorEnforcer.UpdateSecurityPolicies(endPoint)
237248
}
249+
// if present enabled
250+
251+
if re.EnforcerType == "DNS" {
252+
re.dns.UpdateSecurityPolicies(endPoint)
253+
}
238254
}
239255

240256
// UpdateHostSecurityPolicies Function

0 commit comments

Comments
 (0)