diff --git a/cmd/tetra/tracingpolicy/tracingpolicy.go b/cmd/tetra/tracingpolicy/tracingpolicy.go index d49dfe234a0..ca49debbdf2 100644 --- a/cmd/tetra/tracingpolicy/tracingpolicy.go +++ b/cmd/tetra/tracingpolicy/tracingpolicy.go @@ -23,6 +23,7 @@ import ( "github.com/cilium/tetragon/api/v1/tetragon" "github.com/cilium/tetragon/cmd/tetra/common" "github.com/cilium/tetragon/pkg/btf" + "github.com/cilium/tetragon/pkg/ftrace" "github.com/cilium/tetragon/pkg/logger" "github.com/spf13/cobra" ) @@ -76,17 +77,19 @@ func New() *cobra.Command { tpListFlags.StringVarP(&tpListOutputFlag, common.KeyOutput, "o", "text", "Output format. text or json") var tpGenerateMatchBinary string + var tpGenerateRegex string tpGenerateCmd := &cobra.Command{ - Use: "generate ", + Use: "generate ", Short: "generate tracing policies", Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { - generateTracingPolicy(args[0], tpGenerateMatchBinary) + generateTracingPolicy(args[0], tpGenerateMatchBinary, tpGenerateRegex) }, } tpGenerateFlags := tpGenerateCmd.Flags() tpGenerateFlags.StringVarP(&tpGenerateMatchBinary, "match-binary", "m", "", "Add binary to matchBinaries selector") + tpGenerateFlags.StringVarP(&tpGenerateRegex, "regex", "r", "", "Use regex to limit the generated symbols") tpCmd.AddCommand(tpAddCmd, tpDelCmd, tpListCmd, tpGenerateCmd) return tpCmd @@ -158,6 +161,52 @@ func generateAllSyscalls(binary string) { fmt.Printf("%s\n", crd) } +func generateAllSyscallsList(binary string) { + crd, err := btf.GetSyscallsYamlList(binary) + if err != nil { + fmt.Print(err) + return + } + fmt.Printf("%s\n", crd) +} + +func generateFtrace(binary, regex string) { + syms, err := ftrace.ReadAvailFuncs(regex) + if err != nil { + logger.GetLogger().WithError(err).Fatalf("failed to read ftrace functions: %s", err) + } + + crd := `apiVersion: cilium.io/v1alpha1 +kind: TracingPolicy +metadata: + name: "ftrace" +spec: + lists: + - name: "ftrace" + values:` + + for idx := range syms { + crd = crd + "\n" + fmt.Sprintf(" - \"%s\"", syms[idx]) + } + + crd = crd + ` + kprobes: + - call: "list:ftrace"` + + if binary != "" { + filter := ` + selectors: + - matchBinaries: + - operator: "In" + values: + - "` + binary + `"` + + crd = crd + filter + } + + fmt.Printf("%s\n", crd) +} + func generateEmpty() { crd := `apiVersion: cilium.io/v1alpha1 kind: TracingPolicy @@ -167,10 +216,14 @@ metadata: fmt.Printf("%s\n", crd) } -func generateTracingPolicy(cmd, binary string) { +func generateTracingPolicy(cmd, binary, regex string) { switch cmd { case "all-syscalls": generateAllSyscalls(binary) + case "all-syscalls-list": + generateAllSyscallsList(binary) + case "ftrace-list": + generateFtrace(binary, regex) case "empty": generateEmpty() } diff --git a/examples/tracingpolicy/list-generated-ftrace.yaml b/examples/tracingpolicy/list-generated-ftrace.yaml new file mode 100644 index 00000000000..e5c0e95195a --- /dev/null +++ b/examples/tracingpolicy/list-generated-ftrace.yaml @@ -0,0 +1,16 @@ +apiVersion: cilium.io/v1alpha1 +kind: TracingPolicy +metadata: + name: "all-ksys-for-kill" +spec: + lists: + - name: "ksys" + type: "generated_ftrace" + pattern: "^ksys_*" + kprobes: + - call: "list:ksys" + selectors: + - matchBinaries: + - operator: "In" + values: + - "/usr/bin/kill" diff --git a/examples/tracingpolicy/list-syscalls-generated.yaml b/examples/tracingpolicy/list-syscalls-generated.yaml new file mode 100644 index 00000000000..dcdd00d1585 --- /dev/null +++ b/examples/tracingpolicy/list-syscalls-generated.yaml @@ -0,0 +1,15 @@ +apiVersion: cilium.io/v1alpha1 +kind: TracingPolicy +metadata: + name: "all-syscalls-for-kill" +spec: + lists: + - name: "all-syscalls" + type: "generated_syscalls" + kprobes: + - call: "list:all-syscalls" + selectors: + - matchBinaries: + - operator: "In" + values: + - "/usr/bin/kill" diff --git a/examples/tracingpolicy/list-syscalls.yaml b/examples/tracingpolicy/list-syscalls.yaml new file mode 100644 index 00000000000..8ebb8437de1 --- /dev/null +++ b/examples/tracingpolicy/list-syscalls.yaml @@ -0,0 +1,13 @@ +apiVersion: cilium.io/v1alpha1 +kind: TracingPolicy +metadata: + name: "list-syscalls" +spec: + lists: + - name: "syscalls" + type: "syscalls" + values: + - "sys_dup" + - "sys_dup2" + kprobes: + - call: "list:syscalls" diff --git a/go.mod b/go.mod index 5b4cf6c9be0..3c0c4ad8b47 100644 --- a/go.mod +++ b/go.mod @@ -39,6 +39,7 @@ require ( github.com/vishvananda/netlink v1.2.1-beta.2.0.20230621221334-77712cff8739 go.uber.org/atomic v1.11.0 go.uber.org/multierr v1.11.0 + golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 golang.org/x/sync v0.3.0 golang.org/x/sys v0.11.0 golang.org/x/time v0.3.0 @@ -163,7 +164,6 @@ require ( go.opentelemetry.io/otel/trace v1.16.0 // indirect go.uber.org/dig v1.17.0 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.12.0 // indirect golang.org/x/oauth2 v0.7.0 // indirect diff --git a/pkg/btf/validation.go b/pkg/btf/validation.go index 7ea76063108..cfbf3ce82ad 100644 --- a/pkg/btf/validation.go +++ b/pkg/btf/validation.go @@ -331,3 +331,109 @@ spec: return crd, nil } + +func GetSyscallsList() ([]string, error) { + btfFile := "/sys/kernel/btf/vmlinux" + + tetragonBtfEnv := os.Getenv("TETRAGON_BTF") + if tetragonBtfEnv != "" { + if _, err := os.Stat(tetragonBtfEnv); err != nil { + return []string{}, fmt.Errorf("Failed to find BTF: %s", tetragonBtfEnv) + } + btfFile = tetragonBtfEnv + } + + bspec, err := btf.LoadSpec(btfFile) + if err != nil { + return []string{}, fmt.Errorf("BTF load failed: %v", err) + } + + var list []string + + for _, key := range syscallinfo.SyscallsNames() { + var fn *btf.Func + + if key == "" { + continue + } + + sym, err := arch.AddSyscallPrefix(key) + if err != nil { + return []string{}, err + } + + err = bspec.TypeByName(sym, &fn) + if err != nil { + continue + } + + list = append(list, sym) + } + + return list, nil +} + +func GetSyscallsYamlList(binary string) (string, error) { + crd := `apiVersion: cilium.io/v1alpha1 +kind: TracingPolicy +metadata: + name: "syscalls" +spec: + lists: + - name: "syscalls" + type: "syscalls" + values:` + + btfFile := "/sys/kernel/btf/vmlinux" + + tetragonBtfEnv := os.Getenv("TETRAGON_BTF") + if tetragonBtfEnv != "" { + if _, err := os.Stat(tetragonBtfEnv); err != nil { + return "", fmt.Errorf("Failed to find BTF: %s", tetragonBtfEnv) + } + btfFile = tetragonBtfEnv + } + + bspec, err := btf.LoadSpec(btfFile) + if err != nil { + return "", fmt.Errorf("BTF load failed: %v", err) + } + + for _, key := range syscallinfo.SyscallsNames() { + var fn *btf.Func + + if key == "" { + continue + } + + sym, err := arch.AddSyscallPrefix(key) + if err != nil { + return "", err + } + + err = bspec.TypeByName(sym, &fn) + if err != nil { + continue + } + + crd = crd + "\n" + fmt.Sprintf(" - \"%s\"", key) + } + + crd = crd + ` + kprobes: + - call: "list:syscalls" + syscall: true` + + if binary != "" { + filter := ` + selectors: + - matchBinaries: + - operator: "In" + values: + - "` + binary + `"` + + crd = crd + filter + } + + return crd, nil +} diff --git a/pkg/ftrace/ftrace.go b/pkg/ftrace/ftrace.go new file mode 100644 index 00000000000..74858119a78 --- /dev/null +++ b/pkg/ftrace/ftrace.go @@ -0,0 +1,65 @@ +package ftrace + +import ( + "bufio" + "os" + "regexp" + "strings" + + "golang.org/x/exp/slices" +) + +func readLines(path string) ([]string, error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + + var lines []string + scanner := bufio.NewScanner(file) + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + return lines, scanner.Err() +} + +func ReadAvailFuncs(pattern string) ([]string, error) { + list, err := readLines("/sys/kernel/debug/tracing/available_filter_functions") + if err != nil { + return []string{}, err + } + + for idx := range list { + line := list[idx] + // skip modules + if strings.ContainsAny(line, " ") { + list = list[:idx] + break + } + } + + slices.Sort[string](list) + list = slices.Compact[[]string, string](list) + + var r *regexp.Regexp + + if pattern != "" { + r, _ = regexp.Compile(pattern) + } + + final := []string{} + + for idx := range list { + line := list[idx] + if strings.Contains(line, "__ftrace_invalid_address__") { + continue + } + if r != nil && !r.MatchString(line) { + continue + } + final = append(final, line) + } + + return final, nil +} 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 934a9f880d0..0f693b360b7 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 @@ -548,6 +548,32 @@ spec: - call type: object type: array + lists: + description: A list of list specs. + items: + properties: + name: + description: Name of the list + type: string + pattern: + description: Pattern for 'generated' lists. + type: string + type: + description: Indicates the type of the list values. + enum: + - syscalls + - generated_syscalls + - generated_ftrace + type: string + values: + description: Values of the list + items: + type: string + type: array + required: + - name + type: object + type: array loader: description: Enable loader events type: boolean 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 d93747af1a6..7f0b8c0ee22 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 @@ -548,6 +548,32 @@ spec: - call type: object type: array + lists: + description: A list of list specs. + items: + properties: + name: + description: Name of the list + type: string + pattern: + description: Pattern for 'generated' lists. + type: string + type: + description: Indicates the type of the list values. + enum: + - syscalls + - generated_syscalls + - generated_ftrace + type: string + values: + description: Values of the list + items: + type: string + type: array + required: + - name + type: object + type: array loader: description: Enable loader events type: boolean diff --git a/pkg/k8s/apis/cilium.io/v1alpha1/types.go b/pkg/k8s/apis/cilium.io/v1alpha1/types.go index a3d232a3ed5..9694fc7c4e9 100644 --- a/pkg/k8s/apis/cilium.io/v1alpha1/types.go +++ b/pkg/k8s/apis/cilium.io/v1alpha1/types.go @@ -89,6 +89,10 @@ type TracingPolicySpec struct { // +kubebuilder:validation:Optional // PodSelector selects pods that this policy applies to PodSelector *slimv1.LabelSelector `json:"podSelector,omitempty"` + + // +kubebuilder:validation:Optional + // A list of list specs. + Lists []ListSpec `json:"lists"` } func (tp *TracingPolicy) TpName() string { @@ -331,3 +335,18 @@ type UProbeSpec struct { // Selectors to apply before producing trace output. Selectors are ORed. Selectors []KProbeSelector `json:"selectors"` } + +type ListSpec struct { + // Name of the list + Name string `json:"name"` + // +kubebuilder:validation:Optional + // Values of the list + Values []string `json:"values"` + // +kubebuilder:validation:Optional + // +kubebuilder:validation:Enum=syscalls;generated_syscalls;generated_ftrace + // Indicates the type of the list values. + Type string `json:"type"` + // +kubebuilder:validation:Optional + // Pattern for 'generated' lists. + Pattern string `json:"pattern"` +} 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 b968a52b827..c0d4d144b16 100644 --- a/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go @@ -214,6 +214,27 @@ func (in *KProbeSpec) DeepCopy() *KProbeSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ListSpec) DeepCopyInto(out *ListSpec) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListSpec. +func (in *ListSpec) DeepCopy() *ListSpec { + if in == nil { + return nil + } + out := new(ListSpec) + 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 @@ -454,6 +475,13 @@ func (in *TracingPolicySpec) DeepCopyInto(out *TracingPolicySpec) { *out = new(v1.LabelSelector) (*in).DeepCopyInto(*out) } + if in.Lists != nil { + in, out := &in.Lists, &out.Lists + *out = make([]ListSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } diff --git a/pkg/sensors/tracing/generickprobe.go b/pkg/sensors/tracing/generickprobe.go index dcf76ba6c2d..d208ebe7fee 100644 --- a/pkg/sensors/tracing/generickprobe.go +++ b/pkg/sensors/tracing/generickprobe.go @@ -290,7 +290,7 @@ func createMultiKprobeSensor(sensorPath string, multiIDs, multiRetIDs []idtable. // // Pre validate the kprobe semantics and BTF information in order to separate // the kprobe errors from BPF related ones. -func preValidateKprobes(name string, kprobes []v1alpha1.KProbeSpec) error { +func preValidateKprobes(name string, kprobes []v1alpha1.KProbeSpec, lists []v1alpha1.ListSpec) error { btfobj, err := btf.NewBTF() if err != nil { return err @@ -303,6 +303,16 @@ func preValidateKprobes(name string, kprobes []v1alpha1.KProbeSpec) error { } } + // validate lists first + for i := range lists { + list := &lists[i] + + err := preValidateList(list) + if err != nil { + return err + } + } + for i := range kprobes { f := &kprobes[i] @@ -315,6 +325,17 @@ func preValidateKprobes(name string, kprobes []v1alpha1.KProbeSpec) error { } } + if strings.HasPrefix(f.Call, "list:") { + listName := f.Call[len("list:"):] + + if !hasList(listName, lists) { + return fmt.Errorf("Error list '%s' not found", listName) + } + + // all lists are already validated, we're done + continue + } + // modifying f.Call directly since BTF validation // later will use v1alpha1.KProbeSpec object if f.Syscall { @@ -373,313 +394,373 @@ func isLTOperator(op string) bool { return op == "LT" || op == "LessThan" } +type addKprobeIn struct { + useMulti bool + sensorPath string + policyName string + policyID policyfilter.PolicyID +} + +type addKprobeOut struct { + multiIDs []idtable.EntryID + multiRetIDs []idtable.EntryID + progs []*program.Program + maps []*program.Map +} + +func getKprobeSymbols(symbol string, syscall bool, lists []v1alpha1.ListSpec) ([]string, bool, error) { + if strings.HasPrefix(symbol, "list:") { + name := symbol[len("list:"):] + for idx := range lists { + list := lists[idx] + if list.Name == name { + return list.Values, isSyscallListType(list.Type), nil + } + } + return []string{""}, false, fmt.Errorf("list '%s' not found", name) + } + return []string{symbol}, syscall, nil +} + func createGenericKprobeSensor( name string, kprobes []v1alpha1.KProbeSpec, policyID policyfilter.PolicyID, policyName string, + lists []v1alpha1.ListSpec, ) (*sensors.Sensor, error) { var progs []*program.Program var maps []*program.Map var multiIDs, multiRetIDs []idtable.EntryID var useMulti bool - sensorPath := name - loadProgName, loadProgRetName := kernels.GenericKprobeObjs() - // use multi kprobe only if: // - it's not disabled by user // - there's support detected useMulti = !option.Config.DisableKprobeMulti && bpf.HasKprobeMulti() + in := addKprobeIn{ + useMulti: useMulti, + sensorPath: name, + policyID: policyID, + policyName: policyName, + } + for i := range kprobes { - f := &kprobes[i] - var err error - var argSigPrinters []argPrinters - var argReturnPrinters []argPrinters - var setRetprobe bool - var argRetprobe *v1alpha1.KProbeArg - var argsBTFSet [api.MaxArgsSupported]bool - - config := &api.EventConfig{} - config.PolicyID = uint32(policyID) - if len(f.ReturnArgAction) > 0 { - if !kernels.EnableLargeProgs() { - return nil, fmt.Errorf("ReturnArgAction requires kernel >=5.3") - } - config.ArgReturnAction = selectors.ActionTypeFromString(f.ReturnArgAction) - if config.ArgReturnAction == selectors.ActionTypeInvalid { - return nil, fmt.Errorf("ReturnArgAction type '%s' unsupported", f.ReturnArgAction) - } + syms, syscall, err := getKprobeSymbols(kprobes[i].Call, kprobes[i].Syscall, lists) + if err != nil { + return nil, err } - argRetprobe = nil // holds pointer to arg for return handler - funcName := f.Call + // Syscall flag might be changed in list definition + kprobes[i].Syscall = syscall - // Parse Arguments - for j, a := range f.Args { - argType := gt.GenericTypeFromString(a.Type) - if argType == gt.GenericInvalidType { - return nil, fmt.Errorf("Arg(%d) type '%s' unsupported", j, a.Type) - } - if a.MaxData { - if argType != gt.GenericCharBuffer { - logger.GetLogger().Warnf("maxData flag is ignored (supported for char_buf type)") - } - if !kernels.EnableLargeProgs() { - logger.GetLogger().Warnf("maxData flag is ignored (supported from large programs)") - } - } - argMValue, err := getMetaValue(&a) + for idx := range syms { + out, err := addKprobe(syms[idx], &kprobes[i], &in) if err != nil { return nil, err } - if argReturnCopy(argMValue) { - argRetprobe = &f.Args[j] - } - if a.Index > 4 { - return nil, - fmt.Errorf("Error add arg: ArgType %s Index %d out of bounds", - a.Type, int(a.Index)) + + if useMulti { + multiRetIDs = append(multiRetIDs, out.multiRetIDs...) + multiIDs = append(multiIDs, out.multiIDs...) + } else { + progs = append(progs, out.progs...) + maps = append(maps, out.maps...) } - config.Arg[a.Index] = int32(argType) - config.ArgM[a.Index] = uint32(argMValue) + } + } + + if useMulti { + progs, maps = createMultiKprobeSensor(in.sensorPath, multiIDs, multiRetIDs) + } + + return &sensors.Sensor{ + Name: name, + Progs: progs, + Maps: maps, + }, nil +} - argsBTFSet[a.Index] = true - argP := argPrinters{index: j, ty: argType, maxData: a.MaxData, label: a.Label} - argSigPrinters = append(argSigPrinters, argP) +func addKprobe(funcName string, f *v1alpha1.KProbeSpec, in *addKprobeIn) (out *addKprobeOut, err error) { + var argSigPrinters []argPrinters + var argReturnPrinters []argPrinters + var setRetprobe bool + var argRetprobe *v1alpha1.KProbeArg + var argsBTFSet [api.MaxArgsSupported]bool + + out = &addKprobeOut{} + + loadProgName, loadProgRetName := kernels.GenericKprobeObjs() + + config := &api.EventConfig{} + config.PolicyID = uint32(in.policyID) + if len(f.ReturnArgAction) > 0 { + if !kernels.EnableLargeProgs() { + return nil, fmt.Errorf("ReturnArgAction requires kernel >=5.3") + } + config.ArgReturnAction = selectors.ActionTypeFromString(f.ReturnArgAction) + if config.ArgReturnAction == selectors.ActionTypeInvalid { + return nil, fmt.Errorf("ReturnArgAction type '%s' unsupported", f.ReturnArgAction) } + } - // Parse ReturnArg, we have two types of return arg parsing. We - // support populating a kprobe buffer from kretprobe hooks. This - // is used to capture data that is populated by the function hoooked. - // For example Read calls supply a buffer to the syscall, but we - // wont have its contents until kretprobe is run. The other type is - // the f.Return case. These capture the return value of the function - // without context from the kprobe hook. The BTF argument 'argreturn' - // instructs the BPF kretprobe program which type of copy to use. And - // argReturnPrinters tell golang printer piece how to print the event. - if f.Return { - argType := gt.GenericTypeFromString(f.ReturnArg.Type) - if argType == gt.GenericInvalidType { - if f.ReturnArg.Type == "" { - return nil, fmt.Errorf("ReturnArg not specified with Return=true") - } - return nil, fmt.Errorf("ReturnArg type '%s' unsupported", f.ReturnArg.Type) + argRetprobe = nil // holds pointer to arg for return handler + + // Parse Arguments + for j, a := range f.Args { + argType := gt.GenericTypeFromString(a.Type) + if argType == gt.GenericInvalidType { + return nil, fmt.Errorf("Arg(%d) type '%s' unsupported", j, a.Type) + } + if a.MaxData { + if argType != gt.GenericCharBuffer { + logger.GetLogger().Warnf("maxData flag is ignored (supported for char_buf type)") + } + if !kernels.EnableLargeProgs() { + logger.GetLogger().Warnf("maxData flag is ignored (supported from large programs)") } - config.ArgReturn = int32(argType) - argsBTFSet[api.ReturnArgIndex] = true - argP := argPrinters{index: api.ReturnArgIndex, ty: argType} - argReturnPrinters = append(argReturnPrinters, argP) - } else { - config.ArgReturn = int32(0) } + argMValue, err := getMetaValue(&a) + if err != nil { + return nil, err + } + if argReturnCopy(argMValue) { + argRetprobe = &f.Args[j] + } + if a.Index > 4 { + return nil, + fmt.Errorf("Error add arg: ArgType %s Index %d out of bounds", + a.Type, int(a.Index)) + } + config.Arg[a.Index] = int32(argType) + config.ArgM[a.Index] = uint32(argMValue) - if argRetprobe != nil { - argsBTFSet[api.ReturnArgIndex] = true - setRetprobe = true - - argType := gt.GenericTypeFromString(argRetprobe.Type) - config.ArgReturnCopy = int32(argType) + argsBTFSet[a.Index] = true + argP := argPrinters{index: j, ty: argType, maxData: a.MaxData, label: a.Label} + argSigPrinters = append(argSigPrinters, argP) + } - argP := argPrinters{index: int(argRetprobe.Index), ty: argType, label: argRetprobe.Label} - argReturnPrinters = append(argReturnPrinters, argP) - } else { - config.ArgReturnCopy = int32(0) + // Parse ReturnArg, we have two types of return arg parsing. We + // support populating a kprobe buffer from kretprobe hooks. This + // is used to capture data that is populated by the function hoooked. + // For example Read calls supply a buffer to the syscall, but we + // wont have its contents until kretprobe is run. The other type is + // the f.Return case. These capture the return value of the function + // without context from the kprobe hook. The BTF argument 'argreturn' + // instructs the BPF kretprobe program which type of copy to use. And + // argReturnPrinters tell golang printer piece how to print the event. + if f.Return { + argType := gt.GenericTypeFromString(f.ReturnArg.Type) + if argType == gt.GenericInvalidType { + if f.ReturnArg.Type == "" { + return nil, fmt.Errorf("ReturnArg not specified with Return=true") + } + return nil, fmt.Errorf("ReturnArg type '%s' unsupported", f.ReturnArg.Type) } + config.ArgReturn = int32(argType) + argsBTFSet[api.ReturnArgIndex] = true + argP := argPrinters{index: api.ReturnArgIndex, ty: argType} + argReturnPrinters = append(argReturnPrinters, argP) + } else { + config.ArgReturn = int32(0) + } - // Mark remaining arguments as 'nops' the kernel side will skip - // copying 'nop' args. - for j, a := range argsBTFSet { - if a == false { - if j != api.ReturnArgIndex { - config.Arg[j] = gt.GenericNopType - config.ArgM[j] = 0 - } + if argRetprobe != nil { + argsBTFSet[api.ReturnArgIndex] = true + setRetprobe = true + + argType := gt.GenericTypeFromString(argRetprobe.Type) + config.ArgReturnCopy = int32(argType) + + argP := argPrinters{index: int(argRetprobe.Index), ty: argType, label: argRetprobe.Label} + argReturnPrinters = append(argReturnPrinters, argP) + } else { + config.ArgReturnCopy = int32(0) + } + + // Mark remaining arguments as 'nops' the kernel side will skip + // copying 'nop' args. + for j, a := range argsBTFSet { + if a == false { + if j != api.ReturnArgIndex { + config.Arg[j] = gt.GenericNopType + config.ArgM[j] = 0 } } + } - // Copy over userspace return filters - var userReturnFilters []v1alpha1.ArgSelector - for _, s := range f.Selectors { - for _, returnArg := range s.MatchReturnArgs { - // we allow integer values so far - for _, v := range returnArg.Values { - if _, err := strconv.Atoi(v); err != nil { - return nil, fmt.Errorf("ReturnArg value supports only integer values, got %s", v) - } + // Copy over userspace return filters + var userReturnFilters []v1alpha1.ArgSelector + for _, s := range f.Selectors { + for _, returnArg := range s.MatchReturnArgs { + // we allow integer values so far + for _, v := range returnArg.Values { + if _, err := strconv.Atoi(v); err != nil { + return nil, fmt.Errorf("ReturnArg value supports only integer values, got %s", v) } - // only single value for GT,LT operators - if isGTOperator(returnArg.Operator) || isLTOperator(returnArg.Operator) { - if len(returnArg.Values) > 1 { - return nil, fmt.Errorf("ReturnArg operater '%s' supports only single value, got %d", - returnArg.Operator, len(returnArg.Values)) - } + } + // only single value for GT,LT operators + if isGTOperator(returnArg.Operator) || isLTOperator(returnArg.Operator) { + if len(returnArg.Values) > 1 { + return nil, fmt.Errorf("ReturnArg operater '%s' supports only single value, got %d", + returnArg.Operator, len(returnArg.Values)) } - userReturnFilters = append(userReturnFilters, returnArg) } + userReturnFilters = append(userReturnFilters, returnArg) } + } - // Write attributes into BTF ptr for use with load - if !setRetprobe { - setRetprobe = f.Return - } + // Write attributes into BTF ptr for use with load + if !setRetprobe { + setRetprobe = f.Return + } - if f.Syscall { - config.Syscall = 1 - } else { - config.Syscall = 0 - } + if f.Syscall { + config.Syscall = 1 + } else { + config.Syscall = 0 + } - if selectors.HasEarlyBinaryFilter(f.Selectors) { - config.Flags |= flagsEarlyFilter - } + if selectors.HasEarlyBinaryFilter(f.Selectors) { + config.Flags |= flagsEarlyFilter + } - // create a new entry on the table, and pass its id to BPF-side - // so that we can do the matching at event-generation time - kprobeEntry := genericKprobe{ - loadArgs: kprobeLoadArgs{ - retprobe: setRetprobe, - syscall: f.Syscall, - config: config, - }, - argSigPrinters: argSigPrinters, - argReturnPrinters: argReturnPrinters, - userReturnFilters: userReturnFilters, - funcName: funcName, - pendingEvents: nil, - tableId: idtable.UninitializedEntryID, - policyName: policyName, - hasOverride: selectors.HasOverride(f), - } + // create a new entry on the table, and pass its id to BPF-side + // so that we can do the matching at event-generation time + kprobeEntry := genericKprobe{ + loadArgs: kprobeLoadArgs{ + retprobe: setRetprobe, + syscall: f.Syscall, + config: config, + }, + argSigPrinters: argSigPrinters, + argReturnPrinters: argReturnPrinters, + userReturnFilters: userReturnFilters, + funcName: funcName, + pendingEvents: nil, + tableId: idtable.UninitializedEntryID, + policyName: in.policyName, + hasOverride: selectors.HasOverride(f), + } - // Parse Filters into kernel filter logic - kprobeEntry.loadArgs.selectors, err = selectors.InitKernelSelectorState(f.Selectors, f.Args, &kprobeEntry.actionArgs) - if err != nil { - return nil, err - } + // Parse Filters into kernel filter logic + kprobeEntry.loadArgs.selectors, err = selectors.InitKernelSelectorState(f.Selectors, f.Args, &kprobeEntry.actionArgs) + if err != nil { + return nil, err + } - kprobeEntry.pendingEvents, err = lru.New[pendingEventKey, pendingEvent](4096) - if err != nil { - return nil, err - } + kprobeEntry.pendingEvents, err = lru.New[pendingEventKey, pendingEvent](4096) + if err != nil { + return nil, err + } - genericKprobeTable.AddEntry(&kprobeEntry) - tidx := kprobeEntry.tableId.ID - kprobeEntry.pinPathPrefix = sensors.PathJoin(sensorPath, fmt.Sprintf("gkp-%d", tidx)) - config.FuncId = uint32(tidx) + genericKprobeTable.AddEntry(&kprobeEntry) + tidx := kprobeEntry.tableId.ID + kprobeEntry.pinPathPrefix = sensors.PathJoin(in.sensorPath, fmt.Sprintf("gkp-%d", tidx)) + config.FuncId = uint32(tidx) - if useMulti { - if setRetprobe { - multiRetIDs = append(multiRetIDs, kprobeEntry.tableId) - } - multiIDs = append(multiIDs, kprobeEntry.tableId) - logger.GetLogger(). - WithField("return", setRetprobe). - WithField("function", kprobeEntry.funcName). - WithField("override", kprobeEntry.hasOverride). - Infof("Added multi kprobe") - continue + if in.useMulti { + if setRetprobe { + out.multiRetIDs = append(out.multiRetIDs, kprobeEntry.tableId) } + out.multiIDs = append(out.multiIDs, kprobeEntry.tableId) + logger.GetLogger(). + WithField("return", setRetprobe). + WithField("function", kprobeEntry.funcName). + WithField("override", kprobeEntry.hasOverride). + Infof("Added multi kprobe") + return out, nil + } - pinPath := kprobeEntry.pinPathPrefix - pinProg := sensors.PathJoin(pinPath, fmt.Sprintf("%s_prog", kprobeEntry.funcName)) - - load := program.Builder( - path.Join(option.Config.HubbleLib, loadProgName), - funcName, - "kprobe/generic_kprobe", - pinProg, - "generic_kprobe"). - SetLoaderData(kprobeEntry.tableId) - load.Override = kprobeEntry.hasOverride - progs = append(progs, load) + pinPath := kprobeEntry.pinPathPrefix + pinProg := sensors.PathJoin(pinPath, fmt.Sprintf("%s_prog", kprobeEntry.funcName)) - fdinstall := program.MapBuilderPin("fdinstall_map", sensors.PathJoin(sensorPath, "fdinstall_map"), load) - maps = append(maps, fdinstall) + load := program.Builder( + path.Join(option.Config.HubbleLib, loadProgName), + funcName, + "kprobe/generic_kprobe", + pinProg, + "generic_kprobe"). + SetLoaderData(kprobeEntry.tableId) + load.Override = kprobeEntry.hasOverride + out.progs = append(out.progs, load) - configMap := program.MapBuilderPin("config_map", sensors.PathJoin(pinPath, "config_map"), load) - maps = append(maps, configMap) + fdinstall := program.MapBuilderPin("fdinstall_map", sensors.PathJoin(in.sensorPath, "fdinstall_map"), load) + out.maps = append(out.maps, fdinstall) - tailCalls := program.MapBuilderPin("kprobe_calls", sensors.PathJoin(pinPath, "kp_calls"), load) - maps = append(maps, tailCalls) + configMap := program.MapBuilderPin("config_map", sensors.PathJoin(pinPath, "config_map"), load) + out.maps = append(out.maps, configMap) - filterMap := program.MapBuilderPin("filter_map", sensors.PathJoin(pinPath, "filter_map"), load) - maps = append(maps, filterMap) + tailCalls := program.MapBuilderPin("kprobe_calls", sensors.PathJoin(pinPath, "kp_calls"), load) + out.maps = append(out.maps, tailCalls) - argFilterMaps := program.MapBuilderPin("argfilter_maps", sensors.PathJoin(pinPath, "argfilter_maps"), load) - if !kernels.MinKernelVersion("5.9") { - // Versions before 5.9 do not allow inner maps to have different sizes. - // See: https://lore.kernel.org/bpf/20200828011800.1970018-1-kafai@fb.com/ - maxEntries := kprobeEntry.loadArgs.selectors.ValueMapsMaxEntries() - argFilterMaps.SetInnerMaxEntries(maxEntries) - } - maps = append(maps, argFilterMaps) - - addr4FilterMaps := program.MapBuilderPin("addr4lpm_maps", sensors.PathJoin(pinPath, "addr4lpm_maps"), load) - if !kernels.MinKernelVersion("5.9") { - // Versions before 5.9 do not allow inner maps to have different sizes. - // See: https://lore.kernel.org/bpf/20200828011800.1970018-1-kafai@fb.com/ - maxEntries := kprobeEntry.loadArgs.selectors.Addr4MapsMaxEntries() - addr4FilterMaps.SetInnerMaxEntries(maxEntries) - } - maps = append(maps, addr4FilterMaps) + filterMap := program.MapBuilderPin("filter_map", sensors.PathJoin(pinPath, "filter_map"), load) + out.maps = append(out.maps, filterMap) - retProbe := program.MapBuilderPin("retprobe_map", sensors.PathJoin(pinPath, "retprobe_map"), load) - maps = append(maps, retProbe) + argFilterMaps := program.MapBuilderPin("argfilter_maps", sensors.PathJoin(pinPath, "argfilter_maps"), load) + if !kernels.MinKernelVersion("5.9") { + // Versions before 5.9 do not allow inner maps to have different sizes. + // See: https://lore.kernel.org/bpf/20200828011800.1970018-1-kafai@fb.com/ + maxEntries := kprobeEntry.loadArgs.selectors.ValueMapsMaxEntries() + argFilterMaps.SetInnerMaxEntries(maxEntries) + } + out.maps = append(out.maps, argFilterMaps) - callHeap := program.MapBuilderPin("process_call_heap", sensors.PathJoin(pinPath, "process_call_heap"), load) - maps = append(maps, callHeap) + addr4FilterMaps := program.MapBuilderPin("addr4lpm_maps", sensors.PathJoin(pinPath, "addr4lpm_maps"), load) + if !kernels.MinKernelVersion("5.9") { + // Versions before 5.9 do not allow inner maps to have different sizes. + // See: https://lore.kernel.org/bpf/20200828011800.1970018-1-kafai@fb.com/ + maxEntries := kprobeEntry.loadArgs.selectors.Addr4MapsMaxEntries() + addr4FilterMaps.SetInnerMaxEntries(maxEntries) + } + out.maps = append(out.maps, addr4FilterMaps) - selNamesMap := program.MapBuilderPin("sel_names_map", sensors.PathJoin(pinPath, "sel_names_map"), load) - maps = append(maps, selNamesMap) + retProbe := program.MapBuilderPin("retprobe_map", sensors.PathJoin(pinPath, "retprobe_map"), load) + out.maps = append(out.maps, retProbe) - if kernels.EnableLargeProgs() { - socktrack := program.MapBuilderPin("socktrack_map", sensors.PathJoin(sensorPath, "socktrack_map"), load) - maps = append(maps, socktrack) - } + callHeap := program.MapBuilderPin("process_call_heap", sensors.PathJoin(pinPath, "process_call_heap"), load) + out.maps = append(out.maps, callHeap) - if setRetprobe { - pinRetProg := sensors.PathJoin(pinPath, fmt.Sprintf("%s_ret_prog", kprobeEntry.funcName)) - loadret := program.Builder( - path.Join(option.Config.HubbleLib, loadProgRetName), - funcName, - "kprobe/generic_retkprobe", - pinRetProg, - "generic_kprobe"). - SetRetProbe(true). - SetLoaderData(kprobeEntry.tableId) - progs = append(progs, loadret) - - retProbe := program.MapBuilderPin("retprobe_map", sensors.PathJoin(pinPath, "retprobe_map"), loadret) - maps = append(maps, retProbe) - - retConfigMap := program.MapBuilderPin("config_map", sensors.PathJoin(pinPath, "retprobe_config_map"), loadret) - maps = append(maps, retConfigMap) - - // add maps with non-default paths (pins) to the retprobe - program.MapBuilderPin("process_call_heap", sensors.PathJoin(pinPath, "process_call_heap"), loadret) - program.MapBuilderPin("fdinstall_map", sensors.PathJoin(sensorPath, "fdinstall_map"), loadret) - if kernels.EnableLargeProgs() { - program.MapBuilderPin("socktrack_map", sensors.PathJoin(sensorPath, "socktrack_map"), loadret) - } - } + selNamesMap := program.MapBuilderPin("sel_names_map", sensors.PathJoin(pinPath, "sel_names_map"), load) + out.maps = append(out.maps, selNamesMap) - logger.GetLogger().WithField("flags", flagsString(config.Flags)). - WithField("override", kprobeEntry.hasOverride). - Infof("Added generic kprobe sensor: %s -> %s", load.Name, load.Attach) + if kernels.EnableLargeProgs() { + socktrack := program.MapBuilderPin("socktrack_map", sensors.PathJoin(in.sensorPath, "socktrack_map"), load) + out.maps = append(out.maps, socktrack) } - if len(multiIDs) != 0 { - progs, maps = createMultiKprobeSensor(sensorPath, multiIDs, multiRetIDs) + if setRetprobe { + pinRetProg := sensors.PathJoin(pinPath, fmt.Sprintf("%s_ret_prog", kprobeEntry.funcName)) + loadret := program.Builder( + path.Join(option.Config.HubbleLib, loadProgRetName), + funcName, + "kprobe/generic_retkprobe", + pinRetProg, + "generic_kprobe"). + SetRetProbe(true). + SetLoaderData(kprobeEntry.tableId) + out.progs = append(out.progs, loadret) + + retProbe := program.MapBuilderPin("retprobe_map", sensors.PathJoin(pinPath, "retprobe_map"), loadret) + out.maps = append(out.maps, retProbe) + + retConfigMap := program.MapBuilderPin("config_map", sensors.PathJoin(pinPath, "retprobe_config_map"), loadret) + out.maps = append(out.maps, retConfigMap) + + // add maps with non-default paths (pins) to the retprobe + program.MapBuilderPin("process_call_heap", sensors.PathJoin(pinPath, "process_call_heap"), loadret) + program.MapBuilderPin("fdinstall_map", sensors.PathJoin(in.sensorPath, "fdinstall_map"), loadret) + if kernels.EnableLargeProgs() { + program.MapBuilderPin("socktrack_map", sensors.PathJoin(in.sensorPath, "socktrack_map"), loadret) + } } - return &sensors.Sensor{ - Name: name, - Progs: progs, - Maps: maps, - }, nil + logger.GetLogger().WithField("flags", flagsString(config.Flags)). + WithField("override", kprobeEntry.hasOverride). + Infof("Added generic kprobe sensor: %s -> %s", load.Name, load.Attach) + return out, nil } func loadSingleKprobeSensor(id idtable.EntryID, bpfDir, mapDir string, load *program.Program, verbose int) error { diff --git a/pkg/sensors/tracing/lists.go b/pkg/sensors/tracing/lists.go new file mode 100644 index 00000000000..f9843ca8841 --- /dev/null +++ b/pkg/sensors/tracing/lists.go @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Authors of Tetragon + +package tracing + +import ( + "fmt" + "strings" + + "github.com/cilium/tetragon/pkg/arch" + "github.com/cilium/tetragon/pkg/btf" + "github.com/cilium/tetragon/pkg/ftrace" + "github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1" +) + +func hasList(name string, lists []v1alpha1.ListSpec) bool { + for idx := range lists { + list := lists[idx] + if list.Name == name { + return true + } + } + return false +} + +const ( + ListTypeInvalid = -1 + ListTypeNone = 0 + ListTypeSyscalls = 1 + ListTypeGeneratedSyscalls = 2 + ListTypeGeneratedFtrace = 3 +) + +var listTypeTable = map[string]uint32{ + "": ListTypeNone, + "syscalls": ListTypeSyscalls, + "generated_syscalls": ListTypeGeneratedSyscalls, + "generated_ftrace": ListTypeGeneratedFtrace, +} + +func listTypeFromString(s string) int32 { + typ, ok := listTypeTable[strings.ToLower(s)] + if !ok { + return ListTypeInvalid + } + return int32(typ) +} + +func isSyscallListType(typ string) bool { + return listTypeFromString(typ) == ListTypeSyscalls || + listTypeFromString(typ) == ListTypeGeneratedSyscalls +} + +func preValidateList(list *v1alpha1.ListSpec) (err error) { + if listTypeFromString(list.Type) == ListTypeInvalid { + return fmt.Errorf("Invalid list type: %s", list.Type) + } + + // Add prefix to syscalls list + if listTypeFromString(list.Type) == ListTypeSyscalls { + for idx := range list.Values { + symbol, err := arch.AddSyscallPrefix(list.Values[idx]) + if err != nil { + return err + } + list.Values[idx] = symbol + } + return nil + } + + // Generate syscalls list + if listTypeFromString(list.Type) == ListTypeGeneratedSyscalls { + if len(list.Values) != 0 { + return fmt.Errorf("Error generated list '%s' has generate and values", list.Name) + } + tmp, err := btf.GetSyscallsList() + if err != nil { + return err + } + list.Values = append(list.Values, tmp...) + return nil + } + + // Generate ftrace list + if listTypeFromString(list.Type) == ListTypeGeneratedFtrace { + if list.Pattern == "" { + return fmt.Errorf("Error generated ftrace list '%s' must specify pattern", list.Name) + } + list.Values, err = ftrace.ReadAvailFuncs(list.Pattern) + return err + } + + return nil +} diff --git a/pkg/sensors/tracing/policyhandler.go b/pkg/sensors/tracing/policyhandler.go index 06f8d20d8c9..66d1b2282fc 100644 --- a/pkg/sensors/tracing/policyhandler.go +++ b/pkg/sensors/tracing/policyhandler.go @@ -28,11 +28,11 @@ func (h policyHandler) PolicyHandler( } if len(spec.KProbes) > 0 { name := fmt.Sprintf("gkp-sensor-%d", atomic.AddUint64(&sensorCounter, 1)) - err := preValidateKprobes(name, spec.KProbes) + err := preValidateKprobes(name, spec.KProbes, spec.Lists) if err != nil { return nil, err } - return createGenericKprobeSensor(name, spec.KProbes, policyID, policyName) + return createGenericKprobeSensor(name, spec.KProbes, policyID, policyName, spec.Lists) } if len(spec.Tracepoints) > 0 { name := fmt.Sprintf("gtp-sensor-%d", atomic.AddUint64(&sensorCounter, 1)) 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 934a9f880d0..0f693b360b7 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 @@ -548,6 +548,32 @@ spec: - call type: object type: array + lists: + description: A list of list specs. + items: + properties: + name: + description: Name of the list + type: string + pattern: + description: Pattern for 'generated' lists. + type: string + type: + description: Indicates the type of the list values. + enum: + - syscalls + - generated_syscalls + - generated_ftrace + type: string + values: + description: Values of the list + items: + type: string + type: array + required: + - name + type: object + type: array loader: description: Enable loader events type: boolean 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 d93747af1a6..7f0b8c0ee22 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 @@ -548,6 +548,32 @@ spec: - call type: object type: array + lists: + description: A list of list specs. + items: + properties: + name: + description: Name of the list + type: string + pattern: + description: Pattern for 'generated' lists. + type: string + type: + description: Indicates the type of the list values. + enum: + - syscalls + - generated_syscalls + - generated_ftrace + type: string + values: + description: Values of the list + items: + type: string + type: array + required: + - name + type: object + type: array loader: description: Enable loader events type: boolean 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 a3d232a3ed5..9694fc7c4e9 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 @@ -89,6 +89,10 @@ type TracingPolicySpec struct { // +kubebuilder:validation:Optional // PodSelector selects pods that this policy applies to PodSelector *slimv1.LabelSelector `json:"podSelector,omitempty"` + + // +kubebuilder:validation:Optional + // A list of list specs. + Lists []ListSpec `json:"lists"` } func (tp *TracingPolicy) TpName() string { @@ -331,3 +335,18 @@ type UProbeSpec struct { // Selectors to apply before producing trace output. Selectors are ORed. Selectors []KProbeSelector `json:"selectors"` } + +type ListSpec struct { + // Name of the list + Name string `json:"name"` + // +kubebuilder:validation:Optional + // Values of the list + Values []string `json:"values"` + // +kubebuilder:validation:Optional + // +kubebuilder:validation:Enum=syscalls;generated_syscalls;generated_ftrace + // Indicates the type of the list values. + Type string `json:"type"` + // +kubebuilder:validation:Optional + // Pattern for 'generated' lists. + Pattern string `json:"pattern"` +} 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 b968a52b827..c0d4d144b16 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 @@ -214,6 +214,27 @@ func (in *KProbeSpec) DeepCopy() *KProbeSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ListSpec) DeepCopyInto(out *ListSpec) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ListSpec. +func (in *ListSpec) DeepCopy() *ListSpec { + if in == nil { + return nil + } + out := new(ListSpec) + 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 @@ -454,6 +475,13 @@ func (in *TracingPolicySpec) DeepCopyInto(out *TracingPolicySpec) { *out = new(v1.LabelSelector) (*in).DeepCopyInto(*out) } + if in.Lists != nil { + in, out := &in.Lists, &out.Lists + *out = make([]ListSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return }