microsoft / microsoft/one-collect
[Record-trace] Linux tracepoint payload values are shifted when native alignment adds padding
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 31
- Forks
- 17
- PR merge metrics
- No merged PRs in 30d
Description
When record-trace records Linux syscall tracepoints with record_event, numeric payload fields after a naturally aligned 32-bit field are decoded from the wrong offset.
For sys_enter_write, a one-byte write on file descriptor 3 is exported as fd=12884901888 (3 << 32). For sys_exit_write, a return value of 1 is exported as ret=4294967296 (1 << 32).
This reproduces with a standalone C program and direct record-trace; .NET and dotnet-trace are not involved.
Reproduction
// repro.c
#include <fcntl.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
int main(void)
{
int fd = open("/dev/null", O_WRONLY);
struct timespec delay = { .tv_sec = 0, .tv_nsec = 10000000 };
char value = 'x';
printf("%d\n", getpid());
fflush(stdout);
sleep(2);
for (int index = 0; index < 200; index++)
{
if (write(fd, &value, 1) != 1)
{
return 1;
}
nanosleep(&delay, NULL);
}
close(fd);
return 0;
}
cc -O2 repro.c -o repro
// write.script
let write_enter = event_from_tracefs("syscalls", "sys_enter_write");
record_event(write_enter);
let write_exit = event_from_tracefs("syscalls", "sys_exit_write");
record_event(write_exit);
Start the workload, then record its PID while it is in the initial sleep:
./repro > repro.log &
repro_pid=$!
sudo timeout --signal=INT --kill-after=30s 7s \
./target/release/record-trace \
--pid "$repro_pid" \
--script-file write.script \
--out write.nettrace \
--log-mode disabled
wait "$repro_pid"
Inspect the payloads for syscalls/sys_enter_write and syscalls/sys_exit_write.
Tested with record-trace 0.1.34271 from OneCollect commit ebfc498ab8b22baa56b1abf5dec72e8832d1c857.
All 200 loop iterations completed successfully, and the trace contained exactly 200 matching entry and exit events for the loop:
200 syscalls/sys_enter_write __syscall_nr=1, fd=12884901888
200 syscalls/sys_exit_write __syscall_nr=1, ret=4294967296
The application values were:
fd=3
count=1
ret=1
count was also not exposed in the NetTrace event payload, but that is the separate metadata-truncation problem already tracked by https://github.com/microsoft/one-collect/issues/191.
Expected
The trace exposes the aligned numeric values described by the tracefs event format:
fd=3
ret=1
Source observations
Tracefs supplies explicit offsets and sizes for every field, and tracefs.rs preserves those values in EventField.
The default record_event(event) path then uses with_record_all_event_data(), which copies the original tracepoint payload including native alignment padding:
https://github.com/microsoft/one-collect/blob/main/one_collect/src/helpers/exporting/scripting.rs
NetTrace metadata, however, describes fields sequentially and has no offsets or padding entries. On x64, the tracefs write formats place:
- the 32-bit syscall number at offset 8;
- the next 64-bit argument or return value at offset 16.
The NetTrace decoder expects the 64-bit value immediately after offset 12. Reading the four padding bytes followed by the low 32 bits of the value produces the observed left shift by 32 bits.
The absent count field occurs because the preceding const char * field truncates NetTrace metadata. That behavior is already tracked by #191 and is not the alignment defect reported here.
Suggested fix
Serialize tracefs fields into a packed export payload that matches the sequential NetTrace metadata rather than copying the native tracepoint buffer verbatim. Alternatively, represent every native padding range explicitly if the NetTrace format and consumers can support it.
Add a test using an event format with a 32-to-64-bit alignment gap, such as sys_exit_write, so the test is independent of the unsupported-pointer issue tracked by #191.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in one_collect/src/helpers/exporting/scripting.rs and trace the record_event path through the tracefs EventField offsets and sizes. Reproduce with sys_exit_write or an event containing a 32-to-64-bit alignment gap, then add a regression test and verify that the exported ret and fd values are 1 and 3 rather than shifted values.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- linux, rust
- Domain
- devtools, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100