Skip to content

Commit 44d1322

Browse files
committed
pkg/sca/sca.go: Implement getLdSoConfDLibPaths
This commit implements the machinery necessary for SCA to consider files under /etc/ld.so.conf.d/. The idea is that, if there is a configuration for ld.so.conf.d being installed by the package on hand, then the libraries shipped by the package should be listed as "provides" if they're installed inside the paths listed in the ld.so.conf.d configuration file. Signed-off-by: Sergio Durigan Junior <[email protected]>
1 parent 2c649a9 commit 44d1322

File tree

1 file changed

+105
-17
lines changed

1 file changed

+105
-17
lines changed

pkg/sca/sca.go

+105-17
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
package sca
1616

1717
import (
18+
"bufio"
1819
"bytes"
1920
"context"
2021
"debug/buildinfo"
2122
"debug/elf"
23+
"errors"
2224
"fmt"
2325
"io"
2426
"io/fs"
@@ -72,9 +74,10 @@ type SCAHandle interface {
7274
BaseDependencies() config.Dependencies
7375
}
7476

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
7881

7982
func isInDir(path string, dirs []string) bool {
8083
mydir := filepath.Dir(path)
@@ -86,7 +89,83 @@ func isInDir(path string, dirs []string) bool {
8689
return false
8790
}
8891

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 {
90169
log := clog.FromContext(ctx)
91170

92171
log.Info("scanning for commands...")
@@ -149,7 +228,7 @@ func findInterpreter(bin *elf.File) (string, error) {
149228

150229
// dereferenceCrossPackageSymlink attempts to dereference a symlink across multiple package
151230
// directories.
152-
func dereferenceCrossPackageSymlink(hdl SCAHandle, path string) (string, string, error) {
231+
func dereferenceCrossPackageSymlink(hdl SCAHandle, path string, extraLibDirs []string) (string, string, error) {
153232
targetPackageNames := hdl.RelativeNames()
154233

155234
pkgFS, err := hdl.Filesystem()
@@ -164,13 +243,15 @@ func dereferenceCrossPackageSymlink(hdl SCAHandle, path string) (string, string,
164243

165244
realPath = filepath.Base(realPath)
166245

246+
expandedLibDirs := append(libDirs, extraLibDirs...)
247+
167248
for _, pkgName := range targetPackageNames {
168249
baseFS, err := hdl.FilesystemForRelative(pkgName)
169250
if err != nil {
170251
return "", "", err
171252
}
172253

173-
for _, libDir := range libDirs {
254+
for _, libDir := range expandedLibDirs {
174255
testPath := filepath.Join(libDir, realPath)
175256

176257
if _, err := baseFS.Stat(testPath); err == nil {
@@ -182,13 +263,13 @@ func dereferenceCrossPackageSymlink(hdl SCAHandle, path string) (string, string,
182263
return "", "", nil
183264
}
184265

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 {
186267
log := clog.FromContext(ctx)
187268
if !strings.Contains(path, ".so") {
188269
return nil
189270
}
190271

191-
targetPkg, realPath, err := dereferenceCrossPackageSymlink(hdl, path)
272+
targetPkg, realPath, err := dereferenceCrossPackageSymlink(hdl, path, extraLibDirs)
192273
if err != nil {
193274
return nil
194275
}
@@ -233,7 +314,7 @@ func processSymlinkSo(ctx context.Context, hdl SCAHandle, path string, generated
233314
return nil
234315
}
235316

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 {
237318
log := clog.FromContext(ctx)
238319
log.Infof("scanning for shared object dependencies...")
239320

@@ -242,6 +323,8 @@ func generateSharedObjectNameDeps(ctx context.Context, hdl SCAHandle, generated
242323
return err
243324
}
244325

326+
expandedLibDirs := append(libDirs, extraLibDirs...)
327+
245328
if err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
246329
if err != nil {
247330
return err
@@ -258,7 +341,7 @@ func generateSharedObjectNameDeps(ctx context.Context, hdl SCAHandle, generated
258341
isLink := mode.Type()&fs.ModeSymlink == fs.ModeSymlink
259342

260343
if isLink {
261-
if err := processSymlinkSo(ctx, hdl, path, generated); err != nil {
344+
if err := processSymlinkSo(ctx, hdl, path, generated, extraLibDirs); err != nil {
262345
return err
263346
}
264347
}
@@ -349,7 +432,7 @@ func generateSharedObjectNameDeps(ctx context.Context, hdl SCAHandle, generated
349432
for _, soname := range sonames {
350433
libver := sonameLibver(soname)
351434

352-
if isInDir(path, libDirs) {
435+
if isInDir(path, expandedLibDirs) {
353436
generated.Provides = append(generated.Provides, fmt.Sprintf("so:%s=%s", soname, libver))
354437
} else {
355438
generated.Vendored = append(generated.Vendored, fmt.Sprintf("so:%s=%s", soname, libver))
@@ -395,7 +478,7 @@ var generateRuntimePkgConfigDeps = true
395478

396479
// generatePkgConfigDeps generates a list of provided pkg-config package names and versions,
397480
// 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 {
399482
log := clog.FromContext(ctx)
400483
log.Infof("scanning for pkg-config data...")
401484

@@ -485,7 +568,7 @@ func generatePkgConfigDeps(ctx context.Context, hdl SCAHandle, generated *config
485568

486569
// generatePythonDeps generates a python-3.X-base dependency for packages which ship
487570
// 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 {
489572
log := clog.FromContext(ctx)
490573
log.Infof("scanning for python modules...")
491574

@@ -549,7 +632,7 @@ func generatePythonDeps(ctx context.Context, hdl SCAHandle, generated *config.De
549632

550633
// generateRubyDeps generates a ruby-X.Y dependency for packages which ship
551634
// 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 {
553636
log := clog.FromContext(ctx)
554637
log.Infof("scanning for ruby gems...")
555638

@@ -596,7 +679,7 @@ func generateRubyDeps(ctx context.Context, hdl SCAHandle, generated *config.Depe
596679
}
597680

598681
// 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 {
600683
log := clog.FromContext(ctx)
601684
log.Infof("scanning for -doc package...")
602685
if !strings.HasSuffix(hdl.PackageName(), "-doc") {
@@ -720,7 +803,7 @@ func getShbang(fp io.Reader) (string, error) {
720803
return bin, nil
721804
}
722805

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 {
724807
log := clog.FromContext(ctx)
725808
log.Infof("scanning for shbang deps...")
726809

@@ -774,6 +857,11 @@ func generateShbangDeps(ctx context.Context, hdl SCAHandle, generated *config.De
774857
// Analyze runs the SCA analyzers on a given SCA handle, modifying the generated dependencies
775858
// set as needed.
776859
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+
777865
generators := []DependencyGenerator{
778866
generateSharedObjectNameDeps,
779867
generateCmdProviders,
@@ -785,7 +873,7 @@ func Analyze(ctx context.Context, hdl SCAHandle, generated *config.Dependencies)
785873
}
786874

787875
for _, gen := range generators {
788-
if err := gen(ctx, hdl, generated); err != nil {
876+
if err := gen(ctx, hdl, generated, extraLibDirs); err != nil {
789877
return err
790878
}
791879
}

0 commit comments

Comments
 (0)