From 82662da9958d150487d24d293e64be3eb36e4638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Szulik?= Date: Mon, 2 Nov 2020 15:10:26 +0100 Subject: [PATCH] Avoid random values in unix.PerfEventAttr{} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Szulik --- perf/collector_libpfm.go | 20 ++++++++++++----- perf/collector_libpfm_test.go | 42 +++++++++++++++++++++++++++++++++++ perf/uncore_libpfm.go | 2 +- 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/perf/collector_libpfm.go b/perf/collector_libpfm.go index 59f5e1cf8a..f6f6f34750 100644 --- a/perf/collector_libpfm.go +++ b/perf/collector_libpfm.go @@ -21,6 +21,7 @@ package perf // #cgo LDFLAGS: -lpfm // #include // #include +// #include import "C" import ( @@ -231,8 +232,18 @@ func (c *collector) setup() error { return nil } -func readPerfEventAttr(name string) (*unix.PerfEventAttr, error) { +func readPerfEventAttr(name string, pfmGetOsEventEncoding func(string, unsafe.Pointer) error) (*unix.PerfEventAttr, error) { perfEventAttrMemory := C.malloc(C.ulong(unsafe.Sizeof(unix.PerfEventAttr{}))) + // Fill memory with 0 values. + C.memset(perfEventAttrMemory, 0, C.ulong(unsafe.Sizeof(unix.PerfEventAttr{}))) + err := pfmGetOsEventEncoding(name, unsafe.Pointer(perfEventAttrMemory)) + if err != nil { + return nil, err + } + return (*unix.PerfEventAttr)(perfEventAttrMemory), nil +} + +func pfmGetOsEventEncoding(name string, perfEventAttrMemory unsafe.Pointer) error { event := pfmPerfEncodeArgT{} fstr := C.CString("") event.fstr = unsafe.Pointer(fstr) @@ -241,10 +252,9 @@ func readPerfEventAttr(name string) (*unix.PerfEventAttr, error) { cSafeName := C.CString(name) pErr := C.pfm_get_os_event_encoding(cSafeName, C.PFM_PLM0|C.PFM_PLM3, C.PFM_OS_PERF_EVENT, unsafe.Pointer(&event)) if pErr != C.PFM_SUCCESS { - return nil, fmt.Errorf("unable to transform event name %s to perf_event_attr: %d", name, int(pErr)) + return fmt.Errorf("unable to transform event name %s to perf_event_attr: %d", name, int(pErr)) } - - return (*unix.PerfEventAttr)(perfEventAttrMemory), nil + return nil } type eventInfo struct { @@ -408,7 +418,7 @@ func (c *collector) createConfigFromRawEvent(event *CustomEvent) *unix.PerfEvent func (c *collector) createConfigFromEvent(event Event) (*unix.PerfEventAttr, error) { klog.V(5).Infof("Setting up perf event %s", string(event)) - config, err := readPerfEventAttr(string(event)) + config, err := readPerfEventAttr(string(event), pfmGetOsEventEncoding) if err != nil { C.free((unsafe.Pointer)(config)) return nil, err diff --git a/perf/collector_libpfm_test.go b/perf/collector_libpfm_test.go index 4f43f0d682..a9e25d13b6 100644 --- a/perf/collector_libpfm_test.go +++ b/perf/collector_libpfm_test.go @@ -21,6 +21,9 @@ import ( "bytes" "encoding/binary" "testing" + "unsafe" + + "golang.org/x/sys/unix" "github.com/stretchr/testify/assert" @@ -387,3 +390,42 @@ func TestReadPerfStat(t *testing.T) { }) } } + +func TestReadPerfEventAttr(t *testing.T) { + var testCases = []struct { + expected *unix.PerfEventAttr + pfmMockedFunc func(string, unsafe.Pointer) error + }{ + { + &unix.PerfEventAttr{ + Type: 0, + Size: 0, + Config: 0, + Sample: 0, + Sample_type: 0, + Read_format: 0, + Bits: 0, + Wakeup: 0, + Bp_type: 0, + Ext1: 0, + Ext2: 0, + Branch_sample_type: 0, + Sample_regs_user: 0, + Sample_stack_user: 0, + Clockid: 0, + Sample_regs_intr: 0, + Aux_watermark: 0, + Sample_max_stack: 0, + }, + func(s string, pointer unsafe.Pointer) error { + return nil + }, + }, + } + + for _, test := range testCases { + got, err := readPerfEventAttr("event_name", test.pfmMockedFunc) + assert.NoError(t, err) + assert.Equal(t, test.expected, got) + } +} diff --git a/perf/uncore_libpfm.go b/perf/uncore_libpfm.go index 001fd9ec58..f46c45a1c1 100644 --- a/perf/uncore_libpfm.go +++ b/perf/uncore_libpfm.go @@ -366,7 +366,7 @@ func (c *uncoreCollector) setupEvent(name string, pmus uncorePMUs, groupIndex in klog.V(5).Infof("Setting up uncore perf event %s", name) - config, err := readPerfEventAttr(name) + config, err := readPerfEventAttr(name, pfmGetOsEventEncoding) if err != nil { C.free((unsafe.Pointer)(config)) return err