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