-
Notifications
You must be signed in to change notification settings - Fork 248
Open
Description
Description
When CONFIG_NET_TIMESTAMP is enabled and a CAN socket sets the CAN_RAW_TIMESTAMP option via setsockopt(), transmitted CAN frames occasionally have incorrect CAN IDs. The corrupted IDs show a linear growth pattern matching system timestamp values.
Symptoms
- CAN frames sent via SocketCAN interface have wrong CAN IDs on the bus
- Corrupted IDs increase linearly over time (e.g., 0x00000001, 0x00000002, ...)
- Issue occurs more frequently when sending multiple frames in rapid succession
- Problem appears in
can_callback()but not incan_poll(), indicating data corruption during callback processing
Environment
- Platform: STM32H7 (STM32H743II)
- Configuration:
CONFIG_NET_TIMESTAMP=y,CONFIG_NET_CAN=y - Driver:
stm32_fdcan_sock.c
Steps to Reproduce
- Enable
CONFIG_NET_TIMESTAMPin NuttX configuration - Create a CAN raw socket:
int sock = socket(PF_CAN, SOCK_RAW, CAN_RAW); - Enable timestamp option:
int enable = 1;
setsockopt(sock, SOL_CAN_RAW, CAN_RAW_TIMESTAMP, &enable, sizeof(enable));
4. Send CAN frames using sendmsg() or write() - Monitor CAN bus - frames will have incorrect IDs matching timestamp values
Root Cause
In net/can/can_callback.c, lines 128-135:
#ifdef CONFIG_NET_TIMESTAMP
if (conn->sconn.s_timestamp)
{
struct timespec *ts = (struct timespec *)&dev->d_appdata[dev->d_len];
struct timeval *tv = (struct timeval *)&dev->d_appdata[dev->d_len];
dev->d_len += sizeof(struct timeval);
clock_systime_timespec(ts);
tv->tv_usec = ts->tv_nsec / 1000;
}
#endif
Issues:
- Buffer overflow: When dev->d_len == 0 (e.g., during CAN_POLL events), timestamp is written to the start of d_appdata, which overlaps with d_buf containing the CAN frame
- Type confusion: ts and tv point to the same memory location but are treated as different types
- Missing bounds check: No validation that dev->d_len > 0 before writing timestamp
The timestamp values (tv_sec and tv_usec) overwrite the can_id field in the CAN frame structure, causing transmission of frames with timestamp values as CAN IDs.
Suggested Fix
#ifdef CONFIG_NET_TIMESTAMP
if (conn->sconn.s_timestamp && dev->d_len > 0)
{
struct timeval *tv = (struct timeval *)&dev->d_appdata[dev->d_len];
struct timespec ts;
dev->d_len += sizeof(struct timeval);
clock_systime_timespec(&ts);
tv->tv_sec = ts.tv_sec;
tv->tv_usec = ts.tv_nsec / 1000;
}
#endif
Changes:
- Add dev->d_len > 0 check to prevent writing to empty buffer
- Use local timespec variable to avoid type confusion
- Properly set both tv_sec and tv_usec fields
Additional Considerations
- The issue is more pronounced with multiple frame transmission due to increased probability of CAN_POLL events with d_len == 0
- Similar code may exist in other network protocol callback functions
- Buffer pointer synchronization between d_buf and d_appdata should be verified in the driver layer
Workaround
Temporarily disable CONFIG_NET_TIMESTAMP or avoid using CAN_RAW_TIMESTAMP socket option.
References - File: nuttx/net/can/can_callback.c
- Related: stm32_fdcan_sock.c buffer management
- SocketCAN documentation on timestamp options
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels