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

Lists #1283

Merged
merged 13 commits into from
Aug 17, 2023
Merged

Lists #1283

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
59 changes: 56 additions & 3 deletions cmd/tetra/tracingpolicy/tracingpolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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 <all-syscalls|empty>",
Use: "generate <all-syscalls|all-syscalls-list|ftrace-list|empty>",
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
Expand Down Expand Up @@ -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
Expand All @@ -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()
}
Expand Down
16 changes: 16 additions & 0 deletions examples/tracingpolicy/list-generated-ftrace.yaml
Original file line number Diff line number Diff line change
@@ -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"
15 changes: 15 additions & 0 deletions examples/tracingpolicy/list-syscalls-generated.yaml
Original file line number Diff line number Diff line change
@@ -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"
13 changes: 13 additions & 0 deletions examples/tracingpolicy/list-syscalls.yaml
Original file line number Diff line number Diff line change
@@ -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"
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
106 changes: 106 additions & 0 deletions pkg/btf/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
65 changes: 65 additions & 0 deletions pkg/ftrace/ftrace.go
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading