Skip to content

Return a typed error with raw bytes for malformed messages - #201

Open
xiaodongw wants to merge 1 commit into
jacobsa:masterfrom
xiaodongw:malformed-message-error
Open

Return a typed error with raw bytes for malformed messages#201
xiaodongw wants to merge 1 commit into
jacobsa:masterfrom
xiaodongw:malformed-message-error

Conversation

@xiaodongw

Copy link
Copy Markdown

Motivation

When a message read from /dev/fuse can't be converted to an op, ReadOp
returns fmt.Errorf("convertInMessage: %v", err). The conversion errors are
opaque (errors.New("Corrupt OpLookup") and friends — no opcode, length, or
payload), and the raw bytes of the offending message are recycled back into the
freelist before the caller ever sees them.

In production this makes malformed-message failures very hard to diagnose: the
only signal is which op parser failed, with no way to inspect what the kernel
actually sent.

What this changes

  • Adds MalformedMessageError, returned from ReadOp when convertInMessage
    fails. It wraps the underlying conversion error (via Unwrap) and carries a
    copy of the raw message bytes in Message, so callers can log/hex-dump them.
  • Adds InMessage.Bytes() in internal/buffer, exposing the full message from
    the most recent Init so ReadOp can copy the bytes before the buffer is
    recycled.
  • Recycles the InMessage on the failure path via putInMessage. Previously
    the buffer was only returned to the freelist by Reply on the success path;
    the error path returns a nil context, so the caller can't call Reply and
    the buffer was orphaned. The copy is taken before recycling, so it stays
    valid under concurrent readers.

Compatibility

  • The error string is unchanged ("convertInMessage: <err>"), so existing log
    output and any string matching keep working.
  • The concrete error type changes from the opaque error produced by
    fmt.Errorf to the exported *MalformedMessageError. Callers that want the
    bytes can recover them with errors.As; errors.Is / Unwrap reach the
    original conversion error.

Testing

  • TestMalformedMessageError — covers Error(), Unwrap, and errors.As
    recovery of the bytes through a wrapped error.
  • TestInMessageBytes — covers the new accessor.
  • go build ./..., go vet, and go test ./... pass.

When convertInMessage fails, ReadOp previously returned a plain
fmt.Errorf whose text discarded the offending message. That makes
kernel/protocol corruption hard to diagnose in production, since the
raw bytes are often the only useful signal.

Introduce MalformedMessageError, which carries the underlying
conversion error (exposed via Unwrap) plus a copy of the raw message
bytes, and return it from ReadOp. A new InMessage.Bytes() accessor
exposes the message read by the most recent Init so ReadOp can copy the
bytes before the buffer is recycled.

The error string is unchanged ("convertInMessage: <err>"), so existing
log output is preserved; callers that want the bytes can recover them
with errors.As.

Co-authored-by: Isaac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants