mirror of
https://github.com/reactos/syzkaller.git
synced 2025-02-13 08:06:14 +00:00
support kmemleak
If you set "leak":true in manager config, it will do leak checking. It's quite slow, though. Also there seems to be false positives and/or non-reproducible leaks.
This commit is contained in:
parent
d823a9221a
commit
cf2089138e
@ -20,6 +20,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/google/syzkaller/cover"
|
||||
@ -39,6 +40,7 @@ var (
|
||||
flagNoCover = flag.Bool("nocover", false, "disable coverage collection/handling")
|
||||
flagDropPrivs = flag.Bool("dropprivs", true, "impersonate into nobody")
|
||||
flagProcs = flag.Int("procs", 1, "number of parallel test processes")
|
||||
flagLeak = flag.Bool("leak", false, "detect memory leaks")
|
||||
flagV = flag.Int("v", 0, "verbosity")
|
||||
)
|
||||
|
||||
@ -82,6 +84,8 @@ var (
|
||||
statExecTriage uint64
|
||||
statExecMinimize uint64
|
||||
statNewInput uint64
|
||||
|
||||
allTriaged uint32
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -116,6 +120,8 @@ func main() {
|
||||
}
|
||||
ct := prog.BuildChoiceTable(r.Prios, calls)
|
||||
|
||||
kmemleakInit()
|
||||
|
||||
flags := ipc.FlagThreaded | ipc.FlagCollide
|
||||
if *flagStrace {
|
||||
flags |= ipc.FlagStrace
|
||||
@ -141,7 +147,7 @@ func main() {
|
||||
|
||||
pid := pid
|
||||
go func() {
|
||||
rs := rand.NewSource(time.Now().UnixNano())
|
||||
rs := rand.NewSource(time.Now().UnixNano() + int64(pid)*1e12)
|
||||
rnd := rand.New(rs)
|
||||
|
||||
for i := 0; ; i++ {
|
||||
@ -245,6 +251,14 @@ func main() {
|
||||
triageMu.Unlock()
|
||||
}
|
||||
}
|
||||
if len(r.Candidates) == 0 {
|
||||
if atomic.LoadUint32(&allTriaged) == 0 {
|
||||
if *flagLeak {
|
||||
kmemleakScan(false)
|
||||
}
|
||||
atomic.StoreUint32(&allTriaged, 1)
|
||||
}
|
||||
}
|
||||
if len(r.NewInputs) == 0 && len(r.Candidates) == 0 {
|
||||
lastPoll = time.Now()
|
||||
}
|
||||
@ -425,6 +439,12 @@ func execute1(pid int, env *ipc.Env, p *prog.Prog, stat *uint64) []cover.Cover {
|
||||
retry:
|
||||
atomic.AddUint64(stat, 1)
|
||||
output, strace, rawCover, failed, hanged, err := env.Exec(p)
|
||||
if failed {
|
||||
// BUG in output should be recognized by manager.
|
||||
logf(0, "BUG: executor-detected bug:\n%s", output)
|
||||
// Don't return any cover so that the input is not added to corpus.
|
||||
return make([]cover.Cover, len(p.Calls))
|
||||
}
|
||||
if err != nil {
|
||||
if try > 10 {
|
||||
panic(err)
|
||||
@ -484,9 +504,55 @@ func (g *Gate) Leave(idx int) {
|
||||
if !g.busy[idx] {
|
||||
panic("broken gate")
|
||||
}
|
||||
if idx == 0 && *flagLeak && atomic.LoadUint32(&allTriaged) != 0 {
|
||||
// Scan for leaks once in a while (it is damn slow).
|
||||
kmemleakScan(true)
|
||||
}
|
||||
g.busy[idx] = false
|
||||
if idx == g.pos {
|
||||
g.cv.Broadcast()
|
||||
}
|
||||
g.cv.L.Unlock()
|
||||
}
|
||||
|
||||
func kmemleakInit() {
|
||||
fd, err := syscall.Open("/sys/kernel/debug/kmemleak", syscall.O_RDWR, 0)
|
||||
if err != nil {
|
||||
if !*flagLeak {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
defer syscall.Close(fd)
|
||||
if _, err := syscall.Write(fd, []byte("scan=off")); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
var kmemleakBuf []byte
|
||||
|
||||
func kmemleakScan(report bool) {
|
||||
fd, err := syscall.Open("/sys/kernel/debug/kmemleak", syscall.O_RDWR, 0)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer syscall.Close(fd)
|
||||
if _, err := syscall.Write(fd, []byte("scan")); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if report {
|
||||
if kmemleakBuf == nil {
|
||||
kmemleakBuf = make([]byte, 128<<10)
|
||||
}
|
||||
n, err := syscall.Read(fd, kmemleakBuf)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if n != 0 {
|
||||
// BUG in output should be recognized by manager.
|
||||
logf(0, "BUG: memory leak:\n%s\n", kmemleakBuf[:n])
|
||||
}
|
||||
}
|
||||
if _, err := syscall.Write(fd, []byte("clear")); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ type Config struct {
|
||||
Procs int // number of parallel processes inside of every VM
|
||||
Port int
|
||||
Nocover bool
|
||||
Leak bool // do memory leak checking
|
||||
Params map[string]interface{}
|
||||
Enable_Syscalls []string
|
||||
Disable_Syscalls []string
|
||||
@ -64,6 +65,7 @@ func main() {
|
||||
Params: params,
|
||||
EnabledSyscalls: enabledSyscalls,
|
||||
NoCover: cfg.Nocover,
|
||||
Leak: cfg.Leak,
|
||||
Procs: cfg.Procs,
|
||||
}
|
||||
|
||||
|
@ -384,8 +384,8 @@ var Calls = []*Call{
|
||||
&Call{ID: 379, Name: "modify_ldt$write", CallName: "modify_ldt", Args: []Type{ConstType{TypeCommon: TypeCommon{TypeName: "func", IsOptional: false}, TypeSize: 0, Val: uintptr(1)}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "user_desc", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "entry", IsOptional: false}, TypeSize: 4}, VmaType{TypeCommon: TypeCommon{TypeName: "base", IsOptional: false}}, LenType{TypeCommon: TypeCommon{TypeName: "limit", IsOptional: false}, Buf: "base", TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 1}, ConstType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 1, Val: uintptr(0)}, ConstType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 2, Val: uintptr(0)}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "buf", TypeSize: 0}}},
|
||||
&Call{ID: 380, Name: "modify_ldt$read_default", CallName: "modify_ldt", Args: []Type{ConstType{TypeCommon: TypeCommon{TypeName: "func", IsOptional: false}, TypeSize: 0, Val: uintptr(2)}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "buf", TypeSize: 0}}},
|
||||
&Call{ID: 381, Name: "modify_ldt$write2", CallName: "modify_ldt", Args: []Type{ConstType{TypeCommon: TypeCommon{TypeName: "func", IsOptional: false}, TypeSize: 0, Val: uintptr(17)}, PtrType{TypeCommon: TypeCommon{TypeName: "buf", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "user_desc", IsOptional: false}, Fields: []Type{IntType{TypeCommon: TypeCommon{TypeName: "entry", IsOptional: false}, TypeSize: 4}, VmaType{TypeCommon: TypeCommon{TypeName: "base", IsOptional: false}}, LenType{TypeCommon: TypeCommon{TypeName: "limit", IsOptional: false}, Buf: "base", TypeSize: 4}, IntType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 1}, ConstType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 1, Val: uintptr(0)}, ConstType{TypeCommon: TypeCommon{TypeName: "pad", IsOptional: false}, TypeSize: 2, Val: uintptr(0)}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "buf", TypeSize: 0}}},
|
||||
&Call{ID: 382, Name: "process_vm_readv", CallName: "process_vm_readv", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "loc_vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_out", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "loc_vlen", IsOptional: false}, Buf: "vec", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "rem_vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_out", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "rem_vlen", IsOptional: false}, Buf: "vec", TypeSize: 0}, ConstType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Val: uintptr(0)}}},
|
||||
&Call{ID: 383, Name: "process_vm_writev", CallName: "process_vm_writev", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "loc_vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_out", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "loc_vlen", IsOptional: false}, Buf: "vec", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "rem_vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_out", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "rem_vlen", IsOptional: false}, Buf: "vec", TypeSize: 0}, ConstType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Val: uintptr(0)}}},
|
||||
&Call{ID: 382, Name: "process_vm_readv", CallName: "process_vm_readv", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "loc_vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_out", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "loc_vlen", IsOptional: false}, Buf: "loc_vec", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "rem_vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_out", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "rem_vlen", IsOptional: false}, Buf: "rem_vec", TypeSize: 0}, ConstType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Val: uintptr(0)}}},
|
||||
&Call{ID: 383, Name: "process_vm_writev", CallName: "process_vm_writev", Args: []Type{ResourceType{TypeCommon: TypeCommon{TypeName: "pid", IsOptional: false}, Kind: ResPid}, PtrType{TypeCommon: TypeCommon{TypeName: "loc_vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_out", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "loc_vlen", IsOptional: false}, Buf: "loc_vec", TypeSize: 0}, PtrType{TypeCommon: TypeCommon{TypeName: "rem_vec", IsOptional: false}, Type: ArrayType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, Type: StructType{TypeCommon: TypeCommon{TypeName: "iovec_out", IsOptional: false}, Fields: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Dir: DirOut, Type: BufferType{TypeCommon: TypeCommon{TypeName: "addr", IsOptional: false}, Kind: BufferBlob}}, LenType{TypeCommon: TypeCommon{TypeName: "len", IsOptional: false}, Buf: "addr", TypeSize: 8}}}}, Dir: DirIn}, LenType{TypeCommon: TypeCommon{TypeName: "rem_vlen", IsOptional: false}, Buf: "rem_vec", TypeSize: 0}, ConstType{TypeCommon: TypeCommon{TypeName: "flags", IsOptional: false}, TypeSize: 0, Val: uintptr(0)}}},
|
||||
&Call{ID: 384, Name: "set_tid_address", CallName: "set_tid_address", Args: []Type{PtrType{TypeCommon: TypeCommon{TypeName: "tidptr", IsOptional: false}, Type: IntType{TypeCommon: TypeCommon{TypeName: "", IsOptional: false}, TypeSize: 4}, Dir: DirOut}}},
|
||||
&Call{ID: 385, Name: "getpriority", CallName: "getpriority", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "which", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2}}, ResourceType{TypeCommon: TypeCommon{TypeName: "who", IsOptional: false}, Kind: ResPid}}},
|
||||
&Call{ID: 386, Name: "setpriority", CallName: "setpriority", Args: []Type{FlagsType{TypeCommon: TypeCommon{TypeName: "which", IsOptional: false}, TypeSize: 0, Vals: []uintptr{0, 1, 2}}, ResourceType{TypeCommon: TypeCommon{TypeName: "who", IsOptional: false}, Kind: ResPid}, IntType{TypeCommon: TypeCommon{TypeName: "prio", IsOptional: false}, TypeSize: 8}}},
|
||||
|
@ -272,8 +272,8 @@ func (inst *Instance) Run() {
|
||||
inst.CreateSSHCommand("echo -n 0 > /proc/sys/debug/exception-trace").Wait(10 * time.Second)
|
||||
|
||||
// Run the binary.
|
||||
cmd := inst.CreateSSHCommand(fmt.Sprintf("/syzkaller_fuzzer -name %v -executor /syzkaller_executor -manager %v:%v -procs %v %v",
|
||||
inst.name, hostAddr, inst.cfg.ManagerPort, inst.cfg.Procs, inst.callsFlag))
|
||||
cmd := inst.CreateSSHCommand(fmt.Sprintf("/syzkaller_fuzzer -name %v -executor /syzkaller_executor -manager %v:%v -procs %v -leak=%v %v",
|
||||
inst.name, hostAddr, inst.cfg.ManagerPort, inst.cfg.Procs, inst.cfg.Leak, inst.callsFlag))
|
||||
|
||||
deadline := start.Add(time.Hour)
|
||||
lastOutput := time.Now()
|
||||
|
Loading…
x
Reference in New Issue
Block a user