From 3068c2945994908bac30959a3e2ab8d3cc53d863 Mon Sep 17 00:00:00 2001 From: Jianlin Lv Date: Sun, 28 Jan 2024 21:28:12 -0700 Subject: [PATCH] bpf & pkg: Add selectors for audit ids This commits introduces the "matchLoginUids" selectors, support filtering based on the audit id of process. A process is given an audit ID on user login, that is the loginuid. This ID set during user authentication and handed down to any child process started by the initial process of the user, even when the user's identity changes. The loginuid is used to track user's activity. For example, the following matchLoginUids filter allow to follow operation performed by user id 1000. ``` - matchLoginUids: - operator: "In" values: - 1000 ``` Signed-off-by: Jianlin Lv --- bpf/lib/process.h | 2 +- bpf/process/bpf_execve_event.c | 1 + bpf/process/bpf_exit.h | 5 +- bpf/process/bpf_generic_retkprobe.c | 5 +- bpf/process/generic_calls.h | 5 - bpf/process/pfilter.h | 62 +++++++++++ bpf/process/types/basic.h | 2 + .../docs/concepts/tracing-policy/selectors.md | 19 ++++ pkg/api/processapi/processapi.go | 2 +- pkg/grpc/exec/exec_test_helper.go | 12 +- .../v1alpha1/cilium.io_tracingpolicies.yaml | 63 +++++++++++ .../cilium.io_tracingpoliciesnamespaced.yaml | 63 +++++++++++ pkg/k8s/apis/cilium.io/v1alpha1/types.go | 11 ++ pkg/k8s/apis/cilium.io/v1alpha1/version.go | 2 +- .../v1alpha1/zz_generated.deepcopy.go | 28 +++++ pkg/selectors/kernel.go | 39 +++++++ pkg/selectors/kernel_test.go | 103 +++++++++++++++--- .../v1alpha1/cilium.io_tracingpolicies.yaml | 63 +++++++++++ .../cilium.io_tracingpoliciesnamespaced.yaml | 63 +++++++++++ .../pkg/k8s/apis/cilium.io/v1alpha1/types.go | 11 ++ .../v1alpha1/zz_generated.deepcopy.go | 28 +++++ 21 files changed, 549 insertions(+), 40 deletions(-) diff --git a/bpf/lib/process.h b/bpf/lib/process.h index bdadea67115..b256692ed28 100644 --- a/bpf/lib/process.h +++ b/bpf/lib/process.h @@ -151,7 +151,7 @@ struct msg_execve_key { __u32 pid; // Process TGID - __u8 pad[4]; + __u32 auid; // loginuid __u64 ktime; }; // All fields aligned so no 'packed' attribute. diff --git a/bpf/process/bpf_execve_event.c b/bpf/process/bpf_execve_event.c index 76b38ce911d..4991b4657f4 100644 --- a/bpf/process/bpf_execve_event.c +++ b/bpf/process/bpf_execve_event.c @@ -274,6 +274,7 @@ execve_send(struct sched_execve_args *ctx) #endif curr->key.pid = p->pid; curr->key.ktime = p->ktime; + curr->key.auid = p->auid; curr->nspid = p->nspid; curr->pkey = event->parent; if (curr->flags & EVENT_COMMON_FLAG_CLONE) { diff --git a/bpf/process/bpf_exit.h b/bpf/process/bpf_exit.h index b683bac7a5d..7292d04e2bd 100644 --- a/bpf/process/bpf_exit.h +++ b/bpf/process/bpf_exit.h @@ -50,10 +50,7 @@ static inline __attribute__((always_inline)) void event_exit_send(void *ctx, __u exit->common.ktime = ktime_get_ns(); exit->current.pid = tgid; - exit->current.pad[0] = 0; - exit->current.pad[1] = 0; - exit->current.pad[2] = 0; - exit->current.pad[3] = 0; + exit->current.auid = enter->key.auid; exit->current.ktime = enter->key.ktime; /** diff --git a/bpf/process/bpf_generic_retkprobe.c b/bpf/process/bpf_generic_retkprobe.c index f5b9bca0b9a..ee65c51a08e 100644 --- a/bpf/process/bpf_generic_retkprobe.c +++ b/bpf/process/bpf_generic_retkprobe.c @@ -150,12 +150,9 @@ BPF_KRETPROBE(generic_retkprobe_event, unsigned long ret) if (enter) { e->current.pid = enter->key.pid; + e->current.auid = enter->key.auid; e->current.ktime = enter->key.ktime; } - e->current.pad[0] = 0; - e->current.pad[1] = 0; - e->current.pad[2] = 0; - e->current.pad[3] = 0; e->func_id = config->func_id; e->common.size = size; diff --git a/bpf/process/generic_calls.h b/bpf/process/generic_calls.h index d23ac848fbc..9dda93968e6 100644 --- a/bpf/process/generic_calls.h +++ b/bpf/process/generic_calls.h @@ -105,11 +105,6 @@ generic_process_init(struct msg_generic_kprobe *e, u8 op, struct event_config *c e->common.size = 0; e->common.ktime = ktime_get_ns(); - e->current.pad[0] = 0; - e->current.pad[1] = 0; - e->current.pad[2] = 0; - e->current.pad[3] = 0; - e->action = 0; /** diff --git a/bpf/process/pfilter.h b/bpf/process/pfilter.h index d8daf84c237..d04d7644afc 100644 --- a/bpf/process/pfilter.h +++ b/bpf/process/pfilter.h @@ -135,6 +135,43 @@ process_filter_pid(__u32 i, __u32 off, __u32 *f, __u64 ty, __u64 flags, return __process_filter_pid(ty, flags, sel, pid, enter); } + + +static inline __attribute__((always_inline)) int +__process_filter_loginuid(__u32 ty, __u32 sel, struct execve_map_value *enter) +{ + __u32 auid; + + auid = enter->key.auid; + if (ty == op_filter_in && sel != auid) + return PFILTER_REJECT; + else if (ty == op_filter_notin && sel == auid) + return PFILTER_REJECT; + return PFILTER_ACCEPT; +} + + +static inline __attribute__((always_inline)) int +process_filter_loginuid(__u32 i, __u32 off, __u32 *f, __u64 ty, __u64 flags, + struct execve_map_value *enter, struct msg_ns *n, + struct msg_capabilities *c) +{ + __u32 sel; + + if (off > 1000) + sel = 0; + else { + __u32 o = off; + + o = o / 4; + asm volatile("%[o] &= 0x3ff;\n" ::[o] "+r"(o) + :); + sel = f[o]; + } + + return __process_filter_loginuid(ty, sel, enter); +} + static inline __attribute__((always_inline)) int process_filter_namespace(__u32 i, __u32 off, __u32 *f, __u64 ty, __u64 nsid, struct execve_map_value *enter, struct msg_ns *n, @@ -374,6 +411,12 @@ struct nc_filter { u32 value; /* contains all namespaces to monitor (i.e. bit 0 is for ns_uts, bit 1 for ns_ipc etc.) */ } __attribute__((packed)); +struct loginuid_filter { + u32 op; + u32 len; /* number of values */ + u32 val[]; /* values */ +} __attribute__((packed)); + #define VALUES_MASK 0x1f /* max 4 values with 4 bytes each | 0x1f == 31 */ /* If you update the value of NUM_NS_FILTERS_SMALL below you should @@ -393,6 +436,7 @@ selector_process_filter(__u32 *f, __u32 index, struct execve_map_value *enter, struct nc_filter *nc; #endif struct caps_filter *caps; + struct loginuid_filter *loginuid; __u32 len; __u64 i; @@ -513,6 +557,24 @@ selector_process_filter(__u32 *f, __u32 index, struct execve_map_value *enter, return res; #endif + /* matchLoginuids */ + len = *(__u32 *)((__u64)f + + (index & + INDEX_MASK)); /* (sizeof(LoginUid1) + sizeof(LoginUid2) + ... + 4) */ + index += 4; /* 4: LoginUid1 header */ + len -= 4; + + if (len > 0) { + loginuid = (struct loginuid_filter *)((u64)f + (index & INDEX_MASK)); + index += sizeof(struct loginuid_filter); /* 4: op */ + res = selector_match(f, index, loginuid->op, 0, loginuid->len, + enter, n, c, &process_filter_loginuid); + index += + ((loginuid->len * sizeof(loginuid->val[0])) & + VALUES_MASK); /* now index points at the end of loginuid filter */ + } + if (res == PFILTER_REJECT) + return res; return res; } diff --git a/bpf/process/types/basic.h b/bpf/process/types/basic.h index 5513fa58848..608199f4608 100644 --- a/bpf/process/types/basic.h +++ b/bpf/process/types/basic.h @@ -1638,6 +1638,8 @@ selector_arg_offset(__u8 *f, struct msg_generic_kprobe *e, __u32 selidx, seloff += *(__u32 *)((__u64)f + (seloff & INDEX_MASK)); /* skip the matchCapabilityChanges by reading its length */ seloff += *(__u32 *)((__u64)f + (seloff & INDEX_MASK)); + /* skip the matchLoginuids by reading its length */ + seloff += *(__u32 *)((__u64)f + (seloff & INDEX_MASK)); } /* Making binary selectors fixes size helps on some kernels */ diff --git a/docs/content/en/docs/concepts/tracing-policy/selectors.md b/docs/content/en/docs/concepts/tracing-policy/selectors.md index ad68f54788c..fcdd138bfdc 100644 --- a/docs/content/en/docs/concepts/tracing-policy/selectors.md +++ b/docs/content/en/docs/concepts/tracing-policy/selectors.md @@ -19,6 +19,7 @@ A `TracingPolicy` can contain from 0 to 5 selectors. A selector is composed of - [`matchCapabilityChanges`](#capability-changes-filter): filter on Linux capabilities changes. - [`matchActions`](#actions-filter): apply an action on selector matching. - [`matchReturnActions`](#return-actions-filter): apply an action on return selector matching. +- [`matchLoginUids`](#auid-filter): filter on audit ID. ## Arguments filter @@ -1468,3 +1469,21 @@ exist. Return actions filters are a list of actions that execute when an return selector matches. They are defined under `matchReturnActions` and currently support all the [Actions filter](#actions-filter) `action` types. + +## Auid filter + +Auids filters can be specified under the `matchLoginUids` field and provide filtering +based on the value of audit id of the process. For example, the following +`matchLoginUids` filter tells the BPF code that observe only hooks for which the +audit id is not equal to `-1`: + +```yaml +- matchLoginUids: + - operator: "NotIn" + values: + - 4294967295 +``` + +The available operators for `matchLoginUids` are: +- `In` +- `NotIn` diff --git a/pkg/api/processapi/processapi.go b/pkg/api/processapi/processapi.go index dffcec3da15..ba0180d6e0d 100644 --- a/pkg/api/processapi/processapi.go +++ b/pkg/api/processapi/processapi.go @@ -63,7 +63,7 @@ type MsgExec struct { type MsgExecveKey struct { Pid uint32 `align:"pid"` - Pad uint32 `align:"pad"` + Auid uint32 `align:"auid"` Ktime uint64 `align:"ktime"` } diff --git a/pkg/grpc/exec/exec_test_helper.go b/pkg/grpc/exec/exec_test_helper.go index d0a0376288e..e5cf3e34ec8 100644 --- a/pkg/grpc/exec/exec_test_helper.go +++ b/pkg/grpc/exec/exec_test_helper.go @@ -99,7 +99,7 @@ func CreateEvents[EXEC notify.Message, EXIT notify.Message](Pid uint32, Ktime ui }, Parent: tetragonAPI.MsgExecveKey{ Pid: 0, - Pad: 0, + Auid: 0, Ktime: 0, }, ParentFlags: 0, @@ -140,7 +140,7 @@ func CreateEvents[EXEC notify.Message, EXIT notify.Message](Pid uint32, Ktime ui }, Parent: tetragonAPI.MsgExecveKey{ Pid: 1, - Pad: 0, + Auid: 0, Ktime: 0, }, ParentFlags: 0, @@ -181,7 +181,7 @@ func CreateEvents[EXEC notify.Message, EXIT notify.Message](Pid uint32, Ktime ui }, Parent: tetragonAPI.MsgExecveKey{ Pid: ParentPid, - Pad: 0, + Auid: 0, Ktime: ParentKtime, }, ParentFlags: 0, @@ -215,7 +215,7 @@ func CreateEvents[EXEC notify.Message, EXIT notify.Message](Pid uint32, Ktime ui }, ProcessKey: tetragonAPI.MsgExecveKey{ Pid: Pid, - Pad: 0, + Auid: 0, Ktime: Ktime, }, Info: tetragonAPI.MsgExitInfo{ @@ -241,7 +241,7 @@ func CreateCloneEvents[CLONE notify.Message, EXIT notify.Message](Pid uint32, Kt }, Parent: tetragonAPI.MsgExecveKey{ Pid: ParentPid, - Pad: 0, + Auid: 0, Ktime: ParentKtime, }, PID: Pid, @@ -263,7 +263,7 @@ func CreateCloneEvents[CLONE notify.Message, EXIT notify.Message](Pid uint32, Kt }, ProcessKey: tetragonAPI.MsgExecveKey{ Pid: Pid, - Pad: 0, + Auid: 0, Ktime: Ktime, }, Info: tetragonAPI.MsgExitInfo{ diff --git a/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpolicies.yaml b/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpolicies.yaml index 420dda7775b..1176970d1de 100644 --- a/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpolicies.yaml +++ b/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpolicies.yaml @@ -461,6 +461,27 @@ spec: - values type: object type: array + matchLoginUids: + description: A list of login uid filters. + items: + properties: + operator: + description: LoginUid selector operator. + enum: + - In + - NotIn + type: string + values: + description: LoginUid to match. + items: + format: int32 + type: integer + type: array + required: + - operator + - values + type: object + type: array matchNamespaceChanges: description: IDs for namespace changes items: @@ -1114,6 +1135,27 @@ spec: - values type: object type: array + matchLoginUids: + description: A list of login uid filters. + items: + properties: + operator: + description: LoginUid selector operator. + enum: + - In + - NotIn + type: string + values: + description: LoginUid to match. + items: + format: int32 + type: integer + type: array + required: + - operator + - values + type: object + type: array matchNamespaceChanges: description: IDs for namespace changes items: @@ -1668,6 +1710,27 @@ spec: - values type: object type: array + matchLoginUids: + description: A list of login uid filters. + items: + properties: + operator: + description: LoginUid selector operator. + enum: + - In + - NotIn + type: string + values: + description: LoginUid to match. + items: + format: int32 + type: integer + type: array + required: + - operator + - values + type: object + type: array matchNamespaceChanges: description: IDs for namespace changes items: diff --git a/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpoliciesnamespaced.yaml b/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpoliciesnamespaced.yaml index 8436d3a23e6..bb3227787b0 100644 --- a/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpoliciesnamespaced.yaml +++ b/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpoliciesnamespaced.yaml @@ -461,6 +461,27 @@ spec: - values type: object type: array + matchLoginUids: + description: A list of login uid filters. + items: + properties: + operator: + description: LoginUid selector operator. + enum: + - In + - NotIn + type: string + values: + description: LoginUid to match. + items: + format: int32 + type: integer + type: array + required: + - operator + - values + type: object + type: array matchNamespaceChanges: description: IDs for namespace changes items: @@ -1114,6 +1135,27 @@ spec: - values type: object type: array + matchLoginUids: + description: A list of login uid filters. + items: + properties: + operator: + description: LoginUid selector operator. + enum: + - In + - NotIn + type: string + values: + description: LoginUid to match. + items: + format: int32 + type: integer + type: array + required: + - operator + - values + type: object + type: array matchNamespaceChanges: description: IDs for namespace changes items: @@ -1668,6 +1710,27 @@ spec: - values type: object type: array + matchLoginUids: + description: A list of login uid filters. + items: + properties: + operator: + description: LoginUid selector operator. + enum: + - In + - NotIn + type: string + values: + description: LoginUid to match. + items: + format: int32 + type: integer + type: array + required: + - operator + - values + type: object + type: array matchNamespaceChanges: description: IDs for namespace changes items: diff --git a/pkg/k8s/apis/cilium.io/v1alpha1/types.go b/pkg/k8s/apis/cilium.io/v1alpha1/types.go index f31c3a2c69c..40fac5bd2c8 100644 --- a/pkg/k8s/apis/cilium.io/v1alpha1/types.go +++ b/pkg/k8s/apis/cilium.io/v1alpha1/types.go @@ -125,6 +125,9 @@ type KProbeSelector struct { // +kubebuilder:validation:Optional // IDs for capabilities changes MatchCapabilityChanges []CapabilitiesSelector `json:"matchCapabilityChanges,omitempty"` + // +kubebuilder:validation:Optional + // A list of login uid filters. + MatchLoginUids []LoginUidSelector `json:"matchLoginUids,omitempty"` } type NamespaceChangesSelector struct { @@ -163,6 +166,14 @@ type CapabilitiesSelector struct { Values []string `json:"values"` } +type LoginUidSelector struct { + // +kubebuilder:validation:Enum=In;NotIn + // LoginUid selector operator. + Operator string `json:"operator"` + // LoginUid to match. + Values []uint32 `json:"values"` +} + type PIDSelector struct { // +kubebuilder:validation:Enum=In;NotIn // PID selector operator. diff --git a/pkg/k8s/apis/cilium.io/v1alpha1/version.go b/pkg/k8s/apis/cilium.io/v1alpha1/version.go index 2fc6ffa15ad..a530ed77ef6 100644 --- a/pkg/k8s/apis/cilium.io/v1alpha1/version.go +++ b/pkg/k8s/apis/cilium.io/v1alpha1/version.go @@ -7,4 +7,4 @@ package v1alpha1 // Used to determine if CRD needs to be updated in cluster // // Developers: Bump patch for each change in the CRD schema. -const CustomResourceDefinitionSchemaVersion = "1.1.4" +const CustomResourceDefinitionSchemaVersion = "1.1.5" diff --git a/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go b/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go index ee75b704aae..4f4afa6e55a 100644 --- a/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go @@ -177,6 +177,13 @@ func (in *KProbeSelector) DeepCopyInto(out *KProbeSelector) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.MatchLoginUids != nil { + in, out := &in.MatchLoginUids, &out.MatchLoginUids + *out = make([]LoginUidSelector, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -270,6 +277,27 @@ func (in *ListSpec) DeepCopy() *ListSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LoginUidSelector) DeepCopyInto(out *LoginUidSelector) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]uint32, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoginUidSelector. +func (in *LoginUidSelector) DeepCopy() *LoginUidSelector { + if in == nil { + return nil + } + out := new(LoginUidSelector) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespaceChangesSelector) DeepCopyInto(out *NamespaceChangesSelector) { *out = *in diff --git a/pkg/selectors/kernel.go b/pkg/selectors/kernel.go index 2eb91e221e6..62a4b3fe039 100644 --- a/pkg/selectors/kernel.go +++ b/pkg/selectors/kernel.go @@ -405,6 +405,40 @@ func ParseMatchPids(k *KernelSelectorState, matchPids []v1alpha1.PIDSelector) er return nil } +func loginuidSelectorValue(loginuid *v1alpha1.LoginUidSelector) ([]byte, uint32) { + b := make([]byte, len(loginuid.Values)*4) + + for i, v := range loginuid.Values { + off := i * 4 + binary.LittleEndian.PutUint32(b[off:], v) + } + return b, uint32(len(b)) +} + +func ParseMatchLoginuid(k *KernelSelectorState, loginuid *v1alpha1.LoginUidSelector) error { + op, err := SelectorOp(loginuid.Operator) + if err != nil { + return fmt.Errorf("matchloginuid error: %w", err) + } + WriteSelectorUint32(&k.data, op) + + value, size := loginuidSelectorValue(loginuid) + WriteSelectorUint32(&k.data, size/4) + WriteSelectorByteArray(&k.data, value, size) + return nil +} + +func ParseMatchLoginuids(k *KernelSelectorState, matchLoginuids []v1alpha1.LoginUidSelector) error { + loff := AdvanceSelectorLength(&k.data) + for _, p := range matchLoginuids { + if err := ParseMatchLoginuid(k, &p); err != nil { + return err + } + } + WriteSelectorLength(&k.data, loff) + return nil +} + func kprobeArgType(t string) uint32 { return argTypeTable[t] } @@ -1292,6 +1326,7 @@ func ParseMatchBinaries(k *KernelSelectorState, binarys []v1alpha1.BinarySelecto // [matchCapabilities] // [matchNamespaceChanges] // [matchCapabilityChanges] +// [matchLoginuids] // [matchArgs] // [matchActions] // @@ -1300,6 +1335,7 @@ func ParseMatchBinaries(k *KernelSelectorState, binarys []v1alpha1.BinarySelecto // matchCapabilities := [length][CAx][CAy]...[CAn] // matchNamespaceChanges := [length][NCx][NCy]...[NCn] // matchCapabilityChanges := [length][CAx][CAy]...[CAn] +// matchLoginuids := [length] [LoginUid1][LoginUid2]...[LoginUidn] // matchArgs := [length][ARGx][ARGy]...[ARGn] // PIDn := [op][flags][nValues][v1]...[vn] // Argn := [index][op][valueGen] @@ -1365,6 +1401,9 @@ func InitKernelSelectorState(selectors []v1alpha1.KProbeSelector, args []v1alpha if err := ParseMatchCapabilityChanges(k, selectors.MatchCapabilityChanges); err != nil { return fmt.Errorf("parseMatchCapabilityChanges error: %w", err) } + if err := ParseMatchLoginuids(k, selectors.MatchLoginUids); err != nil { + return fmt.Errorf("parseMatchLoginuids error: %w", err) + } if err := ParseMatchBinaries(k, selectors.MatchBinaries, selIdx); err != nil { return fmt.Errorf("parseMatchBinaries error: %w", err) } diff --git a/pkg/selectors/kernel_test.go b/pkg/selectors/kernel_test.go index 909af89f6d1..5a7f625c679 100644 --- a/pkg/selectors/kernel_test.go +++ b/pkg/selectors/kernel_test.go @@ -374,6 +374,46 @@ func TestParseMatchPid(t *testing.T) { } } +func TestParseMatchLoginuids(t *testing.T) { + loginuids1 := &v1alpha1.LoginUidSelector{Operator: "In", Values: []uint32{1, 2, 3}} + k := &KernelSelectorState{data: KernelSelectorData{off: 0}} + d := &k.data + expected1 := []byte{ + 0x05, 0x00, 0x00, 0x00, // op == In + 0x03, 0x00, 0x00, 0x00, // length == 0x3 + 0x01, 0x00, 0x00, 0x00, // Values[0] == 1 + 0x02, 0x00, 0x00, 0x00, // Values[1] == 2 + 0x03, 0x00, 0x00, 0x00, // Values[2] == 3 + } + if err := ParseMatchLoginuid(k, loginuids1); err != nil || bytes.Equal(expected1, d.e[0:d.off]) == false { + t.Errorf("ParseMatchLoginuids: error %v expected %v bytes %v parsing %v\n", err, expected1, d.e[0:d.off], loginuids1) + } + + nextloginuids := d.off + loginuids2 := &v1alpha1.LoginUidSelector{Operator: "NotIn", Values: []uint32{1, 2, 3, 4}} + expected2 := []byte{ + 0x06, 0x00, 0x00, 0x00, // op == NotIn + 0x04, 0x00, 0x00, 0x00, // length == 0x4 + 0x01, 0x00, 0x00, 0x00, // Values[0] == 1 + 0x02, 0x00, 0x00, 0x00, // Values[1] == 2 + 0x03, 0x00, 0x00, 0x00, // Values[2] == 3 + 0x04, 0x00, 0x00, 0x00, // Values[2] == 3 + } + if err := ParseMatchLoginuid(k, loginuids2); err != nil || bytes.Equal(expected2, d.e[nextloginuids:d.off]) == false { + t.Errorf("ParseMatchLoginuids: error %v expected %v bytes %v parsing %v\n", err, expected2, d.e[nextloginuids:d.off], loginuids2) + } + + length := []byte{48, 0x00, 0x00, 0x00} + expected3 := append(length, expected1[:]...) + expected3 = append(expected3, expected2[:]...) + loginuids3 := []v1alpha1.LoginUidSelector{*loginuids1, *loginuids2} + ks := &KernelSelectorState{data: KernelSelectorData{off: 0}} + d = &ks.data + if err := ParseMatchLoginuids(ks, loginuids3); err != nil || bytes.Equal(expected3, d.e[0:d.off]) == false { + t.Errorf("ParseMatchLoginuids: error %v expected %v bytes %v parsing %v\n", err, expected3, d.e[0:d.off], loginuids3) + } +} + func TestParseMatchNamespaces(t *testing.T) { ns1 := &v1alpha1.NamespaceSelector{Namespace: "Pid", Operator: "In", Values: []string{"1", "2", "3"}} k := &KernelSelectorState{data: KernelSelectorData{off: 0}} @@ -553,8 +593,8 @@ func TestMultipleSelectorsExample(t *testing.T) { // value absolute offset explanation expU32Push(2) // off: 0 number of selectors expU32Push(8) // off: 4 relative ofset of 1st selector (4 + 8 = 12) - expU32Push(100) // off: 8 relative ofset of 2nd selector (8 + 124 = 132) - expU32Push(96) // off: 12 selector1: length (76 + 12 = 96) + expU32Push(104) // off: 8 relative ofset of 2nd selector (8 + 104 = 112) + expU32Push(100) // off: 12 selector1: length (4+24+5*4+48+4=100) expU32Push(24) // off: 16 selector1: MatchPIDs: len expU32Push(SelectorOpNotIn) // off: 20 selector1: MatchPIDs[0]: op expU32Push(0) // off: 24 selector1: MatchPIDs[0]: flags @@ -565,20 +605,21 @@ func TestMultipleSelectorsExample(t *testing.T) { expU32Push(4) // off: 44 selector1: MatchCapabilities: len expU32Push(4) // off: 48 selector1: MatchNamespaceChanges: len expU32Push(4) // off: 52 selector1: MatchCapabilityChanges: len - expU32Push(48) // off: 80 selector1: matchArgs: len - expU32Push(24) // off: 84 selector1: matchArgs[0]: offset - expU32Push(0) // off: 88 selector1: matchArgs[1]: offset - expU32Push(0) // off: 92 selector1: matchArgs[2]: offset - expU32Push(0) // off: 96 selector1: matchArgs[3]: offset - expU32Push(0) // off: 100 selector1: matchArgs[4]: offset - expU32Push(1) // off: 104 selector1: matchArgs: arg0: index - expU32Push(SelectorOpEQ) // off: 108 selector1: matchArgs: arg0: operator - expU32Push(16) // off: 112 selector1: matchArgs: arg0: len of vals - expU32Push(argTypeInt) // off: 116 selector1: matchArgs: arg0: type - expU32Push(10) // off: 120 selector1: matchArgs: arg0: val0: 10 - expU32Push(20) // off: 124 selector1: matchArgs: arg0: val1: 20 - expU32Push(4) // off: 128 selector1: matchActions: length - expU32Push(96) // off: 132 selector2: length + expU32Push(4) // off: 56 selector1: MatchLoginuids: len + expU32Push(48) // off: 60 selector1: matchArgs: len + expU32Push(24) // off: 64 selector1: matchArgs[0]: offset + expU32Push(0) // off: 68 selector1: matchArgs[1]: offset + expU32Push(0) // off: 72 selector1: matchArgs[2]: offset + expU32Push(0) // off: 76 selector1: matchArgs[3]: offset + expU32Push(0) // off: 80 selector1: matchArgs[4]: offset + expU32Push(1) // off: 84 selector1: matchArgs: arg0: index + expU32Push(SelectorOpEQ) // off: 88 selector1: matchArgs: arg0: operator + expU32Push(16) // off: 92 selector1: matchArgs: arg0: len of vals + expU32Push(argTypeInt) // off: 96 selector1: matchArgs: arg0: type + expU32Push(10) // off: 100 selector1: matchArgs: arg0: val0: 10 + expU32Push(20) // off: 104 selector1: matchArgs: arg0: val1: 20 + expU32Push(4) // off: 108 selector1: matchActions: length + expU32Push(100) // off: 112 selector2: length // ... everything else should be the same as selector1 ... if bytes.Equal(expected[:expectedLen], b[:expectedLen]) == false { @@ -595,11 +636,11 @@ func TestInitKernelSelectors(t *testing.T) { } expected_selsize_small := []byte{ - 0xfc, 0x00, 0x00, 0x00, // size = pids + args + actions + namespaces + capabilities + 4 + 0x2c, 0x01, 0x00, 0x00, // size = pids + args + actions + namespaces + capabilities + loginuid + 4 } expected_selsize_large := []byte{ - 0x30, 0x01, 0x00, 0x00, // size = pids + args + actions + namespaces + namespacesChanges + capabilities + capabilityChanges + 4 + 0x60, 0x01, 0x00, 0x00, // size = pids + args + actions + namespaces + namespacesChanges + capabilities + capabilityChanges + loginuid + 4 } expected_filters := []byte{ @@ -682,6 +723,26 @@ func TestInitKernelSelectors(t *testing.T) { 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, // Values (uint64) } + expected_loginuid := []byte{ + // loginuid header + 48, 0x00, 0x00, 0x00, // size = sizeof(loginuids1) + sizeof(loginuids2) + 4 + + //loginuids1 size = 20 + 0x05, 0x00, 0x00, 0x00, // op == In + 0x03, 0x00, 0x00, 0x00, // length == 0x3 + 0x01, 0x00, 0x00, 0x00, // Values[0] == 1 + 0x02, 0x00, 0x00, 0x00, // Values[1] == 2 + 0x03, 0x00, 0x00, 0x00, // Values[2] == 3 + + //loginuids2 size = 24 + 0x06, 0x00, 0x00, 0x00, // op == NotIn + 0x04, 0x00, 0x00, 0x00, // length == 0x4 + 0x01, 0x00, 0x00, 0x00, // Values[0] == 1 + 0x02, 0x00, 0x00, 0x00, // Values[1] == 2 + 0x03, 0x00, 0x00, 0x00, // Values[2] == 3 + 0x04, 0x00, 0x00, 0x00, // Values[2] == 3 + } + expected_last_large := []byte{ // arg header 88, 0x00, 0x00, 0x00, // size = sizeof(arg2) + sizeof(arg1) + 24 @@ -759,11 +820,13 @@ func TestInitKernelSelectors(t *testing.T) { expected = append(expected, expected_selsize_large...) expected = append(expected, expected_filters...) expected = append(expected, expected_changes...) + expected = append(expected, expected_loginuid...) expected = append(expected, expected_last_large...) } else { expected = append(expected, expected_selsize_small...) expected = append(expected, expected_filters...) expected = append(expected, expected_changes_empty...) + expected = append(expected, expected_loginuid...) expected = append(expected, expected_last_small...) } @@ -786,6 +849,9 @@ func TestInitKernelSelectors(t *testing.T) { cc := &v1alpha1.CapabilitiesSelector{Type: "Effective", Operator: "In", IsNamespaceCapability: false, Values: []string{"CAP_SYS_ADMIN", "CAP_NET_RAW"}} matchCapabilityChanges = append(matchCapabilityChanges, *cc) } + loginuids1 := &v1alpha1.LoginUidSelector{Operator: "In", Values: []uint32{1, 2, 3}} + loginuids2 := &v1alpha1.LoginUidSelector{Operator: "NotIn", Values: []uint32{1, 2, 3, 4}} + matchLoginuids := []v1alpha1.LoginUidSelector{*loginuids1, *loginuids2} var matchArgs []v1alpha1.ArgSelector if kernels.EnableLargeProgs() { arg1 := &v1alpha1.ArgSelector{Index: 1, Operator: "Equal", Values: []string{"foobar"}} @@ -808,6 +874,7 @@ func TestInitKernelSelectors(t *testing.T) { MatchCapabilities: matchCapabilities, MatchNamespaceChanges: matchNamespaceChanges, MatchCapabilityChanges: matchCapabilityChanges, + MatchLoginUids: matchLoginuids, MatchArgs: matchArgs, MatchActions: matchActions, }, diff --git a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpolicies.yaml b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpolicies.yaml index 420dda7775b..1176970d1de 100644 --- a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpolicies.yaml +++ b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpolicies.yaml @@ -461,6 +461,27 @@ spec: - values type: object type: array + matchLoginUids: + description: A list of login uid filters. + items: + properties: + operator: + description: LoginUid selector operator. + enum: + - In + - NotIn + type: string + values: + description: LoginUid to match. + items: + format: int32 + type: integer + type: array + required: + - operator + - values + type: object + type: array matchNamespaceChanges: description: IDs for namespace changes items: @@ -1114,6 +1135,27 @@ spec: - values type: object type: array + matchLoginUids: + description: A list of login uid filters. + items: + properties: + operator: + description: LoginUid selector operator. + enum: + - In + - NotIn + type: string + values: + description: LoginUid to match. + items: + format: int32 + type: integer + type: array + required: + - operator + - values + type: object + type: array matchNamespaceChanges: description: IDs for namespace changes items: @@ -1668,6 +1710,27 @@ spec: - values type: object type: array + matchLoginUids: + description: A list of login uid filters. + items: + properties: + operator: + description: LoginUid selector operator. + enum: + - In + - NotIn + type: string + values: + description: LoginUid to match. + items: + format: int32 + type: integer + type: array + required: + - operator + - values + type: object + type: array matchNamespaceChanges: description: IDs for namespace changes items: diff --git a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpoliciesnamespaced.yaml b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpoliciesnamespaced.yaml index 8436d3a23e6..bb3227787b0 100644 --- a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpoliciesnamespaced.yaml +++ b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/client/crds/v1alpha1/cilium.io_tracingpoliciesnamespaced.yaml @@ -461,6 +461,27 @@ spec: - values type: object type: array + matchLoginUids: + description: A list of login uid filters. + items: + properties: + operator: + description: LoginUid selector operator. + enum: + - In + - NotIn + type: string + values: + description: LoginUid to match. + items: + format: int32 + type: integer + type: array + required: + - operator + - values + type: object + type: array matchNamespaceChanges: description: IDs for namespace changes items: @@ -1114,6 +1135,27 @@ spec: - values type: object type: array + matchLoginUids: + description: A list of login uid filters. + items: + properties: + operator: + description: LoginUid selector operator. + enum: + - In + - NotIn + type: string + values: + description: LoginUid to match. + items: + format: int32 + type: integer + type: array + required: + - operator + - values + type: object + type: array matchNamespaceChanges: description: IDs for namespace changes items: @@ -1668,6 +1710,27 @@ spec: - values type: object type: array + matchLoginUids: + description: A list of login uid filters. + items: + properties: + operator: + description: LoginUid selector operator. + enum: + - In + - NotIn + type: string + values: + description: LoginUid to match. + items: + format: int32 + type: integer + type: array + required: + - operator + - values + type: object + type: array matchNamespaceChanges: description: IDs for namespace changes items: diff --git a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/types.go b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/types.go index f31c3a2c69c..40fac5bd2c8 100644 --- a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/types.go +++ b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/types.go @@ -125,6 +125,9 @@ type KProbeSelector struct { // +kubebuilder:validation:Optional // IDs for capabilities changes MatchCapabilityChanges []CapabilitiesSelector `json:"matchCapabilityChanges,omitempty"` + // +kubebuilder:validation:Optional + // A list of login uid filters. + MatchLoginUids []LoginUidSelector `json:"matchLoginUids,omitempty"` } type NamespaceChangesSelector struct { @@ -163,6 +166,14 @@ type CapabilitiesSelector struct { Values []string `json:"values"` } +type LoginUidSelector struct { + // +kubebuilder:validation:Enum=In;NotIn + // LoginUid selector operator. + Operator string `json:"operator"` + // LoginUid to match. + Values []uint32 `json:"values"` +} + type PIDSelector struct { // +kubebuilder:validation:Enum=In;NotIn // PID selector operator. diff --git a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go index ee75b704aae..4f4afa6e55a 100644 --- a/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go @@ -177,6 +177,13 @@ func (in *KProbeSelector) DeepCopyInto(out *KProbeSelector) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.MatchLoginUids != nil { + in, out := &in.MatchLoginUids, &out.MatchLoginUids + *out = make([]LoginUidSelector, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -270,6 +277,27 @@ func (in *ListSpec) DeepCopy() *ListSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LoginUidSelector) DeepCopyInto(out *LoginUidSelector) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]uint32, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoginUidSelector. +func (in *LoginUidSelector) DeepCopy() *LoginUidSelector { + if in == nil { + return nil + } + out := new(LoginUidSelector) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamespaceChangesSelector) DeepCopyInto(out *NamespaceChangesSelector) { *out = *in