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