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/symbolizer/nm.go | 28 ++++++++++++++++++++++------ pkg/symbolizer/nm_test.go | 2 +- 2 files changed, 23 insertions(+), 7 deletions(-) (limited to 'pkg/symbolizer') 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