diff options
author | Dumitru Ceara <dceara@redhat.com> | 2022-04-11 13:38:59 +0200 |
---|---|---|
committer | Ilya Maximets <i.maximets@ovn.org> | 2022-05-17 23:13:55 +0200 |
commit | bea3efc85a3ea33514d244d81049bece8cde50ce (patch) | |
tree | 89f2b92236dfb5b1cc462e058309a6d72599a345 | |
parent | 2236212ce1e17aa744aec1afdbbf99a98a43d61d (diff) | |
download | openvswitch-bea3efc85a3ea33514d244d81049bece8cde50ce.tar.gz |
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>
-rw-r--r-- | include/openvswitch/util.h | 3 | ||||
-rw-r--r-- | lib/netdev-linux.c | 9 |
2 files changed, 11 insertions, 1 deletions
diff --git a/include/openvswitch/util.h b/include/openvswitch/util.h index 9a924719b..aa7104c68 100644 --- a/include/openvswitch/util.h +++ b/include/openvswitch/util.h @@ -427,6 +427,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 diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index 216ea208a..ef996eab0 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -6227,7 +6227,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); |