diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2025-08-29 14:29:23 +0200 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2025-08-29 16:37:53 +0000 |
| commit | 807a3b61ca22f8988561c180eb47268ea6e244db (patch) | |
| tree | c29598ca28b49bca60e3961dc49d41ff7142cd8f /pkg/build | |
| parent | b0c32b0591eb98d9fd9a2590b140eb771cf86c46 (diff) | |
syz-cluster: consider global/static variable values
When determining whether a patch series is worth fuzzing, consider not
only the hashes of .text symbols, but also the hashes of the global
(static and non-static) variables.
As before, calculate the hashes during build and process them at the
beginning of the fuzz step.
Diffstat (limited to 'pkg/build')
| -rw-r--r-- | pkg/build/linux.go | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/pkg/build/linux.go b/pkg/build/linux.go index 6fc15733d..baa77dc62 100644 --- a/pkg/build/linux.go +++ b/pkg/build/linux.go @@ -10,7 +10,6 @@ import ( "debug/elf" "encoding/hex" "fmt" - "io" "os" "path" "path/filepath" @@ -260,55 +259,80 @@ func queryLinuxCompiler(kernelDir string) (string, error) { return string(result[1]), nil } -// ElfSymbolHashes returns a map of sha256 hashes per a symbol contained in the elf file. +type SectionHashes struct { + Text map[string]string `json:"text"` + Data map[string]string `json:"data"` // Merged .data and .rodata. +} + +// ElfSymbolHashes returns a map of sha256 hashes per section per symbol contained in the elf file. // It's best to call it on vmlinux.o since PCs in the binary code are not patched yet. -func ElfSymbolHashes(bin string) (map[string]string, error) { +func ElfSymbolHashes(bin string) (SectionHashes, error) { + result := SectionHashes{ + Text: make(map[string]string), + Data: make(map[string]string), + } + file, err := elf.Open(bin) if err != nil { - return nil, err + return SectionHashes{}, err } defer file.Close() symbols, err := file.Symbols() if err != nil { - return nil, err + return SectionHashes{}, err } - textSection := file.Section(".text") - if textSection == nil { - return nil, fmt.Errorf(".text section not found") + rawFile, err := os.Open(bin) + if err != nil { + return SectionHashes{}, err } + defer rawFile.Close() - sectionReader, ok := textSection.Open().(io.ReaderAt) - if !ok { - return nil, fmt.Errorf(".text section reader does not support ReadAt") + sections := make(map[elf.SectionIndex]*elf.Section) + for i, s := range file.Sections { + sections[elf.SectionIndex(i)] = s } - hashes := make(map[string]string) for _, s := range symbols { - if elf.ST_TYPE(s.Info) != elf.STT_FUNC || s.Size == 0 { + if s.Name == "" || s.Size == 0 || s.Section >= elf.SHN_LORESERVE { continue } - if s.Section >= elf.SHN_LORESERVE || int(s.Section) >= len(file.Sections) || - file.Sections[s.Section] != textSection { + symbolSection, ok := sections[s.Section] + if !ok || symbolSection.Type == elf.SHT_NOBITS { continue } - offset := s.Value - textSection.Addr - if offset+s.Size > textSection.Size { + var targetMap map[string]string + + symbolType := elf.ST_TYPE(s.Info) + sectionFlags := symbolSection.Flags + switch { + case symbolType == elf.STT_FUNC && (sectionFlags&elf.SHF_EXECINSTR) != 0: + targetMap = result.Text + case symbolType == elf.STT_OBJECT && (sectionFlags&elf.SHF_ALLOC) != 0 && + (sectionFlags&elf.SHF_EXECINSTR) == 0: + targetMap = result.Data + default: continue } - code := make([]byte, s.Size) - _, err := sectionReader.ReadAt(code, int64(offset)) + offset := s.Value - symbolSection.Addr + if offset+s.Size > symbolSection.Size { + continue + } + + data := make([]byte, s.Size) + _, err := rawFile.ReadAt(data, int64(symbolSection.Offset+offset)) if err != nil { continue } - hash := sha256.Sum256(code) - hashes[s.Name] = hex.EncodeToString(hash[:]) + + hash := sha256.Sum256(data) + targetMap[s.Name] = hex.EncodeToString(hash[:]) } - return hashes, nil + return result, nil } // elfBinarySignature calculates signature of an elf binary aiming at runtime behavior |
