Skip to content

Commit

Permalink
Merge pull request #759 from rksharma95/ptrace-syscall
Browse files Browse the repository at this point in the history
added ptrace system call to system monitor
  • Loading branch information
daemon1024 authored Nov 25, 2022
2 parents 4e9a492 + 1582995 commit 8406aba
Show file tree
Hide file tree
Showing 12 changed files with 196 additions and 28 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-systemd-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
uses: goreleaser/goreleaser-action@v2
with:
distribution: goreleaser
version: latest
version: v1.12.2
args: release --rm-dist
workdir: KubeArmor
env:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci-test-systemd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
uses: goreleaser/goreleaser-action@v2
with:
install-only: true
version: v1.12.2

- name: Build Systemd Release
run: make local-release
Expand Down
53 changes: 49 additions & 4 deletions KubeArmor/BPF/system_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
#define SOCK_TYPE_T 16UL
#define FILE_TYPE_T 17UL
#define UNLINKAT_FLAG_T 19UL
#define PTRACE_REQ_T 23UL

#define MAX_ARGS 6
#define ENC_ARG_TYPE(n, type) type<<(8*n)
Expand Down Expand Up @@ -159,6 +160,7 @@ enum {
_DO_EXIT = 351,
_SYS_RMDIR = 84,

_SYS_PTRACE = 101,
// lsm
_SECURITY_BPRM_CHECK = 352,

Expand Down Expand Up @@ -338,6 +340,10 @@ static __always_inline u32 get_task_ppid(struct task_struct *task)

}

static struct file *get_task_file(struct task_struct *task) {
return BPF_CORE_READ(task, mm, exe_file);
}

// == Pid NS Management == //

static __always_inline u32 add_pid_ns()
Expand Down Expand Up @@ -774,6 +780,9 @@ static __always_inline int save_args_to_buffer(u64 types, args_t *args)
case FILE_TYPE_T:
save_file_to_buffer(bufs_p, (void *)args->args[i]);
break;
case PTRACE_REQ_T:
save_to_buffer(bufs_p, (void*)&(args->args[i]), sizeof(int), PTRACE_REQ_T);
break;
case STR_T:
save_str_to_buffer(bufs_p, (void *)args->args[i]);
break;
Expand Down Expand Up @@ -847,6 +856,24 @@ static __always_inline int security_path__dir_path_args(struct pt_regs *ctx){
return 0;
}

// args: struct task_struct *task
static __always_inline int security_path_task_arg(struct pt_regs *ctx){
struct task_struct *task = (struct task_struct*) PT_REGS_PARM1(ctx);
if(task == NULL){
return 0;
}

struct file *file_p = get_task_file(task);
if (file_p == NULL)
return 0;

struct path p = READ_KERN(file_p->f_path);

u64 tgid = bpf_get_current_pid_tgid();
bpf_map_update_elem(&file_map, &tgid, &p, BPF_ANY);
return 0;
}

#if defined(SECURITY_PATH)
SEC("kprobe/security_path_unlink")
int kprobe__security_path_unlink(struct pt_regs *ctx){
Expand All @@ -863,6 +890,13 @@ int kprobe__security_path_rmdir(struct pt_regs *ctx){
}
#endif

SEC("kprobe/security_ptrace_access_check")
int kprobe__security_ptrace_access_check(struct pt_regs *ctx){
if (skip_syscall())
return 0;
return security_path_task_arg(ctx);
}

SEC("kprobe/security_bprm_check")
int kprobe__security_bprm_check(struct pt_regs *ctx)
{
Expand Down Expand Up @@ -1414,6 +1448,20 @@ int kretprobe__setgid(struct pt_regs *ctx)
{
return trace_ret_generic(_SYS_SETGID, ctx, ARG_TYPE0(INT_T));
}

SEC("kprobe/__x64_sys_ptrace")
int kprobe__ptrace(struct pt_regs *ctx)
{
if (skip_syscall())
return 0;
return save_args(_SYS_PTRACE, 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));
}

struct tracepoint_syscalls_sys_exit_t {
unsigned short common_type;
Expand Down Expand Up @@ -1547,7 +1595,6 @@ int kretprobe__listen(struct pt_regs *ctx)
return trace_ret_generic(_SYS_LISTEN, ctx, ARG_TYPE0(INT_T)|ARG_TYPE1(INT_T));
}


static __always_inline int get_connection_info(struct sock_common *conn,struct sockaddr_in *sockv4, struct sockaddr_in6 *sockv6,sys_context_t *context, args_t *args, u32 event ) {
switch (conn->skc_family)
{
Expand Down Expand Up @@ -1650,7 +1697,6 @@ if (sk_lingertime_offset - gso_max_segs_offset == 2)
u64 types = ARG_TYPE0(STR_T)|ARG_TYPE1(SOCKADDR_T);
init_context(&context);
context.argnum = get_arg_num(types);


if (get_connection_info(&conn, &sockv4, &sockv6, &context, &args, _TCP_ACCEPT) != 0) {
return 0;
Expand All @@ -1668,5 +1714,4 @@ if (sk_lingertime_offset - gso_max_segs_offset == 2)

return 0;
}

char LICENSE[] SEC("license") = "Dual BSD/GPL";
char LICENSE[] SEC("license") = "Dual BSD/GPL";
1 change: 1 addition & 0 deletions KubeArmor/enforcer/appArmorEnforcer.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ func (ae *AppArmorEnforcer) CreateAppArmorHostProfile() error {
" umount,\n" +
" signal,\n" +
" unix,\n" +
" ptrace,\n" +
"\n" +
" file,\n" +
" network,\n" +
Expand Down
1 change: 1 addition & 0 deletions KubeArmor/enforcer/appArmorHostProfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ func (ae *AppArmorEnforcer) GenerateHostProfileHead() string {
" umount,\n" +
" signal,\n" +
" unix,\n" +
" ptrace,\n" +
"\n" +
" file,\n" +
" network,\n" +
Expand Down
25 changes: 25 additions & 0 deletions KubeArmor/monitor/logUpdate.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,31 @@ func (mon *SystemMonitor) UpdateLogs() {
log.Resource = ""
log.Data = "syscall=" + getSyscallName(int32(msg.ContextSys.EventID)) + " fd=" + fd

case SysPtrace:
if len(msg.ContextArgs) != 3 {
continue
}

var request string
var pid string
var binary string

if val, ok := msg.ContextArgs[0].(string); ok {
request = val
}

if val, ok := msg.ContextArgs[1].(int32); ok {
pid = strconv.Itoa(int(val))
}

if val, ok := msg.ContextArgs[2].(string); ok {
binary = val
}

log.Resource = binary
log.Operation = "Process"
log.Data = "syscall=" + getSyscallName(int32(msg.ContextSys.EventID)) + " request=" + request + " pid=" + pid + " process=" + binary

case SysSocket: // domain, type, proto
if len(msg.ContextArgs) != 3 {
continue
Expand Down
84 changes: 84 additions & 0 deletions KubeArmor/monitor/syscallParser.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const (
capT uint8 = 17
syscallT uint8 = 18
unlinkAtFlagT uint8 = 19
ptraceReqT uint8 = 23
)

// ======================= //
Expand Down Expand Up @@ -226,6 +227,82 @@ func getUnlinkAtFlag(flag uint32) string {
return f
}

// getPtraceReq
func getPtraceReq(req uint32) string {
switch req {
case 0:
return "PTRACE_TRACEME"
case 1:
return "PTRACE_PEEKTEXT"
case 2:
return "PTRACE_PEEKDATA"
case 3:
return "PTRACE_PEEKUSER"
case 4:
return "PTRACE_POKETEXT"
case 5:
return "PTRACE_POKEDATA"
case 6:
return "PTRACE_POKEUSER"
case 7:
return "PTRACE_CONT"
case 8:
return "PTRACE_KILL"
case 9:
return "PTRACE_SINGLESTEP"
case 12:
return "PTRACE_GETREGS"
case 13:
return "PTRACE_SETREGS"
case 14:
return "PTRACE_GETFPREGS"
case 15:
return "PTRACE_SETFPREGS"
case 16:
return "PTRACE_ATTACH"
case 17:
return "PTRACE_DETACH"
case 18:
return "PTRACE_GETFPXREGS"
case 19:
return "PTRACE_SETFPXREGS"
case 24:
return "PTRACE_SYSCALL"
case 0x4200:
return "PTRACE_SETOPTIONS"
case 0x4201:
return "PTRACE_GETEVENTMSG"
case 0x4202:
return "PTRACE_GETSIGINFO"
case 0x4203:
return "PTRACE_SETSIGINFO"
case 0x4204:
return "PTRACE_GETREGSET"
case 0x4205:
return "PTRACE_SETREGSET"
case 0x4206:
return "PTRACE_SEIZE"
case 0x4207:
return "PTRACE_INTERRUPT"
case 0x4208:
return "PTRACE_LISTEN"
case 0x4209:
return "PTRACE_PEEKSIGINFO"
case 0x420a:
return "PTRACE_GETSIGMASK"
case 0x420b:
return "PTRACE_SETSIGMASK"
case 0x420c:
return "PTRACE_SECCOMP_GET_FILTER"
case 0x420d:
return "PTRACE_SECCOMP_GET_METADATA"
case 0x420e:
return "PTRACE_GET_SYSCALL_INFO"
default:
return strconv.Itoa(int(req))
}
}

// getOpenFlags Function
func getOpenFlags(flags uint32) string {
// readOpenFlags prints the `flags` bitmask argument of the `open` syscall
Expand Down Expand Up @@ -736,6 +813,12 @@ func readArgFromBuff(dataBuff io.Reader) (interface{}, error) {
return nil, err
}
res = getExecFlags(flags)
case ptraceReqT:
req, err := readUInt32FromBuff(dataBuff)
if err != nil {
return nil, err
}
res = getPtraceReq(req)
case sockDomT:
dom, err := readUInt32FromBuff(dataBuff)
if err != nil {
Expand Down Expand Up @@ -778,6 +861,7 @@ var auditedSyscalls = map[int]string{
106: "setgid",
260: "fchownat",
263: "unlinkat",
101: "ptrace",
}

func isAuditedSyscall(syscallID int32) bool {
Expand Down
2 changes: 2 additions & 0 deletions KubeArmor/monitor/syscalls_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ const (
SysExecve = 59
SysExecveAt = 322

SysPtrace = 101

DoExit = 351
SecurityBprmCheck = 352

Expand Down
2 changes: 2 additions & 0 deletions KubeArmor/monitor/syscalls_arm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ const (
SysExecve = 221
SysExecveAt = 281

SysPtrace = 101

DoExit = 351
SecurityBprmCheck = 352

Expand Down
9 changes: 6 additions & 3 deletions KubeArmor/monitor/systemMonitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,10 @@ func (mon *SystemMonitor) InitBPF() error {
mon.Logger.Print("Initialized the eBPF system monitor")

// sysPrefix := bcc.GetSyscallPrefix()
systemCalls := []string{"open", "openat", "execve", "execveat", "socket", "connect", "accept", "bind", "listen", "unlink", "unlinkat", "rmdir", "chown", "setuid", "setgid", "fchownat"}
systemCalls := []string{"open", "openat", "execve", "execveat", "socket", "connect", "accept", "bind", "listen", "unlink", "unlinkat", "rmdir", "ptrace", "chown", "setuid", "setgid", "fchownat"}
// {category, event}
sysTracepoints := [][2]string{{"syscalls", "sys_exit_openat"}}
sysKprobes := []string{"do_exit", "security_bprm_check", "security_file_open", "security_path_unlink", "security_path_rmdir"}
sysKprobes := []string{"do_exit", "security_bprm_check", "security_file_open", "security_path_unlink", "security_path_rmdir", "security_ptrace_access_check"}
netSyscalls := []string{"tcp_connect"}
netRetSyscalls := []string{"inet_csk_accept"}

Expand Down Expand Up @@ -464,6 +464,10 @@ func (mon *SystemMonitor) TraceSyscall() {
if len(args) != 1 {
continue
}
} else if ctx.EventID == SysPtrace {
if len(args) != 3 {
continue
}
} else if ctx.EventID == SysChown {
if len(args) != 3 {
continue
Expand All @@ -480,7 +484,6 @@ func (mon *SystemMonitor) TraceSyscall() {
if len(args) != 1 {
continue
}

} else if ctx.EventID == SysExecve {
if len(args) == 2 { // enter
// build a pid node
Expand Down
16 changes: 8 additions & 8 deletions tests/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ replace (
require (
github.com/kubearmor/KubeArmor/protobuf v0.0.0-20220712092628-6b4cef291201
github.com/kubearmor/kubearmor-client v0.7.8
github.com/onsi/ginkgo/v2 v2.3.1
github.com/onsi/gomega v1.22.0
github.com/onsi/ginkgo/v2 v2.4.0
github.com/onsi/gomega v1.22.1
github.com/sirupsen/logrus v1.8.1
google.golang.org/protobuf v1.28.0
k8s.io/api v0.24.2
Expand All @@ -40,7 +40,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-logr/logr v1.2.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect
github.com/go-openapi/swag v0.19.15 // indirect
Expand Down Expand Up @@ -78,12 +78,12 @@ require (
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e // indirect
golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d // indirect
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/term v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 // indirect
Expand Down
Loading

0 comments on commit 8406aba

Please sign in to comment.