Syscalls.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * Copyright (C) 2017 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "netdutils/Syscalls.h"
  17. #include <atomic>
  18. #include <type_traits>
  19. #include <utility>
  20. namespace android {
  21. namespace netdutils {
  22. namespace {
  23. // Retry syscall fn as long as it returns -1 with errno == EINTR
  24. template <typename FnT, typename... Params>
  25. typename std::result_of<FnT(Params...)>::type syscallRetry(FnT fn, Params&&... params) {
  26. auto rv = fn(std::forward<Params>(params)...);
  27. while ((rv == -1) && (errno == EINTR)) {
  28. rv = fn(std::forward<Params>(params)...);
  29. }
  30. return rv;
  31. }
  32. } // namespace
  33. // Production implementation of Syscalls that forwards to libc syscalls.
  34. class RealSyscalls final : public Syscalls {
  35. public:
  36. ~RealSyscalls() override = default;
  37. StatusOr<UniqueFd> open(const std::string& pathname, int flags, mode_t mode) const override {
  38. UniqueFd fd(::open(pathname.c_str(), flags, mode));
  39. if (!isWellFormed(fd)) {
  40. return statusFromErrno(errno, "open(\"" + pathname + "\"...) failed");
  41. }
  42. return fd;
  43. }
  44. StatusOr<UniqueFd> socket(int domain, int type, int protocol) const override {
  45. UniqueFd sock(::socket(domain, type, protocol));
  46. if (!isWellFormed(sock)) {
  47. return statusFromErrno(errno, "socket() failed");
  48. }
  49. return sock;
  50. }
  51. Status getsockname(Fd sock, sockaddr* addr, socklen_t* addrlen) const override {
  52. auto rv = ::getsockname(sock.get(), addr, addrlen);
  53. if (rv == -1) {
  54. return statusFromErrno(errno, "getsockname() failed");
  55. }
  56. return status::ok;
  57. }
  58. Status getsockopt(Fd sock, int level, int optname, void* optval,
  59. socklen_t* optlen) const override {
  60. auto rv = ::getsockopt(sock.get(), level, optname, optval, optlen);
  61. if (rv == -1) {
  62. return statusFromErrno(errno, "getsockopt() failed");
  63. }
  64. return status::ok;
  65. }
  66. Status setsockopt(Fd sock, int level, int optname, const void* optval,
  67. socklen_t optlen) const override {
  68. auto rv = ::setsockopt(sock.get(), level, optname, optval, optlen);
  69. if (rv == -1) {
  70. return statusFromErrno(errno, "setsockopt() failed");
  71. }
  72. return status::ok;
  73. }
  74. Status bind(Fd sock, const sockaddr* addr, socklen_t addrlen) const override {
  75. auto rv = ::bind(sock.get(), addr, addrlen);
  76. if (rv == -1) {
  77. return statusFromErrno(errno, "bind() failed");
  78. }
  79. return status::ok;
  80. }
  81. Status connect(Fd sock, const sockaddr* addr, socklen_t addrlen) const override {
  82. auto rv = syscallRetry(::connect, sock.get(), addr, addrlen);
  83. if (rv == -1) {
  84. return statusFromErrno(errno, "connect() failed");
  85. }
  86. return status::ok;
  87. }
  88. StatusOr<ifreq> ioctl(Fd sock, unsigned long request, ifreq* ifr) const override {
  89. auto rv = ::ioctl(sock.get(), request, ifr);
  90. if (rv == -1) {
  91. return statusFromErrno(errno, "ioctl() failed");
  92. }
  93. return *ifr;
  94. }
  95. StatusOr<UniqueFd> eventfd(unsigned int initval, int flags) const override {
  96. UniqueFd fd(::eventfd(initval, flags));
  97. if (!isWellFormed(fd)) {
  98. return statusFromErrno(errno, "eventfd() failed");
  99. }
  100. return fd;
  101. }
  102. StatusOr<int> ppoll(pollfd* fds, nfds_t nfds, double timeout) const override {
  103. timespec ts = {};
  104. ts.tv_sec = timeout;
  105. ts.tv_nsec = (timeout - ts.tv_sec) * 1e9;
  106. auto rv = syscallRetry(::ppoll, fds, nfds, &ts, nullptr);
  107. if (rv == -1) {
  108. return statusFromErrno(errno, "ppoll() failed");
  109. }
  110. return rv;
  111. }
  112. StatusOr<size_t> writev(Fd fd, const std::vector<iovec>& iov) const override {
  113. auto rv = syscallRetry(::writev, fd.get(), iov.data(), iov.size());
  114. if (rv == -1) {
  115. return statusFromErrno(errno, "writev() failed");
  116. }
  117. return rv;
  118. }
  119. StatusOr<size_t> write(Fd fd, const Slice buf) const override {
  120. auto rv = syscallRetry(::write, fd.get(), buf.base(), buf.size());
  121. if (rv == -1) {
  122. return statusFromErrno(errno, "write() failed");
  123. }
  124. return static_cast<size_t>(rv);
  125. }
  126. StatusOr<Slice> read(Fd fd, const Slice buf) const override {
  127. auto rv = syscallRetry(::read, fd.get(), buf.base(), buf.size());
  128. if (rv == -1) {
  129. return statusFromErrno(errno, "read() failed");
  130. }
  131. return Slice(buf.base(), rv);
  132. }
  133. StatusOr<size_t> sendto(Fd sock, const Slice buf, int flags, const sockaddr* dst,
  134. socklen_t dstlen) const override {
  135. auto rv = syscallRetry(::sendto, sock.get(), buf.base(), buf.size(), flags, dst, dstlen);
  136. if (rv == -1) {
  137. return statusFromErrno(errno, "sendto() failed");
  138. }
  139. return static_cast<size_t>(rv);
  140. }
  141. StatusOr<Slice> recvfrom(Fd sock, const Slice dst, int flags, sockaddr* src,
  142. socklen_t* srclen) const override {
  143. auto rv = syscallRetry(::recvfrom, sock.get(), dst.base(), dst.size(), flags, src, srclen);
  144. if (rv == -1) {
  145. return statusFromErrno(errno, "recvfrom() failed");
  146. }
  147. if (rv == 0) {
  148. return status::eof;
  149. }
  150. return take(dst, rv);
  151. }
  152. Status shutdown(Fd fd, int how) const override {
  153. auto rv = ::shutdown(fd.get(), how);
  154. if (rv == -1) {
  155. return statusFromErrno(errno, "shutdown() failed");
  156. }
  157. return status::ok;
  158. }
  159. Status close(Fd fd) const override {
  160. auto rv = ::close(fd.get());
  161. if (rv == -1) {
  162. return statusFromErrno(errno, "close() failed");
  163. }
  164. return status::ok;
  165. }
  166. StatusOr<UniqueFile> fopen(const std::string& path, const std::string& mode) const override {
  167. UniqueFile file(::fopen(path.c_str(), mode.c_str()));
  168. if (file == nullptr) {
  169. return statusFromErrno(errno, "fopen(\"" + path + "\", \"" + mode + "\") failed");
  170. }
  171. return file;
  172. }
  173. StatusOr<pid_t> fork() const override {
  174. pid_t rv = ::fork();
  175. if (rv == -1) {
  176. return statusFromErrno(errno, "fork() failed");
  177. }
  178. return rv;
  179. }
  180. StatusOr<int> vfprintf(FILE* file, const char* format, va_list ap) const override {
  181. auto rv = ::vfprintf(file, format, ap);
  182. if (rv == -1) {
  183. return statusFromErrno(errno, "vfprintf() failed");
  184. }
  185. return rv;
  186. }
  187. StatusOr<int> vfscanf(FILE* file, const char* format, va_list ap) const override {
  188. auto rv = ::vfscanf(file, format, ap);
  189. if (rv == -1) {
  190. return statusFromErrno(errno, "vfscanf() failed");
  191. }
  192. return rv;
  193. }
  194. Status fclose(FILE* file) const override {
  195. auto rv = ::fclose(file);
  196. if (rv == -1) {
  197. return statusFromErrno(errno, "fclose() failed");
  198. }
  199. return status::ok;
  200. }
  201. };
  202. SyscallsHolder::~SyscallsHolder() {
  203. delete &get();
  204. }
  205. Syscalls& SyscallsHolder::get() {
  206. while (true) {
  207. // memory_order_relaxed gives the compiler and hardware more
  208. // freedom. If we get a stale value (this should only happen
  209. // early in the execution of a program) the exchange code below
  210. // will loop until we get the most current value.
  211. auto* syscalls = mSyscalls.load(std::memory_order_relaxed);
  212. // Common case returns existing syscalls
  213. if (syscalls) {
  214. return *syscalls;
  215. }
  216. // This code will execute on first get()
  217. std::unique_ptr<Syscalls> tmp(new RealSyscalls());
  218. Syscalls* expected = nullptr;
  219. bool success = mSyscalls.compare_exchange_strong(expected, tmp.get());
  220. if (success) {
  221. // Ownership was transferred to mSyscalls already, must release()
  222. return *tmp.release();
  223. }
  224. }
  225. }
  226. Syscalls& SyscallsHolder::swap(Syscalls& syscalls) {
  227. return *mSyscalls.exchange(&syscalls);
  228. }
  229. SyscallsHolder sSyscalls;
  230. } // namespace netdutils
  231. } // namespace android