From ac0c70f74a5badbebec721c2be0602ea98c0437b Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Thu, 27 Apr 2017 20:31:00 +0200 Subject: prog, executor: move checksum computation to executor This commit moves checksum computation to executor. This will allow to embed dynamically generated values (like TCP sequence numbers) into packets. --- csource/common.go | 30 ++++++++++++++++++++++++++++++ csource/csource.go | 27 ++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) (limited to 'csource') diff --git a/csource/common.go b/csource/common.go index f09cbf24d..2551cbbb9 100644 --- a/csource/common.go +++ b/csource/common.go @@ -275,6 +275,36 @@ static uintptr_t syz_emit_ethernet(uintptr_t a0, uintptr_t a1) } #endif +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/csource/csource.go b/csource/csource.go index 1bf3fc7a1..6a21f54e6 100644 --- a/csource/csource.go +++ b/csource/csource.go @@ -226,8 +226,33 @@ loop: esc = append(esc, '\\', 'x', hex(v>>4), hex(v<<4>>4)) } fmt.Fprintf(w, "\tNONFAILING(memcpy((void*)0x%x, \"%s\", %v));\n", addr, esc, size) + case prog.ExecArgCsum: + csum_kind := read() + switch csum_kind { + case prog.ExecArgCsumInet: + fmt.Fprintf(w, "\tstruct csum_inet csum_%d;\n", n) + fmt.Fprintf(w, "\tcsum_inet_init(&csum_%d);\n", n) + csum_chunks_num := read() + for i := uintptr(0); i < csum_chunks_num; i++ { + chunk_kind := read() + chunk_value := read() + chunk_size := read() + switch chunk_kind { + case prog.ExecArgCsumChunkData: + fmt.Fprintf(w, "\tNONFAILING(csum_inet_update(&csum_%d, (const uint8_t*)0x%x, %d));\n", n, chunk_value, chunk_size) + case prog.ExecArgCsumChunkConst: + fmt.Fprintf(w, "\tuint%d_t csum_%d_chunk_%d = 0x%x;\n", chunk_size*8, n, i, chunk_value) + fmt.Fprintf(w, "\tcsum_inet_update(&csum_%d, (const uint8_t*)&csum_%d_chunk_%d, %d);\n", n, n, i, chunk_size) + default: + panic(fmt.Sprintf("unknown checksum chunk kind %v", chunk_kind)) + } + } + fmt.Fprintf(w, "\tNONFAILING(*(uint16_t*)0x%x = csum_inet_digest(&csum_%d));\n", addr, n) + default: + panic(fmt.Sprintf("unknown csum kind %v", csum_kind)) + } default: - panic("bad argument type") + panic(fmt.Sprintf("bad argument type %v", instr)) } case prog.ExecInstrCopyout: addr := read() -- cgit mrf-deployment