From b627fb742e2154f0fbc882548a18c92c9f4845c8 Mon Sep 17 00:00:00 2001 From: Adrian Serrano Date: Wed, 2 Dec 2020 19:39:58 +0100 Subject: [PATCH] system/socket: Add ip_local_out alternative (#22787) This commit adds a new function alternative, `__ip_local_out` for selecting a proper ip_local_out function, and fixes `guess_ip_local_out` logic in order to account for this new function. The new order of precedence is: - ip_local_out_sk (kernels before 3.16) - __ip_local_out (for kernels where ip_local_out calls are inlined) - ip_local_out (all others). Relates #18755 --- .../module/system/socket/guess/iplocalout.go | 21 +++++++++++++------ .../module/system/socket/template.go | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/x-pack/auditbeat/module/system/socket/guess/iplocalout.go b/x-pack/auditbeat/module/system/socket/guess/iplocalout.go index d78140bda13..a0657139178 100644 --- a/x-pack/auditbeat/module/system/socket/guess/iplocalout.go +++ b/x-pack/auditbeat/module/system/socket/guess/iplocalout.go @@ -17,14 +17,22 @@ import ( "github.com/elastic/beats/v7/x-pack/auditbeat/tracing" ) -// Guess how to get a struct sock* from an ip_local_out() call. +// Guess how to get a struct sock* and an sk_buff* from an ip_local_out() call. // This function has three forms depending on kernel version: // - ip_local_out(struct sk_buff *skb) // 2.x//<3.13 // - ip_local_out_sk(struct sock *sk, struct sk_buff *skb) // 3.13..4.3 // - ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb) // 4.4+ // -// what it does is set a probe on tcp_sendmsg (guaranteed to have a *sock) -// and in ip_local_out, which will be called by tcp_sendmsg. +// To make things more complicated, in some 5.x+ kernels, ip_local_out is never +// triggered although it exists, but __ip_local_out always works, so +// this guess expects the template variable IP_LOCAL_OUT to be set to the +// first of these functions that is available for tracing: +// [ "ip_local_out_sk", "__ip_local_out", "ip_local_out" ] +// +// ---- +// +// What it guess does is set a probe on tcp_sendmsg (guaranteed to have a *sock) +// and in .IP_LOCAL_OUT, which will be called by tcp_sendmsg. // It dumps the first param (which can be a struct net* or a struct sk_buff) // and gets the second param. Either the second param is the sock, or is it // found at some point in the dumped first param. @@ -98,8 +106,8 @@ func (g *guessIPLocalOut) Probes() ([]helper.ProbeDef, error) { 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), + Fetchargs: "arg={{if ne .IP_LOCAL_OUT \"ip_local_out_sk\"}}{{.P2}}{{else}}{{.P1}}{{end}} dump=" + + helper.MakeMemoryDump("{{if ne .IP_LOCAL_OUT \"ip_local_out_sk\"}}{{.P1}}{{else}}{{.P2}}{{end}}", 0, skbuffDumpSize), }, Decoder: helper.NewStructDecoder(func() interface{} { return new(skbuffSockGuess) }), }, @@ -149,7 +157,8 @@ func (g *guessIPLocalOut) Extract(ev interface{}) (common.MapStr, bool) { // No tcp_sendmsg received? return nil, false } - isIpLocalOut := g.ctx.Vars["IP_LOCAL_OUT"] == "ip_local_out" + // Special handling for ip_local_out_sk + isIpLocalOut := g.ctx.Vars["IP_LOCAL_OUT"] != "ip_local_out_sk" if v.Arg == g.sock { if isIpLocalOut { return common.MapStr{ diff --git a/x-pack/auditbeat/module/system/socket/template.go b/x-pack/auditbeat/module/system/socket/template.go index 2066d60cdcf..425692c7681 100644 --- a/x-pack/auditbeat/module/system/socket/template.go +++ b/x-pack/auditbeat/module/system/socket/template.go @@ -35,7 +35,7 @@ var baseTemplateVars = common.MapStr{ // These functions names vary between kernel versions. The first available one // will be selected during setup. var functionAlternatives = map[string][]string{ - "IP_LOCAL_OUT": {"ip_local_out", "ip_local_out_sk"}, + "IP_LOCAL_OUT": {"ip_local_out_sk", "__ip_local_out", "ip_local_out"}, "RECV_UDP_DATAGRAM": {"__skb_recv_udp", "__skb_recv_datagram", "skb_recv_datagram"}, "SYS_EXECVE": syscallAlternatives("execve"), "SYS_GETTIMEOFDAY": syscallAlternatives("gettimeofday"),