Skip to content

Commit cd16c9f

Browse files
mergify[bot]efd6
andauthored
x-pack/auditbeat/module/system/socket: get full length path and arg from /proc when not available from kprobe (#29410) (#29958)
Also use first arg from sysinfo.Processes in place of Name to avoid process name truncation. (cherry picked from commit d46bb5f) Co-authored-by: Dan Kortschak <[email protected]>
1 parent 05a46ac commit cd16c9f

File tree

3 files changed

+73
-17
lines changed

3 files changed

+73
-17
lines changed

CHANGELOG.next.asciidoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
4444
*Auditbeat*
4545

4646
- system/socket: Fix startup errors on newer 5.x kernels due to missing _do_fork function. {issue}29607[29607] {pull}29744[29744]
47+
- system/package: Fix parsing of Installed-Size field of DEB packages. {issue}16661[16661] {pull}17188[17188]
48+
- system module: Fix panic during initialisation when /proc/stat can't be read. {pull}17569[17569]
49+
- system/package: Fix an error that can occur while trying to persist package metadata. {issue}18536[18536] {pull}18887[18887]
50+
- system/socket: Fix bugs leading to wrong process being attributed to flows. {pull}29166[29166] {issue}17165[17165]
51+
- system/socket: Fix process name and arg truncation for long names, paths and args lists. {issue}24667[24667] {pull}29410[29410]
4752

4853
*Filebeat*
4954

x-pack/auditbeat/module/system/socket/events.go

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -859,8 +859,10 @@ func (e *inetReleaseCall) Update(s *state) error {
859859
// kernels it needs to dump fixed-size arrays in 8-byte chunks. As the total
860860
// number of fetchargs available is limited, we have to dump only the first
861861
// 128 bytes of every argument.
862-
const maxProgArgLen = 128
863-
const maxProgArgs = 5
862+
const (
863+
maxProgArgLen = 128
864+
maxProgArgs = 5
865+
)
864866

865867
type execveCall struct {
866868
Meta tracing.Metadata `kprobe:"metadata"`
@@ -880,38 +882,78 @@ type execveCall struct {
880882
func (e *execveCall) getProcess() *process {
881883
p := &process{
882884
pid: e.Meta.PID,
883-
path: readCString(e.Path[:]),
884885
created: kernelTime(e.Meta.Timestamp),
885886
}
886-
p.name = filepath.Base(p.path)
887-
var argc int
888-
for argc = 0; argc <= maxProgArgs; argc++ {
889-
if e.Ptrs[argc] == 0 {
890-
break
887+
888+
if idx := bytes.IndexByte(e.Path[:], 0); idx >= 0 {
889+
// Fast path if we already have the path.
890+
p.path = string(e.Path[:idx])
891+
} else {
892+
// Attempt to get the path from the /prox/<pid>/exe symlink.
893+
var err error
894+
p.path, err = filepath.EvalSymlinks(fmt.Sprintf("/proc/%d/exe", e.Meta.PID))
895+
if err != nil {
896+
if pe, ok := err.(*os.PathError); ok && strings.Contains(pe.Path, "(deleted)") {
897+
// Keep the deleted path from the PathError.
898+
p.path = pe.Path
899+
} else {
900+
// Fallback to the truncated path.
901+
p.path = string(e.Path[:]) + " ..."
902+
}
891903
}
892904
}
893-
p.args = make([]string, argc)
894-
params := [maxProgArgs][]byte{
905+
906+
// Check for truncation of arg list or arguments.
907+
params := [...][]byte{
895908
e.Param0[:],
896909
e.Param1[:],
897910
e.Param2[:],
898911
e.Param3[:],
899912
e.Param4[:],
900913
}
901-
limit := argc
902-
if limit > maxProgArgs {
903-
limit = maxProgArgs
904-
p.args[limit] = "..."
914+
var (
915+
argc int
916+
truncatedArg bool
917+
)
918+
for argc = 0; argc < len(e.Ptrs); argc++ {
919+
if e.Ptrs[argc] == 0 {
920+
break
921+
}
922+
if argc < len(params) && bytes.IndexByte(params[argc], 0) < 0 {
923+
truncatedArg = true
924+
}
925+
}
926+
if argc > maxProgArgs || truncatedArg {
927+
// Attempt to get complete args list from /proc/<pid>/cmdline.
928+
cmdline, err := os.ReadFile(fmt.Sprintf("/proc/%d/cmdline", e.Meta.PID))
929+
if err == nil {
930+
p.args = strings.Split(strings.TrimRight(string(cmdline), "\x00"), "\x00")
931+
}
905932
}
906-
for i := 0; i < limit; i++ {
907-
p.args[i] = readCString(params[i])
933+
934+
if p.args == nil {
935+
// Fallback to arg list if unsuccessful or no truncation.
936+
p.args = make([]string, argc)
937+
if argc > maxProgArgs {
938+
argc = maxProgArgs
939+
p.args[argc] = "..."
940+
}
941+
for i, par := range params[:argc] {
942+
p.args[i] = readCString(par)
943+
}
908944
}
909-
if p.hasCreds = e.creds != nil; p.hasCreds {
945+
946+
// Get name from first argument.
947+
p.name = filepath.Base(p.args[0])
948+
949+
if e.creds != nil {
950+
p.hasCreds = true
910951
p.uid = e.creds.UID
911952
p.gid = e.creds.GID
912953
p.euid = e.creds.EUID
913954
p.egid = e.creds.EGID
914955
}
956+
915957
return p
916958
}
917959

x-pack/auditbeat/module/system/socket/socket_linux.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,15 @@ func (m *MetricSet) Run(r mb.PushReporterV2) {
187187
} else {
188188
for _, p := range procs {
189189
if i, err := p.Info(); err == nil {
190+
if len(i.Name) == 16 && len(i.Args) != 0 {
191+
// github.com/prometheus/procfs uses /proc/<pid>/stat for
192+
// the process name which is truncated to 16 bytes, so get
193+
// the name from the cmdline data if it might be truncated.
194+
// The guard for length of i.Args is for cases where there
195+
// is no command line reported by proc fs; this should never
196+
// happen, but does.
197+
i.Name = filepath.Base(i.Args[0])
198+
}
190199
process := &process{
191200
name: i.Name,
192201
pid: uint32(i.PID),

0 commit comments

Comments
 (0)