From 02754a8f9af246f440492295487282e55dc09cc0 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Wed, 22 Jan 2020 12:17:20 +0100 Subject: tools/syz-check: check netlink policy descriptions Overall idea of netlink checking. Currnetly we check netlink policies for common detectable mistakes. First, we detect what looks like a netlink policy in our descriptions (these are structs/unions only with nlattr/nlnext/nlnetw fields). Then we find corresponding symbols (offset/size) in vmlinux using nm. Then we read elf headers and locate where these symbols are in the rodata section. Then read in the symbol data, which is an array of nla_policy structs. These structs allow to easily figure out type/size of attributes. Finally we compare our descriptions with the kernel policy description. Update #590 --- pkg/cover/report.go | 2 +- pkg/report/linux.go | 2 +- pkg/report/netbsd.go | 2 +- pkg/report/openbsd.go | 2 +- pkg/symbolizer/nm.go | 28 ++++++++++++++++++++++------ pkg/symbolizer/nm_test.go | 2 +- 6 files changed, 27 insertions(+), 11 deletions(-) (limited to 'pkg') diff --git a/pkg/cover/report.go b/pkg/cover/report.go index b92c5e982..d66d730b3 100644 --- a/pkg/cover/report.go +++ b/pkg/cover/report.go @@ -313,7 +313,7 @@ func (rg *ReportGenerator) findSymbol(pc uint64) uint64 { } func readSymbols(obj string) ([]symbol, error) { - raw, err := symbolizer.ReadSymbols(obj) + raw, err := symbolizer.ReadTextSymbols(obj) if err != nil { return nil, fmt.Errorf("failed to run nm on %v: %v", obj, err) } diff --git a/pkg/report/linux.go b/pkg/report/linux.go index ac9a78ee5..968bc1692 100644 --- a/pkg/report/linux.go +++ b/pkg/report/linux.go @@ -38,7 +38,7 @@ func ctorLinux(cfg *config) (Reporter, []string, error) { if cfg.kernelObj != "" { vmlinux = filepath.Join(cfg.kernelObj, cfg.target.KernelObject) var err error - symbols, err = symbolizer.ReadSymbols(vmlinux) + symbols, err = symbolizer.ReadTextSymbols(vmlinux) if err != nil { return nil, nil, err } diff --git a/pkg/report/netbsd.go b/pkg/report/netbsd.go index 036e9dc9c..69287ed58 100644 --- a/pkg/report/netbsd.go +++ b/pkg/report/netbsd.go @@ -37,7 +37,7 @@ func ctorNetbsd(cfg *config) (Reporter, []string, error) { if cfg.kernelObj != "" { kernelObject = filepath.Join(cfg.kernelObj, cfg.target.KernelObject) var err error - symbols, err = symbolizer.ReadSymbols(kernelObject) + symbols, err = symbolizer.ReadTextSymbols(kernelObject) if err != nil { return nil, nil, err } diff --git a/pkg/report/openbsd.go b/pkg/report/openbsd.go index 9cf1a593b..99e49c81c 100644 --- a/pkg/report/openbsd.go +++ b/pkg/report/openbsd.go @@ -36,7 +36,7 @@ func ctorOpenbsd(cfg *config) (Reporter, []string, error) { if cfg.kernelObj != "" { kernelObject = filepath.Join(cfg.kernelObj, cfg.target.KernelObject) var err error - symbols, err = symbolizer.ReadSymbols(kernelObject) + symbols, err = symbolizer.ReadTextSymbols(kernelObject) if err != nil { return nil, nil, err } diff --git a/pkg/symbolizer/nm.go b/pkg/symbolizer/nm.go index caa246629..09baf8119 100644 --- a/pkg/symbolizer/nm.go +++ b/pkg/symbolizer/nm.go @@ -16,8 +16,21 @@ type Symbol struct { Size int } -// ReadSymbols returns list of text symbols in the binary bin. -func ReadSymbols(bin string) (map[string][]Symbol, error) { +// ReadTextSymbols returns list of text symbols in the binary bin. +func ReadTextSymbols(bin string) (map[string][]Symbol, error) { + return read(bin, "t", "T") +} + +// ReadRodataSymbols returns list of rodata symbols in the binary bin. +func ReadRodataSymbols(bin string) (map[string][]Symbol, error) { + return read(bin, "r", "R") +} + +func read(bin string, types ...string) (map[string][]Symbol, error) { + if len(types) != 2 || len(types[0]) != 1 || len(types[1]) != 1 { + // We assume these things below. + panic("bad types") + } cmd := osutil.Command("nm", "-Ptx", bin) stdout, err := cmd.StdoutPipe() if err != nil { @@ -30,11 +43,14 @@ func ReadSymbols(bin string) (map[string][]Symbol, error) { defer cmd.Wait() symbols := make(map[string][]Symbol) s := bufio.NewScanner(stdout) - text := [][]byte{[]byte(" t "), []byte(" T ")} + var tt [][]byte + for _, typ := range types { + tt = append(tt, []byte(" "+typ+" ")) + } for s.Scan() { // A line looks as: "snb_uncore_msr_enable_box t ffffffff8104db90 0000000000000059" ln := s.Bytes() - if !bytes.Contains(ln, text[0]) && !bytes.Contains(ln, text[1]) { + if !bytes.Contains(ln, tt[0]) && !bytes.Contains(ln, tt[1]) { continue } @@ -42,11 +58,11 @@ func ReadSymbols(bin string) (map[string][]Symbol, error) { if sp1 == -1 { continue } - if !bytes.HasPrefix(ln[sp1:], text[0]) && !bytes.HasPrefix(ln[sp1:], text[1]) { + if !bytes.HasPrefix(ln[sp1:], tt[0]) && !bytes.HasPrefix(ln[sp1:], tt[1]) { continue } - sp2 := sp1 + len(text[0]) + sp2 := sp1 + len(tt[0]) sp3 := bytes.IndexByte(ln[sp2:], ' ') if sp3 == -1 { continue diff --git a/pkg/symbolizer/nm_test.go b/pkg/symbolizer/nm_test.go index 44a02f3cc..6061608ec 100644 --- a/pkg/symbolizer/nm_test.go +++ b/pkg/symbolizer/nm_test.go @@ -8,7 +8,7 @@ import ( ) func TestSymbols(t *testing.T) { - symbols, err := ReadSymbols("testdata/nm.test.out") + symbols, err := ReadTextSymbols("testdata/nm.test.out") if err != nil { t.Fatalf("failed to read symbols: %v", err) } -- cgit mrf-deployment