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 17 #include <atomic> 18 #include <type_traits> 19 #include <utility> 20 21 #include "netdutils/Syscalls.h" 22 23 namespace android { 24 namespace netdutils { 25 namespace { 26 27 // Retry syscall fn as long as it returns -1 with errno == EINTR 28 template <typename FnT, typename... Params> 29 typename std::result_of<FnT(Params...)>::type syscallRetry(FnT fn, Params&&... params) { 30 auto rv = fn(std::forward<Params>(params)...); 31 while ((rv == -1) && (errno == EINTR)) { 32 rv = fn(std::forward<Params>(params)...); 33 } 34 return rv; 35 } 36 37 } // namespace 38 39 // Production implementation of Syscalls that forwards to libc syscalls. 40 class RealSyscalls final : public Syscalls { 41 public: 42 ~RealSyscalls() override = default; 43 44 StatusOr<UniqueFd> open(const std::string& pathname, int flags, mode_t mode) const override { 45 UniqueFd fd(::open(pathname.c_str(), flags, mode)); 46 if (!isWellFormed(fd)) { 47 return statusFromErrno(errno, "open(\"" + pathname + "\"...) failed"); 48 } 49 return fd; 50 } 51 52 StatusOr<UniqueFd> socket(int domain, int type, int protocol) const override { 53 UniqueFd sock(::socket(domain, type, protocol)); 54 if (!isWellFormed(sock)) { 55 return statusFromErrno(errno, "socket() failed"); 56 } 57 return sock; 58 } 59 60 Status getsockname(Fd sock, sockaddr* addr, socklen_t* addrlen) const override { 61 auto rv = ::getsockname(sock.get(), addr, addrlen); 62 if (rv == -1) { 63 return statusFromErrno(errno, "getsockname() failed"); 64 } 65 return status::ok; 66 } 67 68 Status getsockopt(Fd sock, int level, int optname, void* optval, 69 socklen_t* optlen) const override { 70 auto rv = ::getsockopt(sock.get(), level, optname, optval, optlen); 71 if (rv == -1) { 72 return statusFromErrno(errno, "getsockopt() failed"); 73 } 74 return status::ok; 75 } 76 77 Status setsockopt(Fd sock, int level, int optname, const void* optval, 78 socklen_t optlen) const override { 79 auto rv = ::setsockopt(sock.get(), level, optname, optval, optlen); 80 if (rv == -1) { 81 return statusFromErrno(errno, "setsockopt() failed"); 82 } 83 return status::ok; 84 } 85 86 Status bind(Fd sock, const sockaddr* addr, socklen_t addrlen) const override { 87 auto rv = ::bind(sock.get(), addr, addrlen); 88 if (rv == -1) { 89 return statusFromErrno(errno, "bind() failed"); 90 } 91 return status::ok; 92 } 93 94 Status connect(Fd sock, const sockaddr* addr, socklen_t addrlen) const override { 95 auto rv = syscallRetry(::connect, sock.get(), addr, addrlen); 96 if (rv == -1) { 97 return statusFromErrno(errno, "connect() failed"); 98 } 99 return status::ok; 100 } 101 102 StatusOr<UniqueFd> eventfd(unsigned int initval, int flags) const override { 103 UniqueFd fd(::eventfd(initval, flags)); 104 if (!isWellFormed(fd)) { 105 return statusFromErrno(errno, "eventfd() failed"); 106 } 107 return fd; 108 } 109 110 StatusOr<int> ppoll(pollfd* fds, nfds_t nfds, double timeout) const override { 111 timespec ts = {}; 112 ts.tv_sec = timeout; 113 ts.tv_nsec = (timeout - ts.tv_sec) * 1e9; 114 auto rv = syscallRetry(::ppoll, fds, nfds, &ts, nullptr); 115 if (rv == -1) { 116 return statusFromErrno(errno, "ppoll() failed"); 117 } 118 return rv; 119 } 120 121 StatusOr<size_t> writev(Fd fd, const std::vector<iovec>& iov) const override { 122 auto rv = syscallRetry(::writev, fd.get(), iov.data(), iov.size()); 123 if (rv == -1) { 124 return statusFromErrno(errno, "writev() failed"); 125 } 126 return rv; 127 } 128 129 StatusOr<size_t> write(Fd fd, const Slice buf) const override { 130 auto rv = syscallRetry(::write, fd.get(), buf.base(), buf.size()); 131 if (rv == -1) { 132 return statusFromErrno(errno, "write() failed"); 133 } 134 return static_cast<size_t>(rv); 135 } 136 137 StatusOr<Slice> read(Fd fd, const Slice buf) const override { 138 auto rv = syscallRetry(::read, fd.get(), buf.base(), buf.size()); 139 if (rv == -1) { 140 return statusFromErrno(errno, "read() failed"); 141 } 142 return Slice(buf.base(), rv); 143 } 144 145 StatusOr<size_t> sendto(Fd sock, const Slice buf, int flags, const sockaddr* dst, 146 socklen_t dstlen) const override { 147 auto rv = syscallRetry(::sendto, sock.get(), buf.base(), buf.size(), flags, dst, dstlen); 148 if (rv == -1) { 149 return statusFromErrno(errno, "sendto() failed"); 150 } 151 return static_cast<size_t>(rv); 152 } 153 154 StatusOr<Slice> recvfrom(Fd sock, const Slice dst, int flags, sockaddr* src, 155 socklen_t* srclen) const override { 156 auto rv = syscallRetry(::recvfrom, sock.get(), dst.base(), dst.size(), flags, src, srclen); 157 if (rv == -1) { 158 return statusFromErrno(errno, "recvfrom() failed"); 159 } 160 if (rv == 0) { 161 return status::eof; 162 } 163 return take(dst, rv); 164 } 165 166 Status shutdown(Fd fd, int how) const override { 167 auto rv = ::shutdown(fd.get(), how); 168 if (rv == -1) { 169 return statusFromErrno(errno, "shutdown() failed"); 170 } 171 return status::ok; 172 } 173 174 Status close(Fd fd) const override { 175 auto rv = ::close(fd.get()); 176 if (rv == -1) { 177 return statusFromErrno(errno, "close() failed"); 178 } 179 return status::ok; 180 } 181 182 StatusOr<UniqueFile> fopen(const std::string& path, const std::string& mode) const override { 183 UniqueFile file(::fopen(path.c_str(), mode.c_str())); 184 if (file == NULL) { 185 return statusFromErrno(errno, "fopen(\"" + path + "\", \"" + mode + "\") failed"); 186 } 187 return file; 188 } 189 190 StatusOr<pid_t> fork() const override { 191 pid_t rv = ::fork(); 192 if (rv == -1) { 193 return statusFromErrno(errno, "fork() failed"); 194 } 195 return rv; 196 } 197 198 StatusOr<int> vfprintf(FILE* file, const char* format, va_list ap) const override { 199 auto rv = ::vfprintf(file, format, ap); 200 if (rv == -1) { 201 return statusFromErrno(errno, "vfprintf() failed"); 202 } 203 return rv; 204 } 205 206 StatusOr<int> vfscanf(FILE* file, const char* format, va_list ap) const override { 207 auto rv = ::vfscanf(file, format, ap); 208 if (rv == -1) { 209 return statusFromErrno(errno, "vfscanf() failed"); 210 } 211 return rv; 212 } 213 214 Status fclose(FILE* file) const override { 215 auto rv = ::fclose(file); 216 if (rv == -1) { 217 return statusFromErrno(errno, "fclose() failed"); 218 } 219 return status::ok; 220 } 221 }; 222 223 SyscallsHolder::~SyscallsHolder() { 224 delete &get(); 225 } 226 227 Syscalls& SyscallsHolder::get() { 228 while (true) { 229 // memory_order_relaxed gives the compiler and hardware more 230 // freedom. If we get a stale value (this should only happen 231 // early in the execution of a program) the exchange code below 232 // will loop until we get the most current value. 233 auto* syscalls = mSyscalls.load(std::memory_order_relaxed); 234 // Common case returns existing syscalls 235 if (syscalls) { 236 return *syscalls; 237 } 238 239 // This code will execute on first get() 240 std::unique_ptr<Syscalls> tmp(new RealSyscalls()); 241 Syscalls* expected = nullptr; 242 bool success = mSyscalls.compare_exchange_strong(expected, tmp.get()); 243 if (success) { 244 // Ownership was transferred to mSyscalls already, must release() 245 return *tmp.release(); 246 } 247 } 248 } 249 250 Syscalls& SyscallsHolder::swap(Syscalls& syscalls) { 251 return *mSyscalls.exchange(&syscalls); 252 } 253 254 SyscallsHolder sSyscalls; 255 256 } // namespace netdutils 257 } // namespace android 258