From ae5f100bbf2cd6eb5f5930d3089758ae5cd0c3a1 Mon Sep 17 00:00:00 2001 From: Adrian Serrano Date: Tue, 9 Jul 2019 23:27:41 +0200 Subject: [PATCH] Fix a crash under Windows when fetching process information (#12833) (#12837) This updates gosigar to v0.10.4 and go-sysinfo to v1.0.2. Both releases fix a similar bug under Windows when fetching the command-line of a running process: The offending code expected the command-line strings read from a target process to contain a null character as a terminator. However, this is not always true, and sometimes a terminator needs to be added. Most of the time the missing terminator wasn't an issue due to the runtime allocating extra space for the string, but in some extreme cases it caused a crash. This bug manifested in: Metricbeat's system/process metricset. It is also used by: Auditbeat's system/process. Packetbeat's process monitor (disabled by default). The add_process_metadata processor. Beats monitoring. libbeat/cmd/instance/beat.go Fixes #12826 (cherry picked from commit 3374b3ab3ff238355c5d9268fefee0b22b53286a) --- CHANGELOG.next.asciidoc | 1 + NOTICE.txt | 7 +- .../elastic/go-sysinfo/CHANGELOG.md | 9 +- .../providers/windows/process_windows.go | 26 +++++- .../github.com/elastic/gosigar/CHANGELOG.md | 11 +++ .../gosigar/sys/windows/syscall_windows.go | 32 +++++-- vendor/vendor.json | 90 +++++++++++-------- 7 files changed, 125 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.next.asciidoc b/CHANGELOG.next.asciidoc index 6fb40ac578b7..851fe6b3cc15 100644 --- a/CHANGELOG.next.asciidoc +++ b/CHANGELOG.next.asciidoc @@ -31,6 +31,7 @@ https://github.com/elastic/beats/compare/v7.2.0...7.2[Check the HEAD diff] *Affecting all Beats* - Fix Central Management enroll under Windows {issue}12797[12797] {pull}12799[12799] +- Fixed a crash under Windows when fetching processes information. {pull}12833[12833] *Auditbeat* diff --git a/NOTICE.txt b/NOTICE.txt index 38957751f097..6b5bbb4a0acc 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -715,7 +715,8 @@ Apache License 2.0 -------------------------------------------------------------------- Dependency: github.com/elastic/go-sysinfo -Revision: 9a4be54a53be4c48b44d351d52fb425a5e274be5 +Version: v1.0.2 +Revision: 06c1f463545498d8f4b378d4dcf3171794c28537 License type (autodetected): Apache-2.0 ./vendor/github.com/elastic/go-sysinfo/LICENSE.txt: -------------------------------------------------------------------- @@ -765,8 +766,8 @@ Elasticsearch, B.V. (https://www.elastic.co/). -------------------------------------------------------------------- Dependency: github.com/elastic/gosigar -Version: v0.10.2 -Revision: 1227b9d6877d126ad640087e44439d70dba2df4f +Version: v0.10.4 +Revision: f75810decf6f4d88b130bfc4d2ba7ccdcea0c01d License type (autodetected): Apache-2.0 ./vendor/github.com/elastic/gosigar/LICENSE: -------------------------------------------------------------------- diff --git a/vendor/github.com/elastic/go-sysinfo/CHANGELOG.md b/vendor/github.com/elastic/go-sysinfo/CHANGELOG.md index 562a3b5d04f7..f1727d20b14e 100644 --- a/vendor/github.com/elastic/go-sysinfo/CHANGELOG.md +++ b/vendor/github.com/elastic/go-sysinfo/CHANGELOG.md @@ -16,10 +16,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed -- Fixed a leak when calling the CommandLineToArgv function. [#51](https://github.com/elastic/go-sysinfo/pull/51) - ### Security +## [1.0.2] - 2019-07-09 + +### Fixed + +- Fixed a leak when calling the CommandLineToArgv function. [#51](https://github.com/elastic/go-sysinfo/pull/51) +- Fixed a crash when calling the CommandLineToArgv function. [#58](https://github.com/elastic/go-sysinfo/pull/58) + ## [1.0.1] - 2019-05-08 ### Fixed diff --git a/vendor/github.com/elastic/go-sysinfo/providers/windows/process_windows.go b/vendor/github.com/elastic/go-sysinfo/providers/windows/process_windows.go index 351351debc68..5dfd09057723 100644 --- a/vendor/github.com/elastic/go-sysinfo/providers/windows/process_windows.go +++ b/vendor/github.com/elastic/go-sysinfo/providers/windows/process_windows.go @@ -207,8 +207,14 @@ func getUserProcessParams(handle syscall.Handle, pbi windows.ProcessBasicInforma // read an UTF-16 string from another process memory. Result is an []byte // with the UTF-16 data. func readProcessUnicodeString(handle syscall.Handle, s *windows.UnicodeString) ([]byte, error) { - buf := make([]byte, s.Size) - nRead, err := windows.ReadProcessMemory(handle, s.Buffer, buf) + // Allocate an extra UTF-16 null character at the end in case the read string + // is not terminated. + extra := 2 + if s.Size&1 != 0 { + extra = 3 // If size is odd, need 3 nulls to terminate. + } + buf := make([]byte, int(s.Size)+extra) + nRead, err := windows.ReadProcessMemory(handle, s.Buffer, buf[:s.Size]) if err != nil { return nil, err } @@ -221,9 +227,23 @@ func readProcessUnicodeString(handle syscall.Handle, s *windows.UnicodeString) ( // Use Windows' CommandLineToArgv API to split an UTF-16 command line string // into a list of parameters. func splitCommandline(utf16 []byte) ([]string, error) { - if len(utf16) == 0 { + n := len(utf16) + // Discard odd byte + if n&1 != 0 { + n-- + utf16 = utf16[:n] + } + if n == 0 { return nil, nil } + terminated := false + for i := 0; i < n && !terminated; i += 2 { + terminated = utf16[i] == 0 && utf16[i+1] == 0 + } + if !terminated { + // Append a null uint16 at the end if terminator is missing + utf16 = append(utf16, 0, 0) + } var numArgs int32 argsWide, err := syscall.CommandLineToArgv((*uint16)(unsafe.Pointer(&utf16[0])), &numArgs) if err != nil { diff --git a/vendor/github.com/elastic/gosigar/CHANGELOG.md b/vendor/github.com/elastic/gosigar/CHANGELOG.md index 04051fed8e8b..9377542abb12 100644 --- a/vendor/github.com/elastic/gosigar/CHANGELOG.md +++ b/vendor/github.com/elastic/gosigar/CHANGELOG.md @@ -12,6 +12,17 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Deprecated +## [0.10.4] + +### Fixed + +- Fixed a crash when splitting command-line arguments under Windows. #124 + +## [0.10.3] + +### Fixed +- ProcState.Get() doesn't fail under Windows when it cannot obtain process ownership information. #121 + ## [0.10.2] ### Fixed diff --git a/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go b/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go index 7da8a07135ec..0c11fda312f8 100644 --- a/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go +++ b/vendor/github.com/elastic/gosigar/sys/windows/syscall_windows.go @@ -503,9 +503,17 @@ func GetUserProcessParams(handle syscall.Handle, pbi ProcessBasicInformation) (p return params, nil } +// ReadProcessUnicodeString returns a zero-terminated UTF-16 string from another +// process's memory. func ReadProcessUnicodeString(handle syscall.Handle, s *UnicodeString) ([]byte, error) { - buf := make([]byte, s.Size) - nRead, err := ReadProcessMemory(handle, s.Buffer, buf) + // Allocate an extra UTF-16 null character at the end in case the read string + // is not terminated. + extra := 2 + if s.Size&1 != 0 { + extra = 3 // If size is odd, need 3 nulls to terminate. + } + buf := make([]byte, int(s.Size)+extra) + nRead, err := ReadProcessMemory(handle, s.Buffer, buf[:s.Size]) if err != nil { return nil, err } @@ -515,12 +523,26 @@ func ReadProcessUnicodeString(handle syscall.Handle, s *UnicodeString) ([]byte, return buf, nil } -// Use Windows' CommandLineToArgv API to split an UTF-16 command line string -// into a list of parameters. +// ByteSliceToStringSlice uses CommandLineToArgv API to split an UTF-16 command +// line string into a list of parameters. func ByteSliceToStringSlice(utf16 []byte) ([]string, error) { - if len(utf16) == 0 { + n := len(utf16) + // Discard odd byte + if n&1 != 0 { + n-- + utf16 = utf16[:n] + } + if n == 0 { return nil, nil } + terminated := false + for i := 0; i < n && !terminated; i += 2 { + terminated = utf16[i] == 0 && utf16[i+1] == 0 + } + if !terminated { + // Append a null uint16 at the end if terminator is missing + utf16 = append(utf16, 0, 0) + } var numArgs int32 argsWide, err := syscall.CommandLineToArgv((*uint16)(unsafe.Pointer(&utf16[0])), &numArgs) if err != nil { diff --git a/vendor/vendor.json b/vendor/vendor.json index 115959a1af63..b99f8b0ba270 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -1030,46 +1030,60 @@ "versionExact": "v0.0.5" }, { - "checksumSHA1": "pdGPPNf1TeT3fTl8Uwl55hE9/G8=", + "checksumSHA1": "u5pjOSlI10k6Q9LaRcF7OgBa2tU=", "path": "github.com/elastic/go-sysinfo", - "revision": "9a4be54a53be4c48b44d351d52fb425a5e274be5", - "revisionTime": "2019-05-08T09:33:45Z" + "revision": "06c1f463545498d8f4b378d4dcf3171794c28537", + "revisionTime": "2019-07-09T16:49:53Z", + "version": "v1.0.2", + "versionExact": "v1.0.2" }, { "checksumSHA1": "GiZCjX17K265TtamGZZw4R2Jwbk=", "path": "github.com/elastic/go-sysinfo/internal/registry", - "revision": "9a4be54a53be4c48b44d351d52fb425a5e274be5", - "revisionTime": "2019-05-08T09:33:45Z" + "revision": "06c1f463545498d8f4b378d4dcf3171794c28537", + "revisionTime": "2019-07-09T16:49:53Z", + "version": "v1.0.2", + "versionExact": "v1.0.2" }, { "checksumSHA1": "dVSTUnZHCLNd0tYIENqdj05RyI8=", "path": "github.com/elastic/go-sysinfo/providers/darwin", - "revision": "9a4be54a53be4c48b44d351d52fb425a5e274be5", - "revisionTime": "2019-05-08T09:33:45Z" + "revision": "06c1f463545498d8f4b378d4dcf3171794c28537", + "revisionTime": "2019-07-09T16:49:53Z", + "version": "v1.0.2", + "versionExact": "v1.0.2" }, { "checksumSHA1": "LWMXshdY44+JM7g09dA4tXMZ1rY=", "path": "github.com/elastic/go-sysinfo/providers/linux", - "revision": "9a4be54a53be4c48b44d351d52fb425a5e274be5", - "revisionTime": "2019-05-08T09:33:45Z" + "revision": "06c1f463545498d8f4b378d4dcf3171794c28537", + "revisionTime": "2019-07-09T16:49:53Z", + "version": "v1.0.2", + "versionExact": "v1.0.2" }, { "checksumSHA1": "RWLvcP1w9ynKbuCqiW6prwd+EDU=", "path": "github.com/elastic/go-sysinfo/providers/shared", - "revision": "9a4be54a53be4c48b44d351d52fb425a5e274be5", - "revisionTime": "2019-05-08T09:33:45Z" + "revision": "06c1f463545498d8f4b378d4dcf3171794c28537", + "revisionTime": "2019-07-09T16:49:53Z", + "version": "v1.0.2", + "versionExact": "v1.0.2" }, { - "checksumSHA1": "13qV0fFj6P5m1/n1HsdByRW0Hk4=", + "checksumSHA1": "E+yrwS/aZemnWUvwTvEhiczYuD8=", "path": "github.com/elastic/go-sysinfo/providers/windows", - "revision": "9a4be54a53be4c48b44d351d52fb425a5e274be5", - "revisionTime": "2019-05-08T09:33:45Z" + "revision": "06c1f463545498d8f4b378d4dcf3171794c28537", + "revisionTime": "2019-07-09T16:49:53Z", + "version": "v1.0.2", + "versionExact": "v1.0.2" }, { "checksumSHA1": "OHierbaoOHx79d73DuLrao43rIg=", "path": "github.com/elastic/go-sysinfo/types", - "revision": "9a4be54a53be4c48b44d351d52fb425a5e274be5", - "revisionTime": "2019-05-08T09:33:45Z" + "revision": "06c1f463545498d8f4b378d4dcf3171794c28537", + "revisionTime": "2019-07-09T16:49:53Z", + "version": "v1.0.2", + "versionExact": "v1.0.2" }, { "checksumSHA1": "bNf3GDGhZh86bfCIMM5c5AYfo3g=", @@ -1246,44 +1260,44 @@ "revisionTime": "2018-08-31T13:10:45Z" }, { - "checksumSHA1": "c1rU7WNZ+1AwZcRPBWhPBHcbZjg=", + "checksumSHA1": "0Wy9N78P/Gh12DUbixilznW67ak=", "path": "github.com/elastic/gosigar", - "revision": "1227b9d6877d126ad640087e44439d70dba2df4f", - "revisionTime": "2019-05-08T13:07:01Z", - "version": "v0.10.2", - "versionExact": "v0.10.2" + "revision": "f75810decf6f4d88b130bfc4d2ba7ccdcea0c01d", + "revisionTime": "2019-07-09T16:38:49Z", + "version": "v0.10.4", + "versionExact": "v0.10.4" }, { "checksumSHA1": "TX9y4oPL5YmT4Gb/OU4GIPTdQB4=", "path": "github.com/elastic/gosigar/cgroup", - "revision": "1227b9d6877d126ad640087e44439d70dba2df4f", - "revisionTime": "2019-05-08T13:07:01Z", - "version": "v0.10.2", - "versionExact": "v0.10.2" + "revision": "f75810decf6f4d88b130bfc4d2ba7ccdcea0c01d", + "revisionTime": "2019-07-09T16:38:49Z", + "version": "v0.10.4", + "versionExact": "v0.10.4" }, { "checksumSHA1": "hPqGM3DENaGfipEODoyZ4mKogTQ=", "path": "github.com/elastic/gosigar/sys", - "revision": "1227b9d6877d126ad640087e44439d70dba2df4f", - "revisionTime": "2019-05-08T13:07:01Z", - "version": "v0.10.2", - "versionExact": "v0.10.2" + "revision": "f75810decf6f4d88b130bfc4d2ba7ccdcea0c01d", + "revisionTime": "2019-07-09T16:38:49Z", + "version": "v0.10.4", + "versionExact": "v0.10.4" }, { "checksumSHA1": "mLq5lOyD0ZU39ysXuf1ETOLJ+f0=", "path": "github.com/elastic/gosigar/sys/linux", - "revision": "1227b9d6877d126ad640087e44439d70dba2df4f", - "revisionTime": "2019-05-08T13:07:01Z", - "version": "v0.10.2", - "versionExact": "v0.10.2" + "revision": "f75810decf6f4d88b130bfc4d2ba7ccdcea0c01d", + "revisionTime": "2019-07-09T16:38:49Z", + "version": "v0.10.4", + "versionExact": "v0.10.4" }, { - "checksumSHA1": "R70u1XUHH/t1pquvHEFDeUFtkFk=", + "checksumSHA1": "ZoHlhk6iiV8eMn0ozjy6mvC5+Dc=", "path": "github.com/elastic/gosigar/sys/windows", - "revision": "1227b9d6877d126ad640087e44439d70dba2df4f", - "revisionTime": "2019-05-08T13:07:01Z", - "version": "v0.10.2", - "versionExact": "v0.10.2" + "revision": "f75810decf6f4d88b130bfc4d2ba7ccdcea0c01d", + "revisionTime": "2019-07-09T16:38:49Z", + "version": "v0.10.4", + "versionExact": "v0.10.4" }, { "checksumSHA1": "Klc34HULvwvY4cGA/D8HmqtXLqw=",