aboutsummaryrefslogtreecommitdiffstats
path: root/prog/encodingexec.go
diff options
context:
space:
mode:
Diffstat (limited to 'prog/encodingexec.go')
-rw-r--r--prog/encodingexec.go105
1 files changed, 94 insertions, 11 deletions
diff --git a/prog/encodingexec.go b/prog/encodingexec.go
index 9a9cc4b48..6695836ca 100644
--- a/prog/encodingexec.go
+++ b/prog/encodingexec.go
@@ -8,6 +8,7 @@ package prog
import (
"fmt"
+ "sort"
"github.com/google/syzkaller/sys"
)
@@ -22,6 +23,16 @@ const (
ExecArgConst = uintptr(iota)
ExecArgResult
ExecArgData
+ ExecArgCsum
+)
+
+const (
+ ExecArgCsumInet = uintptr(iota)
+)
+
+const (
+ ExecArgCsumChunkData = uintptr(iota)
+ ExecArgCsumChunkConst
)
const (
@@ -32,6 +43,25 @@ const (
dataOffset = 512 << 20
)
+type Args []*Arg
+
+func (s Args) Len() int {
+ return len(s)
+}
+
+func (s Args) Swap(i, j int) {
+ s[i], s[j] = s[j], s[i]
+}
+
+type ByPhysicalAddr struct {
+ Args
+ Context *execContext
+}
+
+func (s ByPhysicalAddr) Less(i, j int) bool {
+ return s.Context.args[s.Args[i]].Addr < s.Context.args[s.Args[j]].Addr
+}
+
// SerializeForExec serializes program p for execution by process pid into the provided buffer.
// If the provided buffer is too small for the program an error is returned.
func (p *Prog) SerializeForExec(buffer []byte, pid int) error {
@@ -49,13 +79,30 @@ func (p *Prog) SerializeForExec(buffer []byte, pid int) error {
for _, c := range p.Calls {
// Calculate checksums.
csumMap := calcChecksumsCall(c, pid)
+ var csumUses map[*Arg]bool
+ if csumMap != nil {
+ csumUses = make(map[*Arg]bool)
+ for arg, info := range csumMap {
+ csumUses[arg] = true
+ if info.Kind == CsumInet {
+ for _, chunk := range info.Chunks {
+ if chunk.Kind == CsumChunkArg {
+ csumUses[chunk.Arg] = true
+ }
+ }
+ }
+ }
+ }
// Calculate arg offsets within structs.
// Generate copyin instructions that fill in data into pointer arguments.
foreachArg(c, func(arg, _ *Arg, _ *[]*Arg) {
if arg.Kind == ArgPointer && arg.Res != nil {
foreachSubargOffset(arg.Res, func(arg1 *Arg, offset uintptr) {
- if len(arg1.Uses) != 0 {
- w.args[arg1] = argInfo{Offset: offset}
+ if len(arg1.Uses) != 0 || csumUses[arg1] {
+ w.args[arg1] = argInfo{Addr: physicalAddr(arg) + offset}
+ }
+ if arg1.Kind == ArgGroup || arg1.Kind == ArgUnion {
+ return
}
if !sys.IsPad(arg1.Type) &&
!(arg1.Kind == ArgData && len(arg1.Data) == 0) &&
@@ -68,6 +115,47 @@ func (p *Prog) SerializeForExec(buffer []byte, pid int) error {
})
}
})
+ // Generate checksum calculation instructions starting from the last one,
+ // since checksum values can depend on values of the latter ones
+ if csumMap != nil {
+ var csumArgs []*Arg
+ for arg, _ := range csumMap {
+ csumArgs = append(csumArgs, arg)
+ }
+ sort.Sort(ByPhysicalAddr{Args: csumArgs, Context: w})
+ for i := len(csumArgs) - 1; i >= 0; i-- {
+ arg := csumArgs[i]
+ if _, ok := arg.Type.(*sys.CsumType); !ok {
+ panic("csum arg is not csum type")
+ }
+ w.write(ExecInstrCopyin)
+ w.write(w.args[arg].Addr)
+ w.write(ExecArgCsum)
+ w.write(arg.Size())
+ switch csumMap[arg].Kind {
+ case CsumInet:
+ w.write(ExecArgCsumInet)
+ w.write(uintptr(len(csumMap[arg].Chunks)))
+ for _, chunk := range csumMap[arg].Chunks {
+ switch chunk.Kind {
+ case CsumChunkArg:
+ w.write(ExecArgCsumChunkData)
+ w.write(w.args[chunk.Arg].Addr)
+ w.write(chunk.Arg.Size())
+ case CsumChunkConst:
+ w.write(ExecArgCsumChunkConst)
+ w.write(chunk.Value)
+ w.write(chunk.Size)
+ default:
+ panic(fmt.Sprintf("csum chunk has unknown kind %v", chunk.Kind))
+ }
+ }
+ default:
+ panic(fmt.Sprintf("csum arg has unknown kind %v", csumMap[arg].Kind))
+ }
+ instrSeq++
+ }
+ }
// Generate the call itself.
w.write(uintptr(c.Meta.ID))
w.write(uintptr(len(c.Args)))
@@ -96,7 +184,7 @@ func (p *Prog) SerializeForExec(buffer []byte, pid int) error {
instrSeq++
w.args[arg] = info
w.write(ExecInstrCopyout)
- w.write(physicalAddr(base) + info.Offset)
+ w.write(info.Addr)
w.write(arg.Size())
default:
panic("bad arg kind in copyout")
@@ -130,8 +218,8 @@ type execContext struct {
}
type argInfo struct {
- Offset uintptr // from base pointer
- Idx uintptr // instruction index
+ Addr uintptr // physical addr
+ Idx uintptr // instruction index
}
func (w *execContext) write(v uintptr) {
@@ -150,14 +238,9 @@ func (w *execContext) write(v uintptr) {
w.buf = w.buf[8:]
}
-func (w *execContext) writeArg(arg *Arg, pid int, csumMap map[*Arg]*Arg) {
+func (w *execContext) writeArg(arg *Arg, pid int, csumMap map[*Arg]CsumInfo) {
switch arg.Kind {
case ArgConst:
- if _, ok := arg.Type.(*sys.CsumType); ok {
- if arg, ok = csumMap[arg]; !ok {
- panic("csum arg is not in csum map")
- }
- }
w.write(ExecArgConst)
w.write(arg.Size())
w.write(arg.Value(pid))