Skip to content

Commit

Permalink
enforcer: implement CleanupEnforcerNotification
Browse files Browse the repository at this point in the history
This allows to specify an action (CleanupEnforcerNotification) that
checks whether the enforcer notification succeeded.

For example, the following policy:

```
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
  name: "kill-syscalls"
spec:
  enforcers:
  - calls:
    - "sys_swapoff"
    # - "sys_getcpu"
  tracepoints:
  - subsystem: "raw_syscalls"
    event: "sys_enter"
    args:
    - index: 4
      type: "syscall64"
    selectors:
    - matchArgs:
      - index: 0
        operator: "InMap"
        values:
        - 309 # getcpu
        - 168 # swapoff
      matchActions:
      - action: "NotifyEnforcer"
        argError: -1
        argSig: 9
  - subsystem: "raw_syscalls"
    event: "sys_exit"
    selectors:
    - matchActions:
      - action: "CleanupEnforcerNotification"
      - action: "NoPost"
```

Detects missing notifications by adding such a function in the
raw_syscalls/sys_exit tracepoint. This means that missed enforcements
can be detected even if there is no other notifcation for the same
thread.

The metric output in this case would be:
tetragon_enforcer_missed_notifications_total{info="getcpu",policy="kill-syscalls",reason="no_action"} 3

Signed-off-by: Kornilios Kourtis <[email protected]>
  • Loading branch information
kkourt committed Oct 15, 2024
1 parent 43be155 commit 38eac00
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 53 deletions.
16 changes: 16 additions & 0 deletions bpf/process/bpf_enforcer.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct {

enum enforcer_missed_reason {
ENFORCER_MISSED_OVERWRITTEN = 1,
ENFORCER_MISSED_NOACTION = 2,
};

struct enforcer_missed_key {
Expand Down Expand Up @@ -67,6 +68,21 @@ enforcer_update_missed_notifications(struct enforcer_missed_key *key)
}
}

FUNC_INLINE void do_enforcer_cleanup(void)
{
struct enforcer_data *ptr;
__u64 id = get_current_pid_tgid();

ptr = map_lookup_elem(&enforcer_data, &id);
if (ptr) {
struct enforcer_missed_key missed_key = {
.act_info = ptr->act_info,
.reason = ENFORCER_MISSED_NOACTION,
};
enforcer_update_missed_notifications(&missed_key);
}
}

FUNC_INLINE void do_enforcer_action(int error, int signal, struct enforcer_act_info act_info)
{
__u64 id = get_current_pid_tgid();
Expand Down
3 changes: 3 additions & 0 deletions bpf/process/types/basic.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ enum {
ACTION_TRACKSOCK = 10,
ACTION_UNTRACKSOCK = 11,
ACTION_NOTIFY_ENFORCER = 12,
ACTION_CLEANUP_ENFORCER_NOTIFICATION = 13,
};

enum {
Expand Down Expand Up @@ -2281,6 +2282,8 @@ do_action(void *ctx, __u32 i, struct selector_action *actions,
argi = actions->act[++i];
do_action_notify_enforcer(e, error, signal, argi);
break;
case ACTION_CLEANUP_ENFORCER_NOTIFICATION:
do_enforcer_cleanup();
default:
break;
}
Expand Down
27 changes: 14 additions & 13 deletions pkg/api/tracingapi/client_kprobe.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@ const (
)

const (
ActionPost = 0
ActionFollowFd = 1
ActionSigKill = 2
ActionUnfollowFd = 3
ActionOverride = 4
ActionCopyFd = 5
ActionGetUrl = 6
ActionLookupDns = 7
ActionNoPost = 8
ActionSignal = 9
ActionTrackSock = 10
ActionUntrackSock = 11
ActionNotifyEnforcer = 12
ActionPost = 0
ActionFollowFd = 1
ActionSigKill = 2
ActionUnfollowFd = 3
ActionOverride = 4
ActionCopyFd = 5
ActionGetUrl = 6
ActionLookupDns = 7
ActionNoPost = 8
ActionSignal = 9
ActionTrackSock = 10
ActionUntrackSock = 11
ActionNotifyEnforcer = 12
ActionCleanupEnforcerNotification = 13
)

const (
Expand Down
2 changes: 2 additions & 0 deletions pkg/grpc/tracing/tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ func kprobeAction(act uint64) tetragon.KprobeAction {
return tetragon.KprobeAction_KPROBE_ACTION_UNTRACKSOCK
case tracingapi.ActionNotifyEnforcer:
return tetragon.KprobeAction_KPROBE_ACTION_NOTIFYENFORCER
case tracingapi.ActionCleanupEnforcerNotification:
return tetragon.KprobeAction_KPROBE_ACTION_CLEANUPENFORCERNOTIFICATION
default:
return tetragon.KprobeAction_KPROBE_ACTION_UNKNOWN
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/metrics/enforcermetrics/enforcermetrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ func (mk *enforcerMissedMapKey) reason() string {
switch mk.Reason {
case 1:
return "overwritten"
case 2:
return "no_action"
default:
return "unspecified"
}
Expand Down
84 changes: 44 additions & 40 deletions pkg/selectors/kernel.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,52 +22,54 @@ import (
)

const (
ActionTypeInvalid = -1
ActionTypePost = 0
ActionTypeFollowFd = 1
ActionTypeSigKill = 2
ActionTypeUnfollowFd = 3
ActionTypeOverride = 4
ActionTypeCopyFd = 5
ActionTypeGetUrl = 6
ActionTypeDnsLookup = 7
ActionTypeNoPost = 8
ActionTypeSignal = 9
ActionTypeTrackSock = 10
ActionTypeUntrackSock = 11
ActionTypeNotifyEnforcer = 12
ActionTypeInvalid = -1
ActionTypePost = 0
ActionTypeFollowFd = 1
ActionTypeSigKill = 2
ActionTypeUnfollowFd = 3
ActionTypeOverride = 4
ActionTypeCopyFd = 5
ActionTypeGetUrl = 6
ActionTypeDnsLookup = 7
ActionTypeNoPost = 8
ActionTypeSignal = 9
ActionTypeTrackSock = 10
ActionTypeUntrackSock = 11
ActionTypeNotifyEnforcer = 12
ActionTypeCleanupEnforcerNotification = 13
)

var actionTypeTable = map[string]uint32{
"post": ActionTypePost,
"followfd": ActionTypeFollowFd,
"unfollowfd": ActionTypeUnfollowFd,
"sigkill": ActionTypeSigKill,
"override": ActionTypeOverride,
"copyfd": ActionTypeCopyFd,
"geturl": ActionTypeGetUrl,
"dnslookup": ActionTypeDnsLookup,
"nopost": ActionTypeNoPost,
"signal": ActionTypeSignal,
"tracksock": ActionTypeTrackSock,
"untracksock": ActionTypeUntrackSock,
"notifyenforcer": ActionTypeNotifyEnforcer,
"post": ActionTypePost,
"followfd": ActionTypeFollowFd,
"unfollowfd": ActionTypeUnfollowFd,
"sigkill": ActionTypeSigKill,
"override": ActionTypeOverride,
"copyfd": ActionTypeCopyFd,
"geturl": ActionTypeGetUrl,
"dnslookup": ActionTypeDnsLookup,
"nopost": ActionTypeNoPost,
"signal": ActionTypeSignal,
"tracksock": ActionTypeTrackSock,
"untracksock": ActionTypeUntrackSock,
"notifyenforcer": ActionTypeNotifyEnforcer,
"cleanupenforcernotification": ActionTypeCleanupEnforcerNotification,
}

var actionTypeStringTable = map[uint32]string{
ActionTypePost: "post",
ActionTypeFollowFd: "followfd",
ActionTypeUnfollowFd: "unfollowfd",
ActionTypeSigKill: "sigkill",
ActionTypeOverride: "override",
ActionTypeCopyFd: "copyfd",
ActionTypeGetUrl: "geturl",
ActionTypeDnsLookup: "dnslookup",
ActionTypeNoPost: "nopost",
ActionTypeSignal: "signal",
ActionTypeTrackSock: "tracksock",
ActionTypeUntrackSock: "untracksock",
ActionTypeNotifyEnforcer: "notifyenforcer",
ActionTypePost: "post",
ActionTypeFollowFd: "followfd",
ActionTypeUnfollowFd: "unfollowfd",
ActionTypeSigKill: "sigkill",
ActionTypeOverride: "override",
ActionTypeCopyFd: "copyfd",
ActionTypeGetUrl: "geturl",
ActionTypeDnsLookup: "dnslookup",
ActionTypeNoPost: "nopost",
ActionTypeSignal: "signal",
ActionTypeTrackSock: "tracksock",
ActionTypeUntrackSock: "untracksock",
ActionTypeCleanupEnforcerNotification: "cleanupenforcernotification",
}

const (
Expand Down Expand Up @@ -981,6 +983,8 @@ func ParseMatchAction(k *KernelSelectorState, action *v1alpha1.ActionSelector, a
actionArgIndex = *(action.EnforcerNotifyActionArgIndex)
}
WriteSelectorUint32(&k.data, actionArgIndex)
case ActionTypeCleanupEnforcerNotification:
// no arguments
default:
return fmt.Errorf("ParseMatchAction: act %d (%s) is missing a handler", act, actionTypeStringTable[act])
}
Expand Down

0 comments on commit 38eac00

Please sign in to comment.