Skip to content

noq-udp panics on musl targets: assertion failed: align_of::<T>() <= align_of::<C>() #774

Description

@ypopivniak

Describe the bug
noq-udp panics on the first received packet on any musl target.

cmsg::decode() asserts align_of::<T>() <= align_of::<C>(). musl declares cmsghdr as { socklen_t cmsg_len, c_int __pad1, c_int cmsg_level, c_int cmsg_type }align 4, whereas glibc uses size_t cmsg_len → align 8. The SCM_TIMESTAMPNS arm decodes libc::timespec (align 8), so the assert fails. Both operands are compile-time constants, so this is deterministic rather than data-dependent, and SO_TIMESTAMPNS is set unconditionally on Linux, so the path is always live.

Introduced by b454d1799 feat(udp): implement kernel receive timestamps on Linux/Android.

This is not memory unsafety: the control buffer is #[repr(align(8))], so the payload really is 8-aligned in practice. The assert compares the declared alignment of cmsghdr rather than the buffer alignment the code deliberately enforces.

Reproduces in noq's own test suite:

docker run --rm -v "$PWD:/w" -w /w rust:alpine \
  sh -c 'apk add --no-cache musl-dev >/dev/null; cargo test -p noq-udp'

Relevant Logs

thread 'gso' panicked at noq-udp/src/cmsg/mod.rs:81:5:
assertion failed: align_of::<T>() <= align_of::<C>()
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

failures:
    basic
    basic_src_ip
    ecn_v4
    ecn_v4_mapped_v6
    ecn_v6
    ecn_v6_dualstack
    gso
    recv_survives_icmp_unreachable_from_prior_send
    socket_buffers

test result: FAILED. 0 passed; 9 failed; 0 ignored; 0 measured; 0 filtered out

Expected behavior

  • Packets are received on musl targets
  • cargo test -p noq-udp passes

noq

Version: 1.1.0 (also reproduces on main @ 5cf07f4)

noq-udp v1.1.0
├── noq-udp feature "default" (command-line)
├── noq-udp feature "tracing"
│   ├── noq-udp feature "default" (command-line)
│   └── noq-udp feature "tracing-log"
│       └── noq-udp feature "default" (command-line)
└── noq-udp feature "tracing-log" (*)

Platform(s)
Desktop:

  • OS: Alpine Linux (Docker rust:alpine, rustc 1.97.1) reproduced on both aarch64-unknown-linux-musl and x86_64-unknown-linux-musl
  • Version 3.24.1

Desktop (also affected):

  • OS: Ubuntu x86_64 running the statically-linked musl iroh-relay build
  • Version 24.04.3 LTS

Additional Context / Screenshots / GIFs
Real-world impact: the official iroh-relay v1.0.3 static binary (from the n0computer/iroh-relay:v1.0.3 image) is musl-linked and crash-loops on first traffic. Because the cmsg decode happens before any protocol parsing, a single unauthenticated UDP datagram to the QUIC port is enough to abort the process so no handshake required. I confirmed that with nc against two otherwise-identical hosts, one patched and one not.

lolwut

  • This issue was created by a human that thought critically about
    the issue being reported and wrote this as concisely and clearly
    as they could. Taking full responsibility for the issue being
    accurate.
  • This issue isn't slop, and is backed up by evidence.

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

    Projects

    • Status
      ✅ Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions