Skip to content

UCP/WIREUP: are misaligned typed accesses in packed addresses intentional? #11806

Description

@yqtian-se

Describe the bug

I would like to confirm whether the following behavior is expected or should be treated as a bug.

With current UCX built using Clang's alignment sanitizer, the stock examples/ucp_hello_world.c program completes successfully with UCX_TLS=tcp,cma,self, but both processes report misaligned typed loads and stores while packing and unpacking the normal variable-length UCP/UCT address.

The reproducer does not manually construct a misaligned pointer. These addresses are produced by UCX's ordinary wireup layout.

Representative reports from the successful run are:

src/ucp/wireup/address.c:1241:9:
  store to misaligned address for uint64_t

src/ucp/wireup/address.c:1336:13:
  store to misaligned address for uint16_t

src/ucp/wireup/address.c:1167:12:
  load of misaligned address for uint64_t

src/ucp/wireup/address.c:1792:37:
  load of misaligned address for uint16_t

src/uct/sm/self/self.c:140:5:
  store to misaligned address for uct_self_iface_addr_t

src/uct/sm/self/self.c:162:22:
  load of misaligned address for uct_self_iface_addr_t

src/uct/sm/scopy/cma/cma_iface.c:33:23:
  store to misaligned address for pid_t

src/uct/sm/scopy/cma/cma_ep.c:43:12:
  load of misaligned address for pid_t

For example, the generic wireup code performs direct typed accesses through a byte cursor:

*(uint64_t*)ptr = worker->uuid;
*(uint16_t*)ptr = context->tl_rscs[rsc_index].tl_name_csum;
address->tl_name_csum = *(uint16_t*)ptr;

Transport callbacks receive other positions within the same variable-length buffer. Self and CMA then cast those positions to naturally aligned scalar or structure types:

*(uct_self_iface_addr_t*)addr = iface->id;
iface_addr->super.id = getpid();
return *(const pid_t*)iface_addr;

Several adjacent wire-format structures are explicitly declared with UCS_S_PACKED, but these scalar cursor accesses and the CMA address structures retain their natural alignment requirements. The runtime buffer positions do not always satisfy those requirements.

On the tested x86-64 machine, the server and client completed normally and transferred the expected payload. I understand that UCX may intentionally use compact byte representations and may rely on architectures that tolerate unaligned accesses. However, Clang reports these direct typed accesses as alignment violations.

Could you confirm whether these accesses are intentional and supported by UCX's portability assumptions, or whether they should use explicitly packed representations or alignment-safe load/store operations?

I have not observed a crash, corrupted payload, or ordinary non-sanitized failure. I am reporting this as a C correctness and portability question, not as a security issue.

Steps to Reproduce

Build current UCX with CMA and Clang's alignment sanitizer:

./autogen.sh
mkdir build-align
cd build-align

../configure \
  CC=clang \
  CXX=clang++ \
  CFLAGS="-g -O2 -fsanitize=alignment" \
  CXXFLAGS="-g -O2 -fsanitize=alignment" \
  LDFLAGS="-fsanitize=alignment" \
  --prefix=/path/to/install \
  --enable-cma

make -j4
make install

Compile UCX's stock example using the same sanitizer:

export PKG_CONFIG_PATH=/path/to/install/lib/pkgconfig
export LD_LIBRARY_PATH=/path/to/install/lib
export UBSAN_OPTIONS=print_stacktrace=0:halt_on_error=0:report_error_type=1

clang -g -O2 -fsanitize=alignment \
  /path/to/ucx/examples/ucp_hello_world.c \
  $(pkg-config --cflags --libs ucx) \
  -lrt \
  -o ucp-hello-world

Start the server and then the client:

UCX_TLS=tcp,cma,self ./ucp-hello-world -p 15438 \
  >server.stdout 2>server.stderr &
server_pid=$!

sleep 2

UCX_TLS=tcp,cma,self ./ucp-hello-world \
  -n 127.0.0.1 -p 15438 \
  >client.stdout 2>client.stderr

client_rc=$?
wait "$server_pid"
server_rc=$?

echo "client=$client_rc server=$server_rc"

Observed exit status:

client=0 server=0

The client printed:

----- UCP TEST SUCCESS ----

ABCDEFGHIJKLMNO

Both stderr files contained the alignment reports described above.

The complete alignment-sanitizer run also reports locations outside packed address handling, such as allocator and protocol structures. Those locations are intentionally outside the scope of this report. The attached filtered log contains only reports from:

src/ucp/wireup/address.c
src/uct/sm/self/self.c
src/uct/sm/scopy/cma/

UCX version and configure flags

Output from ucx_info -v:

# Library version: 1.23.0
# Library path: /path/to/install/lib/libucs.so.0
# API headers version: 1.23.0
# Git branch '<unknown>', revision bade183
# Configured with: CC=clang CXX=clang++
#   CFLAGS=-g -O2 -fsanitize=alignment
#   CXXFLAGS=-g -O2 -fsanitize=alignment
#   LDFLAGS=-fsanitize=alignment
#   --enable-cma

Full Git revision:

bade18369e5245db37babf05ffbd88b1f5321a25

UCX environment variables

UCX_TLS=tcp,cma,self
UBSAN_OPTIONS=print_stacktrace=0:halt_on_error=0:report_error_type=1

Setup and versions

  • Operating system: Ubuntu 22.04.5 LTS
  • CPU architecture: x86-64
  • Kernel: Linux 5.15.0-185-generic
  • Compiler: Ubuntu Clang 14.0.0
  • RDMA/IB/RoCE: Not involved in this reproducer
  • GPU/CUDA: Not involved in this reproducer

Additional information

  • Open MPI version: Not applicable. The reproducer uses UCX's stock ucp_hello_world example directly.
  • ucx_info -v, successful server/client output, the filtered alignment log, and the reproduction script are included in the attached ucx-packed-address-report-v1.zip.
  • UCX_LOG_LEVEL=data was not used because communication succeeds. The observed output comes from Clang's alignment sanitizer rather than a UCX protocol error.
  • No artificially misaligned buffers or modified UCX examples were used.

I have not prepared a patch because the preferred repair may affect wire compatibility and hot-path performance. Possible directions appear to include:

  1. using memcpy-style alignment-safe load/store helpers for scalar fields;
  2. declaring intended transport address representations as explicitly packed; or
  3. aligning fields in the serialized representation, if wire compatibility permits it.

If this is considered a bug, which repair direction would best preserve UCX's wire-format and performance requirements?

I would be happy to validate a maintainer-preferred direction and prepare a focused patch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions