Skip to content

Heap-buffer-overflow receiving a large distributed priority message #11416

Description

@potatosalad

Heap-buffer-overflow receiving a large distributed priority message

Describe the bug

Receiving one large distributed message sent with [priority] to an erlang:alias([priority]) alias makes ERTS read 8 bytes past a 40-byte allocation. Stock OTP is sufficient: no NIF, driver, or dependency is involved. ASan builds abort; non-ASan builds have been observed to terminate with SIGSEGV.

To Reproduce

With an ASan-enabled stock OTP build, run these in two shells:

# Shell 1: receiver
ERL_AFLAGS='-emu_type asan' \
ASAN_OPTIONS='abort_on_error=1:detect_leaks=0' \
erl -noshell -name v@127.0.0.1 -setcookie c -eval \
  'register(v,self()),A=alias([priority]),receive P->P!A,receive _->P!ok end end.'

# Shell 2: sender
erl -noshell -name u@127.0.0.1 -setcookie c -eval \
  '{v,'\''v@127.0.0.1'\''}!self(),receive A->erlang:send(A,binary:copy(<<0>>,1 bsl 20),[priority]) end,halt().'

The receiver aborts on the first 1 MiB message (exit 134 under ASan). A 32 KiB payload is clean; 64 KiB and larger reproduce the crash.

Expected behavior

The receiver should deliver the priority message without reading outside its allocation or terminating the VM.

Affected versions

Confirmed on every OTP 28.x and OTP 29.x release on both macOS and Linux. Representative exact builds are OTP 28.4.1 on macOS and OTP 29.0.4 / ERTS 17.0.4 on Linux. OTP 27 and earlier are unaffected; priority messages were introduced in OTP 28.

Additional context

ASan excerpt from OTP 29.0.4:

ERROR: AddressSanitizer: heap-buffer-overflow on address 0x5040006cac40
READ of size 8
    #0 erts_save_message_in_proc erl_message.c:981:51
    #1 beam_jit_remove_message beam_jit_common.cpp:1170:5

0x5040006cac40 is located 8 bytes after 40-byte region
[0x5040006cac10,0x5040006cac38)
allocated here:
    #1 erts_alloc_message erl_message.h:578:22
    #2 handle_altact_msg erl_proc_sig_queue.c:6163:18
    #3 erts_proc_sig_handle_incoming erl_proc_sig_queue.c:6874:20

SUMMARY: AddressSanitizer: heap-buffer-overflow
erl_message.c:981:51 in erts_save_message_in_proc

Analysis against tag OTP-29.0.4: the fragmented branch of handle_altact_msg() allocates the 40-byte message reference and keeps the decoded heap-fragment chain separately in mp->data.attached. The priority path at erl_proc_sig_queue.c:6191 calls insert_prepared_prio_msg(), whose wrapper stores ERTS_MSG_COMBINED_HFRAG. That sentinel instead claims an embedded fragment follows the message. erts_save_message_in_proc() trusts it and reads hfp->off_heap.first at offset 48 (erl_message.c:981), exactly matching the 8-byte-overrun geometry above.

Suggested next step: preserve the real attachment at the line 6191 call site, then run the reproducer and a 32/64 KiB boundary regression under ASan.
Candidate for maintainer validation (not build-tested by the reporter):

insert_prepared_prio_msg_attached(c_p, tracing, mp,
                                  mp->data.attached,
                                  ERL_MESSAGE_TERM(mp), token,
                                  next_nm_sig);

Metadata

Metadata

Assignees

Labels

bugIssue is reported as a bugteam:VMAssigned to OTP team VM

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions