Page MenuHomeFreeBSD

hastd: Fix crash on empty message
ClosedPublic

Authored by des on Sep 1 2026, 1:57 PM.
Tags
None
Referenced Files
Unknown Object (File)
Thu, Oct 15, 8:26 PM
Unknown Object (File)
Thu, Oct 15, 8:21 PM
Unknown Object (File)
Thu, Oct 15, 4:12 PM
Unknown Object (File)
Thu, Oct 15, 2:55 AM
Unknown Object (File)
Thu, Oct 15, 2:32 AM
Unknown Object (File)
Tue, Oct 13, 8:45 AM
Unknown Object (File)
Tue, Oct 13, 8:45 AM
Unknown Object (File)
Tue, Oct 13, 8:10 AM
Subscribers

Details

Summary

A HAST message can be empty, in which case ebuf_data() will return NULL,
but in the receive path, we assert that the return value is not NULL.
Thus sending a message to hastd with an empty payload results in an
immediate crash. This is trivially reproducable by running `hastctl
status` or hastctl role init (which the rc script happens to do prior
to stopping hastd).

PR: 298085
MFC after: 3 days

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

des requested review of this revision.Sep 1 2026, 1:57 PM

I'm not convinced this patch is correct. I think we should call proto_recv() in all cases.

In D59306#1360617, @des wrote:

I'm not convinced this patch is correct. I think we should call proto_recv() in all cases.

OK, I misunderstood the code; I thought proto_recv() called the handler for the message, but what it actually does is read the payload from the socket, so we only need to call it if there is a payload to be read, and the patch is fine.

don't call ebuf_add_tail() needlessly

sbin/hastd/hast_proto.c
154

actually this is completely redundant because we already gave hdr.size to ebuf_alloc() so it already allocated enough memory for it (and a whole additional page, for some reason).

sbin/hastd/hast_proto.c
154

hmm that turned out not to be correct in practice, probably a bug in the ebuf code

sbin/hastd/hast_proto.c
154

It's actually not a bug; ebuf_alloc(hdr.size) creates an ebuf with no data but with the expectation that at least hdr.size bytes will be written to it in the future, while ebuf_add_tail(eb, NULL, hdr.size) adds hdr.size bytes of uninitialized data to the ebuf (without allocating any additional memory); ebuf_data() will return NULL until the first call to either ebuf_add_head() or ebuf_add_tail().

This revision resolves the issue for me.

This revision is now accepted and ready to land.Sep 1 2026, 5:13 PM
This revision was automatically updated to reflect the committed changes.