github.com/anchore/syft@v1.4.2-0.20240516191711-1bec1fc5d397/syft/file/cataloger/executable/elf_test.go (about) 1 package executable 2 3 import ( 4 "debug/elf" 5 "os" 6 "path/filepath" 7 "testing" 8 9 "github.com/google/go-cmp/cmp" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 13 "github.com/anchore/syft/syft/file" 14 "github.com/anchore/syft/syft/internal/unionreader" 15 ) 16 17 func Test_findELFSecurityFeatures(t *testing.T) { 18 19 readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader { 20 t.Helper() 21 f, err := os.Open(filepath.Join("test-fixtures/elf", fixture)) 22 require.NoError(t, err) 23 return f 24 } 25 26 tests := []struct { 27 name string 28 fixture string 29 want *file.ELFSecurityFeatures 30 wantStripped bool 31 }{ 32 { 33 name: "detect canary", 34 fixture: "bin/with_canary", 35 want: &file.ELFSecurityFeatures{ 36 StackCanary: boolRef(true), // ! important ! 37 RelocationReadOnly: file.RelocationReadOnlyNone, 38 LlvmSafeStack: boolRef(false), 39 LlvmControlFlowIntegrity: boolRef(false), 40 ClangFortifySource: boolRef(false), 41 }, 42 }, 43 { 44 name: "detect nx", 45 fixture: "bin/with_nx", 46 want: &file.ELFSecurityFeatures{ 47 StackCanary: boolRef(false), 48 NoExecutable: true, // ! important ! 49 RelocationReadOnly: file.RelocationReadOnlyNone, 50 LlvmSafeStack: boolRef(false), 51 LlvmControlFlowIntegrity: boolRef(false), 52 ClangFortifySource: boolRef(false), 53 }, 54 }, 55 { 56 name: "detect relro", 57 fixture: "bin/with_relro", 58 want: &file.ELFSecurityFeatures{ 59 StackCanary: boolRef(false), 60 RelocationReadOnly: file.RelocationReadOnlyFull, // ! important ! 61 LlvmSafeStack: boolRef(false), 62 LlvmControlFlowIntegrity: boolRef(false), 63 ClangFortifySource: boolRef(false), 64 }, 65 }, 66 { 67 name: "detect partial relro", 68 fixture: "bin/with_partial_relro", 69 want: &file.ELFSecurityFeatures{ 70 StackCanary: boolRef(false), 71 RelocationReadOnly: file.RelocationReadOnlyPartial, // ! important ! 72 LlvmSafeStack: boolRef(false), 73 LlvmControlFlowIntegrity: boolRef(false), 74 ClangFortifySource: boolRef(false), 75 }, 76 }, 77 { 78 name: "detect pie", 79 fixture: "bin/with_pie", 80 want: &file.ELFSecurityFeatures{ 81 StackCanary: boolRef(false), 82 RelocationReadOnly: file.RelocationReadOnlyNone, 83 PositionIndependentExecutable: true, // ! important ! 84 DynamicSharedObject: true, // ! important ! 85 LlvmSafeStack: boolRef(false), 86 LlvmControlFlowIntegrity: boolRef(false), 87 ClangFortifySource: boolRef(false), 88 }, 89 }, 90 { 91 name: "detect dso", 92 fixture: "bin/pie_false_positive.so", 93 want: &file.ELFSecurityFeatures{ 94 StackCanary: boolRef(false), 95 RelocationReadOnly: file.RelocationReadOnlyPartial, 96 NoExecutable: true, 97 PositionIndependentExecutable: false, // ! important ! 98 DynamicSharedObject: true, // ! important ! 99 LlvmSafeStack: boolRef(false), 100 LlvmControlFlowIntegrity: boolRef(false), 101 ClangFortifySource: boolRef(false), 102 }, 103 }, 104 { 105 name: "detect safestack", 106 fixture: "bin/with_safestack", 107 want: &file.ELFSecurityFeatures{ 108 NoExecutable: true, 109 StackCanary: boolRef(false), 110 RelocationReadOnly: file.RelocationReadOnlyPartial, 111 PositionIndependentExecutable: false, 112 DynamicSharedObject: false, 113 LlvmSafeStack: boolRef(true), // ! important ! 114 LlvmControlFlowIntegrity: boolRef(false), 115 ClangFortifySource: boolRef(false), 116 }, 117 }, 118 { 119 name: "detect cfi", 120 fixture: "bin/with_cfi", 121 want: &file.ELFSecurityFeatures{ 122 NoExecutable: true, 123 StackCanary: boolRef(false), 124 RelocationReadOnly: file.RelocationReadOnlyPartial, 125 PositionIndependentExecutable: false, 126 DynamicSharedObject: false, 127 LlvmSafeStack: boolRef(false), 128 LlvmControlFlowIntegrity: boolRef(true), // ! important ! 129 ClangFortifySource: boolRef(false), 130 }, 131 }, 132 { 133 name: "detect fortify", 134 fixture: "bin/with_fortify", 135 want: &file.ELFSecurityFeatures{ 136 NoExecutable: true, 137 StackCanary: boolRef(false), 138 RelocationReadOnly: file.RelocationReadOnlyPartial, 139 PositionIndependentExecutable: false, 140 DynamicSharedObject: false, 141 LlvmSafeStack: boolRef(false), 142 LlvmControlFlowIntegrity: boolRef(false), 143 ClangFortifySource: boolRef(true), // ! important ! 144 }, 145 }, 146 } 147 for _, tt := range tests { 148 t.Run(tt.name, func(t *testing.T) { 149 f, err := elf.NewFile(readerForFixture(t, tt.fixture)) 150 require.NoError(t, err) 151 152 got := findELFSecurityFeatures(f) 153 154 if d := cmp.Diff(tt.want, got); d != "" { 155 t.Errorf("findELFSecurityFeatures() mismatch (-want +got):\n%s", d) 156 } 157 }) 158 } 159 } 160 161 func Test_elfHasEntrypoint(t *testing.T) { 162 163 readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader { 164 t.Helper() 165 f, err := os.Open(filepath.Join("test-fixtures/shared-info", fixture)) 166 require.NoError(t, err) 167 return f 168 } 169 170 tests := []struct { 171 name string 172 fixture string 173 want bool 174 }{ 175 { 176 name: "shared lib", 177 fixture: "bin/libhello.so", 178 want: false, 179 }, 180 { 181 name: "application", 182 fixture: "bin/hello_linux", 183 want: true, 184 }, 185 } 186 for _, tt := range tests { 187 t.Run(tt.name, func(t *testing.T) { 188 f, err := elf.NewFile(readerForFixture(t, tt.fixture)) 189 require.NoError(t, err) 190 assert.Equal(t, tt.want, elfHasEntrypoint(f)) 191 }) 192 } 193 } 194 195 func Test_elfHasExports(t *testing.T) { 196 readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader { 197 t.Helper() 198 f, err := os.Open(filepath.Join("test-fixtures/shared-info", fixture)) 199 require.NoError(t, err) 200 return f 201 } 202 203 tests := []struct { 204 name string 205 fixture string 206 want bool 207 }{ 208 { 209 name: "shared lib", 210 fixture: "bin/libhello.so", 211 want: true, 212 }, 213 { 214 name: "application", 215 fixture: "bin/hello_linux", 216 want: false, 217 }, 218 } 219 for _, tt := range tests { 220 t.Run(tt.name, func(t *testing.T) { 221 f, err := elf.NewFile(readerForFixture(t, tt.fixture)) 222 require.NoError(t, err) 223 assert.Equal(t, tt.want, elfHasExports(f)) 224 }) 225 } 226 }