Skip to content
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

feat(monitor):Syscall Visibility #1611

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
70 changes: 61 additions & 9 deletions KubeArmor/BPF/system_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ enum
_PROCESS_PROBE = 1,
_NETWORK_PROBE = 2,
_CAPS_PROBE = 3,
_SYSCALL_PROBE = 4,

_TRACE_SYSCALL = 0,
_IGNORE_SYSCALL = 1,
Expand Down Expand Up @@ -355,6 +356,30 @@ struct kaconfig

struct kaconfig kubearmor_config SEC(".maps");

// == Syscall Visibility == //

struct syscallvis
{
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, u32);
__type(value, u32);
__uint(max_entries, 322);
__uint(pinning, LIBBPF_PIN_BY_NAME);
};

struct syscallvis kubearmor_syscall_vis SEC(".maps");

static __always_inline u32 get_syscalls_visibility(u32 syscallID)
{
u32 *value = bpf_map_lookup_elem(&kubearmor_syscall_vis, &syscallID);
if (!value)
{
return 0;
}

return *value;
}

// == Kernel Helpers == //

static __always_inline u32 get_pid_ns_id(struct nsproxy *ns)
Expand Down Expand Up @@ -1611,7 +1636,10 @@ int kprobe__unlink(struct pt_regs *ctx)
SEC("kretprobe/__x64_sys_unlink")
int kretprobe__unlink(struct pt_regs *ctx)
{
return trace_ret_generic(_SYS_UNLINK, ctx, ARG_TYPE0(INT_T) | ARG_TYPE1(FILE_TYPE_T), _FILE_PROBE);
if (!get_syscalls_visibility(_SYS_UNLINK)){
return 0;
}
return trace_ret_generic(_SYS_UNLINK, ctx, ARG_TYPE0(INT_T) | ARG_TYPE1(FILE_TYPE_T), _SYSCALL_PROBE);
}

SEC("kprobe/__x64_sys_unlinkat")
Expand All @@ -1626,7 +1654,10 @@ int kprobe__unlinkat(struct pt_regs *ctx)
SEC("kretprobe/__x64_sys_unlinkat")
int kretprobe__unlinkat(struct pt_regs *ctx)
{
return trace_ret_generic(_SYS_UNLINKAT, ctx, ARG_TYPE0(INT_T) | ARG_TYPE1(FILE_TYPE_T) | ARG_TYPE2(UNLINKAT_FLAG_T), _FILE_PROBE);
if (!get_syscalls_visibility(_SYS_UNLINKAT)){
return 0;
}
return trace_ret_generic(_SYS_UNLINKAT, ctx, ARG_TYPE0(INT_T) | ARG_TYPE1(FILE_TYPE_T) | ARG_TYPE2(UNLINKAT_FLAG_T), _SYSCALL_PROBE);
}

SEC("kprobe/__x64_sys_rmdir")
Expand Down Expand Up @@ -1670,7 +1701,10 @@ int kprobe__chown(struct pt_regs *ctx)
SEC("kretprobe/__x64_sys_chown")
int kretprobe__chown(struct pt_regs *ctx)
{
return trace_ret_generic(_SYS_CHOWN, ctx, ARG_TYPE0(FILE_TYPE_T) | ARG_TYPE1(INT_T) | ARG_TYPE2(INT_T), _FILE_PROBE);
if (!get_syscalls_visibility(_SYS_CHOWN)){
return 0;
}
return trace_ret_generic(_SYS_CHOWN, ctx, ARG_TYPE0(FILE_TYPE_T) | ARG_TYPE1(INT_T) | ARG_TYPE2(INT_T), _SYSCALL_PROBE);
}

SEC("kprobe/__x64_sys_fchownat")
Expand All @@ -1684,7 +1718,10 @@ int kprobe__fchownat(struct pt_regs *ctx)
SEC("kretprobe/__x64_sys_fchownat")
int kretprobe__fchownat(struct pt_regs *ctx)
{
return trace_ret_generic(_SYS_FCHOWNAT, ctx, ARG_TYPE0(INT_T) | ARG_TYPE1(FILE_TYPE_T) | ARG_TYPE2(INT_T) | ARG_TYPE3(INT_T) | ARG_TYPE4(INT_T), _FILE_PROBE);
if (!get_syscalls_visibility(_SYS_FCHOWNAT)){
return 0;
}
return trace_ret_generic(_SYS_FCHOWNAT, ctx, ARG_TYPE0(INT_T) | ARG_TYPE1(FILE_TYPE_T) | ARG_TYPE2(INT_T) | ARG_TYPE3(INT_T) | ARG_TYPE4(INT_T), _SYSCALL_PROBE);
}

SEC("kprobe/__x64_sys_setuid")
Expand All @@ -1698,7 +1735,10 @@ int kprobe__setuid(struct pt_regs *ctx)
SEC("kretprobe/__x64_sys_setuid")
int kretprobe__setuid(struct pt_regs *ctx)
{
return trace_ret_generic(_SYS_SETUID, ctx, ARG_TYPE0(INT_T), _CAPS_PROBE);
if (!get_syscalls_visibility(_SYS_SETUID)){
return 0;
}
return trace_ret_generic(_SYS_SETUID, ctx, ARG_TYPE0(INT_T), _SYSCALL_PROBE);
}

SEC("kprobe/__x64_sys_setgid")
Expand All @@ -1712,7 +1752,10 @@ int kprobe__setgid(struct pt_regs *ctx)
SEC("kretprobe/__x64_sys_setgid")
int kretprobe__setgid(struct pt_regs *ctx)
{
return trace_ret_generic(_SYS_SETGID, ctx, ARG_TYPE0(INT_T), _CAPS_PROBE);
if (!get_syscalls_visibility(_SYS_SETGID)){
return 0;
}
return trace_ret_generic(_SYS_SETGID, ctx, ARG_TYPE0(INT_T), _SYSCALL_PROBE);
}

SEC("kprobe/__x64_sys_ptrace")
Expand All @@ -1726,7 +1769,10 @@ int kprobe__ptrace(struct pt_regs *ctx)
SEC("kretprobe/__x64_sys_ptrace")
int kretprobe__ptrace(struct pt_regs *ctx)
{
return trace_ret_generic(_SYS_PTRACE, ctx, ARG_TYPE0(PTRACE_REQ_T) | ARG_TYPE1(INT_T) | ARG_TYPE2(FILE_TYPE_T), _CAPS_PROBE);
if (!get_syscalls_visibility(_SYS_PTRACE)){
return 0;
}
return trace_ret_generic(_SYS_PTRACE, ctx, ARG_TYPE0(PTRACE_REQ_T) | ARG_TYPE1(INT_T) | ARG_TYPE2(FILE_TYPE_T), _SYSCALL_PROBE);
}

SEC("kprobe/__x64_sys_mount")
Expand All @@ -1740,7 +1786,10 @@ int kprobe__mount(struct pt_regs *ctx)
SEC("kretprobe/__x64_sys_mount")
int kretprobe__mount(struct pt_regs *ctx)
{
return trace_ret_generic(_SYS_MOUNT, ctx, ARG_TYPE0(STR_T) | ARG_TYPE1(STR_T) | ARG_TYPE2(STR_T) | ARG_TYPE3(MOUNT_FLAG_T) | ARG_TYPE4(STR_T), _CAPS_PROBE);
if (!get_syscalls_visibility(_SYS_MOUNT)){
return 0;
}
return trace_ret_generic(_SYS_MOUNT, ctx, ARG_TYPE0(STR_T) | ARG_TYPE1(STR_T) | ARG_TYPE2(STR_T) | ARG_TYPE3(MOUNT_FLAG_T) | ARG_TYPE4(STR_T), _SYSCALL_PROBE);
}

SEC("kprobe/__x64_sys_umount")
Expand All @@ -1754,7 +1803,10 @@ int kprobe__umount(struct pt_regs *ctx)
SEC("kretprobe/__x64_sys_umount")
int kretprobe__umount(struct pt_regs *ctx)
{
return trace_ret_generic(_SYS_UMOUNT, ctx, ARG_TYPE0(STR_T) | ARG_TYPE1(UMOUNT_FLAG_T), _CAPS_PROBE);
if (!get_syscalls_visibility(_SYS_MOUNT)){
return 0;
}
return trace_ret_generic(_SYS_UMOUNT, ctx, ARG_TYPE0(STR_T) | ARG_TYPE1(UMOUNT_FLAG_T), _SYSCALL_PROBE);
}

struct tracepoint_syscalls_sys_exit_t
Expand Down
15 changes: 12 additions & 3 deletions KubeArmor/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ type KubearmorConfig struct {
InitTimeout string // Timeout for main thread init stages

StateAgent bool // enable KubeArmor state agent

SyscallsVisibility string // Enable/Disable Syscalls Visibility
}

// GlobalCfg Global configuration for Kubearmor
Expand Down Expand Up @@ -96,6 +98,7 @@ const (
ConfigDefaultPostureLogs string = "defaultPostureLogs"
ConfigInitTimeout string = "initTimeout"
ConfigStateAgent string = "enableKubeArmorStateAgent"
ConfigSyscallsVisibility string = "syscallsVisibility"
)

func readCmdLineParams() {
Expand All @@ -111,8 +114,8 @@ func readCmdLineParams() {
seLinuxProfileDirStr := flag.String(ConfigSELinuxProfileDir, "/tmp/kubearmor.selinux", "SELinux profile directory")
criSocket := flag.String(ConfigCRISocket, "", "path to CRI socket (format: unix:///path/to/file.sock)")

visStr := flag.String(ConfigVisibility, "process,file,network,capabilities", "Container Visibility to use [process,file,network,capabilities,none]")
hostVisStr := flag.String(ConfigHostVisibility, "default", "Host Visibility to use [process,file,network,capabilities,none] (default \"none\" for k8s, \"process,file,network,capabilities\" for VM)")
visStr := flag.String(ConfigVisibility, "process,file,network,capabilities,syscall", "Container Visibility to use [process,file,network,capabilities,syscall,none]")
hostVisStr := flag.String(ConfigHostVisibility, "default", "Host Visibility to use [process,file,network,capabilities,syscall,none] (default \"none\" for k8s, \"process,file,network,capabilities,syscall\" for VM)")

policyB := flag.Bool(ConfigKubearmorPolicy, true, "enabling KubeArmorPolicy")
hostPolicyB := flag.Bool(ConfigKubearmorHostPolicy, false, "enabling KubeArmorHostPolicy")
Expand Down Expand Up @@ -144,6 +147,8 @@ func readCmdLineParams() {

stateAgent := flag.Bool(ConfigStateAgent, false, "enabling KubeArmor State Agent client")

syscallsVisibility := flag.String(ConfigSyscallsVisibility, "chown,fchownat,mount,unmount,unlink,unlinkat,setuid,setgid,ptrace", "Syscalls Visibility")

flags := []string{}
flag.VisitAll(func(f *flag.Flag) {
kv := fmt.Sprintf("%s:%v", f.Name, f.Value)
Expand Down Expand Up @@ -197,6 +202,8 @@ func readCmdLineParams() {
viper.SetDefault(ConfigInitTimeout, *initTimeout)

viper.SetDefault(ConfigStateAgent, *stateAgent)

viper.SetDefault(ConfigSyscallsVisibility, *syscallsVisibility)
}

// LoadConfig Load configuration
Expand Down Expand Up @@ -270,7 +277,7 @@ func LoadConfig() error {

if GlobalCfg.HostVisibility == "default" {
if GlobalCfg.KVMAgent || (!GlobalCfg.K8sEnv && GlobalCfg.HostPolicy) {
GlobalCfg.HostVisibility = "process,file,network,capabilities"
GlobalCfg.HostVisibility = "process,file,network,capabilities,syscall"
} else { // k8s
GlobalCfg.HostVisibility = "none"
}
Expand All @@ -292,6 +299,8 @@ func LoadConfig() error {

GlobalCfg.StateAgent = viper.GetBool(ConfigStateAgent)

GlobalCfg.SyscallsVisibility = viper.GetString(ConfigSyscallsVisibility)

kg.Printf("Final Configuration [%+v]", GlobalCfg)

return nil
Expand Down
12 changes: 12 additions & 0 deletions KubeArmor/core/kubeUpdate.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ func (dm *KubeArmorDaemon) HandleNodeAnnotations(node *tp.Node) {
node.NetworkVisibilityEnabled = true
} else if visibility == "capabilities" {
node.CapabilitiesVisibilityEnabled = true
} else if visibility == "syscall" {
node.SyscallVisibilityEnabled = true
}
}
}
Expand Down Expand Up @@ -2177,6 +2179,7 @@ func (dm *KubeArmorDaemon) UpdateVisibility(action string, namespace string, vis
val.File = visibility.File
val.Network = visibility.Network
val.Process = visibility.Process
val.Syscall = visibility.Syscall
dm.SystemMonitor.NamespacePidsMap[namespace] = val
for _, nskey := range val.NsKeys {
dm.SystemMonitor.UpdateNsKeyMap("MODIFIED", nskey, visibility)
Expand All @@ -2188,6 +2191,7 @@ func (dm *KubeArmorDaemon) UpdateVisibility(action string, namespace string, vis
Process: visibility.Process,
Capability: visibility.Capabilities,
Network: visibility.Network,
Syscall: visibility.Syscall,
}
}
dm.Logger.Printf("Namespace %s visibiliy configured %+v", namespace, visibility)
Expand Down Expand Up @@ -2273,6 +2277,7 @@ func (dm *KubeArmorDaemon) WatchDefaultPosture() cache.InformerSynced {
Process: dm.validateVisibility("process", cfg.GlobalCfg.Visibility),
Network: dm.validateVisibility("network", cfg.GlobalCfg.Visibility),
Capabilities: dm.validateVisibility("capabilities", cfg.GlobalCfg.Visibility),
Syscall: dm.validateVisibility("syscall", cfg.GlobalCfg.Visibility),
}

// Set Visibility to Namespace Annotation if exists
Expand All @@ -2282,6 +2287,7 @@ func (dm *KubeArmorDaemon) WatchDefaultPosture() cache.InformerSynced {
Process: dm.validateVisibility("process", ns.Annotations[visibilityKey]),
Network: dm.validateVisibility("network", ns.Annotations[visibilityKey]),
Capabilities: dm.validateVisibility("capabilities", ns.Annotations[visibilityKey]),
Syscall: dm.validateVisibility("syscall", ns.Annotations[visibilityKey]),
}
}
dm.UpdateDefaultPosture("ADDED", ns.Name, defaultPosture, annotated)
Expand All @@ -2305,6 +2311,7 @@ func (dm *KubeArmorDaemon) WatchDefaultPosture() cache.InformerSynced {
Process: dm.validateVisibility("process", cfg.GlobalCfg.Visibility),
Network: dm.validateVisibility("network", cfg.GlobalCfg.Visibility),
Capabilities: dm.validateVisibility("capabilities", cfg.GlobalCfg.Visibility),
Syscall: dm.validateVisibility("syscall", cfg.GlobalCfg.Visibility),
}

// Set Visibility to Namespace Annotation if exists
Expand All @@ -2314,6 +2321,7 @@ func (dm *KubeArmorDaemon) WatchDefaultPosture() cache.InformerSynced {
Process: dm.validateVisibility("process", ns.Annotations[visibilityKey]),
Network: dm.validateVisibility("network", ns.Annotations[visibilityKey]),
Capabilities: dm.validateVisibility("capabilities", ns.Annotations[visibilityKey]),
Syscall: dm.validateVisibility("syscall", ns.Annotations[visibilityKey]),
}
}
dm.UpdateDefaultPosture("MODIFIED", ns.Name, defaultPosture, annotated)
Expand Down Expand Up @@ -2356,6 +2364,8 @@ func (dm *KubeArmorDaemon) WatchConfigMap() cache.InformerSynced {
if cm, ok := obj.(*corev1.ConfigMap); ok && cm.Namespace == cmNS {
cfg.GlobalCfg.HostVisibility = cm.Data[cfg.ConfigHostVisibility]
cfg.GlobalCfg.Visibility = cm.Data[cfg.ConfigVisibility]
cfg.GlobalCfg.SyscallsVisibility = cm.Data[cfg.ConfigSyscallsVisibility]
dm.SystemMonitor.HandleSyscallsVsibility()
if _, ok := cm.Data[cfg.ConfigDefaultPostureLogs]; ok {
cfg.GlobalCfg.DefaultPostureLogs = (cm.Data[cfg.ConfigDefaultPostureLogs] == "true")
}
Expand All @@ -2382,6 +2392,8 @@ func (dm *KubeArmorDaemon) WatchConfigMap() cache.InformerSynced {
if cm, ok := new.(*corev1.ConfigMap); ok && cm.Namespace == cmNS {
cfg.GlobalCfg.HostVisibility = cm.Data[cfg.ConfigHostVisibility]
cfg.GlobalCfg.Visibility = cm.Data[cfg.ConfigVisibility]
cfg.GlobalCfg.SyscallsVisibility = cm.Data[cfg.ConfigSyscallsVisibility]
dm.SystemMonitor.HandleSyscallsVsibility()
if _, ok := cm.Data[cfg.ConfigDefaultPostureLogs]; ok {
cfg.GlobalCfg.DefaultPostureLogs = (cm.Data[cfg.ConfigDefaultPostureLogs] == "true")
}
Expand Down
4 changes: 4 additions & 0 deletions KubeArmor/feeder/policyMatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -1748,6 +1748,10 @@ func (fd *Feeder) UpdateMatchedPolicy(log tp.Log) tp.Log {
if setLogFields(&log, existCapabilitiesAllowPolicy, "allow", fd.Node.CapabilitiesVisibilityEnabled, false) {
return log
}
} else if log.Operation == "Syscall" {
if setLogFields(&log, false, "allow", fd.Node.SyscallVisibilityEnabled, false) {
return log
}
}
} else if log.Type == "MatchedPolicy" {
log.Type = "MatchedHostPolicy"
Expand Down
2 changes: 1 addition & 1 deletion KubeArmor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func main() {
// initial clean up

bpfMapsDir := "/sys/fs/bpf/"
bpfMapsName := []string{"kubearmor_config", "kubearmor_events", "kubearmor_containers", "kubearmor_visibility"}
bpfMapsName := []string{"kubearmor_config", "kubearmor_events", "kubearmor_containers", "kubearmor_visibility", "kubearmor_syscall_vis"}
for _, mp := range bpfMapsName {
path := bpfMapsDir + mp
/* This should not be triggered in ideal cases,
Expand Down
2 changes: 2 additions & 0 deletions KubeArmor/monitor/processTree.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// ============================ //

// LookupContainerID Function
func (mon *SystemMonitor) LookupContainerID(pidns, mntns, ppid, pid uint32) string {

Check warning on line 23 in KubeArmor/monitor/processTree.go

View workflow job for this annotation

GitHub Actions / go-lint

parameter 'ppid' seems to be unused, consider removing or renaming it as _
key := NsKey{PidNS: pidns, MntNS: mntns}

mon.NsMapLock.RLock()
Expand Down Expand Up @@ -60,6 +60,7 @@
Process: val.Process,
Capabilities: val.Capability,
Network: val.Network,
Syscall: val.Syscall,
})
}
} else {
Expand All @@ -74,6 +75,7 @@
Process: strings.Contains(cfg.GlobalCfg.Visibility, "process"),
Network: strings.Contains(cfg.GlobalCfg.Visibility, "network"),
Capabilities: strings.Contains(cfg.GlobalCfg.Visibility, "capabilities"),
Syscall: strings.Contains(cfg.GlobalCfg.Visibility, "syscall"),
}
mon.UpdateNsKeyMap("ADDED", key, visibility)
}
Expand Down
Loading
Loading