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