aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-07-26 20:57:15 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-07-26 20:57:15 +0000
commit050b1b17b292418ca009ff0e07f25d1c036db246 (patch)
treede02337da2f7c450ad3fa0de8f565a44458f901f
parentf364b7ba45a4dc05c24b30f74b5e4561d5d20fec (diff)
parent4bdd7ed4cab82e06565e3de5c53d872f75140196 (diff)
downloadbionic-android11-security-release.tar.gz
Change-Id: Ibb3eca59fd37f77bdd1c2be3c37b5240bb4f0378
-rw-r--r--libc/bionic/ifaddrs.cpp32
1 files changed, 30 insertions, 2 deletions
diff --git a/libc/bionic/ifaddrs.cpp b/libc/bionic/ifaddrs.cpp
index e89b0bf11..153633353 100644
--- a/libc/bionic/ifaddrs.cpp
+++ b/libc/bionic/ifaddrs.cpp
@@ -28,6 +28,7 @@
#include <ifaddrs.h>
+#include <async_safe/log.h>
#include <cutils/misc.h> // FIRST_APPLICATION_UID
#include <errno.h>
#include <linux/if_packet.h>
@@ -205,12 +206,12 @@ static void __getifaddrs_callback(void* context, nlmsghdr* hdr) {
new_addr->interface_index = static_cast<int>(msg->ifa_index);
// If this is a known interface, copy what we already know.
+ // If we don't know about this interface yet, we try to resolve the name and flags using ioctl
+ // calls during postprocessing.
if (known_addr != nullptr) {
strcpy(new_addr->name, known_addr->name);
new_addr->ifa.ifa_name = new_addr->name;
new_addr->ifa.ifa_flags = known_addr->ifa.ifa_flags;
- } else {
- new_addr->ifa.ifa_flags = msg->ifa_flags;
}
// Go through the various bits of information and find the name, address
@@ -271,10 +272,34 @@ static void resolve_or_remove_nameless_interfaces(ifaddrs** list) {
} else {
prev_addr = addr;
}
+
addr = reinterpret_cast<ifaddrs_storage*>(next_addr);
}
}
+static void get_interface_flags_via_ioctl(ifaddrs** list) {
+ ScopedFd s(socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
+ if (s.get() == -1) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+ "socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC) failed in ifaddrs: %s",
+ strerror(errno));
+ return;
+ }
+
+ for (ifaddrs_storage* addr = reinterpret_cast<ifaddrs_storage*>(*list); addr != nullptr;
+ addr = reinterpret_cast<ifaddrs_storage*>(addr->ifa.ifa_next)) {
+ ifreq ifr = {};
+ strlcpy(ifr.ifr_name, addr->ifa.ifa_name, sizeof(ifr.ifr_name));
+ if (ioctl(s.get(), SIOCGIFFLAGS, &ifr) != -1) {
+ addr->ifa.ifa_flags = ifr.ifr_flags;
+ } else {
+ async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+ "ioctl(SIOCGIFFLAGS) for \"%s\" failed in ifaddrs: %s",
+ addr->ifa.ifa_name, strerror(errno));
+ }
+ }
+}
+
int getifaddrs(ifaddrs** out) {
// We construct the result directly into `out`, so terminate the list.
*out = nullptr;
@@ -303,6 +328,9 @@ int getifaddrs(ifaddrs** out) {
// If we weren't able to depend on GETLINK messages, it's possible some
// interfaces never got their name set. Resolve them using if_indextoname or remove them.
resolve_or_remove_nameless_interfaces(out);
+ // Similarly, without GETLINK messages, interfaces will not have their flags set.
+ // Resolve them using the SIOCGIFFLAGS ioctl call.
+ get_interface_flags_via_ioctl(out);
}
return 0;