mirror of
https://github.com/anchore/syft.git
synced 2026-08-20 17:18:30 +02:00
fix(binary): detect multi-arch ingress-nginx (#5179)
* fix(binary): detect multi-arch ingress-nginx
Add v1.9.6 ARM64, ARMv7, and s390x fixtures from the published controller image and match their version marker against the nearby Go build version.
Assisted-by: OpenAI Codex
Signed-off-by: Shurong Cao <170531907+CAOShurong@users.noreply.github.com>
* fix(binary): match ingress-nginx release marker on all arches
The release is injected with `-ldflags -X`, so it lands in its own aligned,
NUL-padded data symbol. Only that padding is portable -- the surrounding bytes
are an arch-specific float constant pool, which is why the existing matchers all
anchor on incidental junk like `$a` and `S=v<y5` and only ever worked on amd64.
Matching `v<version>` followed by two NULs finds exactly one hit in every v1.9.6
binary (amd64, arm, arm64, s390x) and in all nine amd64 releases already under
test. Two NULs matter -- with one, s390x matches a vendored `v1.19.0` earlier in
the file and reports the wrong version.
This also drops the ~8KB wildcard window the marker previously needed, so the new
fixtures are ordinary 369 byte snippets instead of 8.4KB ones.
Two things in the fixture tooling had to move for that to work:
- `config.yaml` pinned the multi-arch *index* digest for all four platforms, but
extraction runs `docker create <ref>` with no `--platform`, so every entry
resolved to whichever image was pulled last. `make download` failed outright on
`linux/arm/v7`, since the registry labels that platform `armv7` and docker
normalizes it to `arm`. Now pinned per-platform, matching the redis entry.
- `write-snippet` only recognized EM_X86_64 and EM_AARCH64, so anything else
landed in a `linux-unknown-<hex>` directory and had to be placed by hand.
Verified against the real binaries with `-must-use-original-binaries`.
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
* fix(binary): put non-amd64 snippets where the tests look for them
`write-snippet` used to fall back to `unknown-<hex>` for any ELF machine it
didn't recognize, so three snippets were sitting in directories nothing reads:
helm/3.12.0/linux-unknown-454d5f53333930 (hex of "EM_S390")
helm/4.1.4/linux-unknown-454d5f53333930
redis-server/7.2.5/linux-unknown-454d5f333836 (hex of "EM_386")
The test table asks for `linux-s390x` and `linux-386`, so those three cases were
quietly falling through to downloading the full binaries instead. Renamed to
match, and taught the tool about EM_386 and EM_RISCV so it stops producing dead
directories (there is an existing `linux-riscv64` snippet it also couldn't have
written).
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
---------
Signed-off-by: Shurong Cao <170531907+CAOShurong@users.noreply.github.com>
Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
Co-authored-by: Shurong Cao <170531907+CAOShurong@users.noreply.github.com>
Co-authored-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
parent
8bb3b5eed1
commit
5c6cf08a8c
@ -2613,6 +2613,39 @@ func Test_Cataloger_PositiveCases(t *testing.T) {
|
||||
Metadata: metadata("ingress-nginx-binary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
logicalFixture: "nginx-ingress-controller/1.9.6/linux-arm64",
|
||||
expected: pkg.Package{
|
||||
Name: "nginx-ingress-controller",
|
||||
Version: "1.9.6",
|
||||
Type: "binary",
|
||||
PURL: "pkg:generic/nginx-ingress-controller@1.9.6",
|
||||
Locations: locations("nginx-ingress-controller"),
|
||||
Metadata: metadata("ingress-nginx-binary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
logicalFixture: "nginx-ingress-controller/1.9.6/linux-arm",
|
||||
expected: pkg.Package{
|
||||
Name: "nginx-ingress-controller",
|
||||
Version: "1.9.6",
|
||||
Type: "binary",
|
||||
PURL: "pkg:generic/nginx-ingress-controller@1.9.6",
|
||||
Locations: locations("nginx-ingress-controller"),
|
||||
Metadata: metadata("ingress-nginx-binary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
logicalFixture: "nginx-ingress-controller/1.9.6/linux-s390x",
|
||||
expected: pkg.Package{
|
||||
Name: "nginx-ingress-controller",
|
||||
Version: "1.9.6",
|
||||
Type: "binary",
|
||||
PURL: "pkg:generic/nginx-ingress-controller@1.9.6",
|
||||
Locations: locations("nginx-ingress-controller"),
|
||||
Metadata: metadata("ingress-nginx-binary"),
|
||||
},
|
||||
},
|
||||
{
|
||||
logicalFixture: "nginx-ingress-controller/1.7.1/linux-amd64",
|
||||
expected: pkg.Package{
|
||||
|
||||
@ -1153,6 +1153,11 @@ func DefaultClassifiers() []binutils.Classifier {
|
||||
Class: "ingress-nginx-binary",
|
||||
FileGlob: "**/nginx-ingress-controller",
|
||||
EvidenceMatcher: binutils.MatchAny(
|
||||
// the release is injected with -ldflags -X, which lands it in its own NUL-padded data symbol.
|
||||
// the surrounding bytes are an arch-specific float constant pool, so only the padding is portable.
|
||||
// e.g. v1.9.6[NUL][NUL] on each of linux/amd64, linux/arm, linux/arm64, and linux/s390x
|
||||
// note: one trailing NUL is not enough -- on s390x that matches a vendored "v1.19.0" earlier in the file
|
||||
m.FileContentsVersionMatcher(`v(?P<version>[0-9]+\.[0-9]+\.[0-9]+(\-(alpha|beta)\.[0-9]+)?)\x00\x00`),
|
||||
// [NUL][NUL]v1.15.1[NUL][NUL]@e[ETX][NUL][NUL][NUL][NUL]go1.26.1[NUL][NUL][NUL]
|
||||
// <20>v1.15.1[NUL][NUL]<5D>z[ETX][NUL][NUL][NUL][NUL]go1.24.4[NUL][NUL][NUL]
|
||||
m.FileContentsVersionMatcher(`v(?P<version>[0-9]+\.[0-9]+\.[0-9]+)\x00+.{0,50}go[0-9]+\.[0-9]+(\-(alpha|beta)\.[0-9])?\.[0-9]+\x00+`),
|
||||
|
||||
@ -215,6 +215,14 @@ func getPlatformElf(f *os.File) string {
|
||||
arch = amd64
|
||||
case elf.EM_AARCH64:
|
||||
arch = arm64
|
||||
case elf.EM_ARM:
|
||||
arch = "arm"
|
||||
case elf.EM_S390:
|
||||
arch = "s390x"
|
||||
case elf.EM_386:
|
||||
arch = "386"
|
||||
case elf.EM_RISCV:
|
||||
arch = "riscv64"
|
||||
// TODO...
|
||||
default:
|
||||
arch = fmt.Sprintf("unknown-%x", elfFile.Machine)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
10
syft/pkg/cataloger/binary/testdata/config.yaml
vendored
10
syft/pkg/cataloger/binary/testdata/config.yaml
vendored
@ -1570,8 +1570,16 @@ from-images:
|
||||
|
||||
- version: 1.9.6
|
||||
images:
|
||||
- ref: registry.k8s.io/ingress-nginx/controller:v1.9.6@sha256:1405cc613bd95b2c6edd8b2a152510ae91c7e62aea4698500d23b2145960ab9c
|
||||
# note: per-platform manifest digests (not the index digest) -- the extraction step creates a
|
||||
# container from the ref alone, so each platform needs its own uniquely addressable ref
|
||||
- ref: registry.k8s.io/ingress-nginx/controller:v1.9.6@sha256:0939639a1f338a9eaaa490fd38b4a7881e47a7fd1a473baf8749ce15952b55b8
|
||||
platform: linux/amd64
|
||||
- ref: registry.k8s.io/ingress-nginx/controller:v1.9.6@sha256:5fb823cc617cbfbee4b250ad5e059c23078ea63e9a7e6acb6d4d30e4456eb0be
|
||||
platform: linux/arm64
|
||||
- ref: registry.k8s.io/ingress-nginx/controller:v1.9.6@sha256:dcea8d021e15cf27f59249ee0cfd211559ef9eb60b10651c3af299499848cf8b
|
||||
platform: linux/arm
|
||||
- ref: registry.k8s.io/ingress-nginx/controller:v1.9.6@sha256:fc53a604eb2d17fa0cf7a3f266d052c2f32fb97209869057d6826d1815cf622d
|
||||
platform: linux/s390x
|
||||
paths:
|
||||
- /nginx-ingress-controller
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user