From ceb5bd787c8ce281e5f4343c5d4f77b41c3e2919 Mon Sep 17 00:00:00 2001 From: Sreeram Ramachandran Date: Mon, 12 May 2014 11:19:16 -0700 Subject: [PATCH] Introduce netd_client, a dynamic library that talks to netd. The library exists outside bionic. It is dynamically loaded, to replace selected standard socket syscalls with versions that talk to netd. Change connect() to use the library if available. (cherry picked from commit 3a6b627a14df8111b03e452f2df4b5f4938e0e49) Change-Id: Ib6198e19dbc306521a26fcecfdf6e8424d163fc9 --- libc/Android.mk | 2 + libc/SYSCALLS.TXT | 4 +- .../syscalls/{connect.S => __connect.S} | 4 +- .../syscalls/{connect.S => __connect.S} | 5 +- .../syscalls/{connect.S => __connect.S} | 4 +- .../syscalls/{connect.S => __connect.S} | 5 +- .../syscalls/{connect.S => __connect.S} | 4 +- .../syscalls/{connect.S => __connect.S} | 5 +- libc/bionic/NetdClient.cpp | 68 +++++++++++++++++++ libc/bionic/connect.cpp | 22 ++++++ libc/bionic/libc_init_dynamic.cpp | 4 ++ libc/private/NetdClient.h | 28 ++++++++ 12 files changed, 141 insertions(+), 14 deletions(-) rename libc/arch-arm/syscalls/{connect.S => __connect.S} (88%) rename libc/arch-arm64/syscalls/{connect.S => __connect.S} (88%) rename libc/arch-mips/syscalls/{connect.S => __connect.S} (89%) rename libc/arch-mips64/syscalls/{connect.S => __connect.S} (87%) rename libc/arch-x86/syscalls/{connect.S => __connect.S} (94%) rename libc/arch-x86_64/syscalls/{connect.S => __connect.S} (84%) create mode 100644 libc/bionic/NetdClient.cpp create mode 100644 libc/bionic/connect.cpp create mode 100644 libc/private/NetdClient.h diff --git a/libc/Android.mk b/libc/Android.mk index 5befacf51..4bae7648c 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -110,6 +110,7 @@ libc_bionic_src_files := \ bionic/clock.cpp \ bionic/clone.cpp \ bionic/cmsg_nxthdr.cpp \ + bionic/connect.cpp \ bionic/dirent.cpp \ bionic/dup2.cpp \ bionic/epoll_create.cpp \ @@ -141,6 +142,7 @@ libc_bionic_src_files := \ bionic/mkfifo.cpp \ bionic/mknod.cpp \ bionic/mntent.cpp \ + bionic/NetdClient.cpp \ bionic/open.cpp \ bionic/pause.cpp \ bionic/pipe.cpp \ diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index 93ed85cba..e9fb57522 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -234,7 +234,7 @@ int signalfd4(int, const sigset_t*, size_t, int) all int socket(int, int, int) arm,arm64,mips,mips64,x86_64 int socketpair(int, int, int, int*) arm,arm64,mips,mips64,x86_64 int bind(int, struct sockaddr*, int) arm,arm64,mips,mips64,x86_64 -int connect(int, struct sockaddr*, socklen_t) arm,arm64,mips,mips64,x86_64 +int __connect:connect(int, struct sockaddr*, socklen_t) arm,arm64,mips,mips64,x86_64 int listen(int, int) arm,arm64,mips,mips64,x86_64 int accept(int, struct sockaddr*, socklen_t*) arm,arm64,mips,mips64,x86_64 int accept4(int, struct sockaddr*, socklen_t*, int) arm,arm64,mips,mips64,x86_64 @@ -253,7 +253,7 @@ int sendmmsg(int, struct mmsghdr*, unsigned int, int) arm,arm64,mips # sockets for x86. These are done as an "indexed" call to socketcall syscall. int socket:socketcall:1(int, int, int) x86 int bind:socketcall:2(int, struct sockaddr*, int) x86 -int connect:socketcall:3(int, struct sockaddr*, socklen_t) x86 +int __connect:socketcall:3(int, struct sockaddr*, socklen_t) x86 int listen:socketcall:4(int, int) x86 int accept:socketcall:5(int, struct sockaddr*, socklen_t*) x86 int getsockname:socketcall:6(int, struct sockaddr*, socklen_t*) x86 diff --git a/libc/arch-arm/syscalls/connect.S b/libc/arch-arm/syscalls/__connect.S similarity index 88% rename from libc/arch-arm/syscalls/connect.S rename to libc/arch-arm/syscalls/__connect.S index f7a518876..8cb026cba 100644 --- a/libc/arch-arm/syscalls/connect.S +++ b/libc/arch-arm/syscalls/__connect.S @@ -2,7 +2,7 @@ #include -ENTRY(connect) +ENTRY(__connect) mov ip, r7 ldr r7, =__NR_connect swi #0 @@ -11,4 +11,4 @@ ENTRY(connect) bxls lr neg r0, r0 b __set_errno -END(connect) +END(__connect) diff --git a/libc/arch-arm64/syscalls/connect.S b/libc/arch-arm64/syscalls/__connect.S similarity index 88% rename from libc/arch-arm64/syscalls/connect.S rename to libc/arch-arm64/syscalls/__connect.S index d3cd43de7..c46f418ce 100644 --- a/libc/arch-arm64/syscalls/connect.S +++ b/libc/arch-arm64/syscalls/__connect.S @@ -2,7 +2,7 @@ #include -ENTRY(connect) +ENTRY(__connect) stp x29, x30, [sp, #-16]! mov x29, sp str x8, [sp, #-16]! @@ -18,4 +18,5 @@ ENTRY(connect) b.hi __set_errno ret -END(connect) +END(__connect) +.hidden __connect diff --git a/libc/arch-mips/syscalls/connect.S b/libc/arch-mips/syscalls/__connect.S similarity index 89% rename from libc/arch-mips/syscalls/connect.S rename to libc/arch-mips/syscalls/__connect.S index 6f106528b..f7ac916cb 100644 --- a/libc/arch-mips/syscalls/connect.S +++ b/libc/arch-mips/syscalls/__connect.S @@ -2,7 +2,7 @@ #include -ENTRY(connect) +ENTRY(__connect) .set noreorder .cpload t9 li v0, __NR_connect @@ -16,4 +16,4 @@ ENTRY(connect) j t9 nop .set reorder -END(connect) +END(__connect) diff --git a/libc/arch-mips64/syscalls/connect.S b/libc/arch-mips64/syscalls/__connect.S similarity index 87% rename from libc/arch-mips64/syscalls/connect.S rename to libc/arch-mips64/syscalls/__connect.S index 8fe2d56c1..b1475fb5a 100644 --- a/libc/arch-mips64/syscalls/connect.S +++ b/libc/arch-mips64/syscalls/__connect.S @@ -2,7 +2,7 @@ #include -ENTRY(connect) +ENTRY(__connect) .set push .set noreorder li v0, __NR_connect @@ -22,4 +22,5 @@ ENTRY(connect) j t9 move ra, t0 .set pop -END(connect) +END(__connect) +.hidden __connect diff --git a/libc/arch-x86/syscalls/connect.S b/libc/arch-x86/syscalls/__connect.S similarity index 94% rename from libc/arch-x86/syscalls/connect.S rename to libc/arch-x86/syscalls/__connect.S index c0d73cab4..2f53b3318 100644 --- a/libc/arch-x86/syscalls/connect.S +++ b/libc/arch-x86/syscalls/__connect.S @@ -2,7 +2,7 @@ #include -ENTRY(connect) +ENTRY(__connect) pushl %ebx pushl %ecx .cfi_def_cfa_offset 8 @@ -24,4 +24,4 @@ ENTRY(connect) popl %ecx popl %ebx ret -END(connect) +END(__connect) diff --git a/libc/arch-x86_64/syscalls/connect.S b/libc/arch-x86_64/syscalls/__connect.S similarity index 84% rename from libc/arch-x86_64/syscalls/connect.S rename to libc/arch-x86_64/syscalls/__connect.S index 23cdbae99..288484e74 100644 --- a/libc/arch-x86_64/syscalls/connect.S +++ b/libc/arch-x86_64/syscalls/__connect.S @@ -2,7 +2,7 @@ #include -ENTRY(connect) +ENTRY(__connect) movl $__NR_connect, %eax syscall cmpq $-MAX_ERRNO, %rax @@ -13,4 +13,5 @@ ENTRY(connect) orq $-1, %rax 1: ret -END(connect) +END(__connect) +.hidden __connect diff --git a/libc/bionic/NetdClient.cpp b/libc/bionic/NetdClient.cpp new file mode 100644 index 000000000..56d82445b --- /dev/null +++ b/libc/bionic/NetdClient.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#ifdef __i386__ +#define __socketcall __attribute__((__cdecl__)) +#else +#define __socketcall +#endif + +extern "C" __socketcall int __connect(int, const sockaddr*, socklen_t); + +NetdClientDispatch __netdClientDispatch __attribute__((aligned(32))) = { + __connect +}; + +#ifndef LIBC_STATIC + +#include + +template +static void netdClientInitFunction(void* handle, const char* symbol, FunctionType* function) { + typedef void (*InitFunctionType)(FunctionType*); + InitFunctionType initFunction = reinterpret_cast(dlsym(handle, symbol)); + if (initFunction != NULL) { + initFunction(function); + } +} + +static void netdClientInitImpl() { + void* netdClientHandle = dlopen("libnetd_client.so", RTLD_LAZY); + if (netdClientHandle == NULL) { + // If the library is not available, it's not an error. We'll just use + // default implementations of functions that it would've overridden. + return; + } + netdClientInitFunction(netdClientHandle, "netdClientInitConnect", + &__netdClientDispatch.connect); +} + +static pthread_once_t netdClientInitOnce = PTHREAD_ONCE_INIT; + +#endif // LIBC_STATIC + +extern "C" __LIBC_HIDDEN__ void netdClientInit() { +#ifndef LIBC_STATIC + if (pthread_once(&netdClientInitOnce, netdClientInitImpl)) { + __libc_format_log(ANDROID_LOG_ERROR, "netdClient", + "Unable to initialize netd_client component."); + } +#endif // LIBC_STATIC +} diff --git a/libc/bionic/connect.cpp b/libc/bionic/connect.cpp new file mode 100644 index 000000000..c5db46b89 --- /dev/null +++ b/libc/bionic/connect.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +int connect(int sockfd, const sockaddr* addr, socklen_t addrlen) { + return __netdClientDispatch.connect(sockfd, addr, addrlen); +} diff --git a/libc/bionic/libc_init_dynamic.cpp b/libc/bionic/libc_init_dynamic.cpp index 61fb887d6..3d98861df 100644 --- a/libc/bionic/libc_init_dynamic.cpp +++ b/libc/bionic/libc_init_dynamic.cpp @@ -58,6 +58,7 @@ extern "C" { extern void pthread_debug_init(void); extern void malloc_debug_init(void); extern void malloc_debug_fini(void); + extern void netdClientInit(void); }; // We flag the __libc_preinit function as a constructor to ensure @@ -79,6 +80,9 @@ __attribute__((constructor)) static void __libc_preinit() { // Hooks for the debug malloc and pthread libraries to let them know that we're starting up. pthread_debug_init(); malloc_debug_init(); + + // Hook for the netd client library to let it know that we're starting up. + netdClientInit(); } __LIBC_HIDDEN__ void __libc_postfini() { diff --git a/libc/private/NetdClient.h b/libc/private/NetdClient.h new file mode 100644 index 000000000..48c05cb9d --- /dev/null +++ b/libc/private/NetdClient.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PRIVATE_NETD_CLIENT_H +#define PRIVATE_NETD_CLIENT_H + +#include + +struct NetdClientDispatch { + int (*connect)(int, const sockaddr*, socklen_t); +}; + +extern NetdClientDispatch __netdClientDispatch; + +#endif // PRIVATE_NETD_CLIENT_H