golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.52k stars 17.6k forks source link

x/vuln: govulncheck ./... ate all available memory and got killed #56391

Closed zak-pawel closed 1 year ago

zak-pawel commented 1 year ago

What version of Go are you using (go version)?

$ go version
go version go1.19.2 linux/amd64

Does this issue reproduce at the latest version of golang.org/x/vuln?

Yes: x/vuln@v0.0.0-20221019194534-41df7bda74f3

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/pzak/.cache/go-build"
GOENV="/home/pzak/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/pzak/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/pzak/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.19.2"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/pzak/repos/telegraf/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2542289712=/tmp/go-build -gno-record-gcc-switches"
uname -a Output
$ uname -a
Linux zak 5.15.0-50-generic #56-Ubuntu SMP Tue Sep 20 13:23:26 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
lscpu Output
$ lscpu
Architecture:            x86_64
  CPU op-mode(s):        32-bit, 64-bit
  Address sizes:         45 bits physical, 48 bits virtual
  Byte Order:            Little Endian
CPU(s):                  8
  On-line CPU(s) list:   0-7
Vendor ID:               GenuineIntel
  Model name:            Intel(R) Core(TM) i7-9850H CPU @ 2.60GHz
    CPU family:          6
    Model:               158
    Thread(s) per core:  1
    Core(s) per socket:  2
    Socket(s):           4
    Stepping:            13
    BogoMIPS:            5184.00
    Flags:               fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid tsc_known_freq pni pclmulqdq vmx ssse3 fma cx16 pcid 
                         sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid 
                         rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 xsaves arat md_clear flush_l1d arch_capabilities
Virtualization features: 
  Virtualization:        VT-x
  Hypervisor vendor:     VMware
  Virtualization type:   full
Caches (sum of all):     
  L1d:                   256 KiB (8 instances)
  L1i:                   256 KiB (8 instances)
  L2:                    2 MiB (8 instances)
  L3:                    48 MiB (4 instances)
NUMA:                    
  NUMA node(s):          1
  NUMA node0 CPU(s):     0-7
Vulnerabilities:         
  Itlb multihit:         KVM: Mitigation: VMX disabled
  L1tf:                  Not affected
  Mds:                   Not affected
  Meltdown:              Not affected
  Mmio stale data:       Vulnerable: Clear CPU buffers attempted, no microcode; SMT Host state unknown
  Retbleed:              Mitigation; Enhanced IBRS
  Spec store bypass:     Mitigation; Speculative Store Bypass disabled via prctl and seccomp
  Spectre v1:            Mitigation; usercopy/swapgs barriers and __user pointer sanitization
  Spectre v2:            Mitigation; Enhanced IBRS, IBPB conditional, RSB filling, PBRSB-eIBRS SW sequence
  Srbds:                 Unknown: Dependent on hypervisor status
  Tsx async abort:       Not affected

free -m Output
$ free -m
               total        used        free      shared  buff/cache   available
Mem:            7915         674        6990          12         251        6980
Swap:           1401         621         780

What did you do?

$ cd /tmp
$ git clone https://github.com/influxdata/telegraf.git
Cloning into 'telegraf'...
remote: Enumerating objects: 74532, done.
remote: Counting objects: 100% (159/159), done.
remote: Compressing objects: 100% (114/114), done.
remote: Total 74532 (delta 67), reused 117 (delta 44), pack-reused 74373
Receiving objects: 100% (74532/74532), 49.51 MiB | 2.21 MiB/s, done.
Resolving deltas: 100% (45775/45775), done.

$ cd telegraf
$ govulncheck ./...

What did you expect to see?

I expected to see govulncheck finishes without any error, potentially with some findings reported.

What did you see instead?

govulncheck is an experimental tool. Share feedback at https://go.dev/s/govulncheck-feedback.

Scanning for dependencies with known vulnerabilities...
[1]    7249 killed     govulncheck ./...

Additionally, I saw in top that govulncheck consumed all available memory before it was killed.

Moreover, govulncheck was also killed in CircleCI job run inside VM with 4 vCPUs and 8GB RAM in official Telegraf CI.

More information

Problematic scan was run in Ubuntu Budgie 22.04 VM (inside VMWare Workstation). 8 CPUs and 8 GB were assigned.

After I increased memory 32 GB, following output appeared:

$ free -m
               total        used        free      shared  buff/cache   available
Mem:           32071        1296       29478           3        1296       30359
Swap:           1401           0        1401

$ govulncheck ./...
govulncheck is an experimental tool. Share feedback at https://go.dev/s/govulncheck-feedback.

Scanning for dependencies with known vulnerabilities...
No vulnerabilities found.

=== Informational ===

The vulnerabilities below are in packages that you import, but your code
doesn't appear to call any vulnerable functions. You may not need to take any
action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
for details.

Vulnerability #1: GO-2022-1059
  An attacker may cause a denial of service by crafting an Accept-Language
  header which ParseAcceptLanguage will take significant time to parse.

  Found in: golang.org/x/text/language@v0.3.7
  Fixed in: golang.org/x/text/language@v0.3.8
  More info: https://pkg.go.dev/vuln/GO-2022-1059
heschi commented 1 year ago

cc @golang/vulndb

timothy-king commented 1 year ago

cc @zpavlinovic

zpavlinovic commented 1 year ago

I can confirm that the peak memory usage for this project goes above 8GB. This is not exactly surprising as govulncheck builds a call graph both for the top packages and all of their transitive dependencies. For the telegraf project, govulncheck works over ~385k functions and just the loaded packages take ~4GB. Conversion to SSA and call graph computation more than double that usage.

While there might be something we can do to make the memory peak go below 8GB for this particular project, there are definitely other large projects that will go well over that. We suggest either increasing the memory or partitioning the package set (if that makes sense in your context) and run govulncheck separately for each partition:

govulncheck partition1
...
govulncheck partitionN
zpavlinovic commented 1 year ago

Closing for now as "working as intended."