Add full support for UIDs in VPNs.
Major:
+ Implement the functions mentioned in http://go/android-multinetwork-routing
correctly, including handling accept(), connect(), setNetworkForSocket()
and protect() and supporting functions like canUserSelectNetwork().
+ Eliminate the old code path of getting/setting UID ranges through
SecondaryTableController (which is currently unused) and mUidMap.
Minor:
+ Rename some methods/variables for clarity and consistency.
+ Moved some methods in .cpp files to match declaration order in the .h files.
Bug: 15409918
Change-Id: Ic6ce3646c58cf645db0d9a53cbeefdd7ffafff93
diff --git a/server/FwmarkServer.cpp b/server/FwmarkServer.cpp
index e2d2079..3a540bd 100644
--- a/server/FwmarkServer.cpp
+++ b/server/FwmarkServer.cpp
@@ -29,10 +29,10 @@
}
bool FwmarkServer::onDataAvailable(SocketClient* client) {
- int fd = -1;
- int error = processClient(client, &fd);
- if (fd >= 0) {
- close(fd);
+ int socketFd = -1;
+ int error = processClient(client, &socketFd);
+ if (socketFd >= 0) {
+ close(socketFd);
}
// Always send a response even if there were connection errors or read errors, so that we don't
@@ -45,7 +45,7 @@
return false;
}
-int FwmarkServer::processClient(SocketClient* client, int* fd) {
+int FwmarkServer::processClient(SocketClient* client, int* socketFd) {
FwmarkCommand command;
iovec iov;
@@ -59,7 +59,7 @@
union {
cmsghdr cmh;
- char cmsg[CMSG_SPACE(sizeof(*fd))];
+ char cmsg[CMSG_SPACE(sizeof(*socketFd))];
} cmsgu;
memset(cmsgu.cmsg, 0, sizeof(cmsgu.cmsg));
@@ -77,17 +77,17 @@
cmsghdr* const cmsgh = CMSG_FIRSTHDR(&message);
if (cmsgh && cmsgh->cmsg_level == SOL_SOCKET && cmsgh->cmsg_type == SCM_RIGHTS &&
- cmsgh->cmsg_len == CMSG_LEN(sizeof(*fd))) {
- memcpy(fd, CMSG_DATA(cmsgh), sizeof(*fd));
+ cmsgh->cmsg_len == CMSG_LEN(sizeof(*socketFd))) {
+ memcpy(socketFd, CMSG_DATA(cmsgh), sizeof(*socketFd));
}
- if (*fd < 0) {
+ if (*socketFd < 0) {
return -EBADF;
}
Fwmark fwmark;
socklen_t fwmarkLen = sizeof(fwmark.intValue);
- if (getsockopt(*fd, SOL_SOCKET, SO_MARK, &fwmark.intValue, &fwmarkLen) == -1) {
+ if (getsockopt(*socketFd, SOL_SOCKET, SO_MARK, &fwmark.intValue, &fwmarkLen) == -1) {
return -errno;
}
@@ -114,27 +114,23 @@
fwmark.netId = command.netId;
if (command.netId == NETID_UNSET) {
fwmark.explicitlySelected = false;
- } else {
+ fwmark.protectedFromVpn = false;
+ permission = PERMISSION_NONE;
+ } else if (mNetworkController->canUserSelectNetwork(client->getUid(), command.netId)) {
fwmark.explicitlySelected = true;
- // If the socket already has the protectedFromVpn bit set, don't reset it, because
- // non-system apps (e.g.: VpnService) may also protect sockets.
- if ((permission & PERMISSION_SYSTEM) == PERMISSION_SYSTEM) {
- fwmark.protectedFromVpn = true;
- }
- if (!mNetworkController->isValidNetwork(command.netId)) {
- return -ENONET;
- }
- if (!mNetworkController->isUserPermittedOnNetwork(client->getUid(),
- command.netId)) {
- return -EPERM;
- }
+ fwmark.protectedFromVpn = mNetworkController->canProtect(client->getUid());
+ } else {
+ return -EPERM;
}
break;
}
case FwmarkCommand::PROTECT_FROM_VPN: {
- // set vpn protect
- // TODO
+ if (!mNetworkController->canProtect(client->getUid())) {
+ return -EPERM;
+ }
+ fwmark.protectedFromVpn = true;
+ permission = static_cast<Permission>(permission | fwmark.permission);
break;
}
@@ -146,7 +142,8 @@
fwmark.permission = permission;
- if (setsockopt(*fd, SOL_SOCKET, SO_MARK, &fwmark.intValue, sizeof(fwmark.intValue)) == -1) {
+ if (setsockopt(*socketFd, SOL_SOCKET, SO_MARK, &fwmark.intValue,
+ sizeof(fwmark.intValue)) == -1) {
return -errno;
}