Bug #46440 memcmp() for struct sockaddr_storage is invalid

Submitted: 28 Jul 2009 22:58 Modified: 29 Jul 2009 5:56
Reporter: Will Murnane Email Updates:
Status: Duplicate Impact on me:
None 
Category:MySQL Server: Compiling Severity:S2 (Serious)
Version:mysql-cluster-gpl-7.0.6 OS:Solaris (Solaris 10u7)
Assigned to: CPU Architecture:Any

[28 Jul 2009 22:58] Will Murnane
Description:
On line 245 of sql/hostname.cc, memcmp is used to compare a struct sockaddr_storage* (in) to a struct sockaddr* (t_res->ai_addr).  I believe this is invalid, because of the following code I added to debug this problem.
printf("Getaddrinfo result: %0*X\n", t_res->ai_addrlen, t_res->ai_addr);
printf("In:                 %0*X\n", addrLen, in);
printf("Getaddrinfo result: %0*X\n", 4, ((struct sockaddr_in*)t_res->ai_addr)->sin_addr);
printf("In:                 %0*X\n", 4, ((struct sockaddr_in*)in)->sin_addr);
printf("Getaddrinfo result: %p\n", &((struct sockaddr_in*)t_res->ai_addr)->sin_addr);
printf("In:                 %p\n", &((struct sockaddr_in*)in)->sin_addr);

This code prints (for example):
Getaddrinfo result: 0000000008062110
In:                 0000000008047B84
Getaddrinfo result: FC5F5582
In:                 FC5F5582
Getaddrinfo result: 8062114
In:                 8047b88

This shows that because t_res->ai_addr (a struct sockaddr*) has a pointer as part of its structure, using memcmp() to compare the contents of "t_res->ai_addr" and "in" is invalid.

The attached patch *should* fix the problem... but it doesn't.

How to repeat:
Build mysql-cluster-gpl-7.0.6 on Solaris (or install the precompiled binaries).  Add a GRANT like:
GRANT ALL ON *.* to 'user'@'chasca.cs.umbc.edu';
Try to connect from the specified user and host.  Get an error like this:
Access denied for user 'user'@'::ffff:130.85.95.252'

Suggested fix:
--- mysql-cluster-gpl-7.0.6/sql/hostname.cc	Tue May 26 10:34:43 2009
+++ mysql-cluster-gpl-7.0.6-mod//sql/hostname.cc	Tue Jul 28 17:22:14 2009
@@ -137,6 +148,18 @@
 char * ip_to_hostname(struct sockaddr_storage *in, int addrLen, uint *errors)
 {
   char *name= NULL;
+  if (in->ss_family == AF_INET6)
+  {
+    if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6*)in)->sin6_addr))
+    {
+      struct sockaddr_in foo;
+      bzero(&foo, sizeof(struct sockaddr));
+      foo.sin_family = AF_INET;
+      foo.sin_port = ((struct sockaddr_in6*)in)->sin6_port;
+      memcpy(&foo.sin_addr.s_addr, &((struct sockaddr_in6*)in)->sin6_addr.s6_addr[12], 4);
+      in = (struct sockaddr_storage*)&foo;
+    }
+  }
 
   struct addrinfo hints,*res_lst= NULL,*t_res;
   int gxi_error;
@@ -149,7 +172,7 @@
   /* Historical comparison for 127.0.0.1 */
   gxi_error= getnameinfo((struct sockaddr *)in, addrLen,
                          hostname_buff, NI_MAXHOST,
-                         NULL, 0, NI_NUMERICHOST);
+                         NULL, 0, 0);
   if (gxi_error)
   {
     DBUG_PRINT("error",("getnameinfo returned %d", gxi_error));
@@ -242,8 +265,16 @@
   /* Check that 'getaddrinfo' returned the used ip */
   for (t_res= res_lst; t_res; t_res=t_res->ai_next)
   {
-    if (!memcmp(&(t_res->ai_addr), in,
-                sizeof(struct sockaddr_storage) ) )
+    if ((in->ss_family == t_res->ai_addr->sa_family) &&
+        (((in->ss_family == AF_INET) && 
+          (((struct sockaddr_in*)in)->sin_addr.s_addr == 
+          ((struct sockaddr_in*)t_res->ai_addr)->sin_addr.s_addr))
+        ||
+         ((in->ss_family == AF_INET6) &&
+           (!memcmp(
+            (void*)&((struct sockaddr_in6*)in)->sin6_addr,
+            (void*)&((struct sockaddr_in6*)t_res->ai_addr)->sin6_addr,
+            sizeof(struct in6_addr))))))
     {
       add_hostname(in,name);
       freeaddrinfo(res_lst);
[29 Jul 2009 5:56] Sveta Smirnova
Thank you for the report.

This is duplicate of bug #46336. Current 5.1 code does not contain memcmp call in sql/hostname.cc

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.051 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.