From 0ab3954dc410297eb5bef5817a33804084e4223a Mon Sep 17 00:00:00 2001 From: Lars Meyer Date: Fri, 4 Jun 2021 10:04:23 +0200 Subject: [PATCH 1/3] [process][linux] fix Processes in SmartOS lx containers In Linux containers running in LX Branded Zones on SmartOS (potentially other Solaris-based OSes with LX Branded Zones), fillFromTIDStatWithContext panics as the delayacct_blkio_ticks field is not present and thus results in an out-of-bounds slice access. Check the slice length before and only attempt to parse the delayacct_blkio_ticks field if there is an appropriate number of fields. --- process/process_linux.go | 11 ++++++++--- v3/process/process_linux.go | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/process/process_linux.go b/process/process_linux.go index c9edf808..f5be5142 100644 --- a/process/process_linux.go +++ b/process/process_linux.go @@ -1024,9 +1024,14 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui // There is no such thing as iotime in stat file. As an approximation, we // will use delayacct_blkio_ticks (aggregated block I/O delays, as per Linux // docs). Note: I am assuming at least Linux 2.6.18 - iotime, err := strconv.ParseFloat(fields[42], 64) - if err != nil { - iotime = 0 // Ancient linux version, most likely + var iotime float64 + if len(fields) > 42 { + iotime, err = strconv.ParseFloat(fields[42], 64) + if err != nil { + iotime = 0 // Ancient linux version, most likely + } + } else { + iotime = 0 // e.g. SmartOS containers } cpuTimes := &cpu.TimesStat{ diff --git a/v3/process/process_linux.go b/v3/process/process_linux.go index 302dc9fc..910c5977 100644 --- a/v3/process/process_linux.go +++ b/v3/process/process_linux.go @@ -1019,9 +1019,14 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui // There is no such thing as iotime in stat file. As an approximation, we // will use delayacct_blkio_ticks (aggregated block I/O delays, as per Linux // docs). Note: I am assuming at least Linux 2.6.18 - iotime, err := strconv.ParseFloat(fields[42], 64) - if err != nil { - iotime = 0 // Ancient linux version, most likely + var iotime float64 + if len(fields) > 42 { + iotime, err = strconv.ParseFloat(fields[42], 64) + if err != nil { + iotime = 0 // Ancient linux version, most likely + } + } else { + iotime = 0 // e.g. SmartOS containers } cpuTimes := &cpu.TimesStat{ From e42c52cb35e2e35002050f4b551b37b140bbeab2 Mon Sep 17 00:00:00 2001 From: Lars Meyer Date: Fri, 4 Jun 2021 10:36:22 +0200 Subject: [PATCH 2/3] [process][linux] add test for missing iotime in SmartOS lx containers --- process/process_linux_test.go | 24 ++++++++++++++++++++++++ process/testdata/lx_brandz/1/stat | 1 + 2 files changed, 25 insertions(+) create mode 100644 process/testdata/lx_brandz/1/stat diff --git a/process/process_linux_test.go b/process/process_linux_test.go index e0ff628c..9a3dfaad 100644 --- a/process/process_linux_test.go +++ b/process/process_linux_test.go @@ -115,3 +115,27 @@ func Test_fillFromStatusWithContext(t *testing.T) { } } } + +func Test_fillFromTIDStatWithContext_lx_brandz(t *testing.T) { + pids, err := ioutil.ReadDir("testdata/lx_brandz/") + if err != nil { + t.Error(err) + } + f := common.MockEnv("HOST_PROC", "testdata/lx_brandz") + defer f() + for _, pid := range pids { + pid, err := strconv.ParseInt(pid.Name(), 0, 32) + if err != nil { + continue + } + if _, err := os.Stat(fmt.Sprintf("testdata/lx_brandz/%d/stat", pid)); err != nil { + continue + } + p, _ := NewProcess(int32(pid)) + _, _, cpuTimes, _, _, _, _, err := p.fillFromTIDStatWithContext(context.Background(), -1) + if err != nil { + t.Error(err) + } + assert.Equal(t, float64(0), cpuTimes.Iowait) + } +} diff --git a/process/testdata/lx_brandz/1/stat b/process/testdata/lx_brandz/1/stat new file mode 100644 index 00000000..82f60621 --- /dev/null +++ b/process/testdata/lx_brandz/1/stat @@ -0,0 +1 @@ +1 (systemd) S 0 0 0 0 -1 0 0 0 0 0 8 15 48 52 1 0 0 0 25 31883264 1413 18446744073709551615 0 0 140737487261696 0 0 0 0 0 0 18446741901776689794 0 0 17 0 From e89412a81e4bd0e4223b6ad011d3c31e26e08209 Mon Sep 17 00:00:00 2001 From: Lars Meyer Date: Mon, 14 Jun 2021 15:17:32 +0200 Subject: [PATCH 3/3] [process][linux] copy test for missing iotime in SmartOS lx containers to v3 --- v3/process/process_linux_test.go | 26 +++++++++++++++++++++++++- v3/process/testdata/lx_brandz/1/stat | 1 + 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 v3/process/testdata/lx_brandz/1/stat diff --git a/v3/process/process_linux_test.go b/v3/process/process_linux_test.go index 2bc65d6d..7519a4f5 100644 --- a/v3/process/process_linux_test.go +++ b/v3/process/process_linux_test.go @@ -114,4 +114,28 @@ func Test_fillFromStatusWithContext(t *testing.T) { t.Error(err) } } -} \ No newline at end of file +} + +func Test_fillFromTIDStatWithContext_lx_brandz(t *testing.T) { + pids, err := ioutil.ReadDir("testdata/lx_brandz/") + if err != nil { + t.Error(err) + } + f := common.MockEnv("HOST_PROC", "testdata/lx_brandz") + defer f() + for _, pid := range pids { + pid, err := strconv.ParseInt(pid.Name(), 0, 32) + if err != nil { + continue + } + if _, err := os.Stat(fmt.Sprintf("testdata/lx_brandz/%d/stat", pid)); err != nil { + continue + } + p, _ := NewProcess(int32(pid)) + _, _, cpuTimes, _, _, _, _, err := p.fillFromTIDStatWithContext(context.Background(), -1) + if err != nil { + t.Error(err) + } + assert.Equal(t, float64(0), cpuTimes.Iowait) + } +} diff --git a/v3/process/testdata/lx_brandz/1/stat b/v3/process/testdata/lx_brandz/1/stat new file mode 100644 index 00000000..82f60621 --- /dev/null +++ b/v3/process/testdata/lx_brandz/1/stat @@ -0,0 +1 @@ +1 (systemd) S 0 0 0 0 -1 0 0 0 0 0 8 15 48 52 1 0 0 0 25 31883264 1413 18446744073709551615 0 0 140737487261696 0 0 0 0 0 0 18446741901776689794 0 0 17 0