diff options
Diffstat (limited to 'prog/encodingexec.go')
| -rw-r--r-- | prog/encodingexec.go | 56 |
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 { |
