Skip to content

Commit

Permalink
adding dns preset
Browse files Browse the repository at this point in the history
Signed-off-by: Shreyas220 <shreyas.ny@gmail.com>

removing unused files

Signed-off-by: Shreyas220 <shreyas.ny@gmail.com>
  • Loading branch information
Shreyas220 committed May 31, 2024
1 parent f50e70d commit 5d0f5f9
Show file tree
Hide file tree
Showing 17 changed files with 834 additions and 9 deletions.
113 changes: 113 additions & 0 deletions KubeArmor/BPF/dnskprobe.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//go:build ignore
#include "shared.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_endian.h>

char LICENSE[] SEC("license") = "Dual BSD/GPL";

#define AF_INET 2
#define ETH_P_IP 0x0800

static __always_inline u32 get_pid_ns_id(struct nsproxy *ns)
{
// Use BPF_CORE_READ to safely access kernel space memory
struct pid_namespace *pidns = BPF_CORE_READ(ns, pid_ns_for_children);
return BPF_CORE_READ(pidns, ns.inum);
}

static __always_inline u32 get_task_pid_ns_id(struct task_struct *task)
{
return get_pid_ns_id(BPF_CORE_READ(task,nsproxy));
}

static __always_inline u32 get_mnt_ns_id(struct nsproxy *ns)
{
// Use BPF_CORE_READ to safely access kernel space memory
struct mnt_namespace *mntns = BPF_CORE_READ(ns, mnt_ns);
return BPF_CORE_READ(mntns, ns.inum);
}

static __always_inline u32 get_task_mnt_ns_id(struct task_struct *task)
{
return get_mnt_ns_id(BPF_CORE_READ(task,nsproxy));
}

struct outer_key {
u32 pid_ns;
u32 mnt_ns;
};

struct pid_maps{
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 256);
__uint(key_size, sizeof(struct outer_key));
__uint(value_size, sizeof(u32));
__uint(pinning, LIBBPF_PIN_BY_NAME);
} ;

struct pid_maps dns_container_maps SEC(".maps");

struct socket_print_key {
__u32 remote_port;
__u32 local_port;
};

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(key_size, sizeof(struct socket_print_key));
__uint(value_size, sizeof(struct __sk_buff));
__uint(max_entries, 128);
} socket_print SEC(".maps");

#define ETH_P_IP 0x0800

SEC("kprobe/udp_sendmsg")
int BPF_KPROBE(ig_udp_sendmsg, struct sock *sk , struct msghdr *msg ,size_t len)
{
struct outer_key key;
u32 *value;

struct task_struct *t = (struct task_struct *)bpf_get_current_task();

key.pid_ns = get_task_pid_ns_id(t);
key.mnt_ns = get_task_mnt_ns_id(t);

value = bpf_map_lookup_elem(&dns_container_maps, &key);
if (!value) {
return 0;
}
bpf_printk("Kprobe container found pid %u and mnt %u", key.pid_ns, key.mnt_ns);

struct sock_common skcom;

bpf_probe_read(&skcom, sizeof(skcom), &sk->__sk_common);

u16 sport = skcom.skc_num;
u16 dport = skcom.skc_dport;

// Processing only packets on port 53.
// 13568 = ntohs(53);
if (sport == 13568 || dport == 13568) {
u32 saddr = skcom.skc_rcv_saddr;
u32 daddr = skcom.skc_daddr;
struct sockets_key socket_key = {0};
BPF_CORE_READ_INTO(&socket_key.netns, sk, __sk_common.skc_net.net,ns.inum);
socket_key.sport = sport;
socket_key.dport = bpf_ntohs(dport);
socket_key.saddr = bpf_ntohs(saddr);
socket_key.daddr = bpf_ntohs(daddr);

struct socket_value socket_value;

socket_value.pid_tgid = bpf_get_current_pid_tgid();
socket_value.uid_gid = bpf_get_current_uid_gid();
bpf_get_current_comm(&socket_value.task, sizeof(socket_value.task));

bpf_map_update_elem(&dns_shared_map, &socket_key, &socket_value, BPF_ANY);

}

return 0;
}
134 changes: 134 additions & 0 deletions KubeArmor/BPF/dnssocket.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
//go:build ignore
#include "shared.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_endian.h>

char LICENSE[] SEC("license") = "Dual BSD/GPL";

#define ETH_P_IP 0x0800 /* Internet Protocol packet */
#define ETH_HLEN 14
#define PACKET_HOST 0
#define MAX_BUF_SIZE 300
#define DNS_TYPE_A 1 // https://datatracker.ietf.org/doc/html/rfc1035#section-3.2.2
#define MAX_DNS_NAME 255

struct event_t {
__u32 netns;
__u32 saddr_v4;
__u32 daddr_v4;
__u32 af;
__u16 sport;
__u16 dport;
__u32 dns_length;
__u64 pid;
__u64 ppid;
__u8 task[TASK_COMM_LEN];
__u16 payload[MAX_BUF_SIZE];
};


struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 1 << 24);
} socket_events SEC(".maps");

# define DNS_OFF (ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))

static volatile const __u32 current_netns ;

SEC("socket")
int simple_socket_handler(struct __sk_buff *skb){

__u32 h_proto;
__u8 protoc;
__u8 name[MAX_DNS_NAME];
__u16 sport, dport, l4_off, dns_off, id;
//Check if the protocol is Ipv4
bpf_skb_load_bytes(skb, offsetof(struct ethhdr, h_proto), &h_proto, sizeof(h_proto));

if (bpf_ntohs(h_proto) == ETH_P_IP){
bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct iphdr, protocol),&protoc, sizeof(protoc));

if (protoc == IPPROTO_UDP){
__u8 ihl_byte;
bpf_skb_load_bytes(skb, ETH_HLEN, &ihl_byte,sizeof(ihl_byte));
struct iphdr *iph = (struct iphdr *)&ihl_byte;
__u8 ip_header_len = iph->ihl * 4;
l4_off = ETH_HLEN + ip_header_len;

int off = l4_off;

if (skb->pkt_type == PACKET_HOST)
off += offsetof(struct udphdr, dest);
else
off += offsetof(struct udphdr, source);

bpf_skb_load_bytes(skb, l4_off + offsetof(struct udphdr, dest),&dport, sizeof(dport));
bpf_skb_load_bytes(skb, l4_off + offsetof(struct udphdr, source),&sport, sizeof(sport));

if (bpf_ntohs(sport) == 53 || bpf_ntohs(dport) == 53 || bpf_ntohs(sport) == 5353 || bpf_ntohs(dport) == 5353 ) {
bpf_printk("currentns is %u",current_netns);
struct sockets_key socket_key = {0,0,0,0};
long err;
__u8 packet_present = 0;

__u32 port;
err = bpf_skb_load_bytes(skb, off, &port , sizeof(port));
if (err < 0)
return 0;

struct event_t *event;
event = bpf_ringbuf_reserve(&socket_events, sizeof(struct event_t), 0);
if (!event) {
return 0;
}

__u16 udp_total_length;
bpf_skb_load_bytes(skb, l4_off + offsetof(struct udphdr, len), &udp_total_length, sizeof(udp_total_length));

__u32 dns_length = bpf_ntohs(udp_total_length) - sizeof(struct udphdr);
event->dns_length = bpf_ntohs(dns_length);

u32 len_payload = 0;
for (len_payload = 0; len_payload < 328; len_payload++) {
if (len_payload == dns_length-1){
break;
}
}
len_payload = len_payload+1;

err = bpf_skb_load_bytes(skb, DNS_OFF, event->payload, len_payload);
if (err != 0) {
bpf_ringbuf_discard(event, 0);
return 0;
}

bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct iphdr, saddr),&event->saddr_v4, sizeof(event->saddr_v4));
bpf_skb_load_bytes(skb, ETH_HLEN + offsetof(struct iphdr, daddr),&event->daddr_v4, sizeof(event->daddr_v4));

socket_key.netns = current_netns;
socket_key.saddr = bpf_ntohs(event->saddr_v4);
socket_key.daddr = bpf_ntohs(event->daddr_v4);
socket_key.sport = bpf_ntohs(sport);
socket_key.dport = bpf_ntohs(dport);

struct socket_value *skb_val;
skb_val = bpf_map_lookup_elem(&dns_shared_map, &socket_key);
if (skb_val != NULL){
event->pid = skb_val->uid_gid;
event->ppid = skb_val->pid_tgid;
packet_present = (uint32_t)1;
}

event->sport = bpf_ntohs(sport);
event->dport = bpf_ntohs(dport);
event->netns = current_netns;

bpf_ringbuf_submit(event, 0);
}
}
}
return 0;
}
24 changes: 24 additions & 0 deletions KubeArmor/BPF/shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,30 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL";

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

struct sockets_key {
__u32 netns;
__u32 saddr;
__u32 daddr;
__u16 sport;
__u16 dport;

};

struct socket_value {
__u8 task[TASK_COMM_LEN];
__u64 pid_tgid;
__u64 uid_gid;
};

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(key_size, sizeof(struct sockets_key));
__uint(value_size, sizeof(struct socket_value));
__uint(max_entries, 128);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} dns_shared_map SEC(".maps");


enum deny_by_default {
dproc = 101,
dfile,
Expand Down
3 changes: 2 additions & 1 deletion KubeArmor/core/containerdHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ func (ch *ContainerdHandler) GetContainerInfo(ctx context.Context, containerID s
}

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

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

if len(endPoint.SecurityPolicies) > 0 { // struct can be empty or no policies registered for the endPoint yet
dm.Logger.UpdateSecurityPolicies("ADDED", endPoint)
Expand Down
3 changes: 2 additions & 1 deletion KubeArmor/core/crioHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ func (ch *CrioHandler) GetContainerInfo(ctx context.Context, containerID string,
container.Privileged = containerInfo.Privileged

pid := strconv.Itoa(containerInfo.Pid)
container.Pid = containerInfo.Pid

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

if len(endpoint.SecurityPolicies) > 0 { // struct can be empty or no policies registered for the endpoint yet
dm.Logger.UpdateSecurityPolicies("ADDED", endpoint)
Expand Down
6 changes: 3 additions & 3 deletions KubeArmor/core/dockerHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func (dh *DockerHandler) GetContainerInfo(containerID string, OwnerInfo map[stri
// == //

pid := strconv.Itoa(inspect.State.Pid)

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

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

if len(endPoint.SecurityPolicies) > 0 { // struct can be empty or no policies registered for the endpoint yet
dm.Logger.UpdateSecurityPolicies("ADDED", endPoint)
Expand Down
20 changes: 18 additions & 2 deletions KubeArmor/enforcer/runtimeEnforcer.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

cle "github.com/cilium/ebpf"

"github.com/kubearmor/KubeArmor/KubeArmor/presets/dns"
probe "github.com/kubearmor/KubeArmor/KubeArmor/utils/bpflsmprobe"

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

// LSM - SELinux
seLinuxEnforcer *SELinuxEnforcer

//DNS
dns *dns.Dnspreset
}

// selectLsm Function
Expand Down Expand Up @@ -176,15 +180,22 @@ probeBPFLSM:
}

// RegisterContainer registers container identifiers to BPFEnforcer Map
func (re *RuntimeEnforcer) RegisterContainer(containerID string, pidns, mntns uint32) {
func (re *RuntimeEnforcer) RegisterContainer(containerId string, container tp.Container) {
// skip if runtime enforcer is not active
if re == nil {
return
}

if re.EnforcerType == "BPFLSM" {
re.bpfEnforcer.AddContainerIDToMap(containerID, pidns, mntns)
re.bpfEnforcer.AddContainerIDToMap(containerId, container.PidNS, container.MntNS)
}

//if preset available
//add containerid to dns map placeholder until we have a check for preset
if re.EnforcerType == "DNS" {
re.dns.RegisterContainer(container)
}

}

// UnregisterContainer removes container identifiers from BPFEnforcer Map
Expand Down Expand Up @@ -235,6 +246,11 @@ func (re *RuntimeEnforcer) UpdateSecurityPolicies(endPoint tp.EndPoint) {
} else if re.EnforcerType == "AppArmor" {
re.appArmorEnforcer.UpdateSecurityPolicies(endPoint)
}
// if present enabled

if re.EnforcerType == "DNS" {
re.dns.UpdateSecurityPolicies(endPoint)
}
}

// UpdateHostSecurityPolicies Function
Expand Down
Loading

0 comments on commit 5d0f5f9

Please sign in to comment.