Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- system module: Fix panic during initialisation when /proc/stat can't be read. {pull}17569[17569]
- system/package: Fix an error that can occur while trying to persist package metadata. {issue}18536[18536] {pull}18887[18887]
- system/socket: Fix bugs leading to wrong process being attributed to flows. {pull}29166[29166] {issue}17165[17165]
- system/socket: Fix process name and arg truncation for long names, paths and args lists. {issue}24667[24667] {pull}29410[29410]

*Filebeat*

Expand Down
76 changes: 59 additions & 17 deletions x-pack/auditbeat/module/system/socket/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -859,8 +859,10 @@ func (e *inetReleaseCall) Update(s *state) error {
// kernels it needs to dump fixed-size arrays in 8-byte chunks. As the total
// number of fetchargs available is limited, we have to dump only the first
// 128 bytes of every argument.
const maxProgArgLen = 128
const maxProgArgs = 5
const (
maxProgArgLen = 128
maxProgArgs = 5
)

type execveCall struct {
Meta tracing.Metadata `kprobe:"metadata"`
Expand All @@ -880,38 +882,78 @@ type execveCall struct {
func (e *execveCall) getProcess() *process {
p := &process{
pid: e.Meta.PID,
path: readCString(e.Path[:]),
created: kernelTime(e.Meta.Timestamp),
}
p.name = filepath.Base(p.path)
var argc int
for argc = 0; argc <= maxProgArgs; argc++ {
if e.Ptrs[argc] == 0 {
break

if idx := bytes.IndexByte(e.Path[:], 0); idx >= 0 {
// Fast path if we already have the path.
p.path = string(e.Path[:idx])
} else {
// Attempt to get the path from the /prox/<pid>/exe symlink.
var err error
p.path, err = filepath.EvalSymlinks(fmt.Sprintf("/proc/%d/exe", e.Meta.PID))
if err != nil {
if pe, ok := err.(*os.PathError); ok && strings.Contains(pe.Path, "(deleted)") {
// Keep the deleted path from the PathError.
p.path = pe.Path
} else {
// Fallback to the truncated path.
p.path = string(e.Path[:]) + " ..."
}
}
}
p.args = make([]string, argc)
params := [maxProgArgs][]byte{

// Check for truncation of arg list or arguments.
params := [...][]byte{
e.Param0[:],
e.Param1[:],
e.Param2[:],
e.Param3[:],
e.Param4[:],
}
limit := argc
if limit > maxProgArgs {
limit = maxProgArgs
p.args[limit] = "..."
var (
argc int
truncatedArg bool
)
for argc = 0; argc < len(e.Ptrs); argc++ {
if e.Ptrs[argc] == 0 {
break
}
if argc < len(params) && bytes.IndexByte(params[argc], 0) < 0 {
truncatedArg = true
}
}
if argc > maxProgArgs || truncatedArg {
// Attempt to get complete args list from /proc/<pid>/cmdline.
cmdline, err := os.ReadFile(fmt.Sprintf("/proc/%d/cmdline", e.Meta.PID))
if err == nil {
p.args = strings.Split(strings.TrimRight(string(cmdline), "\x00"), "\x00")
}
}
for i := 0; i < limit; i++ {
p.args[i] = readCString(params[i])

if p.args == nil {
// Fallback to arg list if unsuccessful or no truncation.
p.args = make([]string, argc)
if argc > maxProgArgs {
argc = maxProgArgs
p.args[argc] = "..."
}
for i, par := range params[:argc] {
p.args[i] = readCString(par)
}
}
if p.hasCreds = e.creds != nil; p.hasCreds {

// Get name from first argument.
p.name = filepath.Base(p.args[0])

if e.creds != nil {
p.hasCreds = true
p.uid = e.creds.UID
p.gid = e.creds.GID
p.euid = e.creds.EUID
p.egid = e.creds.EGID
}

return p
}

Expand Down
9 changes: 9 additions & 0 deletions x-pack/auditbeat/module/system/socket/socket_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,15 @@ func (m *MetricSet) Run(r mb.PushReporterV2) {
} else {
for _, p := range procs {
if i, err := p.Info(); err == nil {
if len(i.Name) == 16 && len(i.Args) != 0 {
// github.com/prometheus/procfs uses /proc/<pid>/stat for
// the process name which is truncated to 16 bytes, so get
// the name from the cmdline data if it might be truncated.
// The guard for length of i.Args is for cases where there
// is no command line reported by proc fs; this should never
// happen, but does.
i.Name = filepath.Base(i.Args[0])
}
process := &process{
name: i.Name,
pid: uint32(i.PID),
Expand Down