2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-31 14:25:26 +00:00

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: c8c49a9db9 ("netdev-linux: Properly access 32-bit aligned rtnl_link_stats64 structs.")
Reviewed-by: Simon Horman <horms@kernel.org>
Acked-by: Dumitru Ceara <dceara@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
Ilya Maximets
2024-08-14 12:35:28 +02:00
parent 8d3cd41c38
commit ea2bd0d6fd

View File

@@ -6735,7 +6735,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);