aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
Diffstat (limited to 'executor')
-rw-r--r--executor/common.h30
-rw-r--r--executor/executor.cc54
-rw-r--r--executor/test.go10
-rw-r--r--executor/test_executor.cc (renamed from executor/test_kvm.cc)168
-rw-r--r--executor/test_test.go24
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)
}