Bug #63055 mysql assumes all ethernet devices are named ethX
Description:
This bug was originally reported in [1].
We can't rely on the fact that network device names are ethX any more. If we use biosdevname Udev helper [2], then for example Ethernet devices are labeled em1, but any other name can be used generally.
MySQL reads the HW address of any non-zero ethX device to generate an UUID. When a user uses biosdevname (which is default in Fedora by the way) then my_gethwaddr() returns 00:00:00:00:00:00 now.
We can loop through all devices using SIOCGIFCONF and get their HW address. There is a comment in mysys/my_gethwaddr.c that says we can use any of non-zero devices, which is how the suggested fix works.
[1] https://bugzilla.redhat.com/show_bug.cgi?id=682365
[2] http://freecode.com/projects/biosdevname
How to repeat:
Log values returned by my_gethwaddr() when biosdevname is used.
Suggested fix:
diff -up mysql-5.5.15/mysys/my_gethwaddr.c.netdevname mysql-5.5.15/mysys/my_gethwaddr.c
--- mysql-5.5.15/mysys/my_gethwaddr.c.netdevname 2011-07-13 21:09:02.000000000 +0200
+++ mysql-5.5.15/mysys/my_gethwaddr.c 2011-11-01 12:32:35.356119715 +0100
@@ -68,28 +68,47 @@ err:
#include <sys/ioctl.h>
#include <net/ethernet.h>
+#define MAX_IFS 64
+
my_bool my_gethwaddr(uchar *to)
{
int fd, res= 1;
struct ifreq ifr;
char zero_array[ETHER_ADDR_LEN] = {0};
+ struct ifconf ifc;
+ struct ifreq ifs[MAX_IFS], *ifri, *ifend;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
goto err;
- bzero(&ifr, sizeof(ifr));
- strnmov(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1);
+ ifc.ifc_len = sizeof(ifs);
+ ifc.ifc_req = ifs;
+ if (ioctl(fd, SIOCGIFCONF, &ifc) < 0)
+ {
+ close(fd);
+ goto err;
+ }
+
+ memcpy(to, zero_array, ETHER_ADDR_LEN);
- do
+ ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
+ for (ifri = ifc.ifc_req; ifri < ifend; ifri++)
{
- if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0)
+ if (ifri->ifr_addr.sa_family == AF_INET)
{
- memcpy(to, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
- res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1;
+ bzero(&ifr, sizeof(ifr));
+ strncpy(ifr.ifr_name, ifri->ifr_name, sizeof(ifr.ifr_name));
+
+ /* Get HW address */
+ if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0)
+ {
+ memcpy(to, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
+ if (!(res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1))
+ break;
+ }
}
- } while (res && (errno == 0 || errno == ENODEV) && ifr.ifr_name[3]++ < '6');
-
+ }
close(fd);
err:
return res;
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.039 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.