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