diff options
| author | Andrey Konovalov <andreyknvl@gmail.com> | 2017-05-17 01:56:40 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-05-17 01:56:40 +0200 |
| commit | 64cd235dcf60d3ab0dec3d4b0f168297782417a7 (patch) | |
| tree | 67c41279da959d253aab080b873284e6e2e5186a /executor | |
| parent | ffb66e506d9083140196d9b4b2a46e15bc4a5d1e (diff) | |
| parent | ac0c70f74a5badbebec721c2be0602ea98c0437b (diff) | |
Merge pull request #169 from xairy/executor-csum
prog, executor: move checksum computation to executor
Diffstat (limited to 'executor')
| -rw-r--r-- | executor/common.h | 30 | ||||
| -rw-r--r-- | executor/executor.cc | 54 | ||||
| -rw-r--r-- | executor/test.go | 10 | ||||
| -rw-r--r-- | executor/test_executor.cc (renamed from executor/test_kvm.cc) | 168 | ||||
| -rw-r--r-- | executor/test_test.go | 24 |
5 files changed, 277 insertions, 9 deletions
diff --git a/executor/common.h b/executor/common.h index 4983802f2..eb56c8ec1 100644 --- a/executor/common.h +++ b/executor/common.h @@ -298,6 +298,36 @@ static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) } #endif // __NR_syz_emit_ethernet +struct csum_inet { + uint32_t acc; +}; + +void csum_inet_init(struct csum_inet* csum) +{ + csum->acc = 0; +} + +void csum_inet_update(struct csum_inet* csum, const uint8_t* data, size_t length) +{ + if (length == 0) + return; + + size_t i; + for (i = 0; i < length - 1; i += 2) + csum->acc += *(uint16_t*)&data[i]; + + if (length & 1) + csum->acc += (uint16_t)data[length - 1]; + + while (csum->acc > 0xffff) + csum->acc = (csum->acc & 0xffff) + (csum->acc >> 16); +} + +uint16_t csum_inet_digest(struct csum_inet* csum) +{ + return ~csum->acc; +} + #ifdef __NR_syz_open_dev static uintptr_t syz_open_dev(uintptr_t a0, uintptr_t a1, uintptr_t a2) { diff --git a/executor/executor.cc b/executor/executor.cc index 63d66d435..52da3a16b 100644 --- a/executor/executor.cc +++ b/executor/executor.cc @@ -57,6 +57,7 @@ const uint64_t instr_copyout = -3; const uint64_t arg_const = 0; const uint64_t arg_result = 1; const uint64_t arg_data = 2; +const uint64_t arg_csum = 3; // We use the default value instead of results of failed syscalls. // -1 is an invalid fd and an invalid address and deterministic, @@ -115,6 +116,13 @@ struct thread_t { thread_t threads[kMaxThreads]; +// Checksum kinds. +const uint64_t arg_csum_inet = 0; + +// Checksum chunk kinds. +const uint64_t arg_csum_chunk_data = 0; +const uint64_t arg_csum_chunk_const = 1; + void execute_one(); uint64_t read_input(uint64_t** input_posp, bool peek = false); uint64_t read_arg(uint64_t** input_posp); @@ -354,6 +362,52 @@ retry: read_input(&input_pos); break; } + case arg_csum: { + debug("checksum found at %llx\n", addr); + char* csum_addr = addr; + uint64_t csum_size = size; + uint64_t csum_kind = read_input(&input_pos); + switch (csum_kind) { + case arg_csum_inet: { + if (csum_size != 2) { + fail("inet checksum must be 2 bytes, not %lu", size); + } + debug("calculating checksum for %llx\n", csum_addr); + struct csum_inet csum; + csum_inet_init(&csum); + uint64_t chunks_num = read_input(&input_pos); + uint64_t chunk; + for (chunk = 0; chunk < chunks_num; chunk++) { + uint64_t chunk_kind = read_input(&input_pos); + uint64_t chunk_value = read_input(&input_pos); + uint64_t chunk_size = read_input(&input_pos); + switch (chunk_kind) { + case arg_csum_chunk_data: + debug("#%d: data chunk, addr: %llx, size: %llu\n", chunk, chunk_value, chunk_size); + NONFAILING(csum_inet_update(&csum, (const uint8_t*)chunk_value, chunk_size)); + break; + case arg_csum_chunk_const: + if (chunk_size != 2 && chunk_size != 4 && chunk_size != 8) { + fail("bad checksum const chunk size %lld\n", chunk_size); + } + // Here we assume that const values come to us big endian. + debug("#%d: const chunk, value: %llx, size: %llu\n", chunk, chunk_value, chunk_size); + csum_inet_update(&csum, (const uint8_t*)&chunk_value, chunk_size); + break; + default: + fail("bad checksum chunk kind %lu", chunk_kind); + } + } + int16_t csum_value = csum_inet_digest(&csum); + debug("writing inet checksum %hx to %llx\n", csum_value, csum_addr); + NONFAILING(copyin(csum_addr, csum_value, 2, 0, 0)); + break; + } + default: + fail("bad checksum kind %lu", csum_kind); + } + break; + } default: fail("bad argument type %lu", typ); } diff --git a/executor/test.go b/executor/test.go index e9709b8d0..47a4e0388 100644 --- a/executor/test.go +++ b/executor/test.go @@ -6,6 +6,8 @@ package executor // int test_copyin(); +// int test_csum_inet(); +// int test_csum_inet_acc(); // int test_kvm(); import "C" @@ -13,6 +15,14 @@ func testCopyin() int { return int(C.test_copyin()) } +func testCsumInet() int { + return int(C.test_csum_inet()) +} + +func testCsumInetAcc() int { + return int(C.test_csum_inet_acc()) +} + func testKVM() int { return int(C.test_kvm()) } diff --git a/executor/test_kvm.cc b/executor/test_executor.cc index 79b951f62..5cf404675 100644 --- a/executor/test_kvm.cc +++ b/executor/test_executor.cc @@ -24,6 +24,174 @@ extern "C" int test_copyin() return 0; } +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +struct csum_inet_test { + const char* data; + size_t length; + uint16_t csum; +}; + +extern "C" int test_csum_inet() +{ + struct csum_inet_test tests[] = { + {// 0 + "", + 0, + 0xffff}, + { + // 1 + "\x00", + 1, + 0xffff, + }, + { + // 2 + "\x00\x00", + 2, + 0xffff, + }, + { + // 3 + "\x00\x00\xff\xff", + 4, + 0x0000, + }, + { + // 4 + "\xfc", + 1, + 0xff03, + }, + { + // 5 + "\xfc\x12", + 2, + 0xed03, + }, + { + // 6 + "\xfc\x12\x3e", + 3, + 0xecc5, + }, + { + // 7 + "\xfc\x12\x3e\x00\xc5\xec", + 6, + 0x0000, + }, + { + // 8 + "\x42\x00\x00\x43\x44\x00\x00\x00\x45\x00\x00\x00\xba\xaa\xbb\xcc\xdd", + 17, + 0x43e1, + }, + { + // 9 + "\x42\x00\x00\x43\x44\x00\x00\x00\x45\x00\x00\x00\xba\xaa\xbb\xcc\xdd\x00", + 18, + 0x43e1, + }, + { + // 10 + "\x00\x00\x42\x00\x00\x43\x44\x00\x00\x00\x45\x00\x00\x00\xba\xaa\xbb\xcc\xdd", + 19, + 0x43e1, + }, + { + // 11 + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\xab\xcd", + 15, + 0x5032, + }, + { + // 12 + "\x00\x00\x12\x34\x56\x78", + 6, + 0x5397, + }, + { + // 13 + "\x00\x00\x12\x34\x00\x00\x56\x78\x00\x06\x00\x04\xab\xcd", + 14, + 0x7beb, + }, + { + // 14 + "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00\x00\x00\x00\x04\x00\x00\x00\x06\x00\x00\xab\xcd", + 44, + 0x2854, + }, + { + // 15 + "\x00\x00\x12\x34\x00\x00\x56\x78\x00\x11\x00\x04\xab\xcd", + 14, + 0x70eb, + }, + { + // 16 + "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00\x00\x00\x00\x04\x00\x00\x00\x11\x00\x00\xab\xcd", + 44, + 0x1d54, + }, + { + // 17 + "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00\x00\x00\x00\x04\x00\x00\x00\x3a\x00\x00\xab\xcd", + 44, + 0xf453, + }}; + + int i; + for (i = 0; i < ARRAY_SIZE(tests); i++) { + struct csum_inet csum; + csum_inet_init(&csum); + csum_inet_update(&csum, (const uint8_t*)tests[i].data, tests[i].length); + if (csum_inet_digest(&csum) != tests[i].csum) { + fprintf(stderr, "bad checksum in test #%d, want: %hx, got: %hx\n", i, tests[i].csum, csum_inet_digest(&csum)); + return 1; + } + } + + return 0; +} + +int randInt(int start, int end) +{ + return rand() % (end + 1 - start) + start; +} + +extern "C" int test_csum_inet_acc() +{ + uint8_t buffer[128]; + + int test; + for (test = 0; test < 256; test++) { + int size = randInt(1, 128); + int step = randInt(1, 8) * 2; + + int i; + for (i = 0; i < size; i++) + buffer[i] = randInt(0, 255); + + struct csum_inet csum_acc; + csum_inet_init(&csum_acc); + + for (i = 0; i < size / step; i++) + csum_inet_update(&csum_acc, &buffer[i * step], step); + if (size % step != 0) + csum_inet_update(&csum_acc, &buffer[size - size % step], size % step); + + struct csum_inet csum; + csum_inet_init(&csum); + csum_inet_update(&csum, &buffer[0], size); + + if (csum_inet_digest(&csum_acc) != csum_inet_digest(&csum)) + return 1; + return 0; + } +} + static unsigned host_kernel_version(); static void dump_cpu_state(int cpufd, char* vm_mem); diff --git a/executor/test_test.go b/executor/test_test.go index f197dbf51..368454ac3 100644 --- a/executor/test_test.go +++ b/executor/test_test.go @@ -5,8 +5,8 @@ package executor import "testing" -func TestCopyin(t *testing.T) { - switch res := testCopyin(); { +func testWrapper(t *testing.T, f func() int) { + switch res := f(); { case res < 0: t.Skip() case res > 0: @@ -15,12 +15,18 @@ func TestCopyin(t *testing.T) { } } +func TestCopyin(t *testing.T) { + testWrapper(t, testCopyin) +} + +func TestCsumInet(t *testing.T) { + testWrapper(t, testCsumInet) +} + +func TestCsumInetAcc(t *testing.T) { + testWrapper(t, testCsumInetAcc) +} + func TestKVM(t *testing.T) { - switch res := testKVM(); { - case res < 0: - t.Skip() - case res > 0: - t.Fail() - default: - } + testWrapper(t, testKVM) } |
