From bca909adef3ff1791d6b67a51655ca2dfeb67a87 Mon Sep 17 00:00:00 2001 From: Peter Gal Date: Wed, 13 Dec 2017 16:26:41 +0100 Subject: [PATCH] Android abstract socket Replace Android TCP communication with unix abstract sockets. This makes it possible to not require INTERNET permission for Android applications. --- renderdoc/CMakeLists.txt | 6 ++ renderdoc/api/replay/replay_enums.h | 5 +- renderdoc/core/android.cpp | 19 ++--- .../os/posix/android/android_network.cpp | 41 +++++++++++ .../os/posix/android/android_process.cpp | 31 +++++++-- renderdoc/os/posix/apple/apple_network.cpp | 39 +++++++++++ renderdoc/os/posix/linux/linux_network.cpp | 39 +++++++++++ renderdoc/os/posix/posix_network.cpp | 69 ++++++++++++++++--- renderdoc/os/posix/posix_network.h | 32 +++++++++ 9 files changed, 248 insertions(+), 33 deletions(-) create mode 100644 renderdoc/os/posix/android/android_network.cpp create mode 100644 renderdoc/os/posix/apple/apple_network.cpp create mode 100644 renderdoc/os/posix/linux/linux_network.cpp create mode 100644 renderdoc/os/posix/posix_network.h diff --git a/renderdoc/CMakeLists.txt b/renderdoc/CMakeLists.txt index dcc05ab47..040561343 100644 --- a/renderdoc/CMakeLists.txt +++ b/renderdoc/CMakeLists.txt @@ -197,7 +197,9 @@ if(ANDROID) os/posix/android/android_process.cpp os/posix/android/android_threading.cpp os/posix/android/android_hook.cpp + os/posix/android/android_network.cpp os/posix/posix_hook.h + os/posix/posix_network.h os/posix/posix_network.cpp os/posix/posix_process.cpp os/posix/posix_stringio.cpp @@ -214,7 +216,9 @@ elseif(APPLE) os/posix/apple/apple_process.cpp os/posix/apple/apple_threading.cpp os/posix/apple/apple_hook.cpp + os/posix/apple/apple_network.cpp os/posix/posix_hook.h + os/posix/posix_network.h os/posix/posix_network.cpp os/posix/posix_process.cpp os/posix/posix_stringio.cpp @@ -231,9 +235,11 @@ elseif(UNIX) os/posix/linux/linux_process.cpp os/posix/linux/linux_threading.cpp os/posix/linux/linux_hook.cpp + os/posix/linux/linux_network.cpp 3rdparty/plthook/plthook.h 3rdparty/plthook/plthook_elf.c os/posix/posix_hook.h + os/posix/posix_network.h os/posix/posix_network.cpp os/posix/posix_process.cpp os/posix/posix_stringio.cpp diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index 44c3e3f57..1f30e46d2 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -3501,9 +3501,8 @@ DOCUMENT(R"(A set of flags giving details of the current status of Android traca .. data:: MissingPermissions - The application being checked does not have the requesite permission: - - android.permission.INTERNET + The application being checked does not have the requesite permission. Currently there + are no required permissions. .. data:: NotDebuggable diff --git a/renderdoc/core/android.cpp b/renderdoc/core/android.cpp index 6f53a274d..042cb209c 100644 --- a/renderdoc/core/android.cpp +++ b/renderdoc/core/android.cpp @@ -112,13 +112,13 @@ string adbGetDeviceList() } void adbForwardPorts(int index, const std::string &deviceID) { + const char *forwardCommand = "forward tcp:%i localabstract:renderdoc_%i"; int offs = RenderDoc_AndroidPortOffset * (index + 1); - adbExecCommand(deviceID, - StringFormat::Fmt("forward tcp:%i tcp:%i", RenderDoc_RemoteServerPort + offs, - RenderDoc_RemoteServerPort)); - adbExecCommand(deviceID, - StringFormat::Fmt("forward tcp:%i tcp:%i", RenderDoc_FirstTargetControlPort + offs, - RenderDoc_FirstTargetControlPort)); + + adbExecCommand(deviceID, StringFormat::Fmt(forwardCommand, RenderDoc_RemoteServerPort + offs, + RenderDoc_RemoteServerPort)); + adbExecCommand(deviceID, StringFormat::Fmt(forwardCommand, RenderDoc_FirstTargetControlPort + offs, + RenderDoc_FirstTargetControlPort)); } uint32_t StartAndroidPackageForCapture(const char *host, const char *package) { @@ -430,12 +430,7 @@ bool PullAPK(const string &deviceID, const string &pkgPath, const string &apk) bool CheckPermissions(const string &dump) { - if(dump.find("android.permission.INTERNET") == string::npos) - { - RDCWARN("APK missing INTERNET permission"); - return false; - } - + // TODO: remove this if we are sure that there are no permissions to check. return true; } diff --git a/renderdoc/os/posix/android/android_network.cpp b/renderdoc/os/posix/android/android_network.cpp new file mode 100644 index 000000000..7a4694821 --- /dev/null +++ b/renderdoc/os/posix/android/android_network.cpp @@ -0,0 +1,41 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include +#include "os/os_specific.h" +#include "os/posix/posix_network.h" + +namespace Network +{ +uint32_t Socket::GetRemoteIP() const +{ + // Android uses abstract sockets which are only "localhost" accessible + return ntohl(MakeIP(127, 0, 0, 1)); +} + +Socket *CreateServerSocket(const char * /* bindaddr */, uint16_t port, int queuesize) +{ + return CreateAbstractServerSocket(port, queuesize); +} +}; diff --git a/renderdoc/os/posix/android/android_process.cpp b/renderdoc/os/posix/android/android_process.cpp index 86e34404a..3f75ed011 100644 --- a/renderdoc/os/posix/android/android_process.cpp +++ b/renderdoc/os/posix/android/android_process.cpp @@ -36,7 +36,7 @@ int GetIdentPort(pid_t childPid) { int ret = 0; - string procfile = StringFormat::Fmt("/proc/%d/net/tcp", (int)childPid); + string procfile = StringFormat::Fmt("/proc/%d/net/unix", (int)childPid); // try for a little while for the /proc entry to appear for(int retry = 0; retry < 10; retry++) @@ -60,14 +60,22 @@ int GetIdentPort(pid_t childPid) line[sz - 1] = 0; fgets(line, sz - 1, f); - int socketnum = 0, hexip = 0, hexport = 0; - int num = sscanf(line, " %d: %x:%x", &socketnum, &hexip, &hexport); + int port = 0; + char *startpos = strstr(line, "@renderdoc_"); - // find open listen socket on 0.0.0.0:port - if(num == 3 && hexip == 0 && hexport >= RenderDoc_FirstTargetControlPort && - hexport <= RenderDoc_LastTargetControlPort) + if(startpos == NULL) { - ret = hexport; + // This is not the line we are looking for, continue the processing. + continue; + } + + int num = sscanf(startpos, "@renderdoc_%d", &port); + + // find open listen abstract socket on 'renderdoc_' + if(num == 1 && port >= RenderDoc_FirstTargetControlPort && + port <= RenderDoc_LastTargetControlPort) + { + ret = port; break; } } @@ -75,6 +83,15 @@ int GetIdentPort(pid_t childPid) FileIO::fclose(f); } + if(ret == 0) + { + RDCWARN( + "Couldn't locate renderdoc target control listening port between @renderdoc_%u and " + "@renderdoc_%u in %s", + (uint32_t)RenderDoc_FirstTargetControlPort, (uint32_t)RenderDoc_LastTargetControlPort, + procfile.c_str()); + } + return ret; } diff --git a/renderdoc/os/posix/apple/apple_network.cpp b/renderdoc/os/posix/apple/apple_network.cpp new file mode 100644 index 000000000..e11d53101 --- /dev/null +++ b/renderdoc/os/posix/apple/apple_network.cpp @@ -0,0 +1,39 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "os/os_specific.h" +#include "os/posix/posix_network.h" + +namespace Network +{ +uint32_t Socket::GetRemoteIP() const +{ + return GetIPFromTCPSocket((int)socket); +} + +Socket *CreateServerSocket(const char *bindaddr, uint16_t port, int queuesize) +{ + return CreateTCPServerSocket(bindaddr, port, queuesize); +} +}; diff --git a/renderdoc/os/posix/linux/linux_network.cpp b/renderdoc/os/posix/linux/linux_network.cpp new file mode 100644 index 000000000..e11d53101 --- /dev/null +++ b/renderdoc/os/posix/linux/linux_network.cpp @@ -0,0 +1,39 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include "os/os_specific.h" +#include "os/posix/posix_network.h" + +namespace Network +{ +uint32_t Socket::GetRemoteIP() const +{ + return GetIPFromTCPSocket((int)socket); +} + +Socket *CreateServerSocket(const char *bindaddr, uint16_t port, int queuesize) +{ + return CreateTCPServerSocket(bindaddr, port, queuesize); +} +}; diff --git a/renderdoc/os/posix/posix_network.cpp b/renderdoc/os/posix/posix_network.cpp index 84541b173..a897a6f66 100644 --- a/renderdoc/os/posix/posix_network.cpp +++ b/renderdoc/os/posix/posix_network.cpp @@ -32,11 +32,14 @@ #include #include #include +#include #include #include #include "os/os_specific.h" #include "strings/string_utils.h" +#include "posix_network.h" + using std::string; // because strerror_r is a complete mess... @@ -96,16 +99,6 @@ bool Socket::Connected() const return (int)socket != -1; } -uint32_t Socket::GetRemoteIP() const -{ - sockaddr_in addr = {}; - socklen_t len = sizeof(addr); - - getpeername((int)socket, (sockaddr *)&addr, &len); - - return ntohl(addr.sin_addr.s_addr); -} - Socket *Socket::AcceptClient(bool wait) { do @@ -317,7 +310,17 @@ bool Socket::RecvDataBlocking(void *buf, uint32_t length) return true; } -Socket *CreateServerSocket(const char *bindaddr, uint16_t port, int queuesize) +uint32_t GetIPFromTCPSocket(int socket) +{ + sockaddr_in addr = {}; + socklen_t len = sizeof(addr); + + getpeername(socket, (sockaddr *)&addr, &len); + + return ntohl(addr.sin_addr.s_addr); +} + +Socket *CreateTCPServerSocket(const char *bindaddr, uint16_t port, int queuesize) { int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -358,6 +361,50 @@ Socket *CreateServerSocket(const char *bindaddr, uint16_t port, int queuesize) return new Socket((ptrdiff_t)s); } +Socket *CreateAbstractServerSocket(uint16_t port, int queuesize) +{ + char socketName[17] = {0}; + StringFormat::snprintf(socketName, 16, "renderdoc_%d", port); + int socketNameLength = strlen(socketName); + int s = socket(AF_UNIX, SOCK_STREAM, 0); + + if(s == -1) + { + RDCWARN("Unable to create unix socket"); + return NULL; + } + + sockaddr_un addr; + RDCEraseEl(addr); + + addr.sun_family = AF_UNIX; + // first char is '\0' + addr.sun_path[0] = '\0'; + strncpy(addr.sun_path + 1, socketName, socketNameLength); + + int result = bind(s, (sockaddr *)&addr, offsetof(sockaddr_un, sun_path) + 1 + socketNameLength); + if(result == -1) + { + RDCWARN("Failed to create abstract socket: %s", socketName); + close(s); + return NULL; + } + RDCLOG("Created and bind socket: %d", s); + + result = listen(s, queuesize); + if(result == -1) + { + RDCWARN("Failed to listen on %s", socketName); + close(s); + return NULL; + } + + int flags = fcntl(s, F_GETFL, 0); + fcntl(s, F_SETFL, flags | O_NONBLOCK); + + return new Socket((ptrdiff_t)s); +} + Socket *CreateClientSocket(const char *host, uint16_t port, int timeoutMS) { char portstr[7] = {0}; diff --git a/renderdoc/os/posix/posix_network.h b/renderdoc/os/posix/posix_network.h new file mode 100644 index 000000000..778a34ce6 --- /dev/null +++ b/renderdoc/os/posix/posix_network.h @@ -0,0 +1,32 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#pragma once + +namespace Network +{ +uint32_t GetIPFromTCPSocket(int socket); +Socket *CreateAbstractServerSocket(uint16_t port, int queuesize); +Socket *CreateTCPServerSocket(const char *bindaddr, uint16_t port, int queuesize); +}