Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed stack corruption on some phones... #4

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Fra-Ktus
Copy link

@Fra-Ktus Fra-Ktus commented Apr 8, 2018

the dynamically allocated array on the stack can crash some phones, moved that to a block allocated in main memory.

…oved that to a block allocated in main memory.
@Mygod
Copy link

Mygod commented Jun 12, 2018

I tried your code and it's still doing stack corruptions... :/

@kerpra
Copy link

kerpra commented Nov 28, 2019

I tried your code and it's still doing stack corruptions... :/

Me too...

@Mario-Klebsch
Copy link

I also had a stack corrution and I think, I found the cause. The array struct ifaddrs *l_links[l_numLinks]; is too small. Its size is determined by counting the RTM_NEWLINK messages, but is is indexed by l_info->ifi_index - 1. When e.g. network namespaces are used, ifi_index values are not continuous. I added some print statements and got this output:

l_numLinks=2
l_info->ifi_index=1
l_info->ifi_index=4

So, l_numLinks should be determined by finding the max value of l_info->ifi_index.

@Mario-Klebsch
Copy link

The code also does not behave correctly, when the buffer for receiving Netlink messages is too small.

Here is my fix for both problems:

--- getifaddrs.c        (revision 15518)
+++ getifaddrs.c        (working copy)
@@ -96,8 +96,11 @@
         l_msg.msg_control = NULL;
         l_msg.msg_controllen = 0;
         l_msg.msg_flags = 0;
-        int l_result = recvmsg(p_socket, &l_msg, 0);
-
+        int l_result = recvmsg(p_socket, &l_msg, MSG_PEEK | MSG_TRUNC);
+        if (l_result > p_len)// buffer was too small
+            return -1;
+
+        l_result = recvmsg(p_socket, &l_msg, 0);
         if(l_result < 0)
         {
             if(errno == EINTR)
@@ -106,11 +109,6 @@
             }
             return -2;
         }
-
-        if(l_msg.msg_flags & MSG_TRUNC)
-        { // buffer was too small
-            return -1;
-        }
         return l_result;
     }
 }
@@ -521,9 +519,9 @@
     }
 }

-static unsigned countLinks(int p_socket, NetlinkList *p_netlinkList)
+static unsigned get_max_ifi_index(int p_socket, NetlinkList *p_netlinkList)
 {
-    unsigned l_links = 0;
+    unsigned l_max_ifi_index = 0;
     pid_t l_pid = getpid();
     for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
     {
@@ -543,12 +541,14 @@

             if(l_hdr->nlmsg_type == RTM_NEWLINK)
             {
-                ++l_links;
+                struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(l_hdr);
+                if (l_max_ifi_index < l_info->ifi_index)
+                   l_max_ifi_index = l_info->ifi_index;
             }
         }
     }

-    return l_links;
+    return l_max_ifi_index;
 }

 int getifaddrs(struct ifaddrs **ifap)
@@ -580,9 +580,9 @@
         return -1;
     }

-    unsigned l_numLinks = countLinks(l_socket, l_linkResults) + countLinks(l_socket, l_addrResults);
-    struct ifaddrs *l_links[l_numLinks];
-    memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *));
+    unsigned l_max_ifi_index = get_max_ifi_index(l_socket, l_linkResults) + get_max_ifi_index(l_socket, l_addrResults);
+    struct ifaddrs *l_links[l_max_ifi_index];
+    memset(l_links, 0, l_max_ifi_index * sizeof(struct ifaddrs *));

     interpret(l_socket, l_linkResults, l_links, ifap);
     interpret(l_socket, l_addrResults, l_links, ifap);

@Mygod
Copy link

Mygod commented Sep 21, 2020

In the end I copied the implementation from aosp: https://github.com/Mygod/DHCPv6-Client-Android/tree/master/mobile/src/main/cpp

@Mario-Klebsch
Copy link

The aosp version is only 240 lines, while this implementation is 600 lines.

But the short version uses an RX buffer with fixed size of 8192. I have not enough experience with Netlink communication to be sure, that it always is lage enough and no Netlink message gets truncated.

@surpass007
Copy link

I tried your code and it's still doing stack corruptions... :/

Me too...

me too..

@ShootingKing-AM
Copy link

The code also does not behave correctly, when the buffer for receiving Netlink messages is too small.

Here is my fix for both problems:

--- getifaddrs.c        (revision 15518)
+++ getifaddrs.c        (working copy)
@@ -96,8 +96,11 @@
         l_msg.msg_control = NULL;
         l_msg.msg_controllen = 0;
         l_msg.msg_flags = 0;
-        int l_result = recvmsg(p_socket, &l_msg, 0);
-
+        int l_result = recvmsg(p_socket, &l_msg, MSG_PEEK | MSG_TRUNC);
+        if (l_result > p_len)// buffer was too small
+            return -1;
+
+        l_result = recvmsg(p_socket, &l_msg, 0);
         if(l_result < 0)
         {
             if(errno == EINTR)
@@ -106,11 +109,6 @@
             }
             return -2;
         }
-
-        if(l_msg.msg_flags & MSG_TRUNC)
-        { // buffer was too small
-            return -1;
-        }
         return l_result;
     }
 }
@@ -521,9 +519,9 @@
     }
 }

-static unsigned countLinks(int p_socket, NetlinkList *p_netlinkList)
+static unsigned get_max_ifi_index(int p_socket, NetlinkList *p_netlinkList)
 {
-    unsigned l_links = 0;
+    unsigned l_max_ifi_index = 0;
     pid_t l_pid = getpid();
     for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
     {
@@ -543,12 +541,14 @@

             if(l_hdr->nlmsg_type == RTM_NEWLINK)
             {
-                ++l_links;
+                struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(l_hdr);
+                if (l_max_ifi_index < l_info->ifi_index)
+                   l_max_ifi_index = l_info->ifi_index;
             }
         }
     }

-    return l_links;
+    return l_max_ifi_index;
 }

 int getifaddrs(struct ifaddrs **ifap)
@@ -580,9 +580,9 @@
         return -1;
     }

-    unsigned l_numLinks = countLinks(l_socket, l_linkResults) + countLinks(l_socket, l_addrResults);
-    struct ifaddrs *l_links[l_numLinks];
-    memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *));
+    unsigned l_max_ifi_index = get_max_ifi_index(l_socket, l_linkResults) + get_max_ifi_index(l_socket, l_addrResults);
+    struct ifaddrs *l_links[l_max_ifi_index];
+    memset(l_links, 0, l_max_ifi_index * sizeof(struct ifaddrs *));

     interpret(l_socket, l_linkResults, l_links, ifap);
     interpret(l_socket, l_addrResults, l_links, ifap);

I cannot understand this diff, please make a PULL REQUEST with the fixed code if possible :( @Mario-Klebsch

@jim518057
Copy link

These days I use this code for try to add functions to support my Android HUAWEI P9. Because my HUAWEI P9 is API level 23, which doesn't have this function in NDK.

When I write a small program for test, It's always cause stack corruption in my Android phone.

After debug and trace, I found at:

char l_mask[16] = {0};

char l_mask[16] = {0};

I change this line to: char l_mask[20] = {0};

It looks like work well now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants