Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tetragon: Add support to pass options through spec #1626

Merged
merged 6 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions docs/content/en/docs/concepts/tracing-policy/options.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: "Options"
icon: "overview"
weight: 3
description: "Pass options to hook"
---

It's possible to pass options through spec file as an array of name and value pairs:

```yaml
spec:
options:
- name: "option-1"
value: "True"
- name: "option-2"
value: "10"
```

Options array is passed and processed by each hook used in the spec file that
supports options. At the moment it's availabe for kprobe hooks.

- [`Kprobe Options`](#kprobe-options): options for kprobe hooks.

## Kprobe options

- [`disable-kprobe-multi`](#disable-kprobe-multi): disable kprobe multi link

### disable-kprobe-multi

This option disables kprobe multi link interface for all the kprobes defined in
the spec file. If enabled, all the defined kprobes will be atached through standard
kprobe interface. It stays enabled for another spec file without this option.

It takes boolean as value, by default it's false.

Example:

```yaml
options:
- name: "disable-kprobe-multi"
value: "1"
```
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,20 @@ spec:
loader:
description: Enable loader events
type: boolean
options:
description: A list of overloaded options
items:
properties:
name:
description: Name of the option
type: string
value:
description: Value of the option
type: string
required:
- name
type: object
type: array
podSelector:
description: PodSelector selects pods that this policy applies to
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,20 @@ spec:
loader:
description: Enable loader events
type: boolean
options:
description: A list of overloaded options
items:
properties:
name:
description: Name of the option
type: string
value:
description: Value of the option
type: string
required:
- name
type: object
type: array
podSelector:
description: PodSelector selects pods that this policy applies to
properties:
Expand Down
4 changes: 4 additions & 0 deletions pkg/k8s/apis/cilium.io/v1alpha1/tracing_policy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ type TracingPolicySpec struct {
// +kubebuilder:validation:Optional
// A killer spec.
Killers []KillerSpec `json:"killers,omitempty"`

// +kubebuilder:validation:Optional
// A list of overloaded options
Options []OptionSpec `json:"options,omitempty"`
tpapagian marked this conversation as resolved.
Show resolved Hide resolved
}

func (tp *TracingPolicy) TpName() string {
Expand Down
8 changes: 8 additions & 0 deletions pkg/k8s/apis/cilium.io/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,14 @@ type ListSpec struct {
Validated bool `json:"validated"`
}

type OptionSpec struct {
// Name of the option
Name string `json:"name"`
// +kubebuilder:validation:Optional
// Value of the option
Value string `json:"value"`
}

type PodInfoSpec struct {
// Host networking requested for this pod. Use the host's network namespace.
// If this option is set, the ports that will be used must be specified.
Expand Down
2 changes: 1 addition & 1 deletion pkg/k8s/apis/cilium.io/v1alpha1/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.0.0"
const CustomResourceDefinitionSchemaVersion = "1.0.1"
21 changes: 21 additions & 0 deletions pkg/k8s/apis/cilium.io/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 15 additions & 5 deletions pkg/sensors/tracing/generickprobe.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,11 +495,10 @@ func getKprobeSymbols(symbol string, syscall bool, lists []v1alpha1.ListSpec) ([
}

func createGenericKprobeSensor(
spec *v1alpha1.TracingPolicySpec,
name string,
kprobes []v1alpha1.KProbeSpec,
policyID policyfilter.PolicyID,
policyName string,
lists []v1alpha1.ListSpec,
customHandler eventhandler.Handler,
) (*sensors.Sensor, error) {
var progs []*program.Program
Expand All @@ -508,11 +507,22 @@ func createGenericKprobeSensor(
var useMulti bool
var selMaps *selectors.KernelSelectorMaps

kprobes := spec.KProbes
lists := spec.Lists

options, err := getKprobeOptions(spec.Options)
if err != nil {
return nil, fmt.Errorf("failed to set options: %s", err)
}

// use multi kprobe only if:
// - it's not disabled by user
// - it's not disabled by spec option
// - it's not disabled by command line option
// - there's support detected
useMulti = !option.Config.DisableKprobeMulti &&
bpf.HasKprobeMulti()
if !options.DisableKprobeMulti {
useMulti = !option.Config.DisableKprobeMulti &&
bpf.HasKprobeMulti()
}

in := addKprobeIn{
useMulti: useMulti,
Expand Down
16 changes: 10 additions & 6 deletions pkg/sensors/tracing/generickprobe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,21 @@ func Test_SensorDestroyHook(t *testing.T) {
t.Errorf("genericKprobeTable expected initial length: 0, got: %d", genericKprobeTable.Len())
}

spec := &v1alpha1.TracingPolicySpec{}

spec.KProbes = []v1alpha1.KProbeSpec{
{
Call: "test_symbol",
Syscall: false,
},
}

// we use createGenericKprobeSensor because it's where the DestroyHook is
// created. It would be technically more correct if it was added just after
// insertion in the table in AddKprobe, but this is done by the caller to
// have just DestroyHook that regroups all the potential multiple kprobes
// contained in one sensor.
sensor, err := createGenericKprobeSensor("test_sensor", []v1alpha1.KProbeSpec{
{
Call: "test_symbol",
Syscall: false,
},
}, 0, "test_policy", nil, nil)
sensor, err := createGenericKprobeSensor(spec, "test_sensor", 0, "test_policy", nil)
if err != nil {
t.Errorf("createGenericKprobeSensor err expected: nil, got: %s", err)
}
Expand Down
8 changes: 2 additions & 6 deletions pkg/sensors/tracing/generictracepoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,6 @@ func (t *tracepointTable) getTracepoint(idx int) (*genericTracepoint, error) {
return nil, fmt.Errorf("tracepoint table: invalid id:%d (len=%d)", idx, len(t.arr))
}

// GenericTracepointConf is the configuration for a generic tracepoint. This is
// a caller-defined structure that configures a tracepoint.
type GenericTracepointConf = v1alpha1.TracepointSpec

// getTracepointMetaArg is a temporary helper to find meta values while tracepoint
// converts into new CRD and config formats.
func getTracepointMetaValue(arg *v1alpha1.KProbeArg) int {
Expand Down Expand Up @@ -318,7 +314,7 @@ func buildGenericTracepointArgs(info *tracepoint.Tracepoint, specArgs []v1alpha1
// the user-provided configuration
func createGenericTracepoint(
sensorName string,
conf *GenericTracepointConf,
conf *v1alpha1.TracepointSpec,
policyID policyfilter.PolicyID,
policyName string,
customHandler eventhandler.Handler,
Expand Down Expand Up @@ -354,7 +350,7 @@ func createGenericTracepoint(
// createGenericTracepointSensor will create a sensor that can be loaded based on a generic tracepoint configuration
func createGenericTracepointSensor(
name string,
confs []GenericTracepointConf,
confs []v1alpha1.TracepointSpec,
policyID policyfilter.PolicyID,
policyName string,
lists []v1alpha1.ListSpec,
Expand Down
7 changes: 3 additions & 4 deletions pkg/sensors/tracing/kprobe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2212,10 +2212,6 @@ func TestKprobeOverrideSecurity(t *testing.T) {
t.Skip("skipping fmod_ret support is not available")
}

if !option.Config.DisableKprobeMulti && bpf.HasKprobeMulti() {
t.Skip("skipping fmod_ret does not work with kprobe multi")
}

pidStr := strconv.Itoa(int(observertesthelper.GetMyPid()))

file, err := os.CreateTemp(t.TempDir(), "kprobe-override-")
Expand All @@ -2230,6 +2226,9 @@ kind: TracingPolicy
metadata:
name: "sys-openat-override"
spec:
options:
- name: "disable-kprobe-multi"
value: "1"
kprobes:
- call: "security_file_open"
syscall: false
Expand Down
47 changes: 47 additions & 0 deletions pkg/sensors/tracing/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Tetragon

package tracing

import (
"fmt"
"strconv"

"github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1"
"github.com/cilium/tetragon/pkg/logger"
"github.com/cilium/tetragon/pkg/option"
)

type kprobeOptions struct {
DisableKprobeMulti bool
}

type opt struct {
set func(val string, options *kprobeOptions) error
}

// Allowed kprobe options
var opts = map[string]opt{
option.KeyDisableKprobeMulti: opt{
set: func(str string, options *kprobeOptions) (err error) {
options.DisableKprobeMulti, err = strconv.ParseBool(str)
return err
},
},
}

func getKprobeOptions(specs []v1alpha1.OptionSpec) (*kprobeOptions, error) {
options := &kprobeOptions{}

for _, spec := range specs {
opt, ok := opts[spec.Name]
if ok {
if err := opt.set(spec.Value, options); err != nil {
return nil, fmt.Errorf("failed to set option %s: %s", spec.Name, err)
}
logger.GetLogger().Infof("Set option %s = %s", spec.Name, spec.Value)
}
}

return options, nil
}
2 changes: 1 addition & 1 deletion pkg/sensors/tracing/policyfilter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ func TestNamespacedPolicies(t *testing.T) {
},
}

tpSpec := GenericTracepointConf{
tpSpec := v1alpha1.TracepointSpec{
Subsystem: "syscalls",
Event: "sys_enter_lseek",
Args: []v1alpha1.KProbeArg{
Expand Down
2 changes: 1 addition & 1 deletion pkg/sensors/tracing/policyhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (h policyHandler) PolicyHandler(
if err != nil {
return nil, fmt.Errorf("validation failed: %w", err)
}
return createGenericKprobeSensor(name, spec.KProbes, policyID, policyName, spec.Lists, handler)
return createGenericKprobeSensor(spec, name, policyID, policyName, handler)
}
if len(spec.Tracepoints) > 0 {
name := fmt.Sprintf("gtp-sensor-%d", atomic.AddUint64(&sensorCounter, 1))
Expand Down
Loading
Loading