From 3ff343a96b4cf21662376296e994a3ae9e7f0c82 Mon Sep 17 00:00:00 2001 From: Ilya Maximets Date: Wed, 14 Aug 2024 12:35:28 +0200 Subject: [PATCH] netdev-linux: Fix unaligned access to rpl_rtnl_link_stats64. Compilers are allowed to make alignment assumptions based on the pointer type passed to memcpy(). We have to cast before using it to avoid misaligned reads: lib/netdev-linux.c:6738:41: runtime error: load of misaligned address 0x51b000008db4 for type 'const struct rpl_rtnl_link_stats64 *', which requires 8 byte alignment 0x51b000008db4: note: pointer points here cc 00 17 00 01 00 00 00 00 00 00 00 01 00 00 00 ^ 0 0xad2d8 in get_stats_via_netlink lib/netdev-linux.c:6738:17 1 0x9dcce in netdev_linux_get_stats lib/netdev-linux.c:2293:13 2 0xee5b8 in netdev_get_stats lib/netdev.c:1722:16 3 0xc07ad in iface_refresh_stats vswitchd/bridge.c:2795:5 4 0xbf4fc in iface_create vswitchd/bridge.c:2274:5 5 0xbf4fc in bridge_add_ports__ vswitchd/bridge.c:1225:21 6 0x989fc in bridge_add_ports vswitchd/bridge.c:1236:5 7 0x989fc in bridge_reconfigure vswitchd/bridge.c:952:9 8 0x9102a in bridge_run vswitchd/bridge.c:3439:9 9 0xc8976 in main vswitchd/ovs-vswitchd.c:137:9 10 0x2a1c9 in __libc_start_call_main 11 0x2a28a in __libc_start_main 12 0xb3ff4 in _start (vswitchd/ovs-vswitchd+0x734ff4) Reported by Clang 18 with UBsan on Ubuntu 24.04. Casting the original 'void *' pointer returned from nl_attr_get() call to 'struct rpl_rtnl_link_stats64 *' also technically constitutes an undefined behavior, since the resulting pointer is not correctly aligned for the referenced type, but compilers do not insist on that today. Fixes: c8c49a9db9f2 ("netdev-linux: Properly access 32-bit aligned rtnl_link_stats64 structs.") Reviewed-by: Simon Horman Acked-by: Dumitru Ceara Signed-off-by: Ilya Maximets --- lib/netdev-linux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index d1ad031f116..6560108d162 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -6588,7 +6588,8 @@ get_stats_via_netlink(const struct netdev *netdev_, struct netdev_stats *stats) struct rtnl_link_stats64 aligned_lstats; if (!IS_PTR_ALIGNED(lstats)) { - memcpy(&aligned_lstats, lstats, sizeof aligned_lstats); + memcpy(&aligned_lstats, (void *) lstats, + sizeof aligned_lstats); lstats = &aligned_lstats; } netdev_stats_from_rtnl_link_stats64(stats, lstats);