15
15
package sca
16
16
17
17
import (
18
+ "bufio"
18
19
"bytes"
19
20
"context"
20
21
"debug/buildinfo"
21
22
"debug/elf"
23
+ "errors"
22
24
"fmt"
23
25
"io"
24
26
"io/fs"
@@ -72,9 +74,10 @@ type SCAHandle interface {
72
74
BaseDependencies () config.Dependencies
73
75
}
74
76
75
- // DependencyGenerator takes an SCAHandle and config.Dependencies pointer and returns
76
- // findings based on analysis.
77
- type DependencyGenerator func (context.Context , SCAHandle , * config.Dependencies ) error
77
+ // DependencyGenerator takes an SCAHandle, config.Dependencies pointer
78
+ // and a list of paths to be appended to libDirs and returns findings
79
+ // based on analysis.
80
+ type DependencyGenerator func (context.Context , SCAHandle , * config.Dependencies , []string ) error
78
81
79
82
func isInDir (path string , dirs []string ) bool {
80
83
mydir := filepath .Dir (path )
@@ -86,7 +89,83 @@ func isInDir(path string, dirs []string) bool {
86
89
return false
87
90
}
88
91
89
- func generateCmdProviders (ctx context.Context , hdl SCAHandle , generated * config.Dependencies ) error {
92
+ // getLdSoConfDLibPaths will iterate over the files being installed by
93
+ // the package and all its subpackages, and for each configuration
94
+ // file found under /etc/ld.so.conf.d/ it will parse the file and add
95
+ // its contents to a string vector. This vector will ultimately
96
+ // contain all extra paths that will be considered by ld when doing
97
+ // symbol resolution.
98
+ func getLdSoConfDLibPaths (ctx context.Context , hdl SCAHandle ) ([]string , error ) {
99
+ var extraLibPaths []string
100
+ targetPackageNames := hdl .RelativeNames ()
101
+
102
+ log := clog .FromContext (ctx )
103
+
104
+ log .Info ("scanning for ld.so.conf.d files..." )
105
+
106
+ for _ , pkgName := range targetPackageNames {
107
+ fsys , err := hdl .FilesystemForRelative (pkgName )
108
+ if err != nil {
109
+ return nil , err
110
+ }
111
+
112
+ if err := fs .WalkDir (fsys , "etc/ld.so.conf.d" , func (path string , d fs.DirEntry , err error ) error {
113
+ if err != nil {
114
+ if errors .Is (err , fs .ErrNotExist ) {
115
+ return fs .SkipAll
116
+ }
117
+ return err
118
+ }
119
+
120
+ // We're only interested in files whose suffix is ".conf"
121
+ if ! strings .HasSuffix (path , ".conf" ) {
122
+ return nil
123
+ }
124
+
125
+ fi , err := d .Info ()
126
+ if err != nil {
127
+ return err
128
+ }
129
+
130
+ if ! fi .Mode ().IsRegular () {
131
+ return nil
132
+ }
133
+
134
+ log .Infof (" found ld.so.conf.d file %s" , path )
135
+
136
+ fd , err := fsys .Open (path )
137
+ if err != nil {
138
+ return err
139
+ }
140
+ defer fd .Close ()
141
+
142
+ scanner := bufio .NewScanner (fd )
143
+ for scanner .Scan () {
144
+ line := scanner .Text ()
145
+ if line == "" || line [0 ] != '/' {
146
+ continue
147
+ }
148
+ // Strip the initial slash since
149
+ // libDirs paths need to be relative.
150
+ line = line [1 :]
151
+ log .Infof (" found extra lib path %s" , line )
152
+ extraLibPaths = append (extraLibPaths , line )
153
+ }
154
+
155
+ if err := scanner .Err (); err != nil {
156
+ return err
157
+ }
158
+
159
+ return nil
160
+ }); err != nil {
161
+ return nil , err
162
+ }
163
+ }
164
+
165
+ return extraLibPaths , nil
166
+ }
167
+
168
+ func generateCmdProviders (ctx context.Context , hdl SCAHandle , generated * config.Dependencies , extraLibDirs []string ) error {
90
169
log := clog .FromContext (ctx )
91
170
92
171
log .Info ("scanning for commands..." )
@@ -149,7 +228,7 @@ func findInterpreter(bin *elf.File) (string, error) {
149
228
150
229
// dereferenceCrossPackageSymlink attempts to dereference a symlink across multiple package
151
230
// directories.
152
- func dereferenceCrossPackageSymlink (hdl SCAHandle , path string ) (string , string , error ) {
231
+ func dereferenceCrossPackageSymlink (hdl SCAHandle , path string , extraLibDirs [] string ) (string , string , error ) {
153
232
targetPackageNames := hdl .RelativeNames ()
154
233
155
234
pkgFS , err := hdl .Filesystem ()
@@ -164,13 +243,15 @@ func dereferenceCrossPackageSymlink(hdl SCAHandle, path string) (string, string,
164
243
165
244
realPath = filepath .Base (realPath )
166
245
246
+ expandedLibDirs := append (libDirs , extraLibDirs ... )
247
+
167
248
for _ , pkgName := range targetPackageNames {
168
249
baseFS , err := hdl .FilesystemForRelative (pkgName )
169
250
if err != nil {
170
251
return "" , "" , err
171
252
}
172
253
173
- for _ , libDir := range libDirs {
254
+ for _ , libDir := range expandedLibDirs {
174
255
testPath := filepath .Join (libDir , realPath )
175
256
176
257
if _ , err := baseFS .Stat (testPath ); err == nil {
@@ -182,13 +263,13 @@ func dereferenceCrossPackageSymlink(hdl SCAHandle, path string) (string, string,
182
263
return "" , "" , nil
183
264
}
184
265
185
- func processSymlinkSo (ctx context.Context , hdl SCAHandle , path string , generated * config.Dependencies ) error {
266
+ func processSymlinkSo (ctx context.Context , hdl SCAHandle , path string , generated * config.Dependencies , extraLibDirs [] string ) error {
186
267
log := clog .FromContext (ctx )
187
268
if ! strings .Contains (path , ".so" ) {
188
269
return nil
189
270
}
190
271
191
- targetPkg , realPath , err := dereferenceCrossPackageSymlink (hdl , path )
272
+ targetPkg , realPath , err := dereferenceCrossPackageSymlink (hdl , path , extraLibDirs )
192
273
if err != nil {
193
274
return nil
194
275
}
@@ -233,7 +314,7 @@ func processSymlinkSo(ctx context.Context, hdl SCAHandle, path string, generated
233
314
return nil
234
315
}
235
316
236
- func generateSharedObjectNameDeps (ctx context.Context , hdl SCAHandle , generated * config.Dependencies ) error {
317
+ func generateSharedObjectNameDeps (ctx context.Context , hdl SCAHandle , generated * config.Dependencies , extraLibDirs [] string ) error {
237
318
log := clog .FromContext (ctx )
238
319
log .Infof ("scanning for shared object dependencies..." )
239
320
@@ -242,6 +323,8 @@ func generateSharedObjectNameDeps(ctx context.Context, hdl SCAHandle, generated
242
323
return err
243
324
}
244
325
326
+ expandedLibDirs := append (libDirs , extraLibDirs ... )
327
+
245
328
if err := fs .WalkDir (fsys , "." , func (path string , d fs.DirEntry , err error ) error {
246
329
if err != nil {
247
330
return err
@@ -258,7 +341,7 @@ func generateSharedObjectNameDeps(ctx context.Context, hdl SCAHandle, generated
258
341
isLink := mode .Type ()& fs .ModeSymlink == fs .ModeSymlink
259
342
260
343
if isLink {
261
- if err := processSymlinkSo (ctx , hdl , path , generated ); err != nil {
344
+ if err := processSymlinkSo (ctx , hdl , path , generated , extraLibDirs ); err != nil {
262
345
return err
263
346
}
264
347
}
@@ -349,7 +432,7 @@ func generateSharedObjectNameDeps(ctx context.Context, hdl SCAHandle, generated
349
432
for _ , soname := range sonames {
350
433
libver := sonameLibver (soname )
351
434
352
- if isInDir (path , libDirs ) {
435
+ if isInDir (path , expandedLibDirs ) {
353
436
generated .Provides = append (generated .Provides , fmt .Sprintf ("so:%s=%s" , soname , libver ))
354
437
} else {
355
438
generated .Vendored = append (generated .Vendored , fmt .Sprintf ("so:%s=%s" , soname , libver ))
@@ -395,7 +478,7 @@ var generateRuntimePkgConfigDeps = true
395
478
396
479
// generatePkgConfigDeps generates a list of provided pkg-config package names and versions,
397
480
// as well as dependency relationships.
398
- func generatePkgConfigDeps (ctx context.Context , hdl SCAHandle , generated * config.Dependencies ) error {
481
+ func generatePkgConfigDeps (ctx context.Context , hdl SCAHandle , generated * config.Dependencies , extraLibDirs [] string ) error {
399
482
log := clog .FromContext (ctx )
400
483
log .Infof ("scanning for pkg-config data..." )
401
484
@@ -485,7 +568,7 @@ func generatePkgConfigDeps(ctx context.Context, hdl SCAHandle, generated *config
485
568
486
569
// generatePythonDeps generates a python-3.X-base dependency for packages which ship
487
570
// Python modules.
488
- func generatePythonDeps (ctx context.Context , hdl SCAHandle , generated * config.Dependencies ) error {
571
+ func generatePythonDeps (ctx context.Context , hdl SCAHandle , generated * config.Dependencies , extraLibDirs [] string ) error {
489
572
log := clog .FromContext (ctx )
490
573
log .Infof ("scanning for python modules..." )
491
574
@@ -549,7 +632,7 @@ func generatePythonDeps(ctx context.Context, hdl SCAHandle, generated *config.De
549
632
550
633
// generateRubyDeps generates a ruby-X.Y dependency for packages which ship
551
634
// Ruby gems.
552
- func generateRubyDeps (ctx context.Context , hdl SCAHandle , generated * config.Dependencies ) error {
635
+ func generateRubyDeps (ctx context.Context , hdl SCAHandle , generated * config.Dependencies , extraLibDirs [] string ) error {
553
636
log := clog .FromContext (ctx )
554
637
log .Infof ("scanning for ruby gems..." )
555
638
@@ -596,7 +679,7 @@ func generateRubyDeps(ctx context.Context, hdl SCAHandle, generated *config.Depe
596
679
}
597
680
598
681
// For a documentation package add a dependency on man-db and / or texinfo as appropriate
599
- func generateDocDeps (ctx context.Context , hdl SCAHandle , generated * config.Dependencies ) error {
682
+ func generateDocDeps (ctx context.Context , hdl SCAHandle , generated * config.Dependencies , extraLibDirs [] string ) error {
600
683
log := clog .FromContext (ctx )
601
684
log .Infof ("scanning for -doc package..." )
602
685
if ! strings .HasSuffix (hdl .PackageName (), "-doc" ) {
@@ -720,7 +803,7 @@ func getShbang(fp io.Reader) (string, error) {
720
803
return bin , nil
721
804
}
722
805
723
- func generateShbangDeps (ctx context.Context , hdl SCAHandle , generated * config.Dependencies ) error {
806
+ func generateShbangDeps (ctx context.Context , hdl SCAHandle , generated * config.Dependencies , extraLibDirs [] string ) error {
724
807
log := clog .FromContext (ctx )
725
808
log .Infof ("scanning for shbang deps..." )
726
809
@@ -774,6 +857,11 @@ func generateShbangDeps(ctx context.Context, hdl SCAHandle, generated *config.De
774
857
// Analyze runs the SCA analyzers on a given SCA handle, modifying the generated dependencies
775
858
// set as needed.
776
859
func Analyze (ctx context.Context , hdl SCAHandle , generated * config.Dependencies ) error {
860
+ extraLibDirs , err := getLdSoConfDLibPaths (ctx , hdl )
861
+ if err != nil {
862
+ return err
863
+ }
864
+
777
865
generators := []DependencyGenerator {
778
866
generateSharedObjectNameDeps ,
779
867
generateCmdProviders ,
@@ -785,7 +873,7 @@ func Analyze(ctx context.Context, hdl SCAHandle, generated *config.Dependencies)
785
873
}
786
874
787
875
for _ , gen := range generators {
788
- if err := gen (ctx , hdl , generated ); err != nil {
876
+ if err := gen (ctx , hdl , generated , extraLibDirs ); err != nil {
789
877
return err
790
878
}
791
879
}
0 commit comments