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