From c6908e428c2a770dd2bb1d904c34836dc90ade7b Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 21 Mar 2024 11:10:48 +0100 Subject: [PATCH] Fix wrong struct layout in getInterfaceSpeedGLinkSettings The `SIOCETHTOOL` IOCTL expects a pointer to an instance of `ethtool_link_settings`. E.g. it will read the `cmd` member to determine what to do. However #346 reordered the memory layout of the pointer such that actually and array of `__32` values (zeroed out) is passed. Hence the IOCTL will either fail because an invalid command (`cmd=0`) is passed or the values read later by e.g. `ecmd.req.link_mode_masks_nwords` are something completely different. So `ethtool_link_settings` has to come before the (stack) memory used in the flexible array at the end of this struct. To avoid GCC warnigns/errors (see #345) an union is used that provides the current struct (i.e. with wrong order) and an access the actually used `struct ethtool_link_settings` at the top. --- gloo/common/linux.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gloo/common/linux.cc b/gloo/common/linux.cc index 423de67b0..b15b817d8 100644 --- a/gloo/common/linux.cc +++ b/gloo/common/linux.cc @@ -192,9 +192,12 @@ const std::string& infinibandToBusID(const std::string& name) { static int getInterfaceSpeedGLinkSettings(int sock, struct ifreq* ifr) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) constexpr auto link_mode_data_nwords = 3 * 127; - struct { - __u32 link_mode_data[link_mode_data_nwords]; + union { struct ethtool_link_settings req; + struct { // Only to provide the memory + __u32 link_mode_data[link_mode_data_nwords]; + struct ethtool_link_settings dummy; + }; } ecmd; int rv;