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

netdev-linux: Properly access 32-bit aligned rtnl_link_stats64 structs.

Detected by UB Sanitizer when running system tests:

  lib/netdev-linux.c:6250:26:
  runtime error: member access within misaligned address 0x00000229a204
  for type 'const struct rpl_rtnl_link_stats64', which requires 8 byte
  alignment
  0x00000229a204: note: pointer points here
    c4 00 17 00 01 00 00 00  00 00 00 00 01 00 00 00
                ^
    00 00 00 00 6e 00 00 00  00 00 00 00 6e 00 00 00

  0  0x89f10e in netdev_stats_from_rtnl_link_stats64 lib/netdev-linux.c:6250
  1  0x89f10e in get_stats_via_netlink lib/netdev-linux.c:6298
  2  0x8a039a in netdev_linux_get_stats lib/netdev-linux.c:2227
  3  0x68e149 in netdev_get_stats lib/netdev.c:1599
  4  0x407b21 in iface_refresh_stats vswitchd/bridge.c:2687
  5  0x419eb6 in iface_create vswitchd/bridge.c:2134
  6  0x419eb6 in bridge_add_ports__ vswitchd/bridge.c:1170
  7  0x41f71c in bridge_add_ports vswitchd/bridge.c:1181
  8  0x41f71c in bridge_reconfigure vswitchd/bridge.c:898
  9  0x429f59 in bridge_run vswitchd/bridge.c:3331
  10 0x430af3 in main vswitchd/ovs-vswitchd.c:129
  11 0x7fbdfd43eb74 in __libc_start_main (/lib64/libc.so.6+0x27b74)
  12 0x4072fd in _start (/root/ovs/vswitchd/ovs-vswitchd+0x4072fd)

Signed-off-by: Dumitru Ceara <dceara@redhat.com>
Acked-by: Aaron Conole <aconole@redhat.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
Dumitru Ceara
2022-04-11 13:38:59 +02:00
committed by Ilya Maximets
parent a5cc859a42
commit c8c49a9db9
2 changed files with 11 additions and 1 deletions

View File

@@ -429,6 +429,9 @@ is_pow2(uintmax_t x)
* segfault, so it is important to be aware of correct alignment. */
#define ALIGNED_CAST(TYPE, ATTR) ((TYPE) (void *) (ATTR))
#define IS_PTR_ALIGNED(OBJ) \
(!(OBJ) || (uintptr_t) (OBJ) % __alignof__(OVS_TYPEOF(OBJ)) == 0)
#ifdef __cplusplus
}
#endif

View File

@@ -6295,7 +6295,14 @@ get_stats_via_netlink(const struct netdev *netdev_, struct netdev_stats *stats)
if (ofpbuf_try_pull(reply, NLMSG_HDRLEN + sizeof(struct ifinfomsg))) {
const struct nlattr *a = nl_attr_find(reply, 0, IFLA_STATS64);
if (a && nl_attr_get_size(a) >= sizeof(struct rtnl_link_stats64)) {
netdev_stats_from_rtnl_link_stats64(stats, nl_attr_get(a));
const struct rtnl_link_stats64 *lstats = nl_attr_get(a);
struct rtnl_link_stats64 aligned_lstats;
if (!IS_PTR_ALIGNED(lstats)) {
memcpy(&aligned_lstats, lstats, sizeof aligned_lstats);
lstats = &aligned_lstats;
}
netdev_stats_from_rtnl_link_stats64(stats, lstats);
error = 0;
} else {
a = nl_attr_find(reply, 0, IFLA_STATS);