diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2020-01-22 12:17:20 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-01-22 12:19:53 +0100 |
| commit | 02754a8f9af246f440492295487282e55dc09cc0 (patch) | |
| tree | 728b59573a119421b2a5e2b89f965edc9ff6f93a /pkg | |
| parent | 8eda0b957e5b39c0c525e74f51d6b39ab8c5b1ac (diff) | |
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
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/cover/report.go | 2 | ||||
| -rw-r--r-- | pkg/report/linux.go | 2 | ||||
| -rw-r--r-- | pkg/report/netbsd.go | 2 | ||||
| -rw-r--r-- | pkg/report/openbsd.go | 2 | ||||
| -rw-r--r-- | pkg/symbolizer/nm.go | 28 | ||||
| -rw-r--r-- | pkg/symbolizer/nm_test.go | 2 |
6 files changed, 27 insertions, 11 deletions
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) } |
