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

Refactor kprobe tracing functionality out of system/socket #21011

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
12 changes: 6 additions & 6 deletions x-pack/auditbeat/module/system/socket/guess/creds.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import (
"golang.org/x/sys/unix"

"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/x-pack/auditbeat/module/system/socket/helper"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing/kprobes"
)

/*
Expand Down Expand Up @@ -57,7 +57,7 @@ func init() {
}

type guessStructCreds struct {
ctx Context
ctx kprobes.GuessContext
}

// Name of this guess.
Expand All @@ -84,22 +84,22 @@ func (g *guessStructCreds) Requires() []string {

// Probes returns a kretprobe on prepare_creds that dumps the first bytes
// pointed to by the return value, which is a struct cred.
func (g *guessStructCreds) Probes() ([]helper.ProbeDef, error) {
return []helper.ProbeDef{
func (g *guessStructCreds) Probes() ([]kprobes.ProbeDef, error) {
return []kprobes.ProbeDef{
{
Probe: tracing.Probe{
Type: tracing.TypeKRetProbe,
Name: "guess_struct_creds",
Address: "prepare_creds",
Fetchargs: helper.MakeMemoryDump("{{.RET}}", 0, credDumpBytes),
Fetchargs: kprobes.MakeMemoryDump("{{.RET}}", 0, credDumpBytes),
},
Decoder: tracing.NewDumpDecoder,
},
}, nil
}

// Prepare is a no-op.
func (g *guessStructCreds) Prepare(ctx Context) error {
func (g *guessStructCreds) Prepare(ctx kprobes.GuessContext) error {
return nil
}

Expand Down
17 changes: 9 additions & 8 deletions x-pack/auditbeat/module/system/socket/guess/cskxmit6.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/x-pack/auditbeat/module/system/socket/helper"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing/kprobes"
)

/*
Expand All @@ -40,7 +41,7 @@ func init() {
}

type guessInet6CskXmit struct {
ctx Context
ctx kprobes.GuessContext
loopback helper.IPv6Loopback
clientAddr, serverAddr unix.SockaddrInet6
client, server int
Expand Down Expand Up @@ -70,38 +71,38 @@ func (g *guessInet6CskXmit) Requires() []string {
}

// Condition allows this probe to run only when IPv6 is enabled.
func (g *guessInet6CskXmit) Condition(ctx Context) (bool, error) {
func (g *guessInet6CskXmit) Condition(ctx kprobes.GuessContext) (bool, error) {
return isIPv6Enabled(ctx.Vars)
}

// Probes returns 2 probes:
// - kretprobe on inet_csk_accept, which returns a struct sock*
// - kprobe on inet6_csk_xmit, returning 1st argument as pointer and dump.
func (g *guessInet6CskXmit) Probes() ([]helper.ProbeDef, error) {
return []helper.ProbeDef{
func (g *guessInet6CskXmit) Probes() ([]kprobes.ProbeDef, error) {
return []kprobes.ProbeDef{
{
Probe: tracing.Probe{
Type: tracing.TypeKRetProbe,
Name: "inet_csk_accept_guess",
Address: "inet_csk_accept",
Fetchargs: "sock={{.RET}}",
},
Decoder: helper.NewStructDecoder(func() interface{} { return new(sockArgumentGuess) }),
Decoder: kprobes.NewStructDecoder(func() interface{} { return new(sockArgumentGuess) }),
},
{
Probe: tracing.Probe{
Name: "inet6_csk_xmit_guess",
Address: "inet6_csk_xmit",
Fetchargs: "arg={{.P1}} dump=" + helper.MakeMemoryDump("{{.P1}}", 0, skbuffDumpSize),
Fetchargs: "arg={{.P1}} dump=" + kprobes.MakeMemoryDump("{{.P1}}", 0, skbuffDumpSize),
},
Decoder: helper.NewStructDecoder(func() interface{} { return new(skbuffSockGuess) }),
Decoder: kprobes.NewStructDecoder(func() interface{} { return new(skbuffSockGuess) }),
},
}, nil
}

// Prepare setups an IPv6 TCP client/server where the server is listening
// and the client is connecting to it.
func (g *guessInet6CskXmit) Prepare(ctx Context) (err error) {
func (g *guessInet6CskXmit) Prepare(ctx kprobes.GuessContext) (err error) {
g.ctx = ctx
g.acceptedFd = -1
g.loopback, err = helper.NewIPv6Loopback()
Expand Down
14 changes: 7 additions & 7 deletions x-pack/auditbeat/module/system/socket/guess/deref.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (
"syscall"

"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/x-pack/auditbeat/module/system/socket/helper"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing/kprobes"
)

/*
Expand All @@ -39,14 +39,14 @@ const (
)

type guessDeref struct {
ctx Context
ctx kprobes.GuessContext
tries int
garbage bool
}

// Condition allows the guess to run if the environment variable is set to a
// decimal value greater than zero.
func (g *guessDeref) Condition(ctx Context) (run bool, err error) {
func (g *guessDeref) Condition(ctx kprobes.GuessContext) (run bool, err error) {
v := os.Getenv(envVar)
if v == "" {
return false, nil
Expand Down Expand Up @@ -79,22 +79,22 @@ func (g *guessDeref) Requires() []string {

// Probes returns a kprobe on uname() that dumps the first bytes
// pointed to by its first parameter.
func (g *guessDeref) Probes() ([]helper.ProbeDef, error) {
return []helper.ProbeDef{
func (g *guessDeref) Probes() ([]kprobes.ProbeDef, error) {
return []kprobes.ProbeDef{
{
Probe: tracing.Probe{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wondering why keep the package different for kprobes v. tracing? Are we planning on doing some other types of tracing (i.e. tracepoint, uprobe, etc?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really. Makes sense to merge the packages.

Type: tracing.TypeKProbe,
Name: "guess_null_ptr_deref",
Address: "{{.SYS_UNAME}}",
Fetchargs: helper.MakeMemoryDump("{{.SYS_P1}}", 0, credDumpBytes),
Fetchargs: kprobes.MakeMemoryDump("{{.SYS_P1}}", 0, credDumpBytes),
},
Decoder: tracing.NewDumpDecoder,
},
}, nil
}

// Prepare is a no-op.
func (g *guessDeref) Prepare(ctx Context) error {
func (g *guessDeref) Prepare(ctx kprobes.GuessContext) error {
g.ctx = ctx
return nil
}
Expand Down
12 changes: 12 additions & 0 deletions x-pack/auditbeat/module/system/socket/guess/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,15 @@ func (cs *inetClientServer) Cleanup() error {
unix.Close(cs.client)
return nil
}

func isIPv6Enabled(vars common.MapStr) (bool, error) {
iface, err := vars.GetValue("HAS_IPV6")
if err != nil {
return false, err
}
hasIPv6, ok := iface.(bool)
if !ok {
return false, errors.New("HAS_IPV6 is not a bool")
}
return hasIPv6, nil
}
12 changes: 6 additions & 6 deletions x-pack/auditbeat/module/system/socket/guess/inetsock.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import (
"golang.org/x/sys/unix"

"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/x-pack/auditbeat/module/system/socket/helper"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing/kprobes"
)

// Guess the offsets within a struct inet_sock where the local and remote
Expand All @@ -41,7 +41,7 @@ func init() {
}

type guessInetSockIPv4 struct {
ctx Context
ctx kprobes.GuessContext
local, remote unix.SockaddrInet4
server, client int
}
Expand Down Expand Up @@ -74,14 +74,14 @@ func (g *guessInetSockIPv4) Requires() []string {

// Probes returns a kretprobe on inet_sock_accept that dumps the return
// value (an inet_sock*).
func (g *guessInetSockIPv4) Probes() ([]helper.ProbeDef, error) {
return []helper.ProbeDef{
func (g *guessInetSockIPv4) Probes() ([]kprobes.ProbeDef, error) {
return []kprobes.ProbeDef{
{
Probe: tracing.Probe{
Type: tracing.TypeKRetProbe,
Name: "inet_sock_guess",
Address: "inet_csk_accept",
Fetchargs: helper.MakeMemoryDump("{{.RET}}", 0, 2048),
Fetchargs: kprobes.MakeMemoryDump("{{.RET}}", 0, 2048),
},
Decoder: tracing.NewDumpDecoder,
},
Expand All @@ -90,7 +90,7 @@ func (g *guessInetSockIPv4) Probes() ([]helper.ProbeDef, error) {

// Prepare creates a TCP/IP client and server bound to random loopback addresses
// (127.x.x.x).
func (g *guessInetSockIPv4) Prepare(ctx Context) (err error) {
func (g *guessInetSockIPv4) Prepare(ctx kprobes.GuessContext) (err error) {
g.ctx = ctx
g.local = unix.SockaddrInet4{
Port: 0,
Expand Down
15 changes: 8 additions & 7 deletions x-pack/auditbeat/module/system/socket/guess/inetsock6.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/x-pack/auditbeat/module/system/socket/helper"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing/kprobes"
)

/*
Expand Down Expand Up @@ -109,7 +110,7 @@ func init() {
}

type guessInetSockIPv6 struct {
ctx Context
ctx kprobes.GuessContext
loopback helper.IPv6Loopback
clientAddr, serverAddr unix.SockaddrInet6
client, server int
Expand Down Expand Up @@ -143,7 +144,7 @@ func (g *guessInetSockIPv6) Requires() []string {
}

// Condition allows this probe to run only when IPv6 is enabled.
func (g *guessInetSockIPv6) Condition(ctx Context) (bool, error) {
func (g *guessInetSockIPv6) Condition(ctx kprobes.GuessContext) (bool, error) {
runs, err := isIPv6Enabled(ctx.Vars)
if err != nil {
return false, err
Expand Down Expand Up @@ -178,13 +179,13 @@ func (d *decoderWrapper) Decode(raw []byte, meta tracing.Metadata) (event interf
// Probes returns a kretprobe in inet_csk_accept that dumps the memory pointed
// to by the return value (an inet_sock*) and a kretprobe that dumps various
// candidates for the ipv6_pinfo struct.
func (g *guessInetSockIPv6) Probes() (probes []helper.ProbeDef, err error) {
probes = append(probes, helper.ProbeDef{
func (g *guessInetSockIPv6) Probes() (probes []kprobes.ProbeDef, err error) {
probes = append(probes, kprobes.ProbeDef{
Probe: tracing.Probe{
Type: tracing.TypeKRetProbe,
Name: "inet_sock_ipv6_guess",
Address: "inet_csk_accept",
Fetchargs: helper.MakeMemoryDump("{{.RET}}", 0, inetSockDumpSize),
Fetchargs: kprobes.MakeMemoryDump("{{.RET}}", 0, inetSockDumpSize),
},
Decoder: tracing.NewDumpDecoder,
})
Expand All @@ -204,7 +205,7 @@ func (g *guessInetSockIPv6) Probes() (probes []helper.ProbeDef, err error) {
// dumps the rcv_saddr field of struct ipv6_pinfo
fetch = append(fetch, fmt.Sprintf("+16(+%d({{.RET}})):u64 +24(+%d({{.RET}})):u64", off, off))
}
probes = append(probes, helper.ProbeDef{
probes = append(probes, kprobes.ProbeDef{
Probe: tracing.Probe{
Type: tracing.TypeKRetProbe,
Name: "inet_sock_ipv6_guess2",
Expand All @@ -225,7 +226,7 @@ func (g *guessInetSockIPv6) Probes() (probes []helper.ProbeDef, err error) {
// Unlike with IPv4, it's not possible to bind to a random IP in the IPv6
// loopback as it is ::1/128 by default. Thus it's necessary to add temporary
// random addresses in the fd00::/8 reserved network to the loopback device.
func (g *guessInetSockIPv6) Prepare(ctx Context) (err error) {
func (g *guessInetSockIPv6) Prepare(ctx kprobes.GuessContext) (err error) {
g.ctx = ctx
g.offsets, err = getListField(g.ctx.Vars, "INET_SOCK_RADDR_LIST")
if err != nil {
Expand Down
12 changes: 6 additions & 6 deletions x-pack/auditbeat/module/system/socket/guess/inetsockaf.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
"golang.org/x/sys/unix"

"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/x-pack/auditbeat/module/system/socket/helper"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing/kprobes"
)

/*
Expand Down Expand Up @@ -51,7 +51,7 @@ func init() {
}

type guessInetSockFamily struct {
ctx Context
ctx kprobes.GuessContext
family int
limit int
canIPv6 bool
Expand Down Expand Up @@ -81,21 +81,21 @@ func (g *guessInetSockFamily) Requires() []string {
// Probes returns a kprobe on inet_release which has a struct socket* as
// single argument. Returns a dump of the (struct socket*)->sk field, which is
// a struct inet_sock* for INET/INET6.
func (g *guessInetSockFamily) Probes() ([]helper.ProbeDef, error) {
return []helper.ProbeDef{
func (g *guessInetSockFamily) Probes() ([]kprobes.ProbeDef, error) {
return []kprobes.ProbeDef{
{
Probe: tracing.Probe{
Name: "inet_sock_af_guess",
Address: "inet_release",
Fetchargs: helper.MakeMemoryDump("+{{.SOCKET_SOCK}}({{.P1}})", 0, inetSockAfDumpSize),
Fetchargs: kprobes.MakeMemoryDump("+{{.SOCKET_SOCK}}({{.P1}})", 0, inetSockAfDumpSize),
},
Decoder: tracing.NewDumpDecoder,
},
}, nil
}

// Prepare is a no-op.
func (g *guessInetSockFamily) Prepare(ctx Context) error {
func (g *guessInetSockFamily) Prepare(ctx kprobes.GuessContext) error {
g.ctx = ctx
var ok bool
// limit is used as a reference point within struct sock_common to know where
Expand Down
16 changes: 8 additions & 8 deletions x-pack/auditbeat/module/system/socket/guess/iplocalout.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (
"golang.org/x/sys/unix"

"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/x-pack/auditbeat/module/system/socket/helper"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing"
"github.com/elastic/beats/v7/x-pack/auditbeat/tracing/kprobes"
)

// Guess how to get a struct sock* from an ip_local_out() call.
Expand Down Expand Up @@ -54,7 +54,7 @@ type skbuffSockGuess struct {
}

type guessIPLocalOut struct {
ctx Context
ctx kprobes.GuessContext
cs inetClientServer
sock uintptr
}
Expand Down Expand Up @@ -92,30 +92,30 @@ func (g *guessIPLocalOut) Requires() []string {
// * arg2 (arg1 if this system has ip_local_out_sk)
// * dump of arg1 (arg2 if this system has ip_local_out_sk)
// - tcp_sendmsg, returning the sock* argument.
func (g *guessIPLocalOut) Probes() ([]helper.ProbeDef, error) {
return []helper.ProbeDef{
func (g *guessIPLocalOut) Probes() ([]kprobes.ProbeDef, error) {
return []kprobes.ProbeDef{
{
Probe: tracing.Probe{
Name: "ip_local_out_sock_guess",
Address: "{{.IP_LOCAL_OUT}}",
Fetchargs: "arg={{if eq .IP_LOCAL_OUT \"ip_local_out\"}}{{.P2}}{{else}}{{.P1}}{{end}} dump=" +
helper.MakeMemoryDump("{{if eq .IP_LOCAL_OUT \"ip_local_out\"}}{{.P1}}{{else}}{{.P2}}{{end}}", 0, skbuffDumpSize),
kprobes.MakeMemoryDump("{{if eq .IP_LOCAL_OUT \"ip_local_out\"}}{{.P1}}{{else}}{{.P2}}{{end}}", 0, skbuffDumpSize),
},
Decoder: helper.NewStructDecoder(func() interface{} { return new(skbuffSockGuess) }),
Decoder: kprobes.NewStructDecoder(func() interface{} { return new(skbuffSockGuess) }),
},
{
Probe: tracing.Probe{
Name: "tcp_sendmsg_in",
Address: "tcp_sendmsg",
Fetchargs: "sock={{.TCP_SENDMSG_SOCK}}",
},
Decoder: helper.NewStructDecoder(func() interface{} { return new(sockArgumentGuess) }),
Decoder: kprobes.NewStructDecoder(func() interface{} { return new(sockArgumentGuess) }),
},
}, nil
}

// Prepare sets up a connected TCP client/server.
func (g *guessIPLocalOut) Prepare(ctx Context) error {
func (g *guessIPLocalOut) Prepare(ctx kprobes.GuessContext) error {
g.ctx = ctx
return g.cs.SetupTCP()
}
Expand Down
Loading