Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit d824421

Browse files
Treehugger RobotGerrit Code Review
authored andcommitted
Merge "Fix ifaddrs error handling."
2 parents 49ef8c8 + 2295068 commit d824421

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

libc/bionic/bionic_netlink.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ bool NetlinkConnection::SendRequest(int type) {
6161
// Did we open a netlink socket yet?
6262
if (fd_ == -1) {
6363
fd_ = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
64+
if (fd_ == -1) return false;
6465
}
6566

6667
// Construct and send the message.
@@ -83,7 +84,11 @@ bool NetlinkConnection::ReadResponses(void callback(void*, nlmsghdr*), void* con
8384
nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(data_);
8485
for (; NLMSG_OK(hdr, static_cast<size_t>(bytes_read)); hdr = NLMSG_NEXT(hdr, bytes_read)) {
8586
if (hdr->nlmsg_type == NLMSG_DONE) return true;
86-
if (hdr->nlmsg_type == NLMSG_ERROR) return false;
87+
if (hdr->nlmsg_type == NLMSG_ERROR) {
88+
nlmsgerr* err = reinterpret_cast<nlmsgerr*>(NLMSG_DATA(hdr));
89+
errno = (hdr->nlmsg_len >= NLMSG_LENGTH(sizeof(nlmsgerr))) ? -err->error : EIO;
90+
return false;
91+
}
8792
callback(context, hdr);
8893
}
8994
}

tests/ifaddrs_test.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <ifaddrs.h>
2020

2121
#include <dirent.h>
22+
#include <fcntl.h>
2223
#include <linux/if_packet.h>
2324
#include <net/ethernet.h>
2425
#include <net/if.h>
@@ -28,6 +29,7 @@
2829

2930
#include <algorithm>
3031
#include <map>
32+
#include <thread>
3133
#include <vector>
3234

3335
TEST(ifaddrs, freeifaddrs_null) {
@@ -267,3 +269,40 @@ TEST(ifaddrs, inet6_scope_ids) {
267269

268270
freeifaddrs(addrs);
269271
}
272+
273+
TEST(ifaddrs, kernel_bug_31038971) {
274+
// Some kernels had a bug that would lead to an NLMSG_ERROR response,
275+
// but bionic wasn't setting errno based on the value in the message.
276+
// This is the test for the kernel bug, but on a device with a bad
277+
// kernel this test was also useful for testing the bionic errno fix.
278+
std::vector<std::thread*> threads;
279+
for (size_t i = 0; i < 128; ++i) {
280+
threads.push_back(new std::thread([]() {
281+
ifaddrs* addrs = nullptr;
282+
ASSERT_EQ(0, getifaddrs(&addrs)) << strerror(errno);
283+
freeifaddrs(addrs);
284+
}));
285+
}
286+
for (auto& t : threads) {
287+
t->join();
288+
delete t;
289+
}
290+
}
291+
292+
TEST(ifaddrs, errno_EMFILE) {
293+
std::vector<int> fds;
294+
while (true) {
295+
int fd = open("/dev/null", O_RDONLY|O_CLOEXEC);
296+
if (fd == -1) {
297+
ASSERT_EQ(EMFILE, errno);
298+
break;
299+
}
300+
fds.push_back(fd);
301+
}
302+
303+
ifaddrs* addrs;
304+
EXPECT_EQ(-1, getifaddrs(&addrs));
305+
EXPECT_EQ(EMFILE, errno);
306+
307+
for (int fd : fds) close(fd);
308+
}

0 commit comments

Comments
 (0)