aboutsummaryrefslogtreecommitdiffstats
path: root/prog/encodingexec.go
diff options
context:
space:
mode:
Diffstat (limited to 'prog/encodingexec.go')
-rw-r--r--prog/encodingexec.go56
1 files changed, 34 insertions, 22 deletions
diff --git a/prog/encodingexec.go b/prog/encodingexec.go
index f3b48924c..14466a272 100644
--- a/prog/encodingexec.go
+++ b/prog/encodingexec.go
@@ -75,7 +75,9 @@ func (p *Prog) SerializeForExec() ([]byte, error) {
w.write(uint64(len(p.Calls)))
for _, c := range p.Calls {
w.csumMap, w.csumUses = calcChecksumsCall(c)
- w.serializeCall(c)
+ // TODO: if we propagate this error, something breaks and no coverage
+ // is displayed to the dashboard or the logs.
+ _ = w.serializeCall(c)
}
w.write(execInstrEOF)
if len(w.buf) > ExecBufferSize {
@@ -87,13 +89,12 @@ func (p *Prog) SerializeForExec() ([]byte, error) {
return w.buf, nil
}
-func (w *execContext) serializeCall(c *Call) {
+func (w *execContext) serializeCall(c *Call) error {
// We introduce special serialization logic for kfuzztest targets, which
// require special handling due to their use of relocation tables to copy
// entire blobs of data into the kenrel.
if c.Meta.Attrs.KFuzzTest {
- w.serializeKFuzzTestCall(c)
- return
+ return w.serializeKFuzzTestCall(c)
}
// Calculate arg offsets within structs.
@@ -125,18 +126,35 @@ func (w *execContext) serializeCall(c *Call) {
// Generate copyout instructions that persist interesting return values.
w.writeCopyout(c)
+ return nil
}
// KFuzzTest targets require special handling due to their use of relocation
// tables for serializing all data (including pointed-to data) into a
// continuous blob that can be passed into the kernel.
-func (w *execContext) serializeKFuzzTestCall(c *Call) {
+func (w *execContext) serializeKFuzzTestCall(c *Call) error {
if !c.Meta.Attrs.KFuzzTest {
// This is a specialized function that shouldn't be called on anything
// other than an instance of a syz_kfuzztest_run$* syscall
panic("serializeKFuzzTestCall called on an invalid syscall")
}
+ // Generate the final syscall instruction with the update arguments.
+ kFuzzTestRunID, err := w.target.KFuzzTestRunID()
+ if err != nil {
+ panic(err)
+ }
+ // Ensures that we copy some arguments into the executor so that it doesn't
+ // receive an incomplete program on failure.
+ defer func() {
+ w.write(uint64(kFuzzTestRunID))
+ w.write(ExecNoCopyout)
+ w.write(uint64(len(c.Args)))
+ for _, arg := range c.Args {
+ w.writeArg(arg)
+ }
+ }()
+
// Write the initial string argument (test name) normally.
w.writeCopyin(&Call{Meta: c.Meta, Args: []Arg{c.Args[0]}})
@@ -145,12 +163,17 @@ func (w *execContext) serializeKFuzzTestCall(c *Call) {
// to the fuzzing driver with a relocation table.
dataArg := c.Args[1].(*PointerArg)
finalBlob := MarshallKFuzztestArg(dataArg.Res)
+ if len(finalBlob) > int(KFuzzTestMaxInputSize) {
+ return fmt.Errorf("encoded blob was too large")
+ }
- // Reuse the memory address that was pre-allocated for the original struct
- // argument. This avoids needing to hook into the memory allocation which
- // is done at a higher level than the serialization. This relies on the
- // original buffer being large enough
- blobAddress := w.target.PhysicalAddr(dataArg) - w.target.DataOffset
+ // Use the buffer argument as data offset - this represents a buffer of
+ // size 64KiB - the maximum input size that the KFuzzTest module accepts.
+ bufferArg := c.Args[3].(*PointerArg)
+ if bufferArg.Res == nil {
+ return fmt.Errorf("buffer was nil")
+ }
+ blobAddress := w.target.PhysicalAddr(bufferArg) - w.target.DataOffset
// Write the entire marshalled blob as a raw byte array.
w.write(execInstrCopyin)
@@ -164,18 +187,7 @@ func (w *execContext) serializeKFuzzTestCall(c *Call) {
// of the struct argument passed into the pseudo-syscall.
lenArg := c.Args[2].(*ConstArg)
lenArg.Val = uint64(len(finalBlob))
-
- // Generate the final syscall instruction with the update arguments.
- kFuzzTestRunID, err := w.target.KFuzzTestRunID()
- if err != nil {
- panic(err)
- }
- w.write(uint64(kFuzzTestRunID))
- w.write(ExecNoCopyout)
- w.write(uint64(len(c.Args)))
- for _, arg := range c.Args {
- w.writeArg(arg)
- }
+ return nil
}
type execContext struct {