From 31be890ab6e5a311f2e46fdad8162f0ee7b8b9ea Mon Sep 17 00:00:00 2001 From: Adrian Serrano Date: Wed, 15 May 2019 10:06:43 -0400 Subject: [PATCH] [Auditbeat] Fix issues with multiple calls to rpmReadConfigFiles (#12168) This patch fixes two issues in Auditbeat's system/package on RPM distros: - Multiple calls to rpmReadConfigFiles lead to a crash (segmentation fault). It is necessary to call rpmFreeRpmrc after each call to rpmReadConfigFiles. See [1] for a similar issue. - In addition, it is also necessary to call rpmFreeMacros (when available) to avoid leaking memory after each rpmReadConfigFiles call. 1: https://lists.fedorahosted.org/pipermail/anaconda-patches/2015-February/015826.html Fixes #12147 (cherry picked from commit a1a7d7e4b9eea43ef88d09e79df5afc6e158a1ea) --- CHANGELOG.next.asciidoc | 1 + .../module/system/package/rpm_linux.go | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 7257b91589a..cbc2007077b 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -39,6 +39,7 @@ https://github.com/elastic/beats/compare/v6.7.2...6.8[Check the HEAD diff] - Package dataset: Log error when Homebrew is not installed. {pull}11667[11667] - Process dataset: Fixed a memory leak under Windows. {pull}12100[12100] +- Package dataset: Fixed a crash inside librpm after Auditbeat has been running for a while. {issue}12147[12147] {pull}12168[12168] *Filebeat* diff --git a/x-pack/auditbeat/module/system/package/rpm_linux.go b/x-pack/auditbeat/module/system/package/rpm_linux.go index 66fb368df3e..f049c169b61 100644 --- a/x-pack/auditbeat/module/system/package/rpm_linux.go +++ b/x-pack/auditbeat/module/system/package/rpm_linux.go @@ -33,6 +33,20 @@ my_rpmtsCreate(void *f) { return rpmtsCreate(); } +void +my_rpmFreeMacros(void *f) { + void (*rpmFreeMacros)(void *); + rpmFreeMacros = (void(*)(void*))f; + rpmFreeMacros(NULL); +} + +void +my_rpmFreeRpmrc(void *f) { + void (*rpmFreeRpmrc)(void); + rpmFreeRpmrc = (void (*)(void))f; + rpmFreeRpmrc(); +} + int my_rpmReadConfigFiles(void *f) { int (*rpmReadConfigFiles)(const char*, const char*); @@ -163,6 +177,8 @@ type cFunctions struct { rpmdbFreeIterator unsafe.Pointer rpmtsFree unsafe.Pointer rpmsqSetInterruptSafety unsafe.Pointer + rpmFreeRpmrc unsafe.Pointer + rpmFreeMacros unsafe.Pointer } var cFun *cFunctions @@ -238,10 +254,19 @@ func dlopenCFunctions() (*cFunctions, error) { return nil, err } + cFun.rpmFreeRpmrc, err = librpm.GetSymbolPointer("rpmFreeRpmrc") + if err != nil { + return nil, err + } + // Only available in librpm>=4.13.0 cFun.rpmsqSetInterruptSafety, err = librpm.GetSymbolPointer("rpmsqSetInterruptSafety") // no error check + // Only available in librpm>=4.6.0 + cFun.rpmFreeMacros, err = librpm.GetSymbolPointer("rpmFreeMacros") + // no error check + return &cFun, nil } @@ -271,10 +296,15 @@ func listRPMPackages() ([]*Package, error) { return nil, fmt.Errorf("Failed to get rpmts") } defer C.my_rpmtsFree(cFun.rpmtsFree, rpmts) + res := C.my_rpmReadConfigFiles(cFun.rpmReadConfigFiles) if int(res) != 0 { return nil, fmt.Errorf("Error: %d", int(res)) } + defer C.my_rpmFreeRpmrc(cFun.rpmFreeRpmrc) + if cFun.rpmFreeMacros != nil { + defer C.my_rpmFreeMacros(cFun.rpmFreeMacros) + } mi := C.my_rpmtsInitIterator(cFun.rpmtsInitIterator, rpmts) if mi == nil {