Skip to content

Segmentation fault lifting a truncated s390x instruction #561

Description

@zardus

THIS MESSAGE WAS GENERATED BY AN AUTOMATED PROCESS

Summary

Lifting seven bytes of s390x code segfaults the interpreter. There is no Python
exception — the process dies with SIGSEGV inside libVEX:

Fatal Python error: Segmentation fault

Current thread (most recent call first):
  File "pyvex/lifting/libvex.py", line 87 in _lift
  File "pyvex/lifting/lifter.py", line 110 in lift
  File "pyvex/lifting/lift_function.py", line 134 in lift

lift_function.py already pads byte input with eight zero bytes specifically to
give libVEX room to over-read, so the intent to tolerate a truncated final
instruction is there. The s390x front end reads past even that padding when the
block ends mid-instruction: the input below is a complete a75b ffff followed by
c6 50 ff, the first three bytes of a six-byte RIL-format instruction.

Because it is a segfault rather than an exception, a caller cannot defend against
it — the whole process is lost, which matters for anything lifting untrusted or
partially-mapped code.

Reproduction

Deterministic, and independent of the load address:

import pyvex
import archinfo

pyvex.lift(bytes.fromhex("a75bffffc650ff"), 0x1000, archinfo.arch_from_id("s390x"))
$ python repro.py; echo "exit=$?"
Fatal Python error: Segmentation fault
exit=139

Tested with pyvex 26f2b61c618bdd4e01be44562c97b824be399200 and archinfo
dad25b035d090c9165e85a65f16322456568df43. Reached in practice through
CFGFast, which lifts at addresses it discovers by scanning and so routinely
hands the lifter a block that ends mid-instruction.

Scope

Found by a corpus sweep running CFGFast over every unit that loads. Native
crashes account for 81 VEX-lifted units at 30% of that sweep, all real-world
material and concentrated in stock Debian port binaries; s390x is the largest
group among them.

The audit records these as a worker killed by a signal, with no Python
traceback, so the true total may be larger — a native crash cannot be attributed
to a call site from inside the dead process.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions