aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-12-22 11:47:04 +0100
committerDmitry Vyukov <dvyukov@google.com>2017-12-22 11:59:46 +0100
commit3645389673af4c62a636cfe36f258ae770e8fb6b (patch)
tree356f9337e5ca323babef0e43fc345b0017dda798
parent6f298a18e582be006780954d6b0c30cbe2f568f4 (diff)
pkg/csource: fix handling of proc types
Generated program always uses pid=0 even when there are multiple processes. Make each process use own pid. Unfortunately required to do quite significant changes to prog, because the current format only supported fixed pid. Fixes #490
-rw-r--r--executor/common_linux.h1
-rw-r--r--executor/executor.h56
-rw-r--r--pkg/csource/csource.go54
-rw-r--r--pkg/csource/linux_common.go1
-rw-r--r--pkg/ipc/ipc.go2
-rw-r--r--prog/checksum.go10
-rw-r--r--prog/checksum_test.go4
-rw-r--r--prog/decodeexec.go11
-rw-r--r--prog/encoding_test.go2
-rw-r--r--prog/encodingexec.go40
-rw-r--r--prog/encodingexec_test.go255
-rw-r--r--prog/prog.go43
12 files changed, 296 insertions, 183 deletions
diff --git a/executor/common_linux.h b/executor/common_linux.h
index 6c43907b2..90a873582 100644
--- a/executor/common_linux.h
+++ b/executor/common_linux.h
@@ -7,6 +7,7 @@
#define _GNU_SOURCE
#endif
+#include <endian.h>
#include <sys/syscall.h>
#include <unistd.h>
#if defined(SYZ_EXECUTOR) || defined(SYZ_THREADED) || defined(SYZ_COLLIDE)
diff --git a/executor/executor.h b/executor/executor.h
index 13072a35e..84cefecf1 100644
--- a/executor/executor.h
+++ b/executor/executor.h
@@ -183,6 +183,7 @@ uint32_t* write_output(uint32_t v);
void write_completed(uint32_t completed);
uint64_t read_input(uint64_t** input_posp, bool peek = false);
uint64_t read_arg(uint64_t** input_posp);
+uint64_t read_const_arg(uint64_t** input_posp, uint64_t* size_p, uint64_t* bf_off_p, uint64_t* bf_len_p);
uint64_t read_result(uint64_t** input_posp);
void copyin(char* addr, uint64_t val, uint64_t size, uint64_t bf_off, uint64_t bf_len);
uint64_t copyout(char* addr, uint64_t size);
@@ -309,22 +310,22 @@ retry:
if (call_num == instr_copyin) {
char* addr = (char*)read_input(&input_pos);
uint64_t typ = read_input(&input_pos);
- uint64_t size = read_input(&input_pos);
debug("copyin to %p\n", addr);
switch (typ) {
case arg_const: {
- uint64_t arg = read_input(&input_pos);
- uint64_t bf_off = read_input(&input_pos);
- uint64_t bf_len = read_input(&input_pos);
+ uint64_t size, bf_off, bf_len;
+ uint64_t arg = read_const_arg(&input_pos, &size, &bf_off, &bf_len);
copyin(addr, arg, size, bf_off, bf_len);
break;
}
case arg_result: {
+ uint64_t size = read_input(&input_pos);
uint64_t val = read_result(&input_pos);
copyin(addr, val, size, 0, 0);
break;
}
case arg_data: {
+ uint64_t size = read_input(&input_pos);
NONFAILING(memcpy(addr, input_pos, size));
// Read out the data.
for (uint64_t i = 0; i < (size + 7) / 8; i++)
@@ -333,12 +334,12 @@ retry:
}
case arg_csum: {
debug("checksum found at %llx\n", addr);
+ uint64_t size = read_input(&input_pos);
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) {
+ if (size != 2) {
fail("inet checksum must be 2 bytes, not %lu", size);
}
debug("calculating checksum for %llx\n", csum_addr);
@@ -725,25 +726,46 @@ uint64_t copyout(char* addr, uint64_t size)
uint64_t read_arg(uint64_t** input_posp)
{
uint64_t typ = read_input(input_posp);
- uint64_t size = read_input(input_posp);
- (void)size;
- uint64_t arg = 0;
switch (typ) {
case arg_const: {
- arg = read_input(input_posp);
- // Bitfields can't be args of a normal syscall, so just ignore them.
- read_input(input_posp); // bit field offset
- read_input(input_posp); // bit field length
- break;
+ uint64_t size, bf_off, bf_len;
+ return read_const_arg(input_posp, &size, &bf_off, &bf_len);
}
case arg_result: {
- arg = read_result(input_posp);
- break;
+ read_input(input_posp); // size
+ return read_result(input_posp);
}
default:
fail("bad argument type %lu", typ);
}
- return arg;
+}
+
+uint64_t read_const_arg(uint64_t** input_posp, uint64_t* size_p, uint64_t* bf_off_p, uint64_t* bf_len_p)
+{
+ uint64_t meta = read_input(input_posp);
+ uint64_t val = read_input(input_posp);
+ *size_p = meta & 0xff;
+ bool be = meta & (1 << 8);
+ *bf_off_p = (meta >> 16) & 0xff;
+ *bf_len_p = (meta >> 24) & 0xff;
+ uint64_t pid_stride = meta >> 32;
+ val += pid_stride * flag_pid;
+ if (be) {
+ switch (*size_p) {
+ case 2:
+ val = htobe16(val);
+ break;
+ case 4:
+ val = htobe32(val);
+ break;
+ case 8:
+ val = htobe64(val);
+ break;
+ default:
+ fail("bad big-endian int size %d", (int)*size_p);
+ }
+ }
+ return val;
}
uint64_t read_result(uint64_t** input_posp)
diff --git a/pkg/csource/csource.go b/pkg/csource/csource.go
index 1fb00d1c0..38814c3b2 100644
--- a/pkg/csource/csource.go
+++ b/pkg/csource/csource.go
@@ -42,7 +42,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
ctx.generateSyscallDefines()
exec := make([]byte, prog.ExecBufferSize)
- progSize, err := ctx.p.SerializeForExec(exec, 0)
+ progSize, err := ctx.p.SerializeForExec(exec)
if err != nil {
return nil, fmt.Errorf("failed to serialize program: %v", err)
}
@@ -54,6 +54,9 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
if nvar != 0 {
ctx.printf("long r[%v];\n", nvar)
}
+ if opts.Procs > 1 {
+ ctx.printf("uint64_t procid;\n")
+ }
if !opts.Repeat {
ctx.generateTestFunc(calls, nvar, "loop")
@@ -102,6 +105,7 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
ctx.print("\tint i;")
ctx.printf("\tfor (i = 0; i < %v; i++) {\n", opts.Procs)
ctx.print("\t\tif (fork() == 0) {\n")
+ ctx.printf("\t\t\tprocid = i;\n")
if opts.HandleSegv {
ctx.printf("\t\t\tinstall_segv_handler();\n")
}
@@ -256,16 +260,6 @@ func (ctx *context) generateSyscallDefines() {
}
func (ctx *context) generateCalls(p prog.ExecProg) ([]string, uint64) {
- resultRef := func(arg prog.ExecArgResult) string {
- res := fmt.Sprintf("r[%v]", arg.Index)
- if arg.DivOp != 0 {
- res = fmt.Sprintf("%v/%v", res, arg.DivOp)
- }
- if arg.AddOp != 0 {
- res = fmt.Sprintf("%v+%v", res, arg.AddOp)
- }
- return res
- }
var calls []string
csumSeq := 0
for ci, call := range p.Calls {
@@ -275,15 +269,16 @@ func (ctx *context) generateCalls(p prog.ExecProg) ([]string, uint64) {
switch arg := copyin.Arg.(type) {
case prog.ExecArgConst:
if arg.BitfieldOffset == 0 && arg.BitfieldLength == 0 {
- fmt.Fprintf(w, "\tNONFAILING(*(uint%v_t*)0x%x = (uint%v_t)0x%x);\n",
- arg.Size*8, copyin.Addr, arg.Size*8, arg.Value)
+ fmt.Fprintf(w, "\tNONFAILING(*(uint%v_t*)0x%x = %v);\n",
+ arg.Size*8, copyin.Addr, ctx.constArgToStr(arg))
} else {
- fmt.Fprintf(w, "\tNONFAILING(STORE_BY_BITMASK(uint%v_t, 0x%x, 0x%x, %v, %v));\n",
- arg.Size*8, copyin.Addr, arg.Value, arg.BitfieldOffset, arg.BitfieldLength)
+ fmt.Fprintf(w, "\tNONFAILING(STORE_BY_BITMASK(uint%v_t, 0x%x, %v, %v, %v));\n",
+ arg.Size*8, copyin.Addr, ctx.constArgToStr(arg),
+ arg.BitfieldOffset, arg.BitfieldLength)
}
case prog.ExecArgResult:
fmt.Fprintf(w, "\tNONFAILING(*(uint%v_t*)0x%x = %v);\n",
- arg.Size*8, copyin.Addr, resultRef(arg))
+ arg.Size*8, copyin.Addr, ctx.resultArgToStr(arg))
case prog.ExecArgData:
fmt.Fprintf(w, "\tNONFAILING(memcpy((void*)0x%x, \"%s\", %v));\n",
copyin.Addr, toCString(arg.Data), len(arg.Data))
@@ -349,9 +344,9 @@ func (ctx *context) generateCalls(p prog.ExecProg) ([]string, uint64) {
}
switch arg := arg.(type) {
case prog.ExecArgConst:
- fmt.Fprintf(w, "0x%xul", arg.Value)
+ fmt.Fprintf(w, "%v", ctx.constArgToStr(arg))
case prog.ExecArgResult:
- fmt.Fprintf(w, "%v", resultRef(arg))
+ fmt.Fprintf(w, "%v", ctx.resultArgToStr(arg))
default:
panic(fmt.Sprintf("unknown arg type: %+v", arg))
}
@@ -382,6 +377,29 @@ func (ctx *context) generateCalls(p prog.ExecProg) ([]string, uint64) {
return calls, p.NumVars
}
+func (ctx *context) constArgToStr(arg prog.ExecArgConst) string {
+ mask := (uint64(1) << (arg.Size * 8)) - 1
+ val := fmt.Sprintf("0x%x", arg.Value&mask)
+ if ctx.opts.Procs > 1 && arg.PidStride != 0 {
+ val += fmt.Sprintf("+procid*0x%xul", arg.PidStride)
+ }
+ if arg.BigEndian {
+ val = fmt.Sprintf("htobe%v(%v)", arg.Size*8, val)
+ }
+ return val
+}
+
+func (ctx *context) resultArgToStr(arg prog.ExecArgResult) string {
+ res := fmt.Sprintf("r[%v]", arg.Index)
+ if arg.DivOp != 0 {
+ res = fmt.Sprintf("%v/%v", res, arg.DivOp)
+ }
+ if arg.AddOp != 0 {
+ res = fmt.Sprintf("%v+%v", res, arg.AddOp)
+ }
+ return res
+}
+
func toCString(data []byte) []byte {
if len(data) == 0 {
return nil
diff --git a/pkg/csource/linux_common.go b/pkg/csource/linux_common.go
index 14a7d91df..5d207bd11 100644
--- a/pkg/csource/linux_common.go
+++ b/pkg/csource/linux_common.go
@@ -8,6 +8,7 @@ var commonHeaderLinux = `
#define _GNU_SOURCE
#endif
+#include <endian.h>
#include <sys/syscall.h>
#include <unistd.h>
#if defined(SYZ_EXECUTOR) || defined(SYZ_THREADED) || defined(SYZ_COLLIDE)
diff --git a/pkg/ipc/ipc.go b/pkg/ipc/ipc.go
index 7aa57dedf..5b716b6e7 100644
--- a/pkg/ipc/ipc.go
+++ b/pkg/ipc/ipc.go
@@ -305,7 +305,7 @@ func (env *Env) Exec(opts *ExecOpts, p *prog.Prog) (output []byte, info []CallIn
})
}
// Copy-in serialized program.
- progSize, err := p.SerializeForExec(env.in, env.pid)
+ progSize, err := p.SerializeForExec(env.in)
if err != nil {
err0 = fmt.Errorf("executor %v: failed to serialize: %v", env.pid, err)
return
diff --git a/prog/checksum.go b/prog/checksum.go
index b5226e715..f1d2c0ddd 100644
--- a/prog/checksum.go
+++ b/prog/checksum.go
@@ -59,7 +59,7 @@ func extractHeaderParamsIPv6(arg Arg) (Arg, Arg) {
return srcAddr, dstAddr
}
-func composePseudoCsumIPv4(tcpPacket, srcAddr, dstAddr Arg, protocol uint8, pid int) CsumInfo {
+func composePseudoCsumIPv4(tcpPacket, srcAddr, dstAddr Arg, protocol uint8) CsumInfo {
info := CsumInfo{Kind: CsumInet}
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkArg, srcAddr, 0, 0})
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkArg, dstAddr, 0, 0})
@@ -69,7 +69,7 @@ func composePseudoCsumIPv4(tcpPacket, srcAddr, dstAddr Arg, protocol uint8, pid
return info
}
-func composePseudoCsumIPv6(tcpPacket, srcAddr, dstAddr Arg, protocol uint8, pid int) CsumInfo {
+func composePseudoCsumIPv6(tcpPacket, srcAddr, dstAddr Arg, protocol uint8) CsumInfo {
info := CsumInfo{Kind: CsumInet}
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkArg, srcAddr, 0, 0})
info.Chunks = append(info.Chunks, CsumChunk{CsumChunkArg, dstAddr, 0, 0})
@@ -95,7 +95,7 @@ func findCsummedArg(arg Arg, typ *CsumType, parentsMap map[Arg]Arg) Arg {
panic(fmt.Sprintf("csum field '%v' references non existent field '%v'", typ.FieldName(), typ.Buf))
}
-func calcChecksumsCall(c *Call, pid int) map[Arg]CsumInfo {
+func calcChecksumsCall(c *Call) map[Arg]CsumInfo {
var inetCsumFields []Arg
var pseudoCsumFields []Arg
@@ -172,9 +172,9 @@ func calcChecksumsCall(c *Call, pid int) map[Arg]CsumInfo {
protocol := uint8(typ.Protocol)
var info CsumInfo
if ipv4HeaderParsed {
- info = composePseudoCsumIPv4(csummedArg, ipSrcAddr, ipDstAddr, protocol, pid)
+ info = composePseudoCsumIPv4(csummedArg, ipSrcAddr, ipDstAddr, protocol)
} else {
- info = composePseudoCsumIPv6(csummedArg, ipSrcAddr, ipDstAddr, protocol, pid)
+ info = composePseudoCsumIPv6(csummedArg, ipSrcAddr, ipDstAddr, protocol)
}
csumMap[arg] = info
}
diff --git a/prog/checksum_test.go b/prog/checksum_test.go
index d466cf2c2..75e18ab70 100644
--- a/prog/checksum_test.go
+++ b/prog/checksum_test.go
@@ -15,12 +15,12 @@ func TestChecksumCalcRandom(t *testing.T) {
for i := 0; i < iters; i++ {
p := target.Generate(rs, 10, nil)
for _, call := range p.Calls {
- CalcChecksumsCall(call, i%32)
+ CalcChecksumsCall(call)
}
for try := 0; try <= 10; try++ {
p.Mutate(rs, 10, nil, nil)
for _, call := range p.Calls {
- CalcChecksumsCall(call, i%32)
+ CalcChecksumsCall(call)
}
}
}
diff --git a/prog/decodeexec.go b/prog/decodeexec.go
index e62569b42..a16461782 100644
--- a/prog/decodeexec.go
+++ b/prog/decodeexec.go
@@ -38,6 +38,8 @@ type ExecArgConst struct {
Value uint64
BitfieldOffset uint64
BitfieldLength uint64
+ PidStride uint64
+ BigEndian bool
}
type ExecArgResult struct {
@@ -127,11 +129,14 @@ func (dec *execDecoder) parse() {
func (dec *execDecoder) readArg() ExecArg {
switch typ := dec.read(); typ {
case execArgConst:
+ meta := dec.read()
return ExecArgConst{
- Size: dec.read(),
Value: dec.read(),
- BitfieldOffset: dec.read(),
- BitfieldLength: dec.read(),
+ Size: meta & 0xff,
+ BitfieldOffset: (meta >> 16) & 0xff,
+ BitfieldLength: (meta >> 24) & 0xff,
+ PidStride: meta >> 32,
+ BigEndian: (meta & (1 << 8)) != 0,
}
case execArgResult:
return ExecArgResult{
diff --git a/prog/encoding_test.go b/prog/encoding_test.go
index 5fce30142..6c063b5a7 100644
--- a/prog/encoding_test.go
+++ b/prog/encoding_test.go
@@ -159,7 +159,7 @@ func TestDeserialize(t *testing.T) {
t.Fatalf("deserialization should have failed with:\n%s\ndata:\n%s\n",
test.err, test.data)
}
- p.SerializeForExec(buf, 0)
+ p.SerializeForExec(buf)
}
}
}
diff --git a/prog/encodingexec.go b/prog/encodingexec.go
index 86ec1f638..2a41e4a53 100644
--- a/prog/encodingexec.go
+++ b/prog/encodingexec.go
@@ -73,7 +73,7 @@ func (s ByPhysicalAddr) Less(i, j int) bool {
// SerializeForExec serializes program p for execution by process pid into the provided buffer.
// Returns number of bytes written to the buffer.
// If the provided buffer is too small for the program an error is returned.
-func (p *Prog) SerializeForExec(buffer []byte, pid int) (int, error) {
+func (p *Prog) SerializeForExec(buffer []byte) (int, error) {
if debug {
if err := p.validate(); err != nil {
panic(fmt.Errorf("serializing invalid program: %v", err))
@@ -88,7 +88,7 @@ func (p *Prog) SerializeForExec(buffer []byte, pid int) (int, error) {
}
for _, c := range p.Calls {
// Calculate checksums.
- csumMap := calcChecksumsCall(c, pid)
+ csumMap := calcChecksumsCall(c)
var csumUses map[Arg]bool
if csumMap != nil {
csumUses = make(map[Arg]bool)
@@ -125,7 +125,7 @@ func (p *Prog) SerializeForExec(buffer []byte, pid int) (int, error) {
if !IsPad(arg1.Type()) && arg1.Type().Dir() != DirOut {
w.write(execInstrCopyin)
w.write(addr)
- w.writeArg(arg1, pid)
+ w.writeArg(arg1)
}
})
}
@@ -181,7 +181,7 @@ func (p *Prog) SerializeForExec(buffer []byte, pid int) (int, error) {
}
w.write(uint64(len(c.Args)))
for _, arg := range c.Args {
- w.writeArg(arg, pid)
+ w.writeArg(arg)
}
// Generate copyout instructions that persist interesting return values.
foreachArg(c, func(arg, base Arg, _ *[]Arg) {
@@ -258,21 +258,15 @@ func (w *execContext) write(v uint64) {
w.buf = w.buf[8:]
}
-func (w *execContext) writeArg(arg Arg, pid int) {
+func (w *execContext) writeArg(arg Arg) {
switch a := arg.(type) {
case *ConstArg:
- w.write(execArgConst)
- w.write(a.Size())
- w.write(a.Value(pid))
- w.write(a.Type().BitfieldOffset())
- w.write(a.Type().BitfieldLength())
+ val, pidStride, bigEndian := a.Value()
+ w.writeConstArg(a.Size(), val, a.Type().BitfieldOffset(), a.Type().BitfieldLength(),
+ pidStride, bigEndian)
case *ResultArg:
if a.Res == nil {
- w.write(execArgConst)
- w.write(a.Size())
- w.write(a.Val)
- w.write(0) // bit field offset
- w.write(0) // bit field length
+ w.writeConstArg(a.Size(), a.Val, 0, 0, 0, false)
} else {
info, ok := w.args[a.Res]
if !ok {
@@ -285,11 +279,7 @@ func (w *execContext) writeArg(arg Arg, pid int) {
w.write(a.OpAdd)
}
case *PointerArg:
- w.write(execArgConst)
- w.write(a.Size())
- w.write(w.target.physicalAddr(arg))
- w.write(0) // bit field offset
- w.write(0) // bit field length
+ w.writeConstArg(a.Size(), w.target.physicalAddr(arg), 0, 0, 0, false)
case *DataArg:
data := a.Data()
w.write(execArgData)
@@ -308,3 +298,13 @@ func (w *execContext) writeArg(arg Arg, pid int) {
panic("unknown arg type")
}
}
+
+func (w *execContext) writeConstArg(size, val, bfOffset, bfLength, pidStride uint64, bigEndian bool) {
+ w.write(execArgConst)
+ meta := size | bfOffset<<16 | bfLength<<24 | pidStride<<32
+ if bigEndian {
+ meta |= 1 << 8
+ }
+ w.write(meta)
+ w.write(val)
+}
diff --git a/prog/encodingexec_test.go b/prog/encodingexec_test.go
index 15d58d873..5c2c18534 100644
--- a/prog/encodingexec_test.go
+++ b/prog/encodingexec_test.go
@@ -16,7 +16,7 @@ func TestSerializeForExecRandom(t *testing.T) {
buf := make([]byte, ExecBufferSize)
for i := 0; i < iters; i++ {
p := target.Generate(rs, 10, nil)
- n, err := p.SerializeForExec(buf, i%16)
+ n, err := p.SerializeForExec(buf)
if err != nil {
t.Fatalf("failed to serialize: %v", err)
}
@@ -65,11 +65,11 @@ func TestSerializeForExec(t *testing.T) {
"syz_test$int(0x1, 0x2, 0x3, 0x4, 0x5)",
[]uint64{
callID("syz_test$int"), ExecNoCopyout, 5,
- execArgConst, 8, 1, 0, 0,
- execArgConst, 1, 2, 0, 0,
- execArgConst, 2, 3, 0, 0,
- execArgConst, 4, 4, 0, 0,
- execArgConst, 8, 5, 0, 0,
+ execArgConst, 8, 1,
+ execArgConst, 1, 2,
+ execArgConst, 2, 3,
+ execArgConst, 4, 4,
+ execArgConst, 8, 5,
execInstrEOF,
},
nil,
@@ -77,12 +77,12 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$align0(&(0x7f0000000000)={0x1, 0x2, 0x3, 0x4, 0x5})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 2, 1, 0, 0,
- execInstrCopyin, dataOffset + 4, execArgConst, 4, 2, 0, 0,
- execInstrCopyin, dataOffset + 8, execArgConst, 1, 3, 0, 0,
- execInstrCopyin, dataOffset + 10, execArgConst, 2, 4, 0, 0,
- execInstrCopyin, dataOffset + 16, execArgConst, 8, 5, 0, 0,
- callID("syz_test$align0"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 2, 1,
+ execInstrCopyin, dataOffset + 4, execArgConst, 4, 2,
+ execInstrCopyin, dataOffset + 8, execArgConst, 1, 3,
+ execInstrCopyin, dataOffset + 10, execArgConst, 2, 4,
+ execInstrCopyin, dataOffset + 16, execArgConst, 8, 5,
+ callID("syz_test$align0"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -90,12 +90,12 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$align1(&(0x7f0000000000)={0x1, 0x2, 0x3, 0x4, 0x5})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 2, 1, 0, 0,
- execInstrCopyin, dataOffset + 2, execArgConst, 4, 2, 0, 0,
- execInstrCopyin, dataOffset + 6, execArgConst, 1, 3, 0, 0,
- execInstrCopyin, dataOffset + 7, execArgConst, 2, 4, 0, 0,
- execInstrCopyin, dataOffset + 9, execArgConst, 8, 5, 0, 0,
- callID("syz_test$align1"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 2, 1,
+ execInstrCopyin, dataOffset + 2, execArgConst, 4, 2,
+ execInstrCopyin, dataOffset + 6, execArgConst, 1, 3,
+ execInstrCopyin, dataOffset + 7, execArgConst, 2, 4,
+ execInstrCopyin, dataOffset + 9, execArgConst, 8, 5,
+ callID("syz_test$align1"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -103,10 +103,10 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$align2(&(0x7f0000000000)={0x42, {[0x43]}, {[0x44]}})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 1, 0x42, 0, 0,
- execInstrCopyin, dataOffset + 1, execArgConst, 2, 0x43, 0, 0,
- execInstrCopyin, dataOffset + 4, execArgConst, 2, 0x44, 0, 0,
- callID("syz_test$align2"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 1, 0x42,
+ execInstrCopyin, dataOffset + 1, execArgConst, 2, 0x43,
+ execInstrCopyin, dataOffset + 4, execArgConst, 2, 0x44,
+ callID("syz_test$align2"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -114,10 +114,10 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$align3(&(0x7f0000000000)={0x42, {0x43}, {0x44}})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 1, 0x42, 0, 0,
- execInstrCopyin, dataOffset + 1, execArgConst, 1, 0x43, 0, 0,
- execInstrCopyin, dataOffset + 4, execArgConst, 1, 0x44, 0, 0,
- callID("syz_test$align3"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 1, 0x42,
+ execInstrCopyin, dataOffset + 1, execArgConst, 1, 0x43,
+ execInstrCopyin, dataOffset + 4, execArgConst, 1, 0x44,
+ callID("syz_test$align3"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -125,10 +125,10 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$align4(&(0x7f0000000000)={{0x42, 0x43}, 0x44})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 1, 0x42, 0, 0,
- execInstrCopyin, dataOffset + 1, execArgConst, 2, 0x43, 0, 0,
- execInstrCopyin, dataOffset + 4, execArgConst, 1, 0x44, 0, 0,
- callID("syz_test$align4"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 1, 0x42,
+ execInstrCopyin, dataOffset + 1, execArgConst, 2, 0x43,
+ execInstrCopyin, dataOffset + 4, execArgConst, 1, 0x44,
+ callID("syz_test$align4"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -136,13 +136,13 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$align5(&(0x7f0000000000)={{0x42, []}, {0x43, [0x44, 0x45, 0x46]}, 0x47})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 8, 0x42, 0, 0,
- execInstrCopyin, dataOffset + 8, execArgConst, 8, 0x43, 0, 0,
- execInstrCopyin, dataOffset + 16, execArgConst, 2, 0x44, 0, 0,
- execInstrCopyin, dataOffset + 18, execArgConst, 2, 0x45, 0, 0,
- execInstrCopyin, dataOffset + 20, execArgConst, 2, 0x46, 0, 0,
- execInstrCopyin, dataOffset + 22, execArgConst, 1, 0x47, 0, 0,
- callID("syz_test$align5"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 8, 0x42,
+ execInstrCopyin, dataOffset + 8, execArgConst, 8, 0x43,
+ execInstrCopyin, dataOffset + 16, execArgConst, 2, 0x44,
+ execInstrCopyin, dataOffset + 18, execArgConst, 2, 0x45,
+ execInstrCopyin, dataOffset + 20, execArgConst, 2, 0x46,
+ execInstrCopyin, dataOffset + 22, execArgConst, 1, 0x47,
+ callID("syz_test$align5"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -150,9 +150,9 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$align6(&(0x7f0000000000)={0x42, [0x43]})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 1, 0x42, 0, 0,
- execInstrCopyin, dataOffset + 4, execArgConst, 4, 0x43, 0, 0,
- callID("syz_test$align6"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 1, 0x42,
+ execInstrCopyin, dataOffset + 4, execArgConst, 4, 0x43,
+ callID("syz_test$align6"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -160,9 +160,9 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$union0(&(0x7f0000000000)={0x1, @f2=0x2})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 8, 1, 0, 0,
- execInstrCopyin, dataOffset + 8, execArgConst, 1, 2, 0, 0,
- callID("syz_test$union0"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 8, 1,
+ execInstrCopyin, dataOffset + 8, execArgConst, 1, 2,
+ callID("syz_test$union0"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -170,9 +170,9 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$union1(&(0x7f0000000000)={@f1=0x42, 0x43})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 4, 0x42, 0, 0,
- execInstrCopyin, dataOffset + 8, execArgConst, 1, 0x43, 0, 0,
- callID("syz_test$union1"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 4, 0x42,
+ execInstrCopyin, dataOffset + 8, execArgConst, 1, 0x43,
+ callID("syz_test$union1"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -180,9 +180,9 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$union2(&(0x7f0000000000)={@f1=0x42, 0x43})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 4, 0x42, 0, 0,
- execInstrCopyin, dataOffset + 4, execArgConst, 1, 0x43, 0, 0,
- callID("syz_test$union2"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 4, 0x42,
+ execInstrCopyin, dataOffset + 4, execArgConst, 1, 0x43,
+ callID("syz_test$union2"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -190,11 +190,11 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$array0(&(0x7f0000000000)={0x1, [@f0=0x2, @f1=0x3], 0x4})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 1, 1, 0, 0,
- execInstrCopyin, dataOffset + 1, execArgConst, 2, 2, 0, 0,
- execInstrCopyin, dataOffset + 3, execArgConst, 8, 3, 0, 0,
- execInstrCopyin, dataOffset + 11, execArgConst, 8, 4, 0, 0,
- callID("syz_test$array0"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 1, 1,
+ execInstrCopyin, dataOffset + 1, execArgConst, 2, 2,
+ execInstrCopyin, dataOffset + 3, execArgConst, 8, 3,
+ execInstrCopyin, dataOffset + 11, execArgConst, 8, 4,
+ callID("syz_test$array0"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -202,9 +202,9 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$array1(&(0x7f0000000000)={0x42, \"0102030405\"})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 1, 0x42, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 1, 0x42,
execInstrCopyin, dataOffset + 1, execArgData, 5, 0x0504030201,
- callID("syz_test$array1"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ callID("syz_test$array1"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -212,10 +212,10 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$array2(&(0x7f0000000000)={0x42, \"aaaaaaaabbbbbbbbccccccccdddddddd\", 0x43})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 2, 0x42, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 2, 0x42,
execInstrCopyin, dataOffset + 2, execArgData, 16, 0xbbbbbbbbaaaaaaaa, 0xddddddddcccccccc,
- execInstrCopyin, dataOffset + 18, execArgConst, 2, 0x43, 0, 0,
- callID("syz_test$array2"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 18, execArgConst, 2, 0x43,
+ callID("syz_test$array2"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -223,11 +223,11 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$end0(&(0x7f0000000000)={0x42, 0x42, 0x42, 0x42})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 1, 0x42, 0, 0,
- execInstrCopyin, dataOffset + 1, execArgConst, 2, 0x4200, 0, 0,
- execInstrCopyin, dataOffset + 3, execArgConst, 4, 0x42000000, 0, 0,
- execInstrCopyin, dataOffset + 7, execArgConst, 8, 0x4200000000000000, 0, 0,
- callID("syz_test$end0"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 1, 0x42,
+ execInstrCopyin, dataOffset + 1, execArgConst, 2 | 1<<8, 0x42,
+ execInstrCopyin, dataOffset + 3, execArgConst, 4 | 1<<8, 0x42,
+ execInstrCopyin, dataOffset + 7, execArgConst, 8 | 1<<8, 0x42,
+ callID("syz_test$end0"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -235,10 +235,10 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$end1(&(0x7f0000000000)={0xe, 0x42, 0x1})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 2, 0x0e00, 0, 0,
- execInstrCopyin, dataOffset + 2, execArgConst, 4, 0x42000000, 0, 0,
- execInstrCopyin, dataOffset + 6, execArgConst, 8, 0x0100000000000000, 0, 0,
- callID("syz_test$end1"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 2 | 1<<8, 0xe,
+ execInstrCopyin, dataOffset + 2, execArgConst, 4 | 1<<8, 0x42,
+ execInstrCopyin, dataOffset + 6, execArgConst, 8 | 1<<8, 0x1,
+ callID("syz_test$end1"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -246,27 +246,112 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$bf0(&(0x7f0000000000)={0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 2, 0x42, 0, 10,
- execInstrCopyin, dataOffset + 8, execArgConst, 8, 0x42, 0, 0,
- execInstrCopyin, dataOffset + 16, execArgConst, 2, 0x42, 0, 5,
- execInstrCopyin, dataOffset + 16, execArgConst, 2, 0x42, 5, 6,
- execInstrCopyin, dataOffset + 20, execArgConst, 4, 0x42, 0, 15,
- execInstrCopyin, dataOffset + 24, execArgConst, 2, 0x42, 0, 11,
- execInstrCopyin, dataOffset + 26, execArgConst, 2, 0x4200, 0, 11,
- execInstrCopyin, dataOffset + 28, execArgConst, 1, 0x42, 0, 0,
- callID("syz_test$bf0"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 2 | 0<<16 | 10<<24, 0x42,
+ execInstrCopyin, dataOffset + 8, execArgConst, 8, 0x42,
+ execInstrCopyin, dataOffset + 16, execArgConst, 2 | 0<<16 | 5<<24, 0x42,
+ execInstrCopyin, dataOffset + 16, execArgConst, 2 | 5<<16 | 6<<24, 0x42,
+ execInstrCopyin, dataOffset + 20, execArgConst, 4 | 0<<16 | 15<<24, 0x42,
+ execInstrCopyin, dataOffset + 24, execArgConst, 2 | 0<<16 | 11<<24, 0x42,
+ execInstrCopyin, dataOffset + 26, execArgConst, 2 | 1<<8 | 0<<16 | 11<<24, 0x42,
+ execInstrCopyin, dataOffset + 28, execArgConst, 1, 0x42,
+ callID("syz_test$bf0"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
- nil,
+ &ExecProg{
+ Calls: []ExecCall{
+ {
+ Meta: target.SyscallMap["syz_test$bf0"],
+ Index: ExecNoCopyout,
+ Args: []ExecArg{
+ ExecArgConst{
+ Size: ptrSize,
+ Value: dataOffset,
+ },
+ },
+ Copyin: []ExecCopyin{
+ {
+ Addr: dataOffset + 0,
+ Arg: ExecArgConst{
+ Size: 2,
+ Value: 0x42,
+ BitfieldOffset: 0,
+ BitfieldLength: 10,
+ },
+ },
+ {
+ Addr: dataOffset + 8,
+ Arg: ExecArgConst{
+ Size: 8,
+ Value: 0x42,
+ },
+ },
+ {
+ Addr: dataOffset + 16,
+ Arg: ExecArgConst{
+ Size: 2,
+ Value: 0x42,
+ BitfieldOffset: 0,
+ BitfieldLength: 5,
+ },
+ },
+ {
+ Addr: dataOffset + 16,
+ Arg: ExecArgConst{
+ Size: 2,
+ Value: 0x42,
+ BitfieldOffset: 5,
+ BitfieldLength: 6,
+ },
+ },
+ {
+ Addr: dataOffset + 20,
+ Arg: ExecArgConst{
+ Size: 4,
+ Value: 0x42,
+ BitfieldOffset: 0,
+ BitfieldLength: 15,
+ },
+ },
+ {
+ Addr: dataOffset + 24,
+ Arg: ExecArgConst{
+ Size: 2,
+ Value: 0x42,
+ BitfieldOffset: 0,
+ BitfieldLength: 11,
+ },
+ },
+ {
+ Addr: dataOffset + 26,
+ Arg: ExecArgConst{
+ Size: 2,
+ Value: 0x42,
+ BitfieldOffset: 0,
+ BitfieldLength: 11,
+ BigEndian: true,
+ },
+ },
+ {
+ Addr: dataOffset + 28,
+ Arg: ExecArgConst{
+ Size: 1,
+ Value: 0x42,
+ },
+ },
+ },
+ },
+ },
+ NumVars: 0,
+ },
},
{
"syz_test$bf1(&(0x7f0000000000)={{0x42, 0x42, 0x42}, 0x42})",
[]uint64{
- execInstrCopyin, dataOffset + 0, execArgConst, 4, 0x42, 0, 10,
- execInstrCopyin, dataOffset + 0, execArgConst, 4, 0x42, 10, 10,
- execInstrCopyin, dataOffset + 0, execArgConst, 4, 0x42, 20, 10,
- execInstrCopyin, dataOffset + 4, execArgConst, 1, 0x42, 0, 0,
- callID("syz_test$bf1"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset, 0, 0,
+ execInstrCopyin, dataOffset + 0, execArgConst, 4 | 0<<16 | 10<<24, 0x42,
+ execInstrCopyin, dataOffset + 0, execArgConst, 4 | 10<<16 | 10<<24, 0x42,
+ execInstrCopyin, dataOffset + 0, execArgConst, 4 | 20<<16 | 10<<24, 0x42,
+ execInstrCopyin, dataOffset + 4, execArgConst, 1, 0x42,
+ callID("syz_test$bf1"), ExecNoCopyout, 1, execArgConst, ptrSize, dataOffset,
execInstrEOF,
},
nil,
@@ -274,7 +359,7 @@ func TestSerializeForExec(t *testing.T) {
{
"syz_test$res1(0xffff)",
[]uint64{
- callID("syz_test$res1"), ExecNoCopyout, 1, execArgConst, 4, 0xffff, 0, 0,
+ callID("syz_test$res1"), ExecNoCopyout, 1, execArgConst, 4, 0xffff,
execInstrEOF,
},
nil,
@@ -289,7 +374,7 @@ func TestSerializeForExec(t *testing.T) {
if err != nil {
t.Fatalf("failed to deserialize prog %v: %v", i, err)
}
- n, err := p.SerializeForExec(buf, i%16)
+ n, err := p.SerializeForExec(buf)
if err != nil {
t.Fatalf("failed to serialize: %v", err)
}
diff --git a/prog/prog.go b/prog/prog.go
index f78aac582..4a612d9ba 100644
--- a/prog/prog.go
+++ b/prog/prog.go
@@ -63,31 +63,28 @@ func (arg *ConstArg) Size() uint64 {
return arg.typ.Size()
}
-// Returns value taking endianness and executor pid into consideration.
-func (arg *ConstArg) Value(pid int) uint64 {
+// Value returns value, pid stride and endianness.
+func (arg *ConstArg) Value() (uint64, uint64, bool) {
switch typ := (*arg).Type().(type) {
case *IntType:
- return encodeValue(arg.Val, typ.Size(), typ.BigEndian)
+ return arg.Val, 0, typ.BigEndian
case *ConstType:
- return encodeValue(arg.Val, typ.Size(), typ.BigEndian)
+ return arg.Val, 0, typ.BigEndian
case *FlagsType:
- return encodeValue(arg.Val, typ.Size(), typ.BigEndian)
+ return arg.Val, 0, typ.BigEndian
case *LenType:
- return encodeValue(arg.Val, typ.Size(), typ.BigEndian)
+ return arg.Val, 0, typ.BigEndian
case *CsumType:
// Checksums are computed dynamically in executor.
- return 0
+ return 0, 0, false
case *ResourceType:
- if t, ok := typ.Desc.Type.(*IntType); ok {
- return encodeValue(arg.Val, t.Size(), t.BigEndian)
- } else {
- panic(fmt.Sprintf("bad base type for a resource: %v", t))
- }
+ t := typ.Desc.Type.(*IntType)
+ return arg.Val, 0, t.BigEndian
case *ProcType:
- val := typ.ValuesStart + typ.ValuesPerProc*uint64(pid) + arg.Val
- return encodeValue(val, typ.Size(), typ.BigEndian)
+ return typ.ValuesStart + arg.Val, typ.ValuesPerProc, typ.BigEndian
+ default:
+ panic(fmt.Sprintf("unknown ConstArg type %#v", typ))
}
- return arg.Val
}
// Used for PtrType and VmaType.
@@ -281,22 +278,6 @@ func InnerArg(arg Arg) Arg {
return arg // Not a pointer.
}
-func encodeValue(value uint64, size uint64, bigEndian bool) uint64 {
- if !bigEndian {
- return value
- }
- switch size {
- case 2:
- return uint64(swap16(uint16(value)))
- case 4:
- return uint64(swap32(uint32(value)))
- case 8:
- return swap64(value)
- default:
- panic(fmt.Sprintf("bad size %v for value %v", size, value))
- }
-}
-
func defaultArg(t Type) Arg {
switch typ := t.(type) {
case *IntType, *ConstType, *FlagsType, *LenType, *ProcType, *CsumType: