1 /*
2 * Copyright (C) 2011 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 #define LOG_TAG "Linux"
18
19 #include <arpa/inet.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <ifaddrs.h>
23 #include <linux/rtnetlink.h>
24 #include <net/if.h>
25 #include <netdb.h>
26 #include <netinet/in.h>
27 #include <netpacket/packet.h>
28 #include <poll.h>
29 #include <pwd.h>
30 #include <signal.h>
31 #include <stdlib.h>
32 #include <sys/capability.h>
33 #include <sys/ioctl.h>
34 #include <sys/mman.h>
35 #include <sys/prctl.h>
36 #include <sys/resource.h>
37 #include <sys/socket.h>
38 #include <sys/stat.h>
39 #include <sys/syscall.h>
40 #include <sys/time.h>
41 #include <sys/types.h>
42 #include <sys/uio.h>
43 #include <sys/un.h>
44 #include <sys/utsname.h>
45 #include <sys/wait.h>
46 #include <sys/xattr.h>
47 #include <termios.h>
48 #include <unistd.h>
49
50 #include <memory>
51
52 #if defined(__BIONIC__)
53 #include <android/fdsan.h>
54 #endif
55
56 #include <android-base/file.h>
57 #include <android-base/logging.h>
58 #include <android-base/macros.h>
59 #include <android-base/strings.h>
60 #include <log/log.h>
61 #include <nativehelper/JNIHelp.h>
62 #include <nativehelper/ScopedBytes.h>
63 #include <nativehelper/ScopedLocalRef.h>
64 #include <nativehelper/ScopedPrimitiveArray.h>
65 #include <nativehelper/ScopedUtfChars.h>
66 #include <nativehelper/jni_macros.h>
67 #include <nativehelper/toStringArray.h>
68
69 #include "AsynchronousCloseMonitor.h"
70 #include "ExecStrings.h"
71 #include "JniConstants.h"
72 #include "JniException.h"
73 #include "NetworkUtilities.h"
74 #include "Portability.h"
75
76 #ifndef __unused
77 #define __unused __attribute__((__unused__))
78 #endif
79
80 #define TO_JAVA_STRING(NAME, EXP) \
81 jstring NAME = env->NewStringUTF(EXP); \
82 if ((NAME) == NULL) return NULL;
83
84 namespace {
85
86 jfieldID int32RefValueFid;
87 jfieldID int64RefValueFid;
88
89 } // namespace
90
91 struct addrinfo_deleter {
operator ()addrinfo_deleter92 void operator()(addrinfo* p) const {
93 if (p != NULL) { // bionic's freeaddrinfo(3) crashes when passed NULL.
94 freeaddrinfo(p);
95 }
96 }
97 };
98
99 struct c_deleter {
operator ()c_deleter100 void operator()(void* p) const {
101 free(p);
102 }
103 };
104
isIPv4MappedAddress(const sockaddr * sa)105 static bool isIPv4MappedAddress(const sockaddr *sa) {
106 const sockaddr_in6 *sin6 = reinterpret_cast<const sockaddr_in6*>(sa);
107 return sa != NULL && sa->sa_family == AF_INET6 &&
108 (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
109 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)); // We map 0.0.0.0 to ::, so :: is mapped.
110 }
111
112 /**
113 * Perform a socket operation that specifies an IP address, possibly falling back from specifying
114 * the address as an IPv4-mapped IPv6 address in a struct sockaddr_in6 to specifying it as an IPv4
115 * address in a struct sockaddr_in.
116 *
117 * This is needed because all sockets created by the java.net APIs are IPv6 sockets, and on those
118 * sockets, IPv4 operations use IPv4-mapped addresses stored in a struct sockaddr_in6. But sockets
119 * created using Linux.socket(AF_INET, ...) are IPv4 sockets and only support operations using IPv4
120 * socket addresses structures.
121 */
122 #define NET_IPV4_FALLBACK(jni_env, return_type, syscall_name, java_fd, java_addr, port, null_addr_ok, args...) ({ \
123 return_type _rc = -1; \
124 do { \
125 sockaddr_storage _ss; \
126 socklen_t _salen; \
127 if ((java_addr) == NULL && (null_addr_ok)) { \
128 /* No IP address specified (e.g., sendto() on a connected socket). */ \
129 _salen = 0; \
130 } else if (!inetAddressToSockaddr(jni_env, java_addr, port, _ss, _salen)) { \
131 /* Invalid socket address, return -1. inetAddressToSockaddr has already thrown. */ \
132 break; \
133 } \
134 sockaddr* _sa = _salen ? reinterpret_cast<sockaddr*>(&_ss) : NULL; \
135 /* inetAddressToSockaddr always returns an IPv6 sockaddr. Assume that java_fd was created \
136 * by Java API calls, which always create IPv6 socket fds, and pass it in as is. */ \
137 _rc = NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ##args, _sa, _salen); \
138 if (_rc == -1 && errno == EAFNOSUPPORT && _salen && isIPv4MappedAddress(_sa)) { \
139 /* We passed in an IPv4 address in an IPv6 sockaddr and the kernel told us that we got \
140 * the address family wrong. Pass in the same address in an IPv4 sockaddr. */ \
141 (jni_env)->ExceptionClear(); \
142 if (!inetAddressToSockaddrVerbatim(jni_env, java_addr, port, _ss, _salen)) { \
143 break; \
144 } \
145 _sa = reinterpret_cast<sockaddr*>(&_ss); \
146 _rc = NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ##args, _sa, _salen); \
147 } \
148 } while (0); \
149 _rc; }) \
150
151 /**
152 * Used to retry networking system calls that can be interrupted with a signal. Unlike
153 * TEMP_FAILURE_RETRY, this also handles the case where
154 * AsynchronousCloseMonitor::signalBlockedThreads(fd) is used to signal a close() or
155 * Thread.interrupt(). Other signals that result in an EINTR result are ignored and the system call
156 * is retried.
157 *
158 * Returns the result of the system call though a Java exception will be pending if the result is
159 * -1: a SocketException if signaled via AsynchronousCloseMonitor, or ErrnoException for other
160 * failures.
161 */
162 #define NET_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ...) ({ \
163 return_type _rc = -1; \
164 int _syscallErrno; \
165 do { \
166 bool _wasSignaled; \
167 { \
168 int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \
169 AsynchronousCloseMonitor _monitor(_fd); \
170 _rc = syscall_name(_fd, __VA_ARGS__); \
171 _syscallErrno = errno; \
172 _wasSignaled = _monitor.wasSignaled(); \
173 } \
174 if (_wasSignaled) { \
175 jniThrowException(jni_env, "java/net/SocketException", "Socket closed"); \
176 _rc = -1; \
177 break; \
178 } \
179 if (_rc == -1 && _syscallErrno != EINTR) { \
180 /* TODO: with a format string we could show the arguments too, like strace(1). */ \
181 throwErrnoException(jni_env, # syscall_name); \
182 break; \
183 } \
184 } while (_rc == -1); /* _syscallErrno == EINTR && !_wasSignaled */ \
185 if (_rc == -1) { \
186 /* If the syscall failed, re-set errno: throwing an exception might have modified it. */ \
187 errno = _syscallErrno; \
188 } \
189 _rc; })
190
191 /**
192 * Used to retry system calls that can be interrupted with a signal. Unlike TEMP_FAILURE_RETRY, this
193 * also handles the case where AsynchronousCloseMonitor::signalBlockedThreads(fd) is used to signal
194 * a close() or Thread.interrupt(). Other signals that result in an EINTR result are ignored and the
195 * system call is retried.
196 *
197 * Returns the result of the system call though a Java exception will be pending if the result is
198 * -1: an IOException if the file descriptor is already closed, a InterruptedIOException if signaled
199 * via AsynchronousCloseMonitor, or ErrnoException for other failures.
200 */
201 #define IO_FAILURE_RETRY(jni_env, return_type, syscall_name, java_fd, ...) ({ \
202 return_type _rc = -1; \
203 int _syscallErrno; \
204 do { \
205 bool _wasSignaled; \
206 { \
207 int _fd = jniGetFDFromFileDescriptor(jni_env, java_fd); \
208 AsynchronousCloseMonitor _monitor(_fd); \
209 _rc = syscall_name(_fd, __VA_ARGS__); \
210 _syscallErrno = errno; \
211 _wasSignaled = _monitor.wasSignaled(); \
212 } \
213 if (_wasSignaled) { \
214 jniThrowException(jni_env, "java/io/InterruptedIOException", # syscall_name " interrupted"); \
215 _rc = -1; \
216 break; \
217 } \
218 if (_rc == -1 && _syscallErrno != EINTR) { \
219 /* TODO: with a format string we could show the arguments too, like strace(1). */ \
220 throwErrnoException(jni_env, # syscall_name); \
221 break; \
222 } \
223 } while (_rc == -1); /* && _syscallErrno == EINTR && !_wasSignaled */ \
224 if (_rc == -1) { \
225 /* If the syscall failed, re-set errno: throwing an exception might have modified it. */ \
226 errno = _syscallErrno; \
227 } \
228 _rc; })
229
230 #define NULL_ADDR_OK true
231 #define NULL_ADDR_FORBIDDEN false
232
throwException(JNIEnv * env,jclass exceptionClass,jmethodID ctor3,jmethodID ctor2,const char * functionName,int error)233 static void throwException(JNIEnv* env, jclass exceptionClass, jmethodID ctor3, jmethodID ctor2,
234 const char* functionName, int error) {
235 jthrowable cause = NULL;
236 if (env->ExceptionCheck()) {
237 cause = env->ExceptionOccurred();
238 env->ExceptionClear();
239 }
240
241 ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName));
242 if (detailMessage.get() == NULL) {
243 // Not really much we can do here. We're probably dead in the water,
244 // but let's try to stumble on...
245 env->ExceptionClear();
246 }
247
248 jobject exception;
249 if (cause != NULL) {
250 exception = env->NewObject(exceptionClass, ctor3, detailMessage.get(), error, cause);
251 } else {
252 exception = env->NewObject(exceptionClass, ctor2, detailMessage.get(), error);
253 }
254 env->Throw(reinterpret_cast<jthrowable>(exception));
255 }
256
throwErrnoException(JNIEnv * env,const char * functionName)257 static void throwErrnoException(JNIEnv* env, const char* functionName) {
258 int error = errno;
259 jclass errnoExceptionClass = JniConstants::GetErrnoExceptionClass(env);
260 static jmethodID ctor3 = env->GetMethodID(errnoExceptionClass,
261 "<init>", "(Ljava/lang/String;ILjava/lang/Throwable;)V");
262 static jmethodID ctor2 = env->GetMethodID(errnoExceptionClass,
263 "<init>", "(Ljava/lang/String;I)V");
264 throwException(env, errnoExceptionClass, ctor3, ctor2, functionName, error);
265 }
266
throwGaiException(JNIEnv * env,const char * functionName,int error)267 static void throwGaiException(JNIEnv* env, const char* functionName, int error) {
268 jclass gaiExceptionClass = JniConstants::GetGaiExceptionClass(env);
269 // Cache the methods ids before we throw, so we don't call GetMethodID with a pending exception.
270 static jmethodID ctor3 = env->GetMethodID(gaiExceptionClass, "<init>",
271 "(Ljava/lang/String;ILjava/lang/Throwable;)V");
272 static jmethodID ctor2 = env->GetMethodID(gaiExceptionClass, "<init>",
273 "(Ljava/lang/String;I)V");
274 if (errno != 0) {
275 // EAI_SYSTEM should mean "look at errno instead", but both glibc and bionic seem to
276 // mess this up. In particular, if you don't have INTERNET permission, errno will be EACCES
277 // but you'll get EAI_NONAME or EAI_NODATA. So we want our GaiException to have a
278 // potentially-relevant ErrnoException as its cause even if error != EAI_SYSTEM.
279 // http://code.google.com/p/android/issues/detail?id=15722
280 throwErrnoException(env, functionName);
281 // Deliberately fall through to throw another exception...
282 }
283 throwException(env, gaiExceptionClass, ctor3, ctor2, functionName, error);
284 }
285
286 template <typename rc_t>
throwIfMinusOne(JNIEnv * env,const char * name,rc_t rc)287 static rc_t throwIfMinusOne(JNIEnv* env, const char* name, rc_t rc) {
288 if (rc == rc_t(-1)) {
289 throwErrnoException(env, name);
290 }
291 return rc;
292 }
293
294 template <typename ScopedT>
295 class IoVec {
296 public:
IoVec(JNIEnv * env,size_t bufferCount)297 IoVec(JNIEnv* env, size_t bufferCount) : mEnv(env), mBufferCount(bufferCount) {
298 }
299
init(jobjectArray javaBuffers,jintArray javaOffsets,jintArray javaByteCounts)300 bool init(jobjectArray javaBuffers, jintArray javaOffsets, jintArray javaByteCounts) {
301 // We can't delete our local references until after the I/O, so make sure we have room.
302 if (mEnv->PushLocalFrame(mBufferCount + 16) < 0) {
303 return false;
304 }
305 ScopedIntArrayRO offsets(mEnv, javaOffsets);
306 if (offsets.get() == NULL) {
307 return false;
308 }
309 ScopedIntArrayRO byteCounts(mEnv, javaByteCounts);
310 if (byteCounts.get() == NULL) {
311 return false;
312 }
313 // TODO: Linux actually has a 1024 buffer limit. glibc works around this, and we should too.
314 // TODO: you can query the limit at runtime with sysconf(_SC_IOV_MAX).
315 for (size_t i = 0; i < mBufferCount; ++i) {
316 jobject buffer = mEnv->GetObjectArrayElement(javaBuffers, i); // We keep this local ref.
317 mScopedBuffers.push_back(new ScopedT(mEnv, buffer));
318 jbyte* ptr = const_cast<jbyte*>(mScopedBuffers.back()->get());
319 if (ptr == NULL) {
320 return false;
321 }
322 struct iovec iov;
323 iov.iov_base = reinterpret_cast<void*>(ptr + offsets[i]);
324 iov.iov_len = byteCounts[i];
325 mIoVec.push_back(iov);
326 }
327 return true;
328 }
329
~IoVec()330 ~IoVec() {
331 for (size_t i = 0; i < mScopedBuffers.size(); ++i) {
332 delete mScopedBuffers[i];
333 }
334 mEnv->PopLocalFrame(NULL);
335 }
336
get()337 iovec* get() {
338 return &mIoVec[0];
339 }
340
size()341 size_t size() {
342 return mBufferCount;
343 }
344
345 private:
346 JNIEnv* mEnv;
347 size_t mBufferCount;
348 std::vector<iovec> mIoVec;
349 std::vector<ScopedT*> mScopedBuffers;
350 };
351
352 /**
353 * Returns a jbyteArray containing the sockaddr_un.sun_path from ss. As per unix(7) sa_len should be
354 * the length of ss as returned by getsockname(2), getpeername(2), or accept(2).
355 * If the returned array is of length 0 the sockaddr_un refers to an unnamed socket.
356 * A null pointer is returned in the event of an error. See unix(7) for more information.
357 */
getUnixSocketPath(JNIEnv * env,const sockaddr_storage & ss,const socklen_t & sa_len)358 static jbyteArray getUnixSocketPath(JNIEnv* env, const sockaddr_storage& ss,
359 const socklen_t& sa_len) {
360 if (ss.ss_family != AF_UNIX) {
361 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
362 "getUnixSocketPath unsupported ss_family: %i", ss.ss_family);
363 return NULL;
364 }
365
366 const struct sockaddr_un* un_addr = reinterpret_cast<const struct sockaddr_un*>(&ss);
367 // The length of sun_path is sa_len minus the length of the overhead (ss_family).
368 // See unix(7) for details. This calculation must match that of socket_make_sockaddr_un() in
369 // socket_local_client.c and javaUnixSocketAddressToSockaddr() to interoperate.
370 size_t pathLength = sa_len - offsetof(struct sockaddr_un, sun_path);
371
372 jbyteArray javaSunPath = env->NewByteArray(pathLength);
373 if (javaSunPath == NULL) {
374 return NULL;
375 }
376
377 if (pathLength > 0) {
378 env->SetByteArrayRegion(javaSunPath, 0, pathLength,
379 reinterpret_cast<const jbyte*>(&un_addr->sun_path));
380 }
381 return javaSunPath;
382 }
383
makeSocketAddress(JNIEnv * env,const sockaddr_storage & ss,const socklen_t sa_len)384 static jobject makeSocketAddress(JNIEnv* env, const sockaddr_storage& ss, const socklen_t sa_len) {
385 if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) {
386 jint port;
387 jobject inetAddress = sockaddrToInetAddress(env, ss, &port);
388 if (inetAddress == NULL) {
389 return NULL; // Exception already thrown.
390 }
391 static jmethodID ctor = env->GetMethodID(JniConstants::GetInetSocketAddressClass(env),
392 "<init>", "(Ljava/net/InetAddress;I)V");
393 if (ctor == NULL) {
394 return NULL;
395 }
396 return env->NewObject(JniConstants::GetInetSocketAddressClass(env), ctor, inetAddress, port);
397 } else if (ss.ss_family == AF_UNIX) {
398 static jmethodID ctor = env->GetMethodID(JniConstants::GetUnixSocketAddressClass(env),
399 "<init>", "([B)V");
400 if (ctor == NULL) {
401 return NULL;
402 }
403 jbyteArray javaSunPath = getUnixSocketPath(env, ss, sa_len);
404 if (!javaSunPath) {
405 return NULL;
406 }
407 return env->NewObject(JniConstants::GetUnixSocketAddressClass(env), ctor, javaSunPath);
408 } else if (ss.ss_family == AF_NETLINK) {
409 const struct sockaddr_nl* nl_addr = reinterpret_cast<const struct sockaddr_nl*>(&ss);
410 static jmethodID ctor = env->GetMethodID(JniConstants::GetNetlinkSocketAddressClass(env),
411 "<init>", "(II)V");
412 if (ctor == NULL) {
413 return NULL;
414 }
415 return env->NewObject(JniConstants::GetNetlinkSocketAddressClass(env), ctor,
416 static_cast<jint>(nl_addr->nl_pid),
417 static_cast<jint>(nl_addr->nl_groups));
418 } else if (ss.ss_family == AF_PACKET) {
419 const struct sockaddr_ll* sll = reinterpret_cast<const struct sockaddr_ll*>(&ss);
420 static jmethodID ctor = env->GetMethodID(JniConstants::GetPacketSocketAddressClass(env),
421 "<init>", "(SISB[B)V");
422 if (ctor == NULL) {
423 return NULL;
424 }
425 ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(sll->sll_halen));
426 if (byteArray.get() == NULL) {
427 return NULL;
428 }
429 env->SetByteArrayRegion(byteArray.get(), 0, sll->sll_halen,
430 reinterpret_cast<const jbyte*>(sll->sll_addr));
431 jobject packetSocketAddress = env->NewObject(JniConstants::GetPacketSocketAddressClass(env), ctor,
432 static_cast<jshort>(ntohs(sll->sll_protocol)),
433 static_cast<jint>(sll->sll_ifindex),
434 static_cast<jshort>(sll->sll_hatype),
435 static_cast<jbyte>(sll->sll_pkttype),
436 byteArray.get());
437 return packetSocketAddress;
438 }
439 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "unsupported ss_family: %d",
440 ss.ss_family);
441 return NULL;
442 }
443
makeStructPasswd(JNIEnv * env,const struct passwd & pw)444 static jobject makeStructPasswd(JNIEnv* env, const struct passwd& pw) {
445 TO_JAVA_STRING(pw_name, pw.pw_name);
446 TO_JAVA_STRING(pw_dir, pw.pw_dir);
447 TO_JAVA_STRING(pw_shell, pw.pw_shell);
448 static jmethodID ctor = env->GetMethodID(JniConstants::GetStructPasswdClass(env), "<init>",
449 "(Ljava/lang/String;IILjava/lang/String;Ljava/lang/String;)V");
450 if (ctor == NULL) {
451 return NULL;
452 }
453 return env->NewObject(JniConstants::GetStructPasswdClass(env), ctor,
454 pw_name, static_cast<jint>(pw.pw_uid), static_cast<jint>(pw.pw_gid), pw_dir, pw_shell);
455 }
456
makeStructTimespec(JNIEnv * env,const struct timespec & ts)457 static jobject makeStructTimespec(JNIEnv* env, const struct timespec& ts) {
458 static jmethodID ctor = env->GetMethodID(JniConstants::GetStructTimespecClass(env), "<init>",
459 "(JJ)V");
460 if (ctor == NULL) {
461 return NULL;
462 }
463 return env->NewObject(JniConstants::GetStructTimespecClass(env), ctor,
464 static_cast<jlong>(ts.tv_sec), static_cast<jlong>(ts.tv_nsec));
465 }
466
makeStructStat(JNIEnv * env,const struct stat64 & sb)467 static jobject makeStructStat(JNIEnv* env, const struct stat64& sb) {
468 static jmethodID ctor = env->GetMethodID(JniConstants::GetStructStatClass(env), "<init>",
469 "(JJIJIIJJLandroid/system/StructTimespec;Landroid/system/StructTimespec;Landroid/system/StructTimespec;JJ)V");
470 if (ctor == NULL) {
471 return NULL;
472 }
473
474 jobject atim_timespec = makeStructTimespec(env, sb.st_atim);
475 if (atim_timespec == NULL) {
476 return NULL;
477 }
478 jobject mtim_timespec = makeStructTimespec(env, sb.st_mtim);
479 if (mtim_timespec == NULL) {
480 return NULL;
481 }
482 jobject ctim_timespec = makeStructTimespec(env, sb.st_ctim);
483 if (ctim_timespec == NULL) {
484 return NULL;
485 }
486
487 return env->NewObject(JniConstants::GetStructStatClass(env), ctor,
488 static_cast<jlong>(sb.st_dev), static_cast<jlong>(sb.st_ino),
489 static_cast<jint>(sb.st_mode), static_cast<jlong>(sb.st_nlink),
490 static_cast<jint>(sb.st_uid), static_cast<jint>(sb.st_gid),
491 static_cast<jlong>(sb.st_rdev), static_cast<jlong>(sb.st_size),
492 atim_timespec, mtim_timespec, ctim_timespec,
493 static_cast<jlong>(sb.st_blksize), static_cast<jlong>(sb.st_blocks));
494 }
495
makeStructStatVfs(JNIEnv * env,const struct statvfs & sb)496 static jobject makeStructStatVfs(JNIEnv* env, const struct statvfs& sb) {
497 static jmethodID ctor = env->GetMethodID(JniConstants::GetStructStatVfsClass(env), "<init>",
498 "(JJJJJJJJJJJ)V");
499 if (ctor == NULL) {
500 return NULL;
501 }
502
503 return env->NewObject(JniConstants::GetStructStatVfsClass(env), ctor,
504 static_cast<jlong>(sb.f_bsize),
505 static_cast<jlong>(sb.f_frsize),
506 static_cast<jlong>(sb.f_blocks),
507 static_cast<jlong>(sb.f_bfree),
508 static_cast<jlong>(sb.f_bavail),
509 static_cast<jlong>(sb.f_files),
510 static_cast<jlong>(sb.f_ffree),
511 static_cast<jlong>(sb.f_favail),
512 static_cast<jlong>(sb.f_fsid),
513 static_cast<jlong>(sb.f_flag),
514 static_cast<jlong>(sb.f_namemax));
515 }
516
makeStructLinger(JNIEnv * env,const struct linger & l)517 static jobject makeStructLinger(JNIEnv* env, const struct linger& l) {
518 static jmethodID ctor = env->GetMethodID(JniConstants::GetStructLingerClass(env), "<init>", "(II)V");
519 if (ctor == NULL) {
520 return NULL;
521 }
522 return env->NewObject(JniConstants::GetStructLingerClass(env), ctor, l.l_onoff, l.l_linger);
523 }
524
makeStructTimeval(JNIEnv * env,const struct timeval & tv)525 static jobject makeStructTimeval(JNIEnv* env, const struct timeval& tv) {
526 static jmethodID ctor = env->GetMethodID(JniConstants::GetStructTimevalClass(env), "<init>", "(JJ)V");
527 if (ctor == NULL) {
528 return NULL;
529 }
530 return env->NewObject(JniConstants::GetStructTimevalClass(env), ctor,
531 static_cast<jlong>(tv.tv_sec), static_cast<jlong>(tv.tv_usec));
532 }
533
makeStructUcred(JNIEnv * env,const struct ucred & u __unused)534 static jobject makeStructUcred(JNIEnv* env, const struct ucred& u __unused) {
535 static jmethodID ctor = env->GetMethodID(JniConstants::GetStructUcredClass(env), "<init>", "(III)V");
536 if (ctor == NULL) {
537 return NULL;
538 }
539 return env->NewObject(JniConstants::GetStructUcredClass(env), ctor, u.pid, u.uid, u.gid);
540 }
541
makeStructUtsname(JNIEnv * env,const struct utsname & buf)542 static jobject makeStructUtsname(JNIEnv* env, const struct utsname& buf) {
543 TO_JAVA_STRING(sysname, buf.sysname);
544 TO_JAVA_STRING(nodename, buf.nodename);
545 TO_JAVA_STRING(release, buf.release);
546 TO_JAVA_STRING(version, buf.version);
547 TO_JAVA_STRING(machine, buf.machine);
548 static jmethodID ctor = env->GetMethodID(JniConstants::GetStructUtsnameClass(env), "<init>",
549 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
550 if (ctor == NULL) {
551 return NULL;
552 }
553 return env->NewObject(JniConstants::GetStructUtsnameClass(env), ctor,
554 sysname, nodename, release, version, machine);
555 };
556
fillIfreq(JNIEnv * env,jstring javaInterfaceName,struct ifreq & req)557 static bool fillIfreq(JNIEnv* env, jstring javaInterfaceName, struct ifreq& req) {
558 ScopedUtfChars interfaceName(env, javaInterfaceName);
559 if (interfaceName.c_str() == NULL) {
560 return false;
561 }
562 memset(&req, 0, sizeof(req));
563 strncpy(req.ifr_name, interfaceName.c_str(), sizeof(req.ifr_name));
564 req.ifr_name[sizeof(req.ifr_name) - 1] = '\0';
565 return true;
566 }
567
fillUnixSocketAddress(JNIEnv * env,jobject javaUnixSocketAddress,const sockaddr_storage & ss,const socklen_t & sa_len)568 static bool fillUnixSocketAddress(JNIEnv* env, jobject javaUnixSocketAddress,
569 const sockaddr_storage& ss, const socklen_t& sa_len) {
570 if (javaUnixSocketAddress == NULL) {
571 return true;
572 }
573 jbyteArray javaSunPath = getUnixSocketPath(env, ss, sa_len);
574 if (!javaSunPath) {
575 return false;
576 }
577
578 static jfieldID sunPathFid =
579 env->GetFieldID(JniConstants::GetUnixSocketAddressClass(env), "sun_path", "[B");
580 env->SetObjectField(javaUnixSocketAddress, sunPathFid, javaSunPath);
581 return true;
582 }
583
fillInetSocketAddress(JNIEnv * env,jobject javaInetSocketAddress,const sockaddr_storage & ss)584 static bool fillInetSocketAddress(JNIEnv* env, jobject javaInetSocketAddress,
585 const sockaddr_storage& ss) {
586 if (javaInetSocketAddress == NULL) {
587 return true;
588 }
589 // Fill out the passed-in InetSocketAddress with the sender's IP address and port number.
590 jint port;
591 jobject sender = sockaddrToInetAddress(env, ss, &port);
592 if (sender == NULL) {
593 return false;
594 }
595 static jfieldID holderFid = env->GetFieldID(JniConstants::GetInetSocketAddressClass(env), "holder",
596 "Ljava/net/InetSocketAddress$InetSocketAddressHolder;");
597 jobject holder = env->GetObjectField(javaInetSocketAddress, holderFid);
598
599 static jfieldID addressFid = env->GetFieldID(JniConstants::GetInetSocketAddressHolderClass(env),
600 "addr", "Ljava/net/InetAddress;");
601 static jfieldID portFid = env->GetFieldID(JniConstants::GetInetSocketAddressHolderClass(env), "port", "I");
602 env->SetObjectField(holder, addressFid, sender);
603 env->SetIntField(holder, portFid, port);
604 return true;
605 }
606
fillSocketAddress(JNIEnv * env,jobject javaSocketAddress,const sockaddr_storage & ss,const socklen_t & sa_len)607 static bool fillSocketAddress(JNIEnv* env, jobject javaSocketAddress, const sockaddr_storage& ss,
608 const socklen_t& sa_len) {
609 if (javaSocketAddress == NULL) {
610 return true;
611 }
612
613 if (env->IsInstanceOf(javaSocketAddress, JniConstants::GetInetSocketAddressClass(env))) {
614 return fillInetSocketAddress(env, javaSocketAddress, ss);
615 } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::GetUnixSocketAddressClass(env))) {
616 return fillUnixSocketAddress(env, javaSocketAddress, ss, sa_len);
617 }
618 jniThrowException(env, "java/lang/UnsupportedOperationException",
619 "unsupported SocketAddress subclass");
620 return false;
621
622 }
623
javaInetSocketAddressToInetAddressAndPort(JNIEnv * env,jobject javaInetSocketAddress,jobject & javaInetAddress,jint & port)624 static void javaInetSocketAddressToInetAddressAndPort(
625 JNIEnv* env, jobject javaInetSocketAddress, jobject& javaInetAddress, jint& port) {
626 static jfieldID holderFid = env->GetFieldID(JniConstants::GetInetSocketAddressClass(env), "holder",
627 "Ljava/net/InetSocketAddress$InetSocketAddressHolder;");
628 jobject holder = env->GetObjectField(javaInetSocketAddress, holderFid);
629
630 static jfieldID addressFid = env->GetFieldID(
631 JniConstants::GetInetSocketAddressHolderClass(env), "addr", "Ljava/net/InetAddress;");
632 static jfieldID portFid = env->GetFieldID(JniConstants::GetInetSocketAddressHolderClass(env), "port", "I");
633
634 javaInetAddress = env->GetObjectField(holder, addressFid);
635 port = env->GetIntField(holder, portFid);
636 }
637
javaInetSocketAddressToSockaddr(JNIEnv * env,jobject javaSocketAddress,sockaddr_storage & ss,socklen_t & sa_len)638 static bool javaInetSocketAddressToSockaddr(
639 JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
640 jobject javaInetAddress;
641 jint port;
642 javaInetSocketAddressToInetAddressAndPort(env, javaSocketAddress, javaInetAddress, port);
643 return inetAddressToSockaddr(env, javaInetAddress, port, ss, sa_len);
644 }
645
javaNetlinkSocketAddressToSockaddr(JNIEnv * env,jobject javaSocketAddress,sockaddr_storage & ss,socklen_t & sa_len)646 static bool javaNetlinkSocketAddressToSockaddr(
647 JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
648 static jfieldID nlPidFid = env->GetFieldID(
649 JniConstants::GetNetlinkSocketAddressClass(env), "nlPortId", "I");
650 static jfieldID nlGroupsFid = env->GetFieldID(
651 JniConstants::GetNetlinkSocketAddressClass(env), "nlGroupsMask", "I");
652
653 sockaddr_nl *nlAddr = reinterpret_cast<sockaddr_nl *>(&ss);
654 nlAddr->nl_family = AF_NETLINK;
655 nlAddr->nl_pid = env->GetIntField(javaSocketAddress, nlPidFid);
656 nlAddr->nl_groups = env->GetIntField(javaSocketAddress, nlGroupsFid);
657 sa_len = sizeof(sockaddr_nl);
658 return true;
659 }
660
javaUnixSocketAddressToSockaddr(JNIEnv * env,jobject javaUnixSocketAddress,sockaddr_storage & ss,socklen_t & sa_len)661 static bool javaUnixSocketAddressToSockaddr(
662 JNIEnv* env, jobject javaUnixSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
663 static jfieldID sunPathFid = env->GetFieldID(
664 JniConstants::GetUnixSocketAddressClass(env), "sun_path", "[B");
665
666 struct sockaddr_un* un_addr = reinterpret_cast<struct sockaddr_un*>(&ss);
667 memset (un_addr, 0, sizeof(sockaddr_un));
668 un_addr->sun_family = AF_UNIX;
669
670 jbyteArray javaSunPath = (jbyteArray) env->GetObjectField(javaUnixSocketAddress, sunPathFid);
671 jsize pathLength = env->GetArrayLength(javaSunPath);
672 if ((size_t) pathLength > sizeof(sockaddr_un::sun_path)) {
673 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
674 "sun_path too long: max=%i, is=%i",
675 sizeof(sockaddr_un::sun_path), pathLength);
676 return false;
677 }
678 env->GetByteArrayRegion(javaSunPath, 0, pathLength, (jbyte*) un_addr->sun_path);
679 // sa_len is sun_path plus the length of the overhead (ss_family_t). See unix(7) for
680 // details. This calculation must match that of socket_make_sockaddr_un() in
681 // socket_local_client.c and getUnixSocketPath() to interoperate.
682 sa_len = offsetof(struct sockaddr_un, sun_path) + pathLength;
683 return true;
684 }
685
javaPacketSocketAddressToSockaddr(JNIEnv * env,jobject javaSocketAddress,sockaddr_storage & ss,socklen_t & sa_len)686 static bool javaPacketSocketAddressToSockaddr(
687 JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
688 static jfieldID protocolFid = env->GetFieldID(
689 JniConstants::GetPacketSocketAddressClass(env), "sll_protocol", "S");
690 static jfieldID ifindexFid = env->GetFieldID(
691 JniConstants::GetPacketSocketAddressClass(env), "sll_ifindex", "I");
692 static jfieldID hatypeFid = env->GetFieldID(
693 JniConstants::GetPacketSocketAddressClass(env), "sll_hatype", "S");
694 static jfieldID pkttypeFid = env->GetFieldID(
695 JniConstants::GetPacketSocketAddressClass(env), "sll_pkttype", "B");
696 static jfieldID addrFid = env->GetFieldID(
697 JniConstants::GetPacketSocketAddressClass(env), "sll_addr", "[B");
698
699 sockaddr_ll *sll = reinterpret_cast<sockaddr_ll *>(&ss);
700 sll->sll_family = AF_PACKET;
701 sll->sll_protocol = htons(env->GetShortField(javaSocketAddress, protocolFid));
702 sll->sll_ifindex = env->GetIntField(javaSocketAddress, ifindexFid);
703 sll->sll_hatype = env->GetShortField(javaSocketAddress, hatypeFid);
704 sll->sll_pkttype = env->GetByteField(javaSocketAddress, pkttypeFid);
705
706 jbyteArray sllAddr = (jbyteArray) env->GetObjectField(javaSocketAddress, addrFid);
707 if (sllAddr == NULL) {
708 sll->sll_halen = 0;
709 memset(&sll->sll_addr, 0, sizeof(sll->sll_addr));
710 } else {
711 jsize len = env->GetArrayLength(sllAddr);
712 if ((size_t) len > sizeof(sll->sll_addr)) {
713 len = sizeof(sll->sll_addr);
714 }
715 sll->sll_halen = len;
716 env->GetByteArrayRegion(sllAddr, 0, len, (jbyte*) sll->sll_addr);
717 }
718 sa_len = sizeof(sockaddr_ll);
719 return true;
720 }
721
javaSocketAddressToSockaddr(JNIEnv * env,jobject javaSocketAddress,sockaddr_storage & ss,socklen_t & sa_len)722 static bool javaSocketAddressToSockaddr(
723 JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
724 if (javaSocketAddress == NULL) {
725 jniThrowNullPointerException(env, NULL);
726 return false;
727 }
728
729 if (env->IsInstanceOf(javaSocketAddress, JniConstants::GetNetlinkSocketAddressClass(env))) {
730 return javaNetlinkSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
731 } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::GetInetSocketAddressClass(env))) {
732 return javaInetSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
733 } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::GetPacketSocketAddressClass(env))) {
734 return javaPacketSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
735 } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::GetUnixSocketAddressClass(env))) {
736 return javaUnixSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
737 }
738 jniThrowException(env, "java/lang/UnsupportedOperationException",
739 "unsupported SocketAddress subclass");
740 return false;
741 }
742
doStat(JNIEnv * env,jstring javaPath,bool isLstat)743 static jobject doStat(JNIEnv* env, jstring javaPath, bool isLstat) {
744 ScopedUtfChars path(env, javaPath);
745 if (path.c_str() == NULL) {
746 return NULL;
747 }
748 struct stat64 sb;
749 int rc = isLstat ? TEMP_FAILURE_RETRY(lstat64(path.c_str(), &sb))
750 : TEMP_FAILURE_RETRY(stat64(path.c_str(), &sb));
751 if (rc == -1) {
752 throwErrnoException(env, isLstat ? "lstat" : "stat");
753 return NULL;
754 }
755 return makeStructStat(env, sb);
756 }
757
doGetSockName(JNIEnv * env,jobject javaFd,bool is_sockname)758 static jobject doGetSockName(JNIEnv* env, jobject javaFd, bool is_sockname) {
759 int fd = jniGetFDFromFileDescriptor(env, javaFd);
760 sockaddr_storage ss;
761 sockaddr* sa = reinterpret_cast<sockaddr*>(&ss);
762 socklen_t byteCount = sizeof(ss);
763 memset(&ss, 0, byteCount);
764 int rc = is_sockname ? TEMP_FAILURE_RETRY(getsockname(fd, sa, &byteCount))
765 : TEMP_FAILURE_RETRY(getpeername(fd, sa, &byteCount));
766 if (rc == -1) {
767 throwErrnoException(env, is_sockname ? "getsockname" : "getpeername");
768 return NULL;
769 }
770 return makeSocketAddress(env, ss, byteCount);
771 }
772
773 class Passwd {
774 public:
Passwd(JNIEnv * env)775 explicit Passwd(JNIEnv* env) : mEnv(env), mResult(NULL) {
776 mBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX);
777 mBuffer.reset(new char[mBufferSize]);
778 }
779
getpwnam(const char * name)780 jobject getpwnam(const char* name) {
781 return process("getpwnam_r", getpwnam_r(name, &mPwd, mBuffer.get(), mBufferSize, &mResult));
782 }
783
getpwuid(uid_t uid)784 jobject getpwuid(uid_t uid) {
785 return process("getpwuid_r", getpwuid_r(uid, &mPwd, mBuffer.get(), mBufferSize, &mResult));
786 }
787
get()788 struct passwd* get() {
789 return mResult;
790 }
791
792 private:
process(const char * syscall,int error)793 jobject process(const char* syscall, int error) {
794 if (mResult == NULL) {
795 errno = error;
796 throwErrnoException(mEnv, syscall);
797 return NULL;
798 }
799 return makeStructPasswd(mEnv, *mResult);
800 }
801
802 JNIEnv* mEnv;
803 std::unique_ptr<char[]> mBuffer;
804 size_t mBufferSize;
805 struct passwd mPwd;
806 struct passwd* mResult;
807 };
808
AssertException(JNIEnv * env)809 static void AssertException(JNIEnv* env) {
810 if (env->ExceptionCheck() == JNI_FALSE) {
811 env->FatalError("Expected exception");
812 }
813 }
814
815 // Note for capabilities functions:
816 // We assume the calls are rare enough that it does not make sense to cache class objects. The
817 // advantage is lower maintenance burden.
818
ReadStructCapUserHeader(JNIEnv * env,jobject java_header,__user_cap_header_struct * c_header)819 static bool ReadStructCapUserHeader(
820 JNIEnv* env, jobject java_header, __user_cap_header_struct* c_header) {
821 if (java_header == nullptr) {
822 jniThrowNullPointerException(env, "header is null");
823 return false;
824 }
825
826 ScopedLocalRef<jclass> header_class(env, env->FindClass("android/system/StructCapUserHeader"));
827 if (header_class.get() == nullptr) {
828 return false;
829 }
830
831 {
832 static jfieldID version_fid = env->GetFieldID(header_class.get(), "version", "I");
833 if (version_fid == nullptr) {
834 return false;
835 }
836 c_header->version = env->GetIntField(java_header, version_fid);
837 }
838
839 {
840 static jfieldID pid_fid = env->GetFieldID(header_class.get(), "pid", "I");
841 if (pid_fid == nullptr) {
842 return false;
843 }
844 c_header->pid = env->GetIntField(java_header, pid_fid);
845 }
846
847 return true;
848 }
849
SetStructCapUserHeaderVersion(JNIEnv * env,jobject java_header,__user_cap_header_struct * c_header)850 static void SetStructCapUserHeaderVersion(
851 JNIEnv* env, jobject java_header, __user_cap_header_struct* c_header) {
852 ScopedLocalRef<jclass> header_class(env, env->FindClass("android/system/StructCapUserHeader"));
853 if (header_class.get() == nullptr) {
854 env->ExceptionClear();
855 return;
856 }
857
858 static jfieldID version_fid = env->GetFieldID(header_class.get(), "version", "I");
859 if (version_fid == nullptr) {
860 env->ExceptionClear();
861 return;
862 }
863 env->SetIntField(java_header, version_fid, c_header->version);
864 }
865
CreateStructCapUserData(JNIEnv * env,jclass data_class,__user_cap_data_struct * c_data)866 static jobject CreateStructCapUserData(
867 JNIEnv* env, jclass data_class, __user_cap_data_struct* c_data) {
868 if (c_data == nullptr) {
869 // Should not happen.
870 jniThrowNullPointerException(env, "data is null");
871 return nullptr;
872 }
873
874 static jmethodID data_cons = env->GetMethodID(data_class, "<init>", "(III)V");
875 if (data_cons == nullptr) {
876 return nullptr;
877 }
878
879 jint e = static_cast<jint>(c_data->effective);
880 jint p = static_cast<jint>(c_data->permitted);
881 jint i = static_cast<jint>(c_data->inheritable);
882 return env->NewObject(data_class, data_cons, e, p, i);
883 }
884
ReadStructCapUserData(JNIEnv * env,jobject java_data,__user_cap_data_struct * c_data)885 static bool ReadStructCapUserData(JNIEnv* env, jobject java_data, __user_cap_data_struct* c_data) {
886 if (java_data == nullptr) {
887 jniThrowNullPointerException(env, "data is null");
888 return false;
889 }
890
891 ScopedLocalRef<jclass> data_class(env, env->FindClass("android/system/StructCapUserData"));
892 if (data_class.get() == nullptr) {
893 return false;
894 }
895
896 {
897 static jfieldID effective_fid = env->GetFieldID(data_class.get(), "effective", "I");
898 if (effective_fid == nullptr) {
899 return false;
900 }
901 c_data->effective = env->GetIntField(java_data, effective_fid);
902 }
903
904 {
905 static jfieldID permitted_fid = env->GetFieldID(data_class.get(), "permitted", "I");
906 if (permitted_fid == nullptr) {
907 return false;
908 }
909 c_data->permitted = env->GetIntField(java_data, permitted_fid);
910 }
911
912
913 {
914 static jfieldID inheritable_fid = env->GetFieldID(data_class.get(), "inheritable", "I");
915 if (inheritable_fid == nullptr) {
916 return false;
917 }
918 c_data->inheritable = env->GetIntField(java_data, inheritable_fid);
919 }
920
921 return true;
922 }
923
924 static constexpr size_t kMaxCapUserDataLength = 2U;
925 #ifdef _LINUX_CAPABILITY_VERSION_1
926 static_assert(kMaxCapUserDataLength >= _LINUX_CAPABILITY_U32S_1, "Length too small.");
927 #endif
928 #ifdef _LINUX_CAPABILITY_VERSION_2
929 static_assert(kMaxCapUserDataLength >= _LINUX_CAPABILITY_U32S_2, "Length too small.");
930 #endif
931 #ifdef _LINUX_CAPABILITY_VERSION_3
932 static_assert(kMaxCapUserDataLength >= _LINUX_CAPABILITY_U32S_3, "Length too small.");
933 #endif
934 #ifdef _LINUX_CAPABILITY_VERSION_4
935 static_assert(false, "Unsupported capability version, please update.");
936 #endif
937
GetCapUserDataLength(uint32_t version)938 static size_t GetCapUserDataLength(uint32_t version) {
939 #ifdef _LINUX_CAPABILITY_VERSION_1
940 if (version == _LINUX_CAPABILITY_VERSION_1) {
941 return _LINUX_CAPABILITY_U32S_1;
942 }
943 #endif
944 #ifdef _LINUX_CAPABILITY_VERSION_2
945 if (version == _LINUX_CAPABILITY_VERSION_2) {
946 return _LINUX_CAPABILITY_U32S_2;
947 }
948 #endif
949 #ifdef _LINUX_CAPABILITY_VERSION_3
950 if (version == _LINUX_CAPABILITY_VERSION_3) {
951 return _LINUX_CAPABILITY_U32S_3;
952 }
953 #endif
954 return 0;
955 }
956
Linux_accept(JNIEnv * env,jobject,jobject javaFd,jobject javaSocketAddress)957 static jobject Linux_accept(JNIEnv* env, jobject, jobject javaFd, jobject javaSocketAddress) {
958 sockaddr_storage ss;
959 socklen_t sl = sizeof(ss);
960 memset(&ss, 0, sizeof(ss));
961 sockaddr* peer = (javaSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;
962 socklen_t* peerLength = (javaSocketAddress != NULL) ? &sl : 0;
963 jint clientFd = NET_FAILURE_RETRY(env, int, accept, javaFd, peer, peerLength);
964 if (clientFd == -1 || !fillSocketAddress(env, javaSocketAddress, ss, *peerLength)) {
965 close(clientFd);
966 return NULL;
967 }
968 return (clientFd != -1) ? jniCreateFileDescriptor(env, clientFd) : NULL;
969 }
970
Linux_access(JNIEnv * env,jobject,jstring javaPath,jint mode)971 static jboolean Linux_access(JNIEnv* env, jobject, jstring javaPath, jint mode) {
972 ScopedUtfChars path(env, javaPath);
973 if (path.c_str() == NULL) {
974 return JNI_FALSE;
975 }
976 int rc = TEMP_FAILURE_RETRY(access(path.c_str(), mode));
977 if (rc == -1) {
978 throwErrnoException(env, "access");
979 }
980 return (rc == 0);
981 }
982
Linux_bind(JNIEnv * env,jobject,jobject javaFd,jobject javaAddress,jint port)983 static void Linux_bind(JNIEnv* env, jobject, jobject javaFd, jobject javaAddress, jint port) {
984 // We don't need the return value because we'll already have thrown.
985 (void) NET_IPV4_FALLBACK(env, int, bind, javaFd, javaAddress, port, NULL_ADDR_FORBIDDEN);
986 }
987
Linux_bindSocketAddress(JNIEnv * env,jobject thisObj,jobject javaFd,jobject javaSocketAddress)988 static void Linux_bindSocketAddress(
989 JNIEnv* env, jobject thisObj, jobject javaFd, jobject javaSocketAddress) {
990 if (javaSocketAddress != NULL &&
991 env->IsInstanceOf(javaSocketAddress, JniConstants::GetInetSocketAddressClass(env))) {
992 // Use the InetAddress version so we get the benefit of NET_IPV4_FALLBACK.
993 jobject javaInetAddress;
994 jint port;
995 javaInetSocketAddressToInetAddressAndPort(env, javaSocketAddress, javaInetAddress, port);
996 Linux_bind(env, thisObj, javaFd, javaInetAddress, port);
997 return;
998 }
999 sockaddr_storage ss;
1000 socklen_t sa_len;
1001 if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) {
1002 return; // Exception already thrown.
1003 }
1004
1005 const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss);
1006 // We don't need the return value because we'll already have thrown.
1007 (void) NET_FAILURE_RETRY(env, int, bind, javaFd, sa, sa_len);
1008 }
1009
Linux_capget(JNIEnv * env,jobject,jobject header)1010 static jobjectArray Linux_capget(JNIEnv* env, jobject, jobject header) {
1011 // Convert Java header struct to kernel datastructure.
1012 __user_cap_header_struct cap_header;
1013 if (!ReadStructCapUserHeader(env, header, &cap_header)) {
1014 AssertException(env);
1015 return nullptr;
1016 }
1017
1018 // Call capget.
1019 __user_cap_data_struct cap_data[kMaxCapUserDataLength];
1020 if (capget(&cap_header, &cap_data[0]) == -1) {
1021 // Check for EINVAL. In that case, mutate the header.
1022 if (errno == EINVAL) {
1023 int saved_errno = errno;
1024 SetStructCapUserHeaderVersion(env, header, &cap_header);
1025 errno = saved_errno;
1026 }
1027 throwErrnoException(env, "capget");
1028 return nullptr;
1029 }
1030
1031 // Create the result array.
1032 ScopedLocalRef<jclass> data_class(env, env->FindClass("android/system/StructCapUserData"));
1033 if (data_class.get() == nullptr) {
1034 return nullptr;
1035 }
1036 size_t result_size = GetCapUserDataLength(cap_header.version);
1037 ScopedLocalRef<jobjectArray> result(
1038 env, env->NewObjectArray(result_size, data_class.get(), nullptr));
1039 if (result.get() == nullptr) {
1040 return nullptr;
1041 }
1042 // Translate the values we got.
1043 for (size_t i = 0; i < result_size; ++i) {
1044 ScopedLocalRef<jobject> value(
1045 env, CreateStructCapUserData(env, data_class.get(), &cap_data[i]));
1046 if (value.get() == nullptr) {
1047 AssertException(env);
1048 return nullptr;
1049 }
1050 env->SetObjectArrayElement(result.get(), i, value.get());
1051 }
1052 return result.release();
1053 }
1054
Linux_capset(JNIEnv * env,jobject,jobject header,jobjectArray data)1055 static void Linux_capset(
1056 JNIEnv* env, jobject, jobject header, jobjectArray data) {
1057 // Convert Java header struct to kernel datastructure.
1058 __user_cap_header_struct cap_header;
1059 if (!ReadStructCapUserHeader(env, header, &cap_header)) {
1060 AssertException(env);
1061 return;
1062 }
1063 size_t result_size = GetCapUserDataLength(cap_header.version);
1064 // Ensure that the array has the expected length.
1065 if (env->GetArrayLength(data) != static_cast<jint>(result_size)) {
1066 jniThrowExceptionFmt(env,
1067 "java/lang/IllegalArgumentException",
1068 "Unsupported input length %d (expected %zu)",
1069 env->GetArrayLength(data),
1070 result_size);
1071 return;
1072 }
1073
1074 __user_cap_data_struct cap_data[kMaxCapUserDataLength];
1075 // Translate the values we got.
1076 for (size_t i = 0; i < result_size; ++i) {
1077 ScopedLocalRef<jobject> value(env, env->GetObjectArrayElement(data, i));
1078 if (!ReadStructCapUserData(env, value.get(), &cap_data[i])) {
1079 AssertException(env);
1080 return;
1081 }
1082 }
1083
1084 throwIfMinusOne(env, "capset", capset(&cap_header, &cap_data[0]));
1085 }
1086
Linux_chmod(JNIEnv * env,jobject,jstring javaPath,jint mode)1087 static void Linux_chmod(JNIEnv* env, jobject, jstring javaPath, jint mode) {
1088 ScopedUtfChars path(env, javaPath);
1089 if (path.c_str() == NULL) {
1090 return;
1091 }
1092 throwIfMinusOne(env, "chmod", TEMP_FAILURE_RETRY(chmod(path.c_str(), mode)));
1093 }
1094
Linux_chown(JNIEnv * env,jobject,jstring javaPath,jint uid,jint gid)1095 static void Linux_chown(JNIEnv* env, jobject, jstring javaPath, jint uid, jint gid) {
1096 ScopedUtfChars path(env, javaPath);
1097 if (path.c_str() == NULL) {
1098 return;
1099 }
1100 throwIfMinusOne(env, "chown", TEMP_FAILURE_RETRY(chown(path.c_str(), uid, gid)));
1101 }
1102
Linux_close(JNIEnv * env,jobject,jobject javaFd)1103 static void Linux_close(JNIEnv* env, jobject, jobject javaFd) {
1104 // Get the FileDescriptor's 'fd' field and clear it.
1105 // We need to do this before we can throw an IOException (http://b/3222087).
1106 if (javaFd == nullptr) {
1107 jniThrowNullPointerException(env, "null fd");
1108 return;
1109 }
1110 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1111 jniSetFileDescriptorOfFD(env, javaFd, -1);
1112
1113 #if defined(__BIONIC__)
1114 jlong ownerId = jniGetOwnerIdFromFileDescriptor(env, javaFd);
1115
1116 // Close with bionic's fd ownership tracking (which returns 0 in the case of EINTR).
1117 throwIfMinusOne(env, "close", android_fdsan_close_with_tag(fd, ownerId));
1118 #else
1119 // Even if close(2) fails with EINTR, the fd will have been closed.
1120 // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone else's fd.
1121 // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
1122 throwIfMinusOne(env, "close", close(fd));
1123 #endif
1124 }
1125
Linux_android_fdsan_exchange_owner_tag(JNIEnv * env,jclass,jobject javaFd,jlong expectedOwnerId,jlong newOwnerId)1126 static void Linux_android_fdsan_exchange_owner_tag(JNIEnv* env, jclass,
1127 jobject javaFd,
1128 jlong expectedOwnerId,
1129 jlong newOwnerId) {
1130 #if defined(__BIONIC__)
1131 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1132 android_fdsan_exchange_owner_tag(fd, expectedOwnerId, newOwnerId);
1133 #else
1134 UNUSED(env, javaFd, expectedOwnerId, newOwnerId);
1135 #endif
1136 }
1137
Linux_android_fdsan_get_owner_tag(JNIEnv * env,jclass,jobject javaFd)1138 static jlong Linux_android_fdsan_get_owner_tag(JNIEnv* env, jclass, jobject javaFd) {
1139 #if defined(__BIONIC__)
1140 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1141 return android_fdsan_get_owner_tag(fd);
1142 #else
1143 UNUSED(env, javaFd);
1144 return 0;
1145 #endif
1146 }
1147
Linux_android_fdsan_get_tag_type(JNIEnv * env,jclass,jlong tag)1148 static jstring Linux_android_fdsan_get_tag_type(JNIEnv* env, jclass, jlong tag) {
1149 #if defined(__BIONIC__)
1150 return env->NewStringUTF(android_fdsan_get_tag_type(tag));
1151 #else
1152 UNUSED(tag);
1153 return env->NewStringUTF("unknown");
1154 #endif
1155 }
1156
Linux_android_fdsan_get_tag_value(JNIEnv * env,jclass,jlong tag)1157 static jlong Linux_android_fdsan_get_tag_value(JNIEnv* env, jclass, jlong tag) {
1158 #if defined(__BIONIC__)
1159 UNUSED(env);
1160 return android_fdsan_get_tag_value(tag);
1161 #else
1162 UNUSED(env, tag);
1163 return 0;
1164 #endif
1165 }
1166
Linux_connect(JNIEnv * env,jobject,jobject javaFd,jobject javaAddress,jint port)1167 static void Linux_connect(JNIEnv* env, jobject, jobject javaFd, jobject javaAddress, jint port) {
1168 (void) NET_IPV4_FALLBACK(env, int, connect, javaFd, javaAddress, port, NULL_ADDR_FORBIDDEN);
1169 }
1170
Linux_connectSocketAddress(JNIEnv * env,jobject thisObj,jobject javaFd,jobject javaSocketAddress)1171 static void Linux_connectSocketAddress(
1172 JNIEnv* env, jobject thisObj, jobject javaFd, jobject javaSocketAddress) {
1173 if (javaSocketAddress != NULL &&
1174 env->IsInstanceOf(javaSocketAddress, JniConstants::GetInetSocketAddressClass(env))) {
1175 // Use the InetAddress version so we get the benefit of NET_IPV4_FALLBACK.
1176 jobject javaInetAddress;
1177 jint port;
1178 javaInetSocketAddressToInetAddressAndPort(env, javaSocketAddress, javaInetAddress, port);
1179 Linux_connect(env, thisObj, javaFd, javaInetAddress, port);
1180 return;
1181 }
1182 sockaddr_storage ss;
1183 socklen_t sa_len;
1184 if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) {
1185 return; // Exception already thrown.
1186 }
1187
1188 const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss);
1189 // We don't need the return value because we'll already have thrown.
1190 (void) NET_FAILURE_RETRY(env, int, connect, javaFd, sa, sa_len);
1191 }
1192
Linux_dup(JNIEnv * env,jobject,jobject javaOldFd)1193 static jobject Linux_dup(JNIEnv* env, jobject, jobject javaOldFd) {
1194 int oldFd = jniGetFDFromFileDescriptor(env, javaOldFd);
1195 int newFd = throwIfMinusOne(env, "dup", TEMP_FAILURE_RETRY(dup(oldFd)));
1196 return (newFd != -1) ? jniCreateFileDescriptor(env, newFd) : NULL;
1197 }
1198
Linux_dup2(JNIEnv * env,jobject,jobject javaOldFd,jint newFd)1199 static jobject Linux_dup2(JNIEnv* env, jobject, jobject javaOldFd, jint newFd) {
1200 int oldFd = jniGetFDFromFileDescriptor(env, javaOldFd);
1201 int fd = throwIfMinusOne(env, "dup2", TEMP_FAILURE_RETRY(dup2(oldFd, newFd)));
1202 return (fd != -1) ? jniCreateFileDescriptor(env, fd) : NULL;
1203 }
1204
Linux_environ(JNIEnv * env,jobject)1205 static jobjectArray Linux_environ(JNIEnv* env, jobject) {
1206 extern char** environ; // Standard, but not in any header file.
1207 return toStringArray(env, environ);
1208 }
1209
Linux_execve(JNIEnv * env,jobject,jstring javaFilename,jobjectArray javaArgv,jobjectArray javaEnvp)1210 static void Linux_execve(JNIEnv* env, jobject, jstring javaFilename, jobjectArray javaArgv, jobjectArray javaEnvp) {
1211 ScopedUtfChars path(env, javaFilename);
1212 if (path.c_str() == NULL) {
1213 return;
1214 }
1215
1216 ExecStrings argv(env, javaArgv);
1217 ExecStrings envp(env, javaEnvp);
1218 TEMP_FAILURE_RETRY(execve(path.c_str(), argv.get(), envp.get()));
1219
1220 throwErrnoException(env, "execve");
1221 }
1222
Linux_execv(JNIEnv * env,jobject,jstring javaFilename,jobjectArray javaArgv)1223 static void Linux_execv(JNIEnv* env, jobject, jstring javaFilename, jobjectArray javaArgv) {
1224 ScopedUtfChars path(env, javaFilename);
1225 if (path.c_str() == NULL) {
1226 return;
1227 }
1228
1229 ExecStrings argv(env, javaArgv);
1230 TEMP_FAILURE_RETRY(execv(path.c_str(), argv.get()));
1231
1232 throwErrnoException(env, "execv");
1233 }
1234
Linux_fchmod(JNIEnv * env,jobject,jobject javaFd,jint mode)1235 static void Linux_fchmod(JNIEnv* env, jobject, jobject javaFd, jint mode) {
1236 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1237 throwIfMinusOne(env, "fchmod", TEMP_FAILURE_RETRY(fchmod(fd, mode)));
1238 }
1239
Linux_fchown(JNIEnv * env,jobject,jobject javaFd,jint uid,jint gid)1240 static void Linux_fchown(JNIEnv* env, jobject, jobject javaFd, jint uid, jint gid) {
1241 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1242 throwIfMinusOne(env, "fchown", TEMP_FAILURE_RETRY(fchown(fd, uid, gid)));
1243 }
1244
Linux_fcntlFlock(JNIEnv * env,jobject,jobject javaFd,jint cmd,jobject javaFlock)1245 static jint Linux_fcntlFlock(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaFlock) {
1246 static jfieldID typeFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_type", "S");
1247 static jfieldID whenceFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_whence", "S");
1248 static jfieldID startFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_start", "J");
1249 static jfieldID lenFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_len", "J");
1250 static jfieldID pidFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_pid", "I");
1251
1252 struct flock64 lock;
1253 memset(&lock, 0, sizeof(lock));
1254 lock.l_type = env->GetShortField(javaFlock, typeFid);
1255 lock.l_whence = env->GetShortField(javaFlock, whenceFid);
1256 lock.l_start = env->GetLongField(javaFlock, startFid);
1257 lock.l_len = env->GetLongField(javaFlock, lenFid);
1258 lock.l_pid = env->GetIntField(javaFlock, pidFid);
1259
1260 int rc = IO_FAILURE_RETRY(env, int, fcntl, javaFd, cmd, &lock);
1261 if (rc != -1) {
1262 env->SetShortField(javaFlock, typeFid, lock.l_type);
1263 env->SetShortField(javaFlock, whenceFid, lock.l_whence);
1264 env->SetLongField(javaFlock, startFid, lock.l_start);
1265 env->SetLongField(javaFlock, lenFid, lock.l_len);
1266 env->SetIntField(javaFlock, pidFid, lock.l_pid);
1267 }
1268 return rc;
1269 }
1270
Linux_fcntlInt(JNIEnv * env,jobject,jobject javaFd,jint cmd,jint arg)1271 static jint Linux_fcntlInt(JNIEnv* env, jobject, jobject javaFd, jint cmd, jint arg) {
1272 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1273 return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd, arg)));
1274 }
1275
Linux_fcntlVoid(JNIEnv * env,jobject,jobject javaFd,jint cmd)1276 static jint Linux_fcntlVoid(JNIEnv* env, jobject, jobject javaFd, jint cmd) {
1277 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1278 return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd)));
1279 }
1280
Linux_fdatasync(JNIEnv * env,jobject,jobject javaFd)1281 static void Linux_fdatasync(JNIEnv* env, jobject, jobject javaFd) {
1282 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1283 throwIfMinusOne(env, "fdatasync", TEMP_FAILURE_RETRY(fdatasync(fd)));
1284 }
1285
Linux_fstat(JNIEnv * env,jobject,jobject javaFd)1286 static jobject Linux_fstat(JNIEnv* env, jobject, jobject javaFd) {
1287 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1288 struct stat64 sb;
1289 int rc = TEMP_FAILURE_RETRY(fstat64(fd, &sb));
1290 if (rc == -1) {
1291 throwErrnoException(env, "fstat");
1292 return NULL;
1293 }
1294 return makeStructStat(env, sb);
1295 }
1296
Linux_fstatvfs(JNIEnv * env,jobject,jobject javaFd)1297 static jobject Linux_fstatvfs(JNIEnv* env, jobject, jobject javaFd) {
1298 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1299 struct statvfs sb;
1300 int rc = TEMP_FAILURE_RETRY(fstatvfs(fd, &sb));
1301 if (rc == -1) {
1302 throwErrnoException(env, "fstatvfs");
1303 return NULL;
1304 }
1305 return makeStructStatVfs(env, sb);
1306 }
1307
Linux_fsync(JNIEnv * env,jobject,jobject javaFd)1308 static void Linux_fsync(JNIEnv* env, jobject, jobject javaFd) {
1309 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1310 throwIfMinusOne(env, "fsync", TEMP_FAILURE_RETRY(fsync(fd)));
1311 }
1312
Linux_ftruncate(JNIEnv * env,jobject,jobject javaFd,jlong length)1313 static void Linux_ftruncate(JNIEnv* env, jobject, jobject javaFd, jlong length) {
1314 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1315 throwIfMinusOne(env, "ftruncate", TEMP_FAILURE_RETRY(ftruncate64(fd, length)));
1316 }
1317
Linux_gai_strerror(JNIEnv * env,jobject,jint error)1318 static jstring Linux_gai_strerror(JNIEnv* env, jobject, jint error) {
1319 return env->NewStringUTF(gai_strerror(error));
1320 }
1321
Linux_android_getaddrinfo(JNIEnv * env,jobject,jstring javaNode,jobject javaHints,jint netId)1322 static jobjectArray Linux_android_getaddrinfo(JNIEnv* env, jobject, jstring javaNode,
1323 jobject javaHints, jint netId) {
1324 ScopedUtfChars node(env, javaNode);
1325 if (node.c_str() == NULL) {
1326 return NULL;
1327 }
1328
1329 static jfieldID flagsFid = env->GetFieldID(JniConstants::GetStructAddrinfoClass(env), "ai_flags", "I");
1330 static jfieldID familyFid = env->GetFieldID(JniConstants::GetStructAddrinfoClass(env), "ai_family", "I");
1331 static jfieldID socktypeFid = env->GetFieldID(JniConstants::GetStructAddrinfoClass(env), "ai_socktype", "I");
1332 static jfieldID protocolFid = env->GetFieldID(JniConstants::GetStructAddrinfoClass(env), "ai_protocol", "I");
1333
1334 addrinfo hints;
1335 memset(&hints, 0, sizeof(hints));
1336 hints.ai_flags = env->GetIntField(javaHints, flagsFid);
1337 hints.ai_family = env->GetIntField(javaHints, familyFid);
1338 hints.ai_socktype = env->GetIntField(javaHints, socktypeFid);
1339 hints.ai_protocol = env->GetIntField(javaHints, protocolFid);
1340
1341 addrinfo* addressList = NULL;
1342 errno = 0;
1343 int rc = android_getaddrinfofornet(node.c_str(), NULL, &hints, netId, 0, &addressList);
1344 std::unique_ptr<addrinfo, addrinfo_deleter> addressListDeleter(addressList);
1345 if (rc != 0) {
1346 throwGaiException(env, "android_getaddrinfo", rc);
1347 return NULL;
1348 }
1349
1350 // Count results so we know how to size the output array.
1351 int addressCount = 0;
1352 for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) {
1353 if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) {
1354 ++addressCount;
1355 } else {
1356 ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family);
1357 }
1358 }
1359 if (addressCount == 0) {
1360 return NULL;
1361 }
1362
1363 // Prepare output array.
1364 jobjectArray result = env->NewObjectArray(addressCount, JniConstants::GetInetAddressClass(env), NULL);
1365 if (result == NULL) {
1366 return NULL;
1367 }
1368
1369 // Examine returned addresses one by one, save them in the output array.
1370 int index = 0;
1371 for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) {
1372 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) {
1373 // Unknown address family. Skip this address.
1374 ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family);
1375 continue;
1376 }
1377
1378 // Convert each IP address into a Java byte array.
1379 sockaddr_storage& address = *reinterpret_cast<sockaddr_storage*>(ai->ai_addr);
1380 ScopedLocalRef<jobject> inetAddress(env, sockaddrToInetAddress(env, address, NULL));
1381 if (inetAddress.get() == NULL) {
1382 return NULL;
1383 }
1384 env->SetObjectArrayElement(result, index, inetAddress.get());
1385 ++index;
1386 }
1387 return result;
1388 }
1389
Linux_getegid(JNIEnv *,jobject)1390 static jint Linux_getegid(JNIEnv*, jobject) {
1391 return getegid();
1392 }
1393
Linux_geteuid(JNIEnv *,jobject)1394 static jint Linux_geteuid(JNIEnv*, jobject) {
1395 return geteuid();
1396 }
1397
Linux_getgid(JNIEnv *,jobject)1398 static jint Linux_getgid(JNIEnv*, jobject) {
1399 return getgid();
1400 }
1401
Linux_getenv(JNIEnv * env,jobject,jstring javaName)1402 static jstring Linux_getenv(JNIEnv* env, jobject, jstring javaName) {
1403 ScopedUtfChars name(env, javaName);
1404 if (name.c_str() == NULL) {
1405 return NULL;
1406 }
1407 return env->NewStringUTF(getenv(name.c_str()));
1408 }
1409
Linux_getnameinfo(JNIEnv * env,jobject,jobject javaAddress,jint flags)1410 static jstring Linux_getnameinfo(JNIEnv* env, jobject, jobject javaAddress, jint flags) {
1411 sockaddr_storage ss;
1412 socklen_t sa_len;
1413 if (!inetAddressToSockaddrVerbatim(env, javaAddress, 0, ss, sa_len)) {
1414 return NULL;
1415 }
1416 char buf[NI_MAXHOST]; // NI_MAXHOST is longer than INET6_ADDRSTRLEN.
1417 errno = 0;
1418 int rc = getnameinfo(reinterpret_cast<sockaddr*>(&ss), sa_len, buf, sizeof(buf), NULL, 0, flags);
1419 if (rc != 0) {
1420 throwGaiException(env, "getnameinfo", rc);
1421 return NULL;
1422 }
1423 return env->NewStringUTF(buf);
1424 }
1425
Linux_getpeername(JNIEnv * env,jobject,jobject javaFd)1426 static jobject Linux_getpeername(JNIEnv* env, jobject, jobject javaFd) {
1427 return doGetSockName(env, javaFd, false);
1428 }
1429
Linux_getpgid(JNIEnv * env,jobject,jint pid)1430 static jint Linux_getpgid(JNIEnv* env, jobject, jint pid) {
1431 return throwIfMinusOne(env, "getpgid", TEMP_FAILURE_RETRY(getpgid(pid)));
1432 }
1433
Linux_getpid(JNIEnv *,jobject)1434 static jint Linux_getpid(JNIEnv*, jobject) {
1435 return TEMP_FAILURE_RETRY(getpid());
1436 }
1437
Linux_getppid(JNIEnv *,jobject)1438 static jint Linux_getppid(JNIEnv*, jobject) {
1439 return TEMP_FAILURE_RETRY(getppid());
1440 }
1441
Linux_getpwnam(JNIEnv * env,jobject,jstring javaName)1442 static jobject Linux_getpwnam(JNIEnv* env, jobject, jstring javaName) {
1443 ScopedUtfChars name(env, javaName);
1444 if (name.c_str() == NULL) {
1445 return NULL;
1446 }
1447 return Passwd(env).getpwnam(name.c_str());
1448 }
1449
Linux_getpwuid(JNIEnv * env,jobject,jint uid)1450 static jobject Linux_getpwuid(JNIEnv* env, jobject, jint uid) {
1451 return Passwd(env).getpwuid(uid);
1452 }
1453
Linux_getrlimit(JNIEnv * env,jobject,jint resource)1454 static jobject Linux_getrlimit(JNIEnv* env, jobject, jint resource) {
1455 struct rlimit r;
1456 if (throwIfMinusOne(env, "getrlimit", TEMP_FAILURE_RETRY(getrlimit(resource, &r))) == -1) {
1457 return nullptr;
1458 }
1459
1460 ScopedLocalRef<jclass> rlimit_class(env, env->FindClass("android/system/StructRlimit"));
1461 jmethodID ctor = env->GetMethodID(rlimit_class.get(), "<init>", "(JJ)V");
1462 if (ctor == NULL) {
1463 return NULL;
1464 }
1465 return env->NewObject(rlimit_class.get(), ctor,
1466 static_cast<jlong>(r.rlim_cur),
1467 static_cast<jlong>(r.rlim_max));
1468 }
1469
Linux_getsockname(JNIEnv * env,jobject,jobject javaFd)1470 static jobject Linux_getsockname(JNIEnv* env, jobject, jobject javaFd) {
1471 return doGetSockName(env, javaFd, true);
1472 }
1473
Linux_getsockoptByte(JNIEnv * env,jobject,jobject javaFd,jint level,jint option)1474 static jint Linux_getsockoptByte(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
1475 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1476 u_char result = 0;
1477 socklen_t size = sizeof(result);
1478 throwIfMinusOne(env, "getsockopt", TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &result, &size)));
1479 return result;
1480 }
1481
Linux_getsockoptInAddr(JNIEnv * env,jobject,jobject javaFd,jint level,jint option)1482 static jobject Linux_getsockoptInAddr(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
1483 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1484 sockaddr_storage ss;
1485 memset(&ss, 0, sizeof(ss));
1486 ss.ss_family = AF_INET; // This is only for the IPv4-only IP_MULTICAST_IF.
1487 sockaddr_in* sa = reinterpret_cast<sockaddr_in*>(&ss);
1488 socklen_t size = sizeof(sa->sin_addr);
1489 int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &sa->sin_addr, &size));
1490 if (rc == -1) {
1491 throwErrnoException(env, "getsockopt");
1492 return NULL;
1493 }
1494 return sockaddrToInetAddress(env, ss, NULL);
1495 }
1496
Linux_getsockoptInt(JNIEnv * env,jobject,jobject javaFd,jint level,jint option)1497 static jint Linux_getsockoptInt(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
1498 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1499 jint result = 0;
1500 socklen_t size = sizeof(result);
1501 throwIfMinusOne(env, "getsockopt", TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &result, &size)));
1502 return result;
1503 }
1504
Linux_getsockoptLinger(JNIEnv * env,jobject,jobject javaFd,jint level,jint option)1505 static jobject Linux_getsockoptLinger(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
1506 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1507 struct linger l;
1508 socklen_t size = sizeof(l);
1509 memset(&l, 0, size);
1510 int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &l, &size));
1511 if (rc == -1) {
1512 throwErrnoException(env, "getsockopt");
1513 return NULL;
1514 }
1515 return makeStructLinger(env, l);
1516 }
1517
Linux_getsockoptTimeval(JNIEnv * env,jobject,jobject javaFd,jint level,jint option)1518 static jobject Linux_getsockoptTimeval(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
1519 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1520 struct timeval tv;
1521 socklen_t size = sizeof(tv);
1522 memset(&tv, 0, size);
1523 int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &tv, &size));
1524 if (rc == -1) {
1525 throwErrnoException(env, "getsockopt");
1526 return NULL;
1527 }
1528 // If we didn't get the buffer size we expected then error. If other structures are the same
1529 // size as timeval we might not detect an issue and could return junk.
1530 if (size != sizeof(tv)) {
1531 jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
1532 "getsockoptTimeval() unsupported with level %i and option %i", level, option);
1533 return NULL;
1534 }
1535 return makeStructTimeval(env, tv);
1536 }
1537
Linux_getsockoptUcred(JNIEnv * env,jobject,jobject javaFd,jint level,jint option)1538 static jobject Linux_getsockoptUcred(JNIEnv* env, jobject, jobject javaFd, jint level, jint option) {
1539 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1540 struct ucred u;
1541 socklen_t size = sizeof(u);
1542 memset(&u, 0, size);
1543 int rc = TEMP_FAILURE_RETRY(getsockopt(fd, level, option, &u, &size));
1544 if (rc == -1) {
1545 throwErrnoException(env, "getsockopt");
1546 return NULL;
1547 }
1548 return makeStructUcred(env, u);
1549 }
1550
Linux_gettid(JNIEnv * env __unused,jobject)1551 static jint Linux_gettid(JNIEnv* env __unused, jobject) {
1552 #if defined(__BIONIC__)
1553 return TEMP_FAILURE_RETRY(gettid());
1554 #else
1555 return syscall(__NR_gettid);
1556 #endif
1557 }
1558
Linux_getuid(JNIEnv *,jobject)1559 static jint Linux_getuid(JNIEnv*, jobject) {
1560 return getuid();
1561 }
1562
Linux_getxattr(JNIEnv * env,jobject,jstring javaPath,jstring javaName)1563 static jbyteArray Linux_getxattr(JNIEnv* env, jobject, jstring javaPath,
1564 jstring javaName) {
1565 ScopedUtfChars path(env, javaPath);
1566 if (path.c_str() == NULL) {
1567 return NULL;
1568 }
1569 ScopedUtfChars name(env, javaName);
1570 if (name.c_str() == NULL) {
1571 return NULL;
1572 }
1573
1574 while (true) {
1575 // Get the current size of the named extended attribute.
1576 ssize_t valueLength;
1577 if ((valueLength = getxattr(path.c_str(), name.c_str(), NULL, 0)) < 0) {
1578 throwErrnoException(env, "getxattr");
1579 return NULL;
1580 }
1581
1582 // Create the actual byte array.
1583 std::vector<char> buf(valueLength);
1584 if ((valueLength = getxattr(path.c_str(), name.c_str(), buf.data(), valueLength)) < 0) {
1585 if (errno == ERANGE) {
1586 // The attribute value has changed since last getxattr call and buf no longer fits,
1587 // try again.
1588 continue;
1589 }
1590 throwErrnoException(env, "getxattr");
1591 return NULL;
1592 }
1593 jbyteArray array = env->NewByteArray(valueLength);
1594 if (array == NULL) {
1595 return NULL;
1596 }
1597 env->SetByteArrayRegion(array, 0, valueLength, reinterpret_cast<const jbyte*>(buf.data()));
1598 return array;
1599 }
1600 }
1601
Linux_getifaddrs(JNIEnv * env,jobject)1602 static jobjectArray Linux_getifaddrs(JNIEnv* env, jobject) {
1603 static jmethodID ctor = env->GetMethodID(JniConstants::GetStructIfaddrsClass(env), "<init>",
1604 "(Ljava/lang/String;ILjava/net/InetAddress;Ljava/net/InetAddress;Ljava/net/InetAddress;[B)V");
1605 if (ctor == NULL) {
1606 return NULL;
1607 }
1608
1609 ifaddrs* ifaddr;
1610 int rc = TEMP_FAILURE_RETRY(getifaddrs(&ifaddr));
1611 if (rc == -1) {
1612 throwErrnoException(env, "getifaddrs");
1613 return NULL;
1614 }
1615 std::unique_ptr<ifaddrs, decltype(&freeifaddrs)> ifaddrPtr(ifaddr, freeifaddrs);
1616
1617 // Count results so we know how to size the output array.
1618 jint ifCount = 0;
1619 for (ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
1620 ++ifCount;
1621 }
1622
1623 // Prepare output array.
1624 jobjectArray result = env->NewObjectArray(ifCount, JniConstants::GetStructIfaddrsClass(env), NULL);
1625 if (result == NULL) {
1626 return NULL;
1627 }
1628
1629 // Traverse the list and populate the output array.
1630 int index = 0;
1631 for (ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next, ++index) {
1632 TO_JAVA_STRING(name, ifa->ifa_name);
1633 jint flags = ifa->ifa_flags;
1634 sockaddr_storage* interfaceAddr =
1635 reinterpret_cast<sockaddr_storage*>(ifa->ifa_addr);
1636 sockaddr_storage* netmaskAddr =
1637 reinterpret_cast<sockaddr_storage*>(ifa->ifa_netmask);
1638 sockaddr_storage* broadAddr =
1639 reinterpret_cast<sockaddr_storage*>(ifa->ifa_broadaddr);
1640
1641 jobject addr, netmask, broad;
1642 jbyteArray hwaddr = NULL;
1643 if (interfaceAddr != NULL) {
1644 switch (interfaceAddr->ss_family) {
1645 case AF_INET:
1646 case AF_INET6:
1647 // IPv4 / IPv6.
1648 // interfaceAddr and netmaskAddr are never null.
1649 if ((addr = sockaddrToInetAddress(env, *interfaceAddr, NULL)) == NULL) {
1650 return NULL;
1651 }
1652 if ((netmask = sockaddrToInetAddress(env, *netmaskAddr, NULL)) == NULL) {
1653 return NULL;
1654 }
1655 if (broadAddr != NULL && (ifa->ifa_flags & IFF_BROADCAST)) {
1656 if ((broad = sockaddrToInetAddress(env, *broadAddr, NULL)) == NULL) {
1657 return NULL;
1658 }
1659 } else {
1660 broad = NULL;
1661 }
1662 break;
1663 case AF_PACKET:
1664 // Raw Interface.
1665 sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ifa->ifa_addr);
1666
1667 bool allZero = true;
1668 for (int i = 0; i < sll->sll_halen; ++i) {
1669 if (sll->sll_addr[i] != 0) {
1670 allZero = false;
1671 break;
1672 }
1673 }
1674
1675 if (!allZero) {
1676 hwaddr = env->NewByteArray(sll->sll_halen);
1677 if (hwaddr == NULL) {
1678 return NULL;
1679 }
1680 env->SetByteArrayRegion(hwaddr, 0, sll->sll_halen,
1681 reinterpret_cast<const jbyte*>(sll->sll_addr));
1682 }
1683 addr = netmask = broad = NULL;
1684 break;
1685 }
1686 } else {
1687 // Preserve the entry even if the interface has no interface address.
1688 // http://b/29243557/
1689 addr = netmask = broad = NULL;
1690 }
1691
1692 jobject o = env->NewObject(JniConstants::GetStructIfaddrsClass(env), ctor, name, flags,
1693 addr, netmask, broad, hwaddr);
1694 if (o == NULL) {
1695 return NULL;
1696 }
1697 env->SetObjectArrayElement(result, index, o);
1698 }
1699
1700 return result;
1701 }
1702
Linux_if_indextoname(JNIEnv * env,jobject,jint index)1703 static jstring Linux_if_indextoname(JNIEnv* env, jobject, jint index) {
1704 char buf[IF_NAMESIZE];
1705 char* name = if_indextoname(index, buf);
1706 // if_indextoname(3) returns NULL on failure, which will come out of NewStringUTF unscathed.
1707 // There's no useful information in errno, so we don't bother throwing. Callers can null-check.
1708 return env->NewStringUTF(name);
1709 }
1710
Linux_if_nametoindex(JNIEnv * env,jobject,jstring name)1711 static jint Linux_if_nametoindex(JNIEnv* env, jobject, jstring name) {
1712 ScopedUtfChars cname(env, name);
1713 if (cname.c_str() == NULL) {
1714 return 0;
1715 }
1716
1717 // There's no useful information in errno, so we don't bother throwing. Callers can zero-check.
1718 return if_nametoindex(cname.c_str());
1719 }
1720
Linux_inet_pton(JNIEnv * env,jobject,jint family,jstring javaName)1721 static jobject Linux_inet_pton(JNIEnv* env, jobject, jint family, jstring javaName) {
1722 ScopedUtfChars name(env, javaName);
1723 if (name.c_str() == NULL) {
1724 return NULL;
1725 }
1726 sockaddr_storage ss;
1727 memset(&ss, 0, sizeof(ss));
1728 void* dst;
1729 if (family == AF_INET) {
1730 dst = &reinterpret_cast<sockaddr_in*>(&ss)->sin_addr;
1731 } else if (family == AF_INET6) {
1732 dst = &reinterpret_cast<sockaddr_in6*>(&ss)->sin6_addr;
1733 } else {
1734 return NULL;
1735 }
1736 if (inet_pton(family, name.c_str(), dst) != 1) {
1737 return NULL;
1738 }
1739 ss.ss_family = family;
1740 return sockaddrToInetAddress(env, ss, NULL);
1741 }
1742
Linux_ioctlFlags(JNIEnv * env,jobject,jobject javaFd,jstring javaInterfaceName)1743 static jint Linux_ioctlFlags(JNIEnv* env, jobject, jobject javaFd, jstring javaInterfaceName) {
1744 struct ifreq req;
1745 if (!fillIfreq(env, javaInterfaceName, req)) {
1746 return 0;
1747 }
1748 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1749 throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, SIOCGIFFLAGS, &req)));
1750 return req.ifr_flags;
1751 }
1752
Linux_ioctlInetAddress(JNIEnv * env,jobject,jobject javaFd,jint cmd,jstring javaInterfaceName)1753 static jobject Linux_ioctlInetAddress(JNIEnv* env, jobject, jobject javaFd, jint cmd, jstring javaInterfaceName) {
1754 struct ifreq req;
1755 if (!fillIfreq(env, javaInterfaceName, req)) {
1756 return NULL;
1757 }
1758 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1759 int rc = throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, cmd, &req)));
1760 if (rc == -1) {
1761 return NULL;
1762 }
1763 return sockaddrToInetAddress(env, reinterpret_cast<sockaddr_storage&>(req.ifr_addr), NULL);
1764 }
1765
Linux_ioctlInt(JNIEnv * env,jobject,jobject javaFd,jint cmd,jobject javaArg)1766 static jint Linux_ioctlInt(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaArg) {
1767 // This is complicated because ioctls may return their result by updating their argument
1768 // or via their return value, so we need to support both.
1769 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1770 jint arg = env->GetIntField(javaArg, int32RefValueFid);
1771 int rc = throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, cmd, &arg)));
1772 if (!env->ExceptionCheck()) {
1773 env->SetIntField(javaArg, int32RefValueFid, arg);
1774 }
1775 return rc;
1776 }
1777
Linux_ioctlMTU(JNIEnv * env,jobject,jobject javaFd,jstring javaInterfaceName)1778 static jint Linux_ioctlMTU(JNIEnv* env, jobject, jobject javaFd, jstring javaInterfaceName) {
1779 struct ifreq req;
1780 if (!fillIfreq(env, javaInterfaceName, req)) {
1781 return 0;
1782 }
1783 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1784 throwIfMinusOne(env, "ioctl", TEMP_FAILURE_RETRY(ioctl(fd, SIOCGIFMTU, &req)));
1785 return req.ifr_mtu;
1786 }
1787
Linux_isatty(JNIEnv * env,jobject,jobject javaFd)1788 static jboolean Linux_isatty(JNIEnv* env, jobject, jobject javaFd) {
1789 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1790 return TEMP_FAILURE_RETRY(isatty(fd)) == 1;
1791 }
1792
Linux_kill(JNIEnv * env,jobject,jint pid,jint sig)1793 static void Linux_kill(JNIEnv* env, jobject, jint pid, jint sig) {
1794 throwIfMinusOne(env, "kill", TEMP_FAILURE_RETRY(kill(pid, sig)));
1795 }
1796
Linux_lchown(JNIEnv * env,jobject,jstring javaPath,jint uid,jint gid)1797 static void Linux_lchown(JNIEnv* env, jobject, jstring javaPath, jint uid, jint gid) {
1798 ScopedUtfChars path(env, javaPath);
1799 if (path.c_str() == NULL) {
1800 return;
1801 }
1802 throwIfMinusOne(env, "lchown", TEMP_FAILURE_RETRY(lchown(path.c_str(), uid, gid)));
1803 }
1804
Linux_link(JNIEnv * env,jobject,jstring javaOldPath,jstring javaNewPath)1805 static void Linux_link(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) {
1806 ScopedUtfChars oldPath(env, javaOldPath);
1807 if (oldPath.c_str() == NULL) {
1808 return;
1809 }
1810 ScopedUtfChars newPath(env, javaNewPath);
1811 if (newPath.c_str() == NULL) {
1812 return;
1813 }
1814 throwIfMinusOne(env, "link", TEMP_FAILURE_RETRY(link(oldPath.c_str(), newPath.c_str())));
1815 }
1816
Linux_listen(JNIEnv * env,jobject,jobject javaFd,jint backlog)1817 static void Linux_listen(JNIEnv* env, jobject, jobject javaFd, jint backlog) {
1818 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1819 throwIfMinusOne(env, "listen", TEMP_FAILURE_RETRY(listen(fd, backlog)));
1820 }
1821
Linux_listxattr(JNIEnv * env,jobject,jstring javaPath)1822 static jobjectArray Linux_listxattr(JNIEnv* env, jobject, jstring javaPath) {
1823 ScopedUtfChars path(env, javaPath);
1824 if (path.c_str() == NULL) {
1825 return NULL;
1826 }
1827
1828 while (true) {
1829 // Get the current size of the named extended attribute.
1830 ssize_t valueLength;
1831 if ((valueLength = listxattr(path.c_str(), NULL, 0)) < 0) {
1832 throwErrnoException(env, "listxattr");
1833 return NULL;
1834 }
1835
1836 // Create the actual byte array.
1837 std::string buf(valueLength, '\0');
1838 if ((valueLength = listxattr(path.c_str(), &buf[0], valueLength)) < 0) {
1839 if (errno == ERANGE) {
1840 // The attribute value has changed since last listxattr call and buf no longer fits,
1841 // try again.
1842 continue;
1843 }
1844 throwErrnoException(env, "listxattr");
1845 return NULL;
1846 }
1847
1848 // Split the output by '\0'.
1849 buf.resize(valueLength > 0 ? valueLength - 1 : 0); // Remove the trailing NULL character.
1850 std::string delim("\0", 1);
1851 auto xattrs = android::base::Split(buf, delim);
1852
1853 return toStringArray(env, xattrs);
1854 }
1855 }
1856
Linux_lseek(JNIEnv * env,jobject,jobject javaFd,jlong offset,jint whence)1857 static jlong Linux_lseek(JNIEnv* env, jobject, jobject javaFd, jlong offset, jint whence) {
1858 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1859 return throwIfMinusOne(env, "lseek", TEMP_FAILURE_RETRY(lseek64(fd, offset, whence)));
1860 }
1861
Linux_lstat(JNIEnv * env,jobject,jstring javaPath)1862 static jobject Linux_lstat(JNIEnv* env, jobject, jstring javaPath) {
1863 return doStat(env, javaPath, true);
1864 }
1865
Linux_mincore(JNIEnv * env,jobject,jlong address,jlong byteCount,jbyteArray javaVector)1866 static void Linux_mincore(JNIEnv* env, jobject, jlong address, jlong byteCount, jbyteArray javaVector) {
1867 ScopedByteArrayRW vector(env, javaVector);
1868 if (vector.get() == NULL) {
1869 return;
1870 }
1871 void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
1872 unsigned char* vec = reinterpret_cast<unsigned char*>(vector.get());
1873 throwIfMinusOne(env, "mincore", TEMP_FAILURE_RETRY(mincore(ptr, byteCount, vec)));
1874 }
1875
Linux_mkdir(JNIEnv * env,jobject,jstring javaPath,jint mode)1876 static void Linux_mkdir(JNIEnv* env, jobject, jstring javaPath, jint mode) {
1877 ScopedUtfChars path(env, javaPath);
1878 if (path.c_str() == NULL) {
1879 return;
1880 }
1881 throwIfMinusOne(env, "mkdir", TEMP_FAILURE_RETRY(mkdir(path.c_str(), mode)));
1882 }
1883
Linux_mkfifo(JNIEnv * env,jobject,jstring javaPath,jint mode)1884 static void Linux_mkfifo(JNIEnv* env, jobject, jstring javaPath, jint mode) {
1885 ScopedUtfChars path(env, javaPath);
1886 if (path.c_str() == NULL) {
1887 return;
1888 }
1889 throwIfMinusOne(env, "mkfifo", TEMP_FAILURE_RETRY(mkfifo(path.c_str(), mode)));
1890 }
1891
Linux_mlock(JNIEnv * env,jobject,jlong address,jlong byteCount)1892 static void Linux_mlock(JNIEnv* env, jobject, jlong address, jlong byteCount) {
1893 void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
1894 throwIfMinusOne(env, "mlock", TEMP_FAILURE_RETRY(mlock(ptr, byteCount)));
1895 }
1896
Linux_mmap(JNIEnv * env,jobject,jlong address,jlong byteCount,jint prot,jint flags,jobject javaFd,jlong offset)1897 static jlong Linux_mmap(JNIEnv* env, jobject, jlong address, jlong byteCount, jint prot, jint flags, jobject javaFd, jlong offset) {
1898 int fd = jniGetFDFromFileDescriptor(env, javaFd);
1899 void* suggestedPtr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
1900 void* ptr = mmap64(suggestedPtr, byteCount, prot, flags, fd, offset);
1901 if (ptr == MAP_FAILED) {
1902 throwErrnoException(env, "mmap");
1903 }
1904 return static_cast<jlong>(reinterpret_cast<uintptr_t>(ptr));
1905 }
1906
Linux_msync(JNIEnv * env,jobject,jlong address,jlong byteCount,jint flags)1907 static void Linux_msync(JNIEnv* env, jobject, jlong address, jlong byteCount, jint flags) {
1908 void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
1909 throwIfMinusOne(env, "msync", TEMP_FAILURE_RETRY(msync(ptr, byteCount, flags)));
1910 }
1911
Linux_munlock(JNIEnv * env,jobject,jlong address,jlong byteCount)1912 static void Linux_munlock(JNIEnv* env, jobject, jlong address, jlong byteCount) {
1913 void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
1914 throwIfMinusOne(env, "munlock", TEMP_FAILURE_RETRY(munlock(ptr, byteCount)));
1915 }
1916
Linux_munmap(JNIEnv * env,jobject,jlong address,jlong byteCount)1917 static void Linux_munmap(JNIEnv* env, jobject, jlong address, jlong byteCount) {
1918 void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address));
1919 throwIfMinusOne(env, "munmap", TEMP_FAILURE_RETRY(munmap(ptr, byteCount)));
1920 }
1921
Linux_open(JNIEnv * env,jobject,jstring javaPath,jint flags,jint mode)1922 static jobject Linux_open(JNIEnv* env, jobject, jstring javaPath, jint flags, jint mode) {
1923 ScopedUtfChars path(env, javaPath);
1924 if (path.c_str() == NULL) {
1925 return NULL;
1926 }
1927 int fd = throwIfMinusOne(env, "open", TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode)));
1928 return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL;
1929 }
1930
Linux_pipe2(JNIEnv * env,jobject,jint flags __unused)1931 static jobjectArray Linux_pipe2(JNIEnv* env, jobject, jint flags __unused) {
1932 int fds[2];
1933 int pipe2_result = throwIfMinusOne(env, "pipe2", TEMP_FAILURE_RETRY(pipe2(&fds[0], flags)));
1934 if (pipe2_result == -1) {
1935 return NULL;
1936 }
1937 jobjectArray result = env->NewObjectArray(2, JniConstants::GetFileDescriptorClass(env), NULL);
1938 if (result == NULL) {
1939 return NULL;
1940 }
1941 for (int i = 0; i < 2; ++i) {
1942 ScopedLocalRef<jobject> fd(env, jniCreateFileDescriptor(env, fds[i]));
1943 if (fd.get() == NULL) {
1944 return NULL;
1945 }
1946 env->SetObjectArrayElement(result, i, fd.get());
1947 if (env->ExceptionCheck()) {
1948 return NULL;
1949 }
1950 }
1951 return result;
1952 }
1953
Linux_poll(JNIEnv * env,jobject,jobjectArray javaStructs,jint timeoutMs)1954 static jint Linux_poll(JNIEnv* env, jobject, jobjectArray javaStructs, jint timeoutMs) {
1955 static jfieldID fdFid = env->GetFieldID(JniConstants::GetStructPollfdClass(env), "fd", "Ljava/io/FileDescriptor;");
1956 static jfieldID eventsFid = env->GetFieldID(JniConstants::GetStructPollfdClass(env), "events", "S");
1957 static jfieldID reventsFid = env->GetFieldID(JniConstants::GetStructPollfdClass(env), "revents", "S");
1958
1959 // Turn the Java android.system.StructPollfd[] into a C++ struct pollfd[].
1960 size_t arrayLength = env->GetArrayLength(javaStructs);
1961 std::unique_ptr<struct pollfd[]> fds(new struct pollfd[arrayLength]);
1962 memset(fds.get(), 0, sizeof(struct pollfd) * arrayLength);
1963 size_t count = 0; // Some trailing array elements may be irrelevant. (See below.)
1964 for (size_t i = 0; i < arrayLength; ++i) {
1965 ScopedLocalRef<jobject> javaStruct(env, env->GetObjectArrayElement(javaStructs, i));
1966 if (javaStruct.get() == NULL) {
1967 break; // We allow trailing nulls in the array for caller convenience.
1968 }
1969 ScopedLocalRef<jobject> javaFd(env, env->GetObjectField(javaStruct.get(), fdFid));
1970 if (javaFd.get() == NULL) {
1971 break; // We also allow callers to just clear the fd field (this is what Selector does).
1972 }
1973 fds[count].fd = jniGetFDFromFileDescriptor(env, javaFd.get());
1974 fds[count].events = env->GetShortField(javaStruct.get(), eventsFid);
1975 ++count;
1976 }
1977
1978 std::vector<AsynchronousCloseMonitor*> monitors;
1979 for (size_t i = 0; i < count; ++i) {
1980 monitors.push_back(new AsynchronousCloseMonitor(fds[i].fd));
1981 }
1982
1983 int rc;
1984 while (true) {
1985 timespec before;
1986 clock_gettime(CLOCK_MONOTONIC, &before);
1987
1988 rc = poll(fds.get(), count, timeoutMs);
1989 if (rc >= 0 || errno != EINTR) {
1990 break;
1991 }
1992
1993 // We got EINTR. Work out how much of the original timeout is still left.
1994 if (timeoutMs > 0) {
1995 timespec now;
1996 clock_gettime(CLOCK_MONOTONIC, &now);
1997
1998 timespec diff;
1999 diff.tv_sec = now.tv_sec - before.tv_sec;
2000 diff.tv_nsec = now.tv_nsec - before.tv_nsec;
2001 if (diff.tv_nsec < 0) {
2002 --diff.tv_sec;
2003 diff.tv_nsec += 1000000000;
2004 }
2005
2006 jint diffMs = diff.tv_sec * 1000 + diff.tv_nsec / 1000000;
2007 if (diffMs >= timeoutMs) {
2008 rc = 0; // We have less than 1ms left anyway, so just time out.
2009 break;
2010 }
2011
2012 timeoutMs -= diffMs;
2013 }
2014 }
2015
2016 for (size_t i = 0; i < monitors.size(); ++i) {
2017 delete monitors[i];
2018 }
2019 if (rc == -1) {
2020 throwErrnoException(env, "poll");
2021 return -1;
2022 }
2023
2024 // Update the revents fields in the Java android.system.StructPollfd[].
2025 for (size_t i = 0; i < count; ++i) {
2026 ScopedLocalRef<jobject> javaStruct(env, env->GetObjectArrayElement(javaStructs, i));
2027 if (javaStruct.get() == NULL) {
2028 return -1;
2029 }
2030 env->SetShortField(javaStruct.get(), reventsFid, fds[i].revents);
2031 }
2032 return rc;
2033 }
2034
Linux_posix_fallocate(JNIEnv * env,jobject,jobject javaFd __unused,jlong offset __unused,jlong length __unused)2035 static void Linux_posix_fallocate(JNIEnv* env, jobject, jobject javaFd __unused,
2036 jlong offset __unused, jlong length __unused) {
2037 int fd = jniGetFDFromFileDescriptor(env, javaFd);
2038 while ((errno = posix_fallocate64(fd, offset, length)) == EINTR) {
2039 }
2040 if (errno != 0) {
2041 throwErrnoException(env, "posix_fallocate");
2042 }
2043 }
2044
Linux_prctl(JNIEnv * env,jobject,jint option __unused,jlong arg2 __unused,jlong arg3 __unused,jlong arg4 __unused,jlong arg5 __unused)2045 static jint Linux_prctl(JNIEnv* env, jobject, jint option __unused, jlong arg2 __unused,
2046 jlong arg3 __unused, jlong arg4 __unused, jlong arg5 __unused) {
2047 int result = TEMP_FAILURE_RETRY(prctl(static_cast<int>(option),
2048 static_cast<unsigned long>(arg2),
2049 static_cast<unsigned long>(arg3),
2050 static_cast<unsigned long>(arg4),
2051 static_cast<unsigned long>(arg5)));
2052 return throwIfMinusOne(env, "prctl", result);
2053 }
2054
Linux_preadBytes(JNIEnv * env,jobject,jobject javaFd,jobject javaBytes,jint byteOffset,jint byteCount,jlong offset)2055 static jint Linux_preadBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jlong offset) {
2056 ScopedBytesRW bytes(env, javaBytes);
2057 if (bytes.get() == NULL) {
2058 return -1;
2059 }
2060 return IO_FAILURE_RETRY(env, ssize_t, pread64, javaFd, bytes.get() + byteOffset, byteCount, offset);
2061 }
2062
Linux_pwriteBytes(JNIEnv * env,jobject,jobject javaFd,jobject javaBytes,jint byteOffset,jint byteCount,jlong offset)2063 static jint Linux_pwriteBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jlong offset) {
2064 ScopedBytesRO bytes(env, javaBytes);
2065 if (bytes.get() == NULL) {
2066 return -1;
2067 }
2068 return IO_FAILURE_RETRY(env, ssize_t, pwrite64, javaFd, bytes.get() + byteOffset, byteCount, offset);
2069 }
2070
Linux_readBytes(JNIEnv * env,jobject,jobject javaFd,jobject javaBytes,jint byteOffset,jint byteCount)2071 static jint Linux_readBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount) {
2072 ScopedBytesRW bytes(env, javaBytes);
2073 if (bytes.get() == NULL) {
2074 return -1;
2075 }
2076 return IO_FAILURE_RETRY(env, ssize_t, read, javaFd, bytes.get() + byteOffset, byteCount);
2077 }
2078
Linux_readlink(JNIEnv * env,jobject,jstring javaPath)2079 static jstring Linux_readlink(JNIEnv* env, jobject, jstring javaPath) {
2080 ScopedUtfChars path(env, javaPath);
2081 if (path.c_str() == NULL) {
2082 return NULL;
2083 }
2084
2085 std::string result;
2086 if (!android::base::Readlink(path.c_str(), &result)) {
2087 throwErrnoException(env, "readlink");
2088 return NULL;
2089 }
2090 return env->NewStringUTF(result.c_str());
2091 }
2092
Linux_realpath(JNIEnv * env,jobject,jstring javaPath)2093 static jstring Linux_realpath(JNIEnv* env, jobject, jstring javaPath) {
2094 ScopedUtfChars path(env, javaPath);
2095 if (path.c_str() == NULL) {
2096 return NULL;
2097 }
2098
2099 std::unique_ptr<char, c_deleter> real_path(realpath(path.c_str(), nullptr));
2100 if (real_path.get() == nullptr) {
2101 throwErrnoException(env, "realpath");
2102 return NULL;
2103 }
2104
2105 return env->NewStringUTF(real_path.get());
2106 }
2107
Linux_readv(JNIEnv * env,jobject,jobject javaFd,jobjectArray buffers,jintArray offsets,jintArray byteCounts)2108 static jint Linux_readv(JNIEnv* env, jobject, jobject javaFd, jobjectArray buffers, jintArray offsets, jintArray byteCounts) {
2109 IoVec<ScopedBytesRW> ioVec(env, env->GetArrayLength(buffers));
2110 if (!ioVec.init(buffers, offsets, byteCounts)) {
2111 return -1;
2112 }
2113 return IO_FAILURE_RETRY(env, ssize_t, readv, javaFd, ioVec.get(), ioVec.size());
2114 }
2115
Linux_recvfromBytes(JNIEnv * env,jobject,jobject javaFd,jobject javaBytes,jint byteOffset,jint byteCount,jint flags,jobject javaInetSocketAddress)2116 static jint Linux_recvfromBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaInetSocketAddress) {
2117 ScopedBytesRW bytes(env, javaBytes);
2118 if (bytes.get() == NULL) {
2119 return -1;
2120 }
2121 sockaddr_storage ss;
2122 socklen_t sl = sizeof(ss);
2123 memset(&ss, 0, sizeof(ss));
2124 sockaddr* from = (javaInetSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;
2125 socklen_t* fromLength = (javaInetSocketAddress != NULL) ? &sl : 0;
2126 jint recvCount = NET_FAILURE_RETRY(env, ssize_t, recvfrom, javaFd, bytes.get() + byteOffset, byteCount, flags, from, fromLength);
2127 if (recvCount >= 0) {
2128 // The socket may have performed orderly shutdown and recvCount would return 0 (see man 2
2129 // recvfrom), in which case ss.ss_family == AF_UNIX and fillInetSocketAddress would fail.
2130 // Don't fill in the address if recvfrom didn't succeed. http://b/33483694
2131 if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) {
2132 fillInetSocketAddress(env, javaInetSocketAddress, ss);
2133 }
2134 }
2135 return recvCount;
2136 }
2137
Linux_remove(JNIEnv * env,jobject,jstring javaPath)2138 static void Linux_remove(JNIEnv* env, jobject, jstring javaPath) {
2139 ScopedUtfChars path(env, javaPath);
2140 if (path.c_str() == NULL) {
2141 return;
2142 }
2143 throwIfMinusOne(env, "remove", TEMP_FAILURE_RETRY(remove(path.c_str())));
2144 }
2145
Linux_removexattr(JNIEnv * env,jobject,jstring javaPath,jstring javaName)2146 static void Linux_removexattr(JNIEnv* env, jobject, jstring javaPath, jstring javaName) {
2147 ScopedUtfChars path(env, javaPath);
2148 if (path.c_str() == NULL) {
2149 return;
2150 }
2151 ScopedUtfChars name(env, javaName);
2152 if (name.c_str() == NULL) {
2153 return;
2154 }
2155
2156 int res = removexattr(path.c_str(), name.c_str());
2157 if (res < 0) {
2158 throwErrnoException(env, "removexattr");
2159 }
2160 }
2161
Linux_rename(JNIEnv * env,jobject,jstring javaOldPath,jstring javaNewPath)2162 static void Linux_rename(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) {
2163 ScopedUtfChars oldPath(env, javaOldPath);
2164 if (oldPath.c_str() == NULL) {
2165 return;
2166 }
2167 ScopedUtfChars newPath(env, javaNewPath);
2168 if (newPath.c_str() == NULL) {
2169 return;
2170 }
2171 throwIfMinusOne(env, "rename", TEMP_FAILURE_RETRY(rename(oldPath.c_str(), newPath.c_str())));
2172 }
2173
Linux_sendfile(JNIEnv * env,jobject,jobject javaOutFd,jobject javaInFd,jobject javaOffset,jlong byteCount)2174 static jlong Linux_sendfile(JNIEnv* env, jobject, jobject javaOutFd, jobject javaInFd, jobject javaOffset, jlong byteCount) {
2175 int outFd = jniGetFDFromFileDescriptor(env, javaOutFd);
2176 int inFd = jniGetFDFromFileDescriptor(env, javaInFd);
2177 off_t offset = 0;
2178 off_t* offsetPtr = NULL;
2179 if (javaOffset != NULL) {
2180 // TODO: fix bionic so we can have a 64-bit off_t!
2181 offset = env->GetLongField(javaOffset, int64RefValueFid);
2182 offsetPtr = &offset;
2183 }
2184 jlong result = throwIfMinusOne(env, "sendfile", TEMP_FAILURE_RETRY(sendfile(outFd, inFd, offsetPtr, byteCount)));
2185 if (result == -1) {
2186 return -1;
2187 }
2188 if (javaOffset != NULL) {
2189 env->SetLongField(javaOffset, int64RefValueFid, offset);
2190 }
2191 return result;
2192 }
2193
Linux_sendtoBytes(JNIEnv * env,jobject,jobject javaFd,jobject javaBytes,jint byteOffset,jint byteCount,jint flags,jobject javaInetAddress,jint port)2194 static jint Linux_sendtoBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaInetAddress, jint port) {
2195 ScopedBytesRO bytes(env, javaBytes);
2196 if (bytes.get() == NULL) {
2197 return -1;
2198 }
2199
2200 return NET_IPV4_FALLBACK(env, ssize_t, sendto, javaFd, javaInetAddress, port,
2201 NULL_ADDR_OK, bytes.get() + byteOffset, byteCount, flags);
2202 }
2203
Linux_sendtoBytesSocketAddress(JNIEnv * env,jobject,jobject javaFd,jobject javaBytes,jint byteOffset,jint byteCount,jint flags,jobject javaSocketAddress)2204 static jint Linux_sendtoBytesSocketAddress(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount, jint flags, jobject javaSocketAddress) {
2205 if (javaSocketAddress != NULL &&
2206 env->IsInstanceOf(javaSocketAddress, JniConstants::GetInetSocketAddressClass(env))) {
2207 // Use the InetAddress version so we get the benefit of NET_IPV4_FALLBACK.
2208 jobject javaInetAddress;
2209 jint port;
2210 javaInetSocketAddressToInetAddressAndPort(env, javaSocketAddress, javaInetAddress, port);
2211 return Linux_sendtoBytes(env, NULL, javaFd, javaBytes, byteOffset, byteCount, flags,
2212 javaInetAddress, port);
2213 }
2214
2215 ScopedBytesRO bytes(env, javaBytes);
2216 if (bytes.get() == NULL) {
2217 return -1;
2218 }
2219
2220 sockaddr_storage ss;
2221 socklen_t sa_len;
2222 const sockaddr* sa;
2223
2224 if (javaSocketAddress != NULL) {
2225 if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) {
2226 return -1;
2227 }
2228
2229 sa = reinterpret_cast<const sockaddr*>(&ss);
2230 } else {
2231 sa = NULL;
2232 sa_len = 0;
2233 }
2234
2235 // We don't need the return value because we'll already have thrown.
2236 return NET_FAILURE_RETRY(env, ssize_t, sendto, javaFd, bytes.get() + byteOffset, byteCount, flags, sa, sa_len);
2237 }
2238
Linux_setegid(JNIEnv * env,jobject,jint egid)2239 static void Linux_setegid(JNIEnv* env, jobject, jint egid) {
2240 throwIfMinusOne(env, "setegid", TEMP_FAILURE_RETRY(setegid(egid)));
2241 }
2242
Linux_setenv(JNIEnv * env,jobject,jstring javaName,jstring javaValue,jboolean overwrite)2243 static void Linux_setenv(JNIEnv* env, jobject, jstring javaName, jstring javaValue, jboolean overwrite) {
2244 ScopedUtfChars name(env, javaName);
2245 if (name.c_str() == NULL) {
2246 return;
2247 }
2248 ScopedUtfChars value(env, javaValue);
2249 if (value.c_str() == NULL) {
2250 return;
2251 }
2252 throwIfMinusOne(env, "setenv", setenv(name.c_str(), value.c_str(), overwrite));
2253 }
2254
Linux_seteuid(JNIEnv * env,jobject,jint euid)2255 static void Linux_seteuid(JNIEnv* env, jobject, jint euid) {
2256 throwIfMinusOne(env, "seteuid", TEMP_FAILURE_RETRY(seteuid(euid)));
2257 }
2258
Linux_setgid(JNIEnv * env,jobject,jint gid)2259 static void Linux_setgid(JNIEnv* env, jobject, jint gid) {
2260 throwIfMinusOne(env, "setgid", TEMP_FAILURE_RETRY(setgid(gid)));
2261 }
2262
Linux_setpgid(JNIEnv * env,jobject,jint pid,int pgid)2263 static void Linux_setpgid(JNIEnv* env, jobject, jint pid, int pgid) {
2264 throwIfMinusOne(env, "setpgid", TEMP_FAILURE_RETRY(setpgid(pid, pgid)));
2265 }
2266
Linux_setregid(JNIEnv * env,jobject,jint rgid,int egid)2267 static void Linux_setregid(JNIEnv* env, jobject, jint rgid, int egid) {
2268 throwIfMinusOne(env, "setregid", TEMP_FAILURE_RETRY(setregid(rgid, egid)));
2269 }
2270
Linux_setreuid(JNIEnv * env,jobject,jint ruid,int euid)2271 static void Linux_setreuid(JNIEnv* env, jobject, jint ruid, int euid) {
2272 throwIfMinusOne(env, "setreuid", TEMP_FAILURE_RETRY(setreuid(ruid, euid)));
2273 }
2274
Linux_setsid(JNIEnv * env,jobject)2275 static jint Linux_setsid(JNIEnv* env, jobject) {
2276 return throwIfMinusOne(env, "setsid", TEMP_FAILURE_RETRY(setsid()));
2277 }
2278
Linux_setsockoptByte(JNIEnv * env,jobject,jobject javaFd,jint level,jint option,jint value)2279 static void Linux_setsockoptByte(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) {
2280 int fd = jniGetFDFromFileDescriptor(env, javaFd);
2281 u_char byte = value;
2282 throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &byte, sizeof(byte))));
2283 }
2284
Linux_setsockoptIfreq(JNIEnv * env,jobject,jobject javaFd,jint level,jint option,jstring javaInterfaceName)2285 static void Linux_setsockoptIfreq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jstring javaInterfaceName) {
2286 struct ifreq req;
2287 if (!fillIfreq(env, javaInterfaceName, req)) {
2288 return;
2289 }
2290 int fd = jniGetFDFromFileDescriptor(env, javaFd);
2291 throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req))));
2292 }
2293
Linux_setsockoptInt(JNIEnv * env,jobject,jobject javaFd,jint level,jint option,jint value)2294 static void Linux_setsockoptInt(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) {
2295 int fd = jniGetFDFromFileDescriptor(env, javaFd);
2296 throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value))));
2297 }
2298
Linux_setsockoptIpMreqn(JNIEnv * env,jobject,jobject javaFd,jint level,jint option,jint value)2299 static void Linux_setsockoptIpMreqn(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jint value) {
2300 ip_mreqn req;
2301 memset(&req, 0, sizeof(req));
2302 req.imr_ifindex = value;
2303 int fd = jniGetFDFromFileDescriptor(env, javaFd);
2304 throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req))));
2305 }
2306
Linux_setsockoptGroupReq(JNIEnv * env,jobject,jobject javaFd,jint level,jint option,jobject javaGroupReq)2307 static void Linux_setsockoptGroupReq(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaGroupReq) {
2308 struct group_req req;
2309 memset(&req, 0, sizeof(req));
2310
2311 static jfieldID grInterfaceFid = env->GetFieldID(JniConstants::GetStructGroupReqClass(env), "gr_interface", "I");
2312 req.gr_interface = env->GetIntField(javaGroupReq, grInterfaceFid);
2313 // Get the IPv4 or IPv6 multicast address to join or leave.
2314 static jfieldID grGroupFid = env->GetFieldID(JniConstants::GetStructGroupReqClass(env), "gr_group", "Ljava/net/InetAddress;");
2315 ScopedLocalRef<jobject> javaGroup(env, env->GetObjectField(javaGroupReq, grGroupFid));
2316 socklen_t sa_len;
2317 if (!inetAddressToSockaddrVerbatim(env, javaGroup.get(), 0, req.gr_group, sa_len)) {
2318 return;
2319 }
2320
2321 int fd = jniGetFDFromFileDescriptor(env, javaFd);
2322 int rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req, sizeof(req)));
2323 if (rc == -1 && errno == EINVAL) {
2324 // Maybe we're a 32-bit binary talking to a 64-bit kernel?
2325 // glibc doesn't automatically handle this.
2326 // http://sourceware.org/bugzilla/show_bug.cgi?id=12080
2327 struct group_req64 {
2328 uint32_t gr_interface;
2329 uint32_t my_padding;
2330 sockaddr_storage gr_group;
2331 };
2332 group_req64 req64;
2333 req64.gr_interface = req.gr_interface;
2334 memcpy(&req64.gr_group, &req.gr_group, sizeof(req.gr_group));
2335 rc = TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &req64, sizeof(req64)));
2336 }
2337 throwIfMinusOne(env, "setsockopt", rc);
2338 }
2339
Linux_setsockoptLinger(JNIEnv * env,jobject,jobject javaFd,jint level,jint option,jobject javaLinger)2340 static void Linux_setsockoptLinger(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaLinger) {
2341 static jfieldID lOnoffFid = env->GetFieldID(JniConstants::GetStructLingerClass(env), "l_onoff", "I");
2342 static jfieldID lLingerFid = env->GetFieldID(JniConstants::GetStructLingerClass(env), "l_linger", "I");
2343 int fd = jniGetFDFromFileDescriptor(env, javaFd);
2344 struct linger value;
2345 value.l_onoff = env->GetIntField(javaLinger, lOnoffFid);
2346 value.l_linger = env->GetIntField(javaLinger, lLingerFid);
2347 throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value))));
2348 }
2349
Linux_setsockoptTimeval(JNIEnv * env,jobject,jobject javaFd,jint level,jint option,jobject javaTimeval)2350 static void Linux_setsockoptTimeval(JNIEnv* env, jobject, jobject javaFd, jint level, jint option, jobject javaTimeval) {
2351 if (javaTimeval == nullptr) {
2352 jniThrowNullPointerException(env, "null javaTimeval");
2353 return;
2354 }
2355
2356 static jfieldID tvSecFid = env->GetFieldID(JniConstants::GetStructTimevalClass(env), "tv_sec", "J");
2357 static jfieldID tvUsecFid = env->GetFieldID(JniConstants::GetStructTimevalClass(env), "tv_usec", "J");
2358 int fd = jniGetFDFromFileDescriptor(env, javaFd);
2359 struct timeval value;
2360 value.tv_sec = env->GetLongField(javaTimeval, tvSecFid);
2361 value.tv_usec = env->GetLongField(javaTimeval, tvUsecFid);
2362 throwIfMinusOne(env, "setsockopt", TEMP_FAILURE_RETRY(setsockopt(fd, level, option, &value, sizeof(value))));
2363 }
2364
Linux_setuid(JNIEnv * env,jobject,jint uid)2365 static void Linux_setuid(JNIEnv* env, jobject, jint uid) {
2366 throwIfMinusOne(env, "setuid", TEMP_FAILURE_RETRY(setuid(uid)));
2367 }
2368
Linux_setxattr(JNIEnv * env,jobject,jstring javaPath,jstring javaName,jbyteArray javaValue,jint flags)2369 static void Linux_setxattr(JNIEnv* env, jobject, jstring javaPath, jstring javaName,
2370 jbyteArray javaValue, jint flags) {
2371 ScopedUtfChars path(env, javaPath);
2372 if (path.c_str() == NULL) {
2373 return;
2374 }
2375 ScopedUtfChars name(env, javaName);
2376 if (name.c_str() == NULL) {
2377 return;
2378 }
2379 ScopedBytesRO value(env, javaValue);
2380 if (value.get() == NULL) {
2381 return;
2382 }
2383 size_t valueLength = env->GetArrayLength(javaValue);
2384 int res = setxattr(path.c_str(), name.c_str(), value.get(), valueLength, flags);
2385 if (res < 0) {
2386 throwErrnoException(env, "setxattr");
2387 }
2388 }
2389
Linux_shutdown(JNIEnv * env,jobject,jobject javaFd,jint how)2390 static void Linux_shutdown(JNIEnv* env, jobject, jobject javaFd, jint how) {
2391 int fd = jniGetFDFromFileDescriptor(env, javaFd);
2392 throwIfMinusOne(env, "shutdown", TEMP_FAILURE_RETRY(shutdown(fd, how)));
2393 }
2394
Linux_socket(JNIEnv * env,jobject,jint domain,jint type,jint protocol)2395 static jobject Linux_socket(JNIEnv* env, jobject, jint domain, jint type, jint protocol) {
2396 if (domain == AF_PACKET) {
2397 protocol = htons(protocol); // Packet sockets specify the protocol in host byte order.
2398 }
2399 int fd = throwIfMinusOne(env, "socket", TEMP_FAILURE_RETRY(socket(domain, type, protocol)));
2400 return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL;
2401 }
2402
Linux_socketpair(JNIEnv * env,jobject,jint domain,jint type,jint protocol,jobject javaFd1,jobject javaFd2)2403 static void Linux_socketpair(JNIEnv* env, jobject, jint domain, jint type, jint protocol, jobject javaFd1, jobject javaFd2) {
2404 int fds[2];
2405 // Fail fast to avoid leaking file descriptors if either FileDescriptor is null.
2406 if (javaFd1 == nullptr) {
2407 jniThrowNullPointerException(env, "null fd1");
2408 } else if (javaFd2 == nullptr) {
2409 jniThrowNullPointerException(env, "null fd2");
2410 } else {
2411 int rc = throwIfMinusOne(env, "socketpair",
2412 TEMP_FAILURE_RETRY(socketpair(domain, type, protocol, fds)));
2413 if (rc != -1) {
2414 jniSetFileDescriptorOfFD(env, javaFd1, fds[0]);
2415 jniSetFileDescriptorOfFD(env, javaFd2, fds[1]);
2416 }
2417 }
2418 }
2419
Linux_splice(JNIEnv * env,jobject,jobject javaFdIn,jobject javaOffIn,jobject javaFdOut,jobject javaOffOut,jlong len,jint flags)2420 static jlong Linux_splice(JNIEnv* env, jobject, jobject javaFdIn, jobject javaOffIn, jobject javaFdOut, jobject javaOffOut, jlong len, jint flags) {
2421 int fdIn = jniGetFDFromFileDescriptor(env, javaFdIn);
2422 int fdOut = jniGetFDFromFileDescriptor(env, javaFdOut);
2423 int spliceErrno;
2424
2425 jlong offIn = (javaOffIn == NULL ? 0 : env->GetLongField(javaOffIn, int64RefValueFid));
2426 jlong offOut = (javaOffOut == NULL ? 0 : env->GetLongField(javaOffOut, int64RefValueFid));
2427 jlong ret = -1;
2428 do {
2429 bool wasSignaled = false;
2430 {
2431 AsynchronousCloseMonitor monitorIn(fdIn);
2432 AsynchronousCloseMonitor monitorOut(fdOut);
2433 ret = splice(fdIn, (javaOffIn == NULL ? NULL : &offIn),
2434 fdOut, (javaOffOut == NULL ? NULL : &offOut),
2435 len, flags);
2436 spliceErrno = errno;
2437 wasSignaled = monitorIn.wasSignaled() || monitorOut.wasSignaled();
2438 }
2439 if (wasSignaled) {
2440 jniThrowException(env, "java/io/InterruptedIOException", "splice interrupted");
2441 ret = -1;
2442 break;
2443 }
2444 if (ret == -1 && spliceErrno != EINTR) {
2445 throwErrnoException(env, "splice");
2446 break;
2447 }
2448 } while (ret == -1);
2449 if (ret == -1) {
2450 /* If the syscall failed, re-set errno: throwing an exception might have modified it. */
2451 errno = spliceErrno;
2452 } else {
2453 if (javaOffIn != NULL) {
2454 env->SetLongField(javaOffIn, int64RefValueFid, offIn);
2455 }
2456 if (javaOffOut != NULL) {
2457 env->SetLongField(javaOffOut, int64RefValueFid, offOut);
2458 }
2459 }
2460 return ret;
2461 }
2462
2463
Linux_stat(JNIEnv * env,jobject,jstring javaPath)2464 static jobject Linux_stat(JNIEnv* env, jobject, jstring javaPath) {
2465 return doStat(env, javaPath, false);
2466 }
2467
Linux_statvfs(JNIEnv * env,jobject,jstring javaPath)2468 static jobject Linux_statvfs(JNIEnv* env, jobject, jstring javaPath) {
2469 ScopedUtfChars path(env, javaPath);
2470 if (path.c_str() == NULL) {
2471 return NULL;
2472 }
2473 struct statvfs sb;
2474 int rc = TEMP_FAILURE_RETRY(statvfs(path.c_str(), &sb));
2475 if (rc == -1) {
2476 throwErrnoException(env, "statvfs");
2477 return NULL;
2478 }
2479 return makeStructStatVfs(env, sb);
2480 }
2481
Linux_strerror(JNIEnv * env,jobject,jint errnum)2482 static jstring Linux_strerror(JNIEnv* env, jobject, jint errnum) {
2483 char buffer[BUFSIZ];
2484 const char* message = jniStrError(errnum, buffer, sizeof(buffer));
2485 return env->NewStringUTF(message);
2486 }
2487
Linux_strsignal(JNIEnv * env,jobject,jint signal)2488 static jstring Linux_strsignal(JNIEnv* env, jobject, jint signal) {
2489 return env->NewStringUTF(strsignal(signal));
2490 }
2491
Linux_symlink(JNIEnv * env,jobject,jstring javaOldPath,jstring javaNewPath)2492 static void Linux_symlink(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) {
2493 ScopedUtfChars oldPath(env, javaOldPath);
2494 if (oldPath.c_str() == NULL) {
2495 return;
2496 }
2497 ScopedUtfChars newPath(env, javaNewPath);
2498 if (newPath.c_str() == NULL) {
2499 return;
2500 }
2501 throwIfMinusOne(env, "symlink", TEMP_FAILURE_RETRY(symlink(oldPath.c_str(), newPath.c_str())));
2502 }
2503
Linux_sysconf(JNIEnv * env,jobject,jint name)2504 static jlong Linux_sysconf(JNIEnv* env, jobject, jint name) {
2505 // Since -1 is a valid result from sysconf(3), detecting failure is a little more awkward.
2506 errno = 0;
2507 long result = sysconf(name);
2508 if (result == -1L && errno == EINVAL) {
2509 throwErrnoException(env, "sysconf");
2510 }
2511 return result;
2512 }
2513
Linux_tcdrain(JNIEnv * env,jobject,jobject javaFd)2514 static void Linux_tcdrain(JNIEnv* env, jobject, jobject javaFd) {
2515 int fd = jniGetFDFromFileDescriptor(env, javaFd);
2516 throwIfMinusOne(env, "tcdrain", TEMP_FAILURE_RETRY(tcdrain(fd)));
2517 }
2518
Linux_tcsendbreak(JNIEnv * env,jobject,jobject javaFd,jint duration)2519 static void Linux_tcsendbreak(JNIEnv* env, jobject, jobject javaFd, jint duration) {
2520 int fd = jniGetFDFromFileDescriptor(env, javaFd);
2521 throwIfMinusOne(env, "tcsendbreak", TEMP_FAILURE_RETRY(tcsendbreak(fd, duration)));
2522 }
2523
Linux_umaskImpl(JNIEnv *,jobject,jint mask)2524 static jint Linux_umaskImpl(JNIEnv*, jobject, jint mask) {
2525 return umask(mask);
2526 }
2527
Linux_uname(JNIEnv * env,jobject)2528 static jobject Linux_uname(JNIEnv* env, jobject) {
2529 struct utsname buf;
2530 if (TEMP_FAILURE_RETRY(uname(&buf)) == -1) {
2531 return NULL; // Can't happen.
2532 }
2533 return makeStructUtsname(env, buf);
2534 }
2535
Linux_unlink(JNIEnv * env,jobject,jstring javaPathname)2536 static void Linux_unlink(JNIEnv* env, jobject, jstring javaPathname) {
2537 ScopedUtfChars pathname(env, javaPathname);
2538 if (pathname.c_str() == NULL) {
2539 return;
2540 }
2541 throwIfMinusOne(env, "unlink", unlink(pathname.c_str()));
2542 }
2543
Linux_unsetenv(JNIEnv * env,jobject,jstring javaName)2544 static void Linux_unsetenv(JNIEnv* env, jobject, jstring javaName) {
2545 ScopedUtfChars name(env, javaName);
2546 if (name.c_str() == NULL) {
2547 return;
2548 }
2549 throwIfMinusOne(env, "unsetenv", unsetenv(name.c_str()));
2550 }
2551
Linux_waitpid(JNIEnv * env,jobject,jint pid,jobject javaStatus,jint options)2552 static jint Linux_waitpid(JNIEnv* env, jobject, jint pid, jobject javaStatus, jint options) {
2553 int status;
2554 int rc = throwIfMinusOne(env, "waitpid", TEMP_FAILURE_RETRY(waitpid(pid, &status, options)));
2555 if (javaStatus != NULL && rc != -1) {
2556 env->SetIntField(javaStatus, int32RefValueFid, status);
2557 }
2558 return rc;
2559 }
2560
Linux_writeBytes(JNIEnv * env,jobject,jobject javaFd,jobject javaBytes,jint byteOffset,jint byteCount)2561 static jint Linux_writeBytes(JNIEnv* env, jobject, jobject javaFd, jobject javaBytes, jint byteOffset, jint byteCount) {
2562 ScopedBytesRO bytes(env, javaBytes);
2563 if (bytes.get() == NULL) {
2564 return -1;
2565 }
2566 return IO_FAILURE_RETRY(env, ssize_t, write, javaFd, bytes.get() + byteOffset, byteCount);
2567 }
2568
Linux_writev(JNIEnv * env,jobject,jobject javaFd,jobjectArray buffers,jintArray offsets,jintArray byteCounts)2569 static jint Linux_writev(JNIEnv* env, jobject, jobject javaFd, jobjectArray buffers, jintArray offsets, jintArray byteCounts) {
2570 IoVec<ScopedBytesRO> ioVec(env, env->GetArrayLength(buffers));
2571 if (!ioVec.init(buffers, offsets, byteCounts)) {
2572 return -1;
2573 }
2574 return IO_FAILURE_RETRY(env, ssize_t, writev, javaFd, ioVec.get(), ioVec.size());
2575 }
2576
2577 #define NATIVE_METHOD_OVERLOAD(className, functionName, signature, variant) \
2578 { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName ## variant) }
2579
2580 static JNINativeMethod gMethods[] = {
2581 NATIVE_METHOD(Linux, accept, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)Ljava/io/FileDescriptor;"),
2582 NATIVE_METHOD(Linux, access, "(Ljava/lang/String;I)Z"),
2583 NATIVE_METHOD(Linux, android_fdsan_exchange_owner_tag, "(Ljava/io/FileDescriptor;JJ)V"),
2584 NATIVE_METHOD(Linux, android_fdsan_get_owner_tag, "(Ljava/io/FileDescriptor;)J"),
2585 NATIVE_METHOD(Linux, android_fdsan_get_tag_type, "(J)Ljava/lang/String;"),
2586 NATIVE_METHOD(Linux, android_fdsan_get_tag_value, "(J)J"),
2587 NATIVE_METHOD(Linux, android_getaddrinfo, "(Ljava/lang/String;Landroid/system/StructAddrinfo;I)[Ljava/net/InetAddress;"),
2588 NATIVE_METHOD(Linux, bind, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"),
2589 NATIVE_METHOD_OVERLOAD(Linux, bind, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V", SocketAddress),
2590 NATIVE_METHOD(Linux, capget,
2591 "(Landroid/system/StructCapUserHeader;)[Landroid/system/StructCapUserData;"),
2592 NATIVE_METHOD(Linux, capset,
2593 "(Landroid/system/StructCapUserHeader;[Landroid/system/StructCapUserData;)V"),
2594 NATIVE_METHOD(Linux, chmod, "(Ljava/lang/String;I)V"),
2595 NATIVE_METHOD(Linux, chown, "(Ljava/lang/String;II)V"),
2596 NATIVE_METHOD(Linux, close, "(Ljava/io/FileDescriptor;)V"),
2597 NATIVE_METHOD(Linux, connect, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"),
2598 NATIVE_METHOD_OVERLOAD(Linux, connect, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V", SocketAddress),
2599 NATIVE_METHOD(Linux, dup, "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;"),
2600 NATIVE_METHOD(Linux, dup2, "(Ljava/io/FileDescriptor;I)Ljava/io/FileDescriptor;"),
2601 NATIVE_METHOD(Linux, environ, "()[Ljava/lang/String;"),
2602 NATIVE_METHOD(Linux, execv, "(Ljava/lang/String;[Ljava/lang/String;)V"),
2603 NATIVE_METHOD(Linux, execve, "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V"),
2604 NATIVE_METHOD(Linux, fchmod, "(Ljava/io/FileDescriptor;I)V"),
2605 NATIVE_METHOD(Linux, fchown, "(Ljava/io/FileDescriptor;II)V"),
2606 NATIVE_METHOD(Linux, fcntlFlock, "(Ljava/io/FileDescriptor;ILandroid/system/StructFlock;)I"),
2607 NATIVE_METHOD(Linux, fcntlInt, "(Ljava/io/FileDescriptor;II)I"),
2608 NATIVE_METHOD(Linux, fcntlVoid, "(Ljava/io/FileDescriptor;I)I"),
2609 NATIVE_METHOD(Linux, fdatasync, "(Ljava/io/FileDescriptor;)V"),
2610 NATIVE_METHOD(Linux, fstat, "(Ljava/io/FileDescriptor;)Landroid/system/StructStat;"),
2611 NATIVE_METHOD(Linux, fstatvfs, "(Ljava/io/FileDescriptor;)Landroid/system/StructStatVfs;"),
2612 NATIVE_METHOD(Linux, fsync, "(Ljava/io/FileDescriptor;)V"),
2613 NATIVE_METHOD(Linux, ftruncate, "(Ljava/io/FileDescriptor;J)V"),
2614 NATIVE_METHOD(Linux, gai_strerror, "(I)Ljava/lang/String;"),
2615 NATIVE_METHOD(Linux, getegid, "()I"),
2616 NATIVE_METHOD(Linux, geteuid, "()I"),
2617 NATIVE_METHOD(Linux, getgid, "()I"),
2618 NATIVE_METHOD(Linux, getenv, "(Ljava/lang/String;)Ljava/lang/String;"),
2619 NATIVE_METHOD(Linux, getnameinfo, "(Ljava/net/InetAddress;I)Ljava/lang/String;"),
2620 NATIVE_METHOD(Linux, getpeername, "(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;"),
2621 NATIVE_METHOD(Linux, getpgid, "(I)I"),
2622 NATIVE_METHOD(Linux, getpid, "()I"),
2623 NATIVE_METHOD(Linux, getppid, "()I"),
2624 NATIVE_METHOD(Linux, getpwnam, "(Ljava/lang/String;)Landroid/system/StructPasswd;"),
2625 NATIVE_METHOD(Linux, getpwuid, "(I)Landroid/system/StructPasswd;"),
2626 NATIVE_METHOD(Linux, getrlimit, "(I)Landroid/system/StructRlimit;"),
2627 NATIVE_METHOD(Linux, getsockname, "(Ljava/io/FileDescriptor;)Ljava/net/SocketAddress;"),
2628 NATIVE_METHOD(Linux, getsockoptByte, "(Ljava/io/FileDescriptor;II)I"),
2629 NATIVE_METHOD(Linux, getsockoptInAddr, "(Ljava/io/FileDescriptor;II)Ljava/net/InetAddress;"),
2630 NATIVE_METHOD(Linux, getsockoptInt, "(Ljava/io/FileDescriptor;II)I"),
2631 NATIVE_METHOD(Linux, getsockoptLinger, "(Ljava/io/FileDescriptor;II)Landroid/system/StructLinger;"),
2632 NATIVE_METHOD(Linux, getsockoptTimeval, "(Ljava/io/FileDescriptor;II)Landroid/system/StructTimeval;"),
2633 NATIVE_METHOD(Linux, getsockoptUcred, "(Ljava/io/FileDescriptor;II)Landroid/system/StructUcred;"),
2634 NATIVE_METHOD(Linux, gettid, "()I"),
2635 NATIVE_METHOD(Linux, getuid, "()I"),
2636 NATIVE_METHOD(Linux, getxattr, "(Ljava/lang/String;Ljava/lang/String;)[B"),
2637 NATIVE_METHOD(Linux, getifaddrs, "()[Landroid/system/StructIfaddrs;"),
2638 NATIVE_METHOD(Linux, if_indextoname, "(I)Ljava/lang/String;"),
2639 NATIVE_METHOD(Linux, if_nametoindex, "(Ljava/lang/String;)I"),
2640 NATIVE_METHOD(Linux, inet_pton, "(ILjava/lang/String;)Ljava/net/InetAddress;"),
2641 NATIVE_METHOD(Linux, ioctlFlags, "(Ljava/io/FileDescriptor;Ljava/lang/String;)I"),
2642 NATIVE_METHOD(Linux, ioctlInetAddress, "(Ljava/io/FileDescriptor;ILjava/lang/String;)Ljava/net/InetAddress;"),
2643 NATIVE_METHOD(Linux, ioctlInt, "(Ljava/io/FileDescriptor;ILandroid/system/Int32Ref;)I"),
2644 NATIVE_METHOD(Linux, ioctlMTU, "(Ljava/io/FileDescriptor;Ljava/lang/String;)I"),
2645 NATIVE_METHOD(Linux, isatty, "(Ljava/io/FileDescriptor;)Z"),
2646 NATIVE_METHOD(Linux, kill, "(II)V"),
2647 NATIVE_METHOD(Linux, lchown, "(Ljava/lang/String;II)V"),
2648 NATIVE_METHOD(Linux, link, "(Ljava/lang/String;Ljava/lang/String;)V"),
2649 NATIVE_METHOD(Linux, listen, "(Ljava/io/FileDescriptor;I)V"),
2650 NATIVE_METHOD(Linux, listxattr, "(Ljava/lang/String;)[Ljava/lang/String;"),
2651 NATIVE_METHOD(Linux, lseek, "(Ljava/io/FileDescriptor;JI)J"),
2652 NATIVE_METHOD(Linux, lstat, "(Ljava/lang/String;)Landroid/system/StructStat;"),
2653 NATIVE_METHOD(Linux, mincore, "(JJ[B)V"),
2654 NATIVE_METHOD(Linux, mkdir, "(Ljava/lang/String;I)V"),
2655 NATIVE_METHOD(Linux, mkfifo, "(Ljava/lang/String;I)V"),
2656 NATIVE_METHOD(Linux, mlock, "(JJ)V"),
2657 NATIVE_METHOD(Linux, mmap, "(JJIILjava/io/FileDescriptor;J)J"),
2658 NATIVE_METHOD(Linux, msync, "(JJI)V"),
2659 NATIVE_METHOD(Linux, munlock, "(JJ)V"),
2660 NATIVE_METHOD(Linux, munmap, "(JJ)V"),
2661 NATIVE_METHOD(Linux, open, "(Ljava/lang/String;II)Ljava/io/FileDescriptor;"),
2662 NATIVE_METHOD(Linux, pipe2, "(I)[Ljava/io/FileDescriptor;"),
2663 NATIVE_METHOD(Linux, poll, "([Landroid/system/StructPollfd;I)I"),
2664 NATIVE_METHOD(Linux, posix_fallocate, "(Ljava/io/FileDescriptor;JJ)V"),
2665 NATIVE_METHOD(Linux, prctl, "(IJJJJ)I"),
2666 NATIVE_METHOD(Linux, preadBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIJ)I"),
2667 NATIVE_METHOD(Linux, pwriteBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIJ)I"),
2668 NATIVE_METHOD(Linux, readBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;II)I"),
2669 NATIVE_METHOD(Linux, readlink, "(Ljava/lang/String;)Ljava/lang/String;"),
2670 NATIVE_METHOD(Linux, realpath, "(Ljava/lang/String;)Ljava/lang/String;"),
2671 NATIVE_METHOD(Linux, readv, "(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I"),
2672 NATIVE_METHOD(Linux, recvfromBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetSocketAddress;)I"),
2673 NATIVE_METHOD(Linux, remove, "(Ljava/lang/String;)V"),
2674 NATIVE_METHOD(Linux, removexattr, "(Ljava/lang/String;Ljava/lang/String;)V"),
2675 NATIVE_METHOD(Linux, rename, "(Ljava/lang/String;Ljava/lang/String;)V"),
2676 NATIVE_METHOD(Linux, sendfile, "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Landroid/system/Int64Ref;J)J"),
2677 NATIVE_METHOD(Linux, sendtoBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/InetAddress;I)I"),
2678 NATIVE_METHOD_OVERLOAD(Linux, sendtoBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;IIILjava/net/SocketAddress;)I", SocketAddress),
2679 NATIVE_METHOD(Linux, setegid, "(I)V"),
2680 NATIVE_METHOD(Linux, setenv, "(Ljava/lang/String;Ljava/lang/String;Z)V"),
2681 NATIVE_METHOD(Linux, seteuid, "(I)V"),
2682 NATIVE_METHOD(Linux, setgid, "(I)V"),
2683 NATIVE_METHOD(Linux, setpgid, "(II)V"),
2684 NATIVE_METHOD(Linux, setregid, "(II)V"),
2685 NATIVE_METHOD(Linux, setreuid, "(II)V"),
2686 NATIVE_METHOD(Linux, setsid, "()I"),
2687 NATIVE_METHOD(Linux, setsockoptByte, "(Ljava/io/FileDescriptor;III)V"),
2688 NATIVE_METHOD(Linux, setsockoptIfreq, "(Ljava/io/FileDescriptor;IILjava/lang/String;)V"),
2689 NATIVE_METHOD(Linux, setsockoptInt, "(Ljava/io/FileDescriptor;III)V"),
2690 NATIVE_METHOD(Linux, setsockoptIpMreqn, "(Ljava/io/FileDescriptor;III)V"),
2691 NATIVE_METHOD(Linux, setsockoptGroupReq, "(Ljava/io/FileDescriptor;IILandroid/system/StructGroupReq;)V"),
2692 NATIVE_METHOD(Linux, setsockoptLinger, "(Ljava/io/FileDescriptor;IILandroid/system/StructLinger;)V"),
2693 NATIVE_METHOD(Linux, setsockoptTimeval, "(Ljava/io/FileDescriptor;IILandroid/system/StructTimeval;)V"),
2694 NATIVE_METHOD(Linux, setuid, "(I)V"),
2695 NATIVE_METHOD(Linux, setxattr, "(Ljava/lang/String;Ljava/lang/String;[BI)V"),
2696 NATIVE_METHOD(Linux, shutdown, "(Ljava/io/FileDescriptor;I)V"),
2697 NATIVE_METHOD(Linux, socket, "(III)Ljava/io/FileDescriptor;"),
2698 NATIVE_METHOD(Linux, socketpair, "(IIILjava/io/FileDescriptor;Ljava/io/FileDescriptor;)V"),
2699 NATIVE_METHOD(Linux, splice, "(Ljava/io/FileDescriptor;Landroid/system/Int64Ref;Ljava/io/FileDescriptor;Landroid/system/Int64Ref;JI)J"),
2700 NATIVE_METHOD(Linux, stat, "(Ljava/lang/String;)Landroid/system/StructStat;"),
2701 NATIVE_METHOD(Linux, statvfs, "(Ljava/lang/String;)Landroid/system/StructStatVfs;"),
2702 NATIVE_METHOD(Linux, strerror, "(I)Ljava/lang/String;"),
2703 NATIVE_METHOD(Linux, strsignal, "(I)Ljava/lang/String;"),
2704 NATIVE_METHOD(Linux, symlink, "(Ljava/lang/String;Ljava/lang/String;)V"),
2705 NATIVE_METHOD(Linux, sysconf, "(I)J"),
2706 NATIVE_METHOD(Linux, tcdrain, "(Ljava/io/FileDescriptor;)V"),
2707 NATIVE_METHOD(Linux, tcsendbreak, "(Ljava/io/FileDescriptor;I)V"),
2708 NATIVE_METHOD(Linux, umaskImpl, "(I)I"),
2709 NATIVE_METHOD(Linux, uname, "()Landroid/system/StructUtsname;"),
2710 NATIVE_METHOD(Linux, unlink, "(Ljava/lang/String;)V"),
2711 NATIVE_METHOD(Linux, unsetenv, "(Ljava/lang/String;)V"),
2712 NATIVE_METHOD(Linux, waitpid, "(ILandroid/system/Int32Ref;I)I"),
2713 NATIVE_METHOD(Linux, writeBytes, "(Ljava/io/FileDescriptor;Ljava/lang/Object;II)I"),
2714 NATIVE_METHOD(Linux, writev, "(Ljava/io/FileDescriptor;[Ljava/lang/Object;[I[I)I"),
2715 };
register_libcore_io_Linux(JNIEnv * env)2716 void register_libcore_io_Linux(JNIEnv* env) {
2717 // Note: it is safe to only cache the fields as boot classpath classes are never
2718 // unloaded.
2719 ScopedLocalRef<jclass> int32RefClass(env, env->FindClass("android/system/Int32Ref"));
2720 CHECK(int32RefClass != nullptr);
2721 int32RefValueFid = env->GetFieldID(int32RefClass.get(), "value", "I");
2722 CHECK(int32RefValueFid != nullptr);
2723
2724 ScopedLocalRef<jclass> int64RefClass(env, env->FindClass("android/system/Int64Ref"));
2725 CHECK(int64RefClass != nullptr);
2726 int64RefValueFid = env->GetFieldID(int64RefClass.get(), "value", "J");
2727 CHECK(int64RefValueFid != nullptr);
2728
2729 jniRegisterNativeMethods(env, "libcore/io/Linux", gMethods, NELEM(gMethods));
2730 }
2731