mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-23 11:29:46 +00:00
csource: add EnableTun option
This commit is contained in:
parent
1ab96df885
commit
7d7c9c550f
@ -167,10 +167,6 @@ static void install_segv_handler()
|
||||
*(type*)(addr) = new_val; \
|
||||
}
|
||||
|
||||
#if defined(__NR_syz_emit_ethernet) || defined(__NR_syz_extract_tcp_res)
|
||||
#define SYZ_TUN_ENABLE
|
||||
#endif
|
||||
|
||||
#ifdef SYZ_TUN_ENABLE
|
||||
static void vsnprintf_check(char* str, size_t size, const char* format, va_list args)
|
||||
{
|
||||
@ -279,6 +275,17 @@ static void setup_tun(uint64_t pid, bool enable_tun)
|
||||
initialize_tun(pid);
|
||||
}
|
||||
|
||||
int read_tun(char* data, int size)
|
||||
{
|
||||
int rv = read(tunfd, data, size);
|
||||
if (rv < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return -1;
|
||||
fail("tun: read failed with %d, errno: %d", rv, errno);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void debug_dump_data(const char* data, int length)
|
||||
{
|
||||
int i;
|
||||
@ -292,7 +299,7 @@ void debug_dump_data(const char* data, int length)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__NR_syz_emit_ethernet) || defined(__NR_syz_test)
|
||||
#if (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)) || defined(__NR_syz_test)
|
||||
struct csum_inet {
|
||||
uint32_t acc;
|
||||
};
|
||||
@ -324,7 +331,7 @@ uint16_t csum_inet_digest(struct csum_inet* csum)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __NR_syz_emit_ethernet
|
||||
#if defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)
|
||||
static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1)
|
||||
{
|
||||
|
||||
@ -338,7 +345,16 @@ static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __NR_syz_extract_tcp_res
|
||||
#if (defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT)) && defined(SYZ_TUN_ENABLE)
|
||||
void flush_tun()
|
||||
{
|
||||
char data[SYZ_TUN_MAX_PACKET_SIZE];
|
||||
while (read_tun(&data[0], sizeof(data)) != -1)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__NR_syz_extract_tcp_res) && defined(SYZ_TUN_ENABLE)
|
||||
struct ipv6hdr {
|
||||
__u8 priority : 4,
|
||||
version : 4;
|
||||
@ -357,17 +373,6 @@ struct tcp_resources {
|
||||
int32_t ack;
|
||||
};
|
||||
|
||||
int read_tun(char* data, int size)
|
||||
{
|
||||
int rv = read(tunfd, data, size);
|
||||
if (rv < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return -1;
|
||||
fail("tun: read failed with %d, errno: %d", rv, errno);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2)
|
||||
{
|
||||
|
||||
@ -418,15 +423,6 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SYZ_TUN_ENABLE) && (defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT))
|
||||
void flush_tun()
|
||||
{
|
||||
char data[SYZ_TUN_MAX_PACKET_SIZE];
|
||||
while (read_tun(&data[0], sizeof(data)) != -1)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __NR_syz_open_dev
|
||||
static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2)
|
||||
{
|
||||
@ -1505,13 +1501,21 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a
|
||||
case __NR_syz_fuseblk_mount:
|
||||
return syz_fuseblk_mount(a0, a1, a2, a3, a4, a5, a6, a7);
|
||||
#endif
|
||||
#ifdef __NR_syz_emit_ethernet
|
||||
#if defined(__NR_syz_emit_ethernet)
|
||||
case __NR_syz_emit_ethernet:
|
||||
#if defined(SYZ_TUN_ENABLE)
|
||||
return syz_emit_ethernet(a0, a1);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
#ifdef __NR_syz_extract_tcp_res
|
||||
#endif
|
||||
#if defined(__NR_syz_extract_tcp_res)
|
||||
case __NR_syz_extract_tcp_res:
|
||||
#if defined(SYZ_TUN_ENABLE)
|
||||
return syz_extract_tcp_res(a0, a1, a2);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef __NR_syz_kvm_setup_cpu
|
||||
case __NR_syz_kvm_setup_cpu:
|
||||
|
@ -22,15 +22,22 @@ import (
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
Threaded bool
|
||||
Collide bool
|
||||
Repeat bool
|
||||
Procs int
|
||||
Sandbox string
|
||||
Threaded bool
|
||||
Collide bool
|
||||
Repeat bool
|
||||
Procs int
|
||||
Sandbox string
|
||||
|
||||
Fault bool // inject fault into FaultCall/FaultNth
|
||||
FaultCall int
|
||||
FaultNth int
|
||||
Repro bool // generate code for use with repro package
|
||||
|
||||
// These options allow for a more fine-tuned control over the generated C code.
|
||||
EnableTun bool
|
||||
|
||||
// Generate code for use with repro package to prints log messages,
|
||||
// which allows to distinguish between a hang and an absent crash.
|
||||
Repro bool
|
||||
}
|
||||
|
||||
func Write(p *prog.Prog, opts Options) ([]byte, error) {
|
||||
@ -53,14 +60,6 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
|
||||
}
|
||||
fmt.Fprintf(w, "\n")
|
||||
|
||||
enableTun := "false"
|
||||
if _, ok := handled["syz_emit_ethernet"]; ok {
|
||||
enableTun = "true"
|
||||
}
|
||||
if _, ok := handled["syz_extract_tcp_res"]; ok {
|
||||
enableTun = "true"
|
||||
}
|
||||
|
||||
hdr, err := preprocessCommonHeader(opts, handled)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -76,7 +75,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
|
||||
|
||||
fmt.Fprint(w, "int main()\n{\n")
|
||||
fmt.Fprintf(w, "\tsetup_main_process();\n")
|
||||
fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, enableTun)
|
||||
fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun)
|
||||
fmt.Fprint(w, "\tint status = 0;\n")
|
||||
fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n")
|
||||
fmt.Fprint(w, "\treturn 0;\n}\n")
|
||||
@ -85,7 +84,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
|
||||
if opts.Procs <= 1 {
|
||||
fmt.Fprint(w, "int main()\n{\n")
|
||||
fmt.Fprintf(w, "\tsetup_main_process();\n")
|
||||
fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, enableTun)
|
||||
fmt.Fprintf(w, "\tint pid = do_sandbox_%v(0, %v);\n", opts.Sandbox, opts.EnableTun)
|
||||
fmt.Fprint(w, "\tint status = 0;\n")
|
||||
fmt.Fprint(w, "\twhile (waitpid(pid, &status, __WALL) != pid) {}\n")
|
||||
fmt.Fprint(w, "\treturn 0;\n}\n")
|
||||
@ -95,7 +94,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
|
||||
fmt.Fprintf(w, "\tfor (i = 0; i < %v; i++) {\n", opts.Procs)
|
||||
fmt.Fprint(w, "\t\tif (fork() == 0) {\n")
|
||||
fmt.Fprintf(w, "\t\t\tsetup_main_process();\n")
|
||||
fmt.Fprintf(w, "\t\t\tint pid = do_sandbox_%v(i, %v);\n", opts.Sandbox, enableTun)
|
||||
fmt.Fprintf(w, "\t\t\tint pid = do_sandbox_%v(i, %v);\n", opts.Sandbox, opts.EnableTun)
|
||||
fmt.Fprint(w, "\t\t\tint status = 0;\n")
|
||||
fmt.Fprint(w, "\t\t\twhile (waitpid(pid, &status, __WALL) != pid) {}\n")
|
||||
fmt.Fprint(w, "\t\t\treturn 0;\n")
|
||||
@ -322,6 +321,9 @@ func preprocessCommonHeader(opts Options, handled map[string]int) (string, error
|
||||
if opts.Fault {
|
||||
defines = append(defines, "SYZ_FAULT_INJECTION")
|
||||
}
|
||||
if opts.EnableTun {
|
||||
defines = append(defines, "SYZ_TUN_ENABLE")
|
||||
}
|
||||
for name, _ := range handled {
|
||||
defines = append(defines, "__NR_"+name)
|
||||
}
|
||||
|
@ -32,20 +32,22 @@ func allOptionsPermutations() []Options {
|
||||
for _, opt.Threaded = range []bool{false, true} {
|
||||
for _, opt.Collide = range []bool{false, true} {
|
||||
for _, opt.Repeat = range []bool{false, true} {
|
||||
for _, opt.Repro = range []bool{false, true} {
|
||||
for _, opt.Procs = range []int{1, 4} {
|
||||
for _, opt.Sandbox = range []string{"none", "setuid", "namespace"} {
|
||||
for _, opt.Fault = range []bool{false, true} {
|
||||
if opt.Collide && !opt.Threaded {
|
||||
continue
|
||||
for _, opt.Procs = range []int{1, 4} {
|
||||
for _, opt.Sandbox = range []string{"none", "setuid", "namespace"} {
|
||||
for _, opt.Repro = range []bool{false, true} {
|
||||
for _, opt.EnableTun = range []bool{false, true} {
|
||||
for _, opt.Fault = range []bool{false, true} {
|
||||
if opt.Collide && !opt.Threaded {
|
||||
continue
|
||||
}
|
||||
if !opt.Repeat && opt.Procs != 1 {
|
||||
continue
|
||||
}
|
||||
if testing.Short() && opt.Procs != 1 {
|
||||
continue
|
||||
}
|
||||
options = append(options, opt)
|
||||
}
|
||||
if !opt.Repeat && opt.Procs != 1 {
|
||||
continue
|
||||
}
|
||||
if testing.Short() && opt.Procs != 1 {
|
||||
continue
|
||||
}
|
||||
options = append(options, opt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -189,10 +189,6 @@ static void install_segv_handler()
|
||||
*(type*)(addr) = new_val; \
|
||||
}
|
||||
|
||||
#if defined(__NR_syz_emit_ethernet) || defined(__NR_syz_extract_tcp_res)
|
||||
#define SYZ_TUN_ENABLE
|
||||
#endif
|
||||
|
||||
#ifdef SYZ_TUN_ENABLE
|
||||
static void vsnprintf_check(char* str, size_t size, const char* format, va_list args)
|
||||
{
|
||||
@ -307,6 +303,17 @@ static void setup_tun(uint64_t pid, bool enable_tun)
|
||||
initialize_tun(pid);
|
||||
}
|
||||
|
||||
int read_tun(char* data, int size)
|
||||
{
|
||||
int rv = read(tunfd, data, size);
|
||||
if (rv < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return -1;
|
||||
fail("tun: read failed with %d, errno: %d", rv, errno);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void debug_dump_data(const char* data, int length)
|
||||
{
|
||||
int i;
|
||||
@ -320,7 +327,7 @@ void debug_dump_data(const char* data, int length)
|
||||
}
|
||||
#endif // SYZ_TUN_ENABLE
|
||||
|
||||
#if defined(__NR_syz_emit_ethernet) || defined(__NR_syz_test)
|
||||
#if (defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)) || defined(__NR_syz_test)
|
||||
struct csum_inet {
|
||||
uint32_t acc;
|
||||
};
|
||||
@ -352,7 +359,7 @@ uint16_t csum_inet_digest(struct csum_inet* csum)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __NR_syz_emit_ethernet
|
||||
#if defined(__NR_syz_emit_ethernet) && defined(SYZ_TUN_ENABLE)
|
||||
static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1)
|
||||
{
|
||||
// syz_emit_ethernet(len len[packet], packet ptr[in, eth_packet])
|
||||
@ -367,7 +374,16 @@ static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __NR_syz_extract_tcp_res
|
||||
#if (defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT)) && defined(SYZ_TUN_ENABLE)
|
||||
void flush_tun()
|
||||
{
|
||||
char data[SYZ_TUN_MAX_PACKET_SIZE];
|
||||
while (read_tun(&data[0], sizeof(data)) != -1)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__NR_syz_extract_tcp_res) && defined(SYZ_TUN_ENABLE)
|
||||
// Can't include <linux/ipv6.h>, since it causes
|
||||
// conflicts due to some structs redefinition.
|
||||
struct ipv6hdr {
|
||||
@ -388,17 +404,6 @@ struct tcp_resources {
|
||||
int32_t ack;
|
||||
};
|
||||
|
||||
int read_tun(char* data, int size)
|
||||
{
|
||||
int rv = read(tunfd, data, size);
|
||||
if (rv < 0) {
|
||||
if (errno == EAGAIN)
|
||||
return -1;
|
||||
fail("tun: read failed with %d, errno: %d", rv, errno);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2)
|
||||
{
|
||||
// syz_extract_tcp_res(res ptr[out, tcp_resources], seq_inc int32, ack_inc int32)
|
||||
@ -451,15 +456,6 @@ static uintptr_t syz_extract_tcp_res(uintptr_t a0, uintptr_t a1, uintptr_t a2)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SYZ_TUN_ENABLE) && (defined(SYZ_EXECUTOR) || defined(SYZ_REPEAT))
|
||||
void flush_tun()
|
||||
{
|
||||
char data[SYZ_TUN_MAX_PACKET_SIZE];
|
||||
while (read_tun(&data[0], sizeof(data)) != -1)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __NR_syz_open_dev
|
||||
static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2)
|
||||
{
|
||||
@ -597,14 +593,22 @@ static uintptr_t execute_syscall(int nr, uintptr_t a0, uintptr_t a1, uintptr_t a
|
||||
case __NR_syz_fuseblk_mount:
|
||||
return syz_fuseblk_mount(a0, a1, a2, a3, a4, a5, a6, a7);
|
||||
#endif
|
||||
#ifdef __NR_syz_emit_ethernet
|
||||
#if defined(__NR_syz_emit_ethernet)
|
||||
case __NR_syz_emit_ethernet:
|
||||
#if defined(SYZ_TUN_ENABLE)
|
||||
return syz_emit_ethernet(a0, a1);
|
||||
#endif
|
||||
#ifdef __NR_syz_extract_tcp_res
|
||||
#else
|
||||
return 0;
|
||||
#endif // defined(SYZ_TUN_ENABLE)
|
||||
#endif // defined(__NR_syz_emit_ethernet)
|
||||
#if defined(__NR_syz_extract_tcp_res)
|
||||
case __NR_syz_extract_tcp_res:
|
||||
#if defined(SYZ_TUN_ENABLE)
|
||||
return syz_extract_tcp_res(a0, a1, a2);
|
||||
#endif
|
||||
#else
|
||||
return 0;
|
||||
#endif // defined(SYZ_TUN_ENABLE)
|
||||
#endif // defined(__NR_syz_extract_tcp_res)
|
||||
#ifdef __NR_syz_kvm_setup_cpu
|
||||
case __NR_syz_kvm_setup_cpu:
|
||||
return syz_kvm_setup_cpu(a0, a1, a2, a3, a4, a5, a6, a7);
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "syscalls.h"
|
||||
|
||||
#define SYZ_EXECUTOR
|
||||
#define SYZ_TUN_ENABLE
|
||||
#include "common.h"
|
||||
|
||||
#define KCOV_INIT_TRACE _IOR('c', 1, unsigned long long)
|
||||
|
@ -151,12 +151,13 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er
|
||||
}
|
||||
Logf(2, "reproducing crash '%v': suspecting %v programs", ctx.crashDesc, len(suspected))
|
||||
opts := csource.Options{
|
||||
Threaded: true,
|
||||
Collide: true,
|
||||
Repeat: true,
|
||||
Procs: ctx.cfg.Procs,
|
||||
Sandbox: ctx.cfg.Sandbox,
|
||||
Repro: true,
|
||||
Threaded: true,
|
||||
Collide: true,
|
||||
Repeat: true,
|
||||
Procs: ctx.cfg.Procs,
|
||||
Sandbox: ctx.cfg.Sandbox,
|
||||
EnableTun: true,
|
||||
Repro: true,
|
||||
}
|
||||
// Execute the suspected programs.
|
||||
// We first try to execute each program for 10 seconds, that should detect simple crashes
|
||||
@ -264,24 +265,29 @@ func (ctx *context) repro(entries []*prog.LogEntry, crashStart int) (*Result, er
|
||||
}
|
||||
}
|
||||
|
||||
src, err := csource.Write(res.Prog, res.Opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
srcf, err := fileutil.WriteTempFile(src)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
bin, err := csource.Build("c", srcf)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
defer os.Remove(bin)
|
||||
crashed, err = ctx.testBin(bin, duration)
|
||||
// Try triggering crash with a C reproducer.
|
||||
crashed, err = ctx.testCProg(res.Prog, duration, res.Opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
res.CRepro = crashed
|
||||
if !crashed {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Try to simplify the C reproducer.
|
||||
if res.Opts.EnableTun {
|
||||
opts = res.Opts
|
||||
opts.EnableTun = false
|
||||
crashed, err := ctx.testCProg(res.Prog, duration, opts)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
if crashed {
|
||||
res.Opts = opts
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@ -317,6 +323,29 @@ func (ctx *context) testProg(p *prog.Prog, duration time.Duration, opts csource.
|
||||
return ctx.testImpl(inst.Instance, command, duration)
|
||||
}
|
||||
|
||||
func (ctx *context) testCProg(p *prog.Prog, duration time.Duration, opts csource.Options) (crashed bool, err error) {
|
||||
src, err := csource.Write(p, opts)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
srcf, err := fileutil.WriteTempFile(src)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
bin, err := csource.Build("c", srcf)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer os.Remove(bin)
|
||||
Logf(2, "reproducing crash '%v': testing compiled C program (duration=%v, %+v): %s",
|
||||
ctx.crashDesc, duration, opts, p)
|
||||
crashed, err = ctx.testBin(bin, duration)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return crashed, nil
|
||||
}
|
||||
|
||||
func (ctx *context) testBin(bin string, duration time.Duration) (crashed bool, err error) {
|
||||
inst := <-ctx.instances
|
||||
if inst == nil {
|
||||
|
@ -22,6 +22,7 @@ var (
|
||||
flagProg = flag.String("prog", "", "file with program to convert (required)")
|
||||
flagFaultCall = flag.Int("fault_call", -1, "inject fault into this call (0-based)")
|
||||
flagFaultNth = flag.Int("fault_nth", 0, "inject fault on n-th operation (0-based)")
|
||||
flagEnableTun = flag.Bool("tun", false, "set up TUN/TAP interface")
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -49,6 +50,7 @@ func main() {
|
||||
Fault: *flagFaultCall >= 0,
|
||||
FaultCall: *flagFaultCall,
|
||||
FaultNth: *flagFaultNth,
|
||||
EnableTun: *flagEnableTun,
|
||||
Repro: false,
|
||||
}
|
||||
src, err := csource.Write(p, opts)
|
||||
|
Loading…
Reference in New Issue
Block a user