Skip to content

Commit

Permalink
tetragon: Add support to process uprobe arguments
Browse files Browse the repository at this point in the history
Signed-off-by: Jiri Olsa <[email protected]>
  • Loading branch information
olsajiri committed Jan 15, 2024
1 parent 30b0226 commit ff1b59a
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 8 deletions.
36 changes: 36 additions & 0 deletions pkg/grpc/tracing/tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,7 @@ type MsgGenericUprobeUnix struct {
Symbol string
PolicyName string
Message string
Args []tracingapi.MsgGenericKprobeArg
}

func (msg *MsgGenericUprobeUnix) Notify() bool {
Expand All @@ -637,6 +638,7 @@ func (msg *MsgGenericUprobeUnix) Retry(internal *process.ProcessInternal, ev not

func GetProcessUprobe(event *MsgGenericUprobeUnix) *tetragon.ProcessUprobe {
var tetragonParent, tetragonProcess *tetragon.Process
var tetragonArgs []*tetragon.KprobeArgument

proc, parent := process.GetParentProcessInternal(event.ProcessKey.Pid, event.ProcessKey.Ktime)
if proc == nil {
Expand All @@ -656,13 +658,47 @@ func GetProcessUprobe(event *MsgGenericUprobeUnix) *tetragon.ProcessUprobe {
tetragonParent = parent.UnsafeGetProcess()
}

for _, arg := range event.Args {
a := &tetragon.KprobeArgument{}
switch e := arg.(type) {
case api.MsgGenericKprobeArgInt:
a.Arg = &tetragon.KprobeArgument_IntArg{IntArg: e.Value}
a.Label = e.Label
case api.MsgGenericKprobeArgUInt:
a.Arg = &tetragon.KprobeArgument_UintArg{UintArg: e.Value}
a.Label = e.Label
case api.MsgGenericKprobeArgSize:
a.Arg = &tetragon.KprobeArgument_SizeArg{SizeArg: e.Value}
a.Label = e.Label
case api.MsgGenericKprobeArgString:
a.Arg = &tetragon.KprobeArgument_StringArg{StringArg: e.Value}
a.Label = e.Label
case api.MsgGenericKprobeArgBytes:
if e.OrigSize > uint64(len(e.Value)) {
a.Arg = &tetragon.KprobeArgument_TruncatedBytesArg{
TruncatedBytesArg: &tetragon.KprobeTruncatedBytes{
OrigSize: e.OrigSize,
BytesArg: e.Value,
},
}
} else {
a.Arg = &tetragon.KprobeArgument_BytesArg{BytesArg: e.Value}
}
a.Label = e.Label
default:
logger.GetLogger().WithField("arg", e).Warnf("unexpected type: %T", e)
}
tetragonArgs = append(tetragonArgs, a)
}

tetragonEvent := &tetragon.ProcessUprobe{
Process: tetragonProcess,
Parent: tetragonParent,
Path: event.Path,
Symbol: event.Symbol,
PolicyName: event.PolicyName,
Message: event.Message,
Args: tetragonArgs,
}

if tetragonProcess.Pid == nil {
Expand Down
116 changes: 108 additions & 8 deletions pkg/sensors/tracing/genericuprobe.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/cilium/ebpf"
"github.com/cilium/tetragon/pkg/api/ops"
api "github.com/cilium/tetragon/pkg/api/tracingapi"
gt "github.com/cilium/tetragon/pkg/generictypes"
"github.com/cilium/tetragon/pkg/grpc/tracing"
"github.com/cilium/tetragon/pkg/idtable"
"github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1"
Expand Down Expand Up @@ -47,6 +48,8 @@ type genericUprobe struct {
policyName string
// message field of the Tracing Policy
message string
// argument data printers
argPrinters []argPrinter
}

func (g *genericUprobe) SetID(id idtable.EntryID) {
Expand Down Expand Up @@ -97,6 +100,61 @@ func handleGenericUprobe(r *bytes.Reader) ([]observer.Event, error) {
unix.PolicyName = uprobeEntry.policyName
unix.Message = uprobeEntry.message

for _, a := range uprobeEntry.argPrinters {
switch a.ty {
case gt.GenericIntType, gt.GenericS32Type:
var output int32
var arg api.MsgGenericKprobeArgInt

err := binary.Read(r, binary.LittleEndian, &output)
if err != nil {
logger.GetLogger().WithError(err).Warnf("Int type error")
}

arg.Index = uint64(a.index)
arg.Value = output
arg.Label = a.label
unix.Args = append(unix.Args, arg)
case gt.GenericCharBuffer:
if arg, err := ReadArgBytes(r, a.index, a.maxData); err == nil {
arg.Label = a.label
unix.Args = append(unix.Args, *arg)
} else {
logger.GetLogger().WithError(err).Warnf("failed to read bytes argument")
}
case gt.GenericSizeType, gt.GenericU64Type:
var output uint64
var arg api.MsgGenericKprobeArgSize

err := binary.Read(r, binary.LittleEndian, &output)
if err != nil {
logger.GetLogger().WithError(err).Warnf("Size type error sizeof %d", m.Common.Size)
}

arg.Index = uint64(a.index)
arg.Value = output
arg.Label = a.label
unix.Args = append(unix.Args, arg)
case gt.GenericNopType:
// do nothing
case gt.GenericU32Type:
var output uint32
var arg api.MsgGenericKprobeArgUInt

err := binary.Read(r, binary.LittleEndian, &output)
if err != nil {
logger.GetLogger().WithError(err).Warnf("UInt type error")
}

arg.Index = uint64(a.index)
arg.Value = output
arg.Label = a.label
unix.Args = append(unix.Args, arg)
default:
logger.GetLogger().WithError(err).WithField("event-type", a.ty).Warnf("Unknown event type")
}
}

return []observer.Event{unix}, err
}

Expand Down Expand Up @@ -196,17 +254,59 @@ func createGenericUprobeSensor(
logger.GetLogger().WithField("policy-name", policyName).Warnf("TracingPolicy 'message' field too long, truncated to %d characters", TpMaxMessageLen)
}

var (
argTypes [api.EventConfigMaxArgs]int32
argMeta [api.EventConfigMaxArgs]uint32
argSet [api.EventConfigMaxArgs]bool

argPrinters []argPrinter
)

// Parse Arguments
for i, a := range spec.Args {
argType := gt.GenericTypeFromString(a.Type)
if argType == gt.GenericInvalidType {
return nil, fmt.Errorf("Arg(%d) type '%s' unsupported", i, a.Type)
}
argMValue, err := getMetaValue(&a)
if err != nil {
return nil, err
}
if a.Index > 4 {
return nil, fmt.Errorf("Error add arg: ArgType %s Index %d out of bounds",
a.Type, int(a.Index))
}
argTypes[a.Index] = int32(argType)
argMeta[a.Index] = uint32(argMValue)
argSet[a.Index] = true

argPrinters = append(argPrinters, argPrinter{index: i, ty: argType})
}

// Mark remaining arguments as 'nops' the kernel side will skip
// copying 'nop' args.
for i, a := range argSet {
if !a {
argTypes[i] = gt.GenericNopType
argMeta[i] = 0
}
}

for _, sym := range spec.Symbols {
config := &api.EventConfig{}
config := &api.EventConfig{
Arg: argTypes,
ArgM: argMeta,
}

uprobeEntry := &genericUprobe{
tableId: idtable.UninitializedEntryID,
config: config,
path: spec.Path,
symbol: sym,
selectors: uprobeSelectorState,
policyName: policyName,
message: msgField,
tableId: idtable.UninitializedEntryID,
config: config,
path: spec.Path,
symbol: sym,
selectors: uprobeSelectorState,
policyName: policyName,
message: msgField,
argPrinters: argPrinters,
}

uprobeTable.AddEntry(uprobeEntry)
Expand Down

0 comments on commit ff1b59a

Please sign in to comment.