Detect ELF security features (#2443)

* add detection of ELF security features

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix linting

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* update json schema with file executable data

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* update expected fixure when no tty present

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* more detailed differ

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* use json differ

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix tests

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* remove json schema addition

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* regenerate json schema

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix mimtype set ref

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Alex Goodman
2024-02-02 16:51:18 +00:00
committed by GitHub
parent 3da679066e
commit 3023a5a7bc
39 changed files with 3377 additions and 46 deletions
+16
View File
@@ -221,6 +221,22 @@ func Test_encodeDecodeFileMetadata(t *testing.T) {
},
},
},
Executables: map[file.Coordinates]file.Executable{
c: {
Format: file.ELF,
SecurityFeatures: &file.ELFSecurityFeatures{
SymbolTableStripped: false,
StackCanary: boolRef(true),
NoExecutable: false,
RelocationReadOnly: "partial",
PositionIndependentExecutable: false,
DynamicSharedObject: false,
LlvmSafeStack: boolRef(false),
LlvmControlFlowIntegrity: boolRef(true),
ClangFortifySource: boolRef(true),
},
},
},
LinuxDistribution: &linux.Release{
PrettyName: "some os",
Name: "os",
+7 -6
View File
@@ -6,12 +6,13 @@ import (
)
type File struct {
ID string `json:"id"`
Location file.Coordinates `json:"location"`
Metadata *FileMetadataEntry `json:"metadata,omitempty"`
Contents string `json:"contents,omitempty"`
Digests []file.Digest `json:"digests,omitempty"`
Licenses []FileLicense `json:"licenses,omitempty"`
ID string `json:"id"`
Location file.Coordinates `json:"location"`
Metadata *FileMetadataEntry `json:"metadata,omitempty"`
Contents string `json:"contents,omitempty"`
Digests []file.Digest `json:"digests,omitempty"`
Licenses []FileLicense `json:"licenses,omitempty"`
Executable *file.Executable `json:"executable,omitempty"`
}
type FileMetadataEntry struct {
+12 -6
View File
@@ -119,13 +119,19 @@ func toFile(s sbom.SBOM) []model.File {
})
}
var executable *file.Executable
if exec, exists := artifacts.Executables[coordinates]; exists {
executable = &exec
}
results = append(results, model.File{
ID: string(coordinates.ID()),
Location: coordinates,
Metadata: toFileMetadataEntry(coordinates, metadata),
Digests: digests,
Contents: contents,
Licenses: licenses,
ID: string(coordinates.ID()),
Location: coordinates,
Metadata: toFileMetadataEntry(coordinates, metadata),
Digests: digests,
Contents: contents,
Licenses: licenses,
Executable: executable,
})
}
+6
View File
@@ -35,6 +35,7 @@ func toSyftModel(doc model.Document) *sbom.SBOM {
FileDigests: fileArtifacts.FileDigests,
FileContents: fileArtifacts.FileContents,
FileLicenses: fileArtifacts.FileLicenses,
Executables: fileArtifacts.Executables,
LinuxDistribution: toSyftLinuxRelease(doc.Distro),
},
Source: *toSyftSourceData(doc.Source),
@@ -69,6 +70,7 @@ func toSyftFiles(files []model.File) sbom.Artifacts {
FileDigests: make(map[file.Coordinates][]file.Digest),
FileContents: make(map[file.Coordinates]string),
FileLicenses: make(map[file.Coordinates][]file.License),
Executables: make(map[file.Coordinates]file.Executable),
}
for _, f := range files {
@@ -124,6 +126,10 @@ func toSyftFiles(files []model.File) sbom.Artifacts {
LicenseEvidence: evidence,
})
}
if f.Executable != nil {
ret.Executables[coord] = *f.Executable
}
}
return ret
+38 -1
View File
@@ -230,6 +230,7 @@ func Test_toSyftFiles(t *testing.T) {
want: sbom.Artifacts{
FileMetadata: map[file.Coordinates]file.Metadata{},
FileDigests: map[file.Coordinates][]file.Digest{},
Executables: map[file.Coordinates]file.Executable{},
},
},
{
@@ -245,6 +246,7 @@ func Test_toSyftFiles(t *testing.T) {
Value: "123",
},
},
Executable: nil,
},
},
want: sbom.Artifacts{
@@ -257,6 +259,7 @@ func Test_toSyftFiles(t *testing.T) {
},
},
},
Executables: map[file.Coordinates]file.Executable{},
},
},
{
@@ -280,6 +283,20 @@ func Test_toSyftFiles(t *testing.T) {
Value: "123",
},
},
Executable: &file.Executable{
Format: file.ELF,
SecurityFeatures: &file.ELFSecurityFeatures{
SymbolTableStripped: false,
StackCanary: boolRef(true),
NoExecutable: false,
RelocationReadOnly: "partial",
PositionIndependentExecutable: false,
DynamicSharedObject: false,
LlvmSafeStack: boolRef(false),
LlvmControlFlowIntegrity: boolRef(true),
ClangFortifySource: boolRef(true),
},
},
},
},
want: sbom.Artifacts{
@@ -306,6 +323,22 @@ func Test_toSyftFiles(t *testing.T) {
},
},
},
Executables: map[file.Coordinates]file.Executable{
coord: {
Format: file.ELF,
SecurityFeatures: &file.ELFSecurityFeatures{
SymbolTableStripped: false,
StackCanary: boolRef(true),
NoExecutable: false,
RelocationReadOnly: "partial",
PositionIndependentExecutable: false,
DynamicSharedObject: false,
LlvmSafeStack: boolRef(false),
LlvmControlFlowIntegrity: boolRef(true),
ClangFortifySource: boolRef(true),
},
},
},
},
},
}
@@ -318,7 +351,11 @@ func Test_toSyftFiles(t *testing.T) {
}
}
func Test_toSyfRelationship(t *testing.T) {
func boolRef(b bool) *bool {
return &b
}
func Test_toSyftRelationship(t *testing.T) {
packageWithId := func(id string) *pkg.Package {
p := &pkg.Package{}
p.OverrideID(artifact.ID(id))