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