1 /*
2  * Copyright (C) 2012 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 "Parcel"
18 //#define LOG_NDEBUG 0
19 
20 #include "android_os_Parcel.h"
21 #include "android_util_Binder.h"
22 
23 #include <nativehelper/JNIPlatformHelp.h>
24 
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 
31 #include <binder/IInterface.h>
32 #include <binder/IPCThreadState.h>
33 #include <cutils/atomic.h>
34 #include <utils/Log.h>
35 #include <utils/SystemClock.h>
36 #include <utils/List.h>
37 #include <utils/KeyedVector.h>
38 #include <binder/Parcel.h>
39 #include <binder/ProcessState.h>
40 #include <binder/IServiceManager.h>
41 #include <utils/threads.h>
42 #include <utils/String8.h>
43 
44 #include <nativehelper/ScopedUtfChars.h>
45 #include <nativehelper/ScopedLocalRef.h>
46 
47 #include <android_runtime/AndroidRuntime.h>
48 
49 #include "core_jni_helpers.h"
50 
51 //#undef ALOGV
52 //#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
53 
54 #define DEBUG_DEATH 0
55 #if DEBUG_DEATH
56 #define LOGDEATH ALOGD
57 #else
58 #define LOGDEATH ALOGV
59 #endif
60 
61 namespace android {
62 
63 static struct parcel_offsets_t
64 {
65     jclass clazz;
66     jfieldID mNativePtr;
67     jmethodID obtain;
68     jmethodID recycle;
69 } gParcelOffsets;
70 
parcelForJavaObject(JNIEnv * env,jobject obj)71 Parcel* parcelForJavaObject(JNIEnv* env, jobject obj)
72 {
73     if (obj) {
74         Parcel* p = (Parcel*)env->GetLongField(obj, gParcelOffsets.mNativePtr);
75         if (p != NULL) {
76             return p;
77         }
78         jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!");
79     }
80     return NULL;
81 }
82 
createJavaParcelObject(JNIEnv * env)83 jobject createJavaParcelObject(JNIEnv* env)
84 {
85     return env->CallStaticObjectMethod(gParcelOffsets.clazz, gParcelOffsets.obtain);
86 }
87 
recycleJavaParcelObject(JNIEnv * env,jobject parcelObj)88 void recycleJavaParcelObject(JNIEnv* env, jobject parcelObj)
89 {
90     env->CallVoidMethod(parcelObj, gParcelOffsets.recycle);
91 }
92 
android_os_Parcel_markSensitive(jlong nativePtr)93 static void android_os_Parcel_markSensitive(jlong nativePtr)
94 {
95     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
96     if (parcel) {
97         parcel->markSensitive();
98     }
99 }
100 
android_os_Parcel_markForBinder(JNIEnv * env,jclass clazz,jlong nativePtr,jobject binder)101 static void android_os_Parcel_markForBinder(JNIEnv* env, jclass clazz, jlong nativePtr,
102                                             jobject binder)
103 {
104     LOG_ALWAYS_FATAL_IF(binder == nullptr, "Null binder specified for markForBinder");
105 
106     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
107     if (parcel) {
108         sp<IBinder> nBinder = ibinderForJavaObject(env, binder);
109 
110         if (nBinder == nullptr) {
111             ALOGE("Native binder in markForBinder is null for non-null jobject");
112             return;
113         }
114 
115         parcel->markForBinder(nBinder);
116     }
117 }
118 
android_os_Parcel_isForRpc(jlong nativePtr)119 static jboolean android_os_Parcel_isForRpc(jlong nativePtr) {
120     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
121     return parcel ? parcel->isForRpc() : false;
122 }
123 
android_os_Parcel_dataSize(jlong nativePtr)124 static jint android_os_Parcel_dataSize(jlong nativePtr)
125 {
126     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
127     return parcel ? parcel->dataSize() : 0;
128 }
129 
android_os_Parcel_dataAvail(jlong nativePtr)130 static jint android_os_Parcel_dataAvail(jlong nativePtr)
131 {
132     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
133     return parcel ? parcel->dataAvail() : 0;
134 }
135 
android_os_Parcel_dataPosition(jlong nativePtr)136 static jint android_os_Parcel_dataPosition(jlong nativePtr)
137 {
138     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
139     return parcel ? parcel->dataPosition() : 0;
140 }
141 
android_os_Parcel_dataCapacity(jlong nativePtr)142 static jint android_os_Parcel_dataCapacity(jlong nativePtr)
143 {
144     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
145     return parcel ? parcel->dataCapacity() : 0;
146 }
147 
android_os_Parcel_setDataSize(JNIEnv * env,jclass clazz,jlong nativePtr,jint size)148 static void android_os_Parcel_setDataSize(JNIEnv* env, jclass clazz, jlong nativePtr, jint size)
149 {
150     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
151     if (parcel != NULL) {
152         const status_t err = parcel->setDataSize(size);
153         if (err != NO_ERROR) {
154             signalExceptionForError(env, clazz, err);
155         }
156     }
157 }
158 
android_os_Parcel_setDataPosition(jlong nativePtr,jint pos)159 static void android_os_Parcel_setDataPosition(jlong nativePtr, jint pos)
160 {
161     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
162     if (parcel != NULL) {
163         parcel->setDataPosition(pos);
164     }
165 }
166 
android_os_Parcel_setDataCapacity(JNIEnv * env,jclass clazz,jlong nativePtr,jint size)167 static void android_os_Parcel_setDataCapacity(JNIEnv* env, jclass clazz, jlong nativePtr, jint size)
168 {
169     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
170     if (parcel != NULL) {
171         const status_t err = parcel->setDataCapacity(size);
172         if (err != NO_ERROR) {
173             signalExceptionForError(env, clazz, err);
174         }
175     }
176 }
177 
android_os_Parcel_pushAllowFds(jlong nativePtr,jboolean allowFds)178 static jboolean android_os_Parcel_pushAllowFds(jlong nativePtr, jboolean allowFds)
179 {
180     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
181     jboolean ret = JNI_TRUE;
182     if (parcel != NULL) {
183         ret = (jboolean)parcel->pushAllowFds(allowFds);
184     }
185     return ret;
186 }
187 
android_os_Parcel_restoreAllowFds(jlong nativePtr,jboolean lastValue)188 static void android_os_Parcel_restoreAllowFds(jlong nativePtr, jboolean lastValue)
189 {
190     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
191     if (parcel != NULL) {
192         parcel->restoreAllowFds((bool)lastValue);
193     }
194 }
195 
android_os_Parcel_writeByteArray(JNIEnv * env,jclass clazz,jlong nativePtr,jobject data,jint offset,jint length)196 static void android_os_Parcel_writeByteArray(JNIEnv* env, jclass clazz, jlong nativePtr,
197                                              jobject data, jint offset, jint length)
198 {
199     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
200     if (parcel == NULL) {
201         return;
202     }
203 
204     const status_t err = parcel->writeInt32(length);
205     if (err != NO_ERROR) {
206         signalExceptionForError(env, clazz, err);
207         return;
208     }
209 
210     void* dest = parcel->writeInplace(length);
211     if (dest == NULL) {
212         signalExceptionForError(env, clazz, NO_MEMORY);
213         return;
214     }
215 
216     jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
217     if (ar) {
218         memcpy(dest, ar + offset, length);
219         env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
220     }
221 }
222 
android_os_Parcel_writeBlob(JNIEnv * env,jclass clazz,jlong nativePtr,jobject data,jint offset,jint length)223 static void android_os_Parcel_writeBlob(JNIEnv* env, jclass clazz, jlong nativePtr, jobject data,
224                                         jint offset, jint length) {
225     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
226     if (parcel == NULL) {
227         return;
228     }
229 
230     if (data == NULL) {
231         const status_t err = parcel->writeInt32(-1);
232         if (err != NO_ERROR) {
233             signalExceptionForError(env, clazz, err);
234         }
235         return;
236     }
237 
238     const status_t err = parcel->writeInt32(length);
239     if (err != NO_ERROR) {
240         signalExceptionForError(env, clazz, err);
241         return;
242     }
243 
244     android::Parcel::WritableBlob blob;
245     android::status_t err2 = parcel->writeBlob(length, false, &blob);
246     if (err2 != NO_ERROR) {
247         signalExceptionForError(env, clazz, err2);
248         return;
249     }
250 
251     jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
252     if (ar == NULL) {
253         memset(blob.data(), 0, length);
254     } else {
255         memcpy(blob.data(), ar + offset, length);
256         env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
257     }
258 
259     blob.release();
260 }
261 
android_os_Parcel_writeInt(jlong nativePtr,jint val)262 static int android_os_Parcel_writeInt(jlong nativePtr, jint val) {
263     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
264     return (parcel != NULL) ? parcel->writeInt32(val) : OK;
265 }
266 
android_os_Parcel_writeLong(jlong nativePtr,jlong val)267 static int android_os_Parcel_writeLong(jlong nativePtr, jlong val) {
268     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
269     return (parcel != NULL) ? parcel->writeInt64(val) : OK;
270 }
271 
android_os_Parcel_writeFloat(jlong nativePtr,jfloat val)272 static int android_os_Parcel_writeFloat(jlong nativePtr, jfloat val) {
273     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
274     return (parcel != NULL) ? parcel->writeFloat(val) : OK;
275 }
276 
android_os_Parcel_writeDouble(jlong nativePtr,jdouble val)277 static int android_os_Parcel_writeDouble(jlong nativePtr, jdouble val) {
278     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
279     return (parcel != NULL) ? parcel->writeDouble(val) : OK;
280 }
281 
android_os_Parcel_nativeSignalExceptionForError(JNIEnv * env,jclass clazz,jint err)282 static void android_os_Parcel_nativeSignalExceptionForError(JNIEnv* env, jclass clazz, jint err) {
283     signalExceptionForError(env, clazz, err);
284 }
285 
android_os_Parcel_writeString8(JNIEnv * env,jclass clazz,jlong nativePtr,jstring val)286 static void android_os_Parcel_writeString8(JNIEnv *env, jclass clazz, jlong nativePtr,
287         jstring val) {
288     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
289     if (parcel != nullptr) {
290         status_t err = NO_ERROR;
291         if (val) {
292             // NOTE: Keep this logic in sync with Parcel.cpp
293             const size_t len = env->GetStringLength(val);
294             const size_t allocLen = env->GetStringUTFLength(val);
295             err = parcel->writeInt32(allocLen);
296             char *data = reinterpret_cast<char*>(parcel->writeInplace(allocLen + sizeof(char)));
297             if (data != nullptr) {
298                 env->GetStringUTFRegion(val, 0, len, data);
299                 *(data + allocLen) = 0;
300             } else {
301                 err = NO_MEMORY;
302             }
303         } else {
304             err = parcel->writeString8(nullptr, 0);
305         }
306         if (err != NO_ERROR) {
307             signalExceptionForError(env, clazz, err);
308         }
309     }
310 }
311 
android_os_Parcel_writeString16(JNIEnv * env,jclass clazz,jlong nativePtr,jstring val)312 static void android_os_Parcel_writeString16(JNIEnv *env, jclass clazz, jlong nativePtr,
313         jstring val) {
314     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
315     if (parcel != nullptr) {
316         status_t err = NO_ERROR;
317         if (val) {
318             // NOTE: Keep this logic in sync with Parcel.cpp
319             const size_t len = env->GetStringLength(val);
320             const size_t allocLen = len * sizeof(char16_t);
321             err = parcel->writeInt32(len);
322             char *data = reinterpret_cast<char*>(parcel->writeInplace(allocLen + sizeof(char16_t)));
323             if (data != nullptr) {
324                 env->GetStringRegion(val, 0, len, reinterpret_cast<jchar*>(data));
325                 *reinterpret_cast<char16_t*>(data + allocLen) = 0;
326             } else {
327                 err = NO_MEMORY;
328             }
329         } else {
330             err = parcel->writeString16(nullptr, 0);
331         }
332         if (err != NO_ERROR) {
333             signalExceptionForError(env, clazz, err);
334         }
335     }
336 }
337 
android_os_Parcel_writeStrongBinder(JNIEnv * env,jclass clazz,jlong nativePtr,jobject object)338 static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
339 {
340     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
341     if (parcel != NULL) {
342         const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
343         if (err != NO_ERROR) {
344             signalExceptionForError(env, clazz, err);
345         }
346     }
347 }
348 
android_os_Parcel_writeFileDescriptor(JNIEnv * env,jclass clazz,jlong nativePtr,jobject object)349 static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
350 {
351     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
352     if (parcel != NULL) {
353         const status_t err =
354                 parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
355         if (err != NO_ERROR) {
356             signalExceptionForError(env, clazz, err);
357         }
358     }
359 }
360 
android_os_Parcel_createByteArray(JNIEnv * env,jclass clazz,jlong nativePtr)361 static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jclass clazz, jlong nativePtr)
362 {
363     jbyteArray ret = NULL;
364 
365     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
366     if (parcel != NULL) {
367         int32_t len = parcel->readInt32();
368 
369         // Validate the stored length against the true data size
370         if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
371             ret = env->NewByteArray(len);
372 
373             if (ret != NULL) {
374                 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
375                 if (a2) {
376                     const void* data = parcel->readInplace(len);
377                     if (data) {
378                         memcpy(a2, data, len);
379                     }
380                     env->ReleasePrimitiveArrayCritical(ret, a2, 0);
381                     if (!data) {
382                         ret = NULL;
383                     }
384                 }
385             }
386         }
387     }
388 
389     return ret;
390 }
391 
android_os_Parcel_readByteArray(JNIEnv * env,jclass clazz,jlong nativePtr,jobject dest,jint destLen)392 static jboolean android_os_Parcel_readByteArray(JNIEnv* env, jclass clazz, jlong nativePtr,
393                                                 jobject dest, jint destLen)
394 {
395     jboolean ret = JNI_FALSE;
396     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
397     if (parcel == NULL) {
398         return ret;
399     }
400 
401     int32_t len = parcel->readInt32();
402     if (len >= 0 && len <= (int32_t)parcel->dataAvail() && len == destLen) {
403         jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)dest, 0);
404         if (ar) {
405             const void* data = parcel->readInplace(len);
406             if (data) {
407                 memcpy(ar, data, len);
408                 ret = JNI_TRUE;
409             } else {
410                 ret = JNI_FALSE;
411             }
412 
413             env->ReleasePrimitiveArrayCritical((jarray)dest, ar, 0);
414         }
415     }
416     return ret;
417 }
418 
android_os_Parcel_readBlob(JNIEnv * env,jclass clazz,jlong nativePtr)419 static jbyteArray android_os_Parcel_readBlob(JNIEnv* env, jclass clazz, jlong nativePtr)
420 {
421     jbyteArray ret = NULL;
422 
423     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
424     if (parcel != NULL) {
425         int32_t len = parcel->readInt32();
426         if (len >= 0) {
427             android::Parcel::ReadableBlob blob;
428             android::status_t err = parcel->readBlob(len, &blob);
429             if (err != NO_ERROR) {
430                 signalExceptionForError(env, clazz, err);
431                 return NULL;
432             }
433 
434             ret = env->NewByteArray(len);
435             if (ret != NULL) {
436                 jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
437                 if (a2) {
438                     memcpy(a2, blob.data(), len);
439                     env->ReleasePrimitiveArrayCritical(ret, a2, 0);
440                 }
441             }
442             blob.release();
443         }
444     }
445 
446     return ret;
447 }
448 
android_os_Parcel_readInt(jlong nativePtr)449 static jint android_os_Parcel_readInt(jlong nativePtr)
450 {
451     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
452     if (parcel != NULL) {
453         return parcel->readInt32();
454     }
455     return 0;
456 }
457 
android_os_Parcel_readLong(jlong nativePtr)458 static jlong android_os_Parcel_readLong(jlong nativePtr)
459 {
460     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
461     if (parcel != NULL) {
462         return parcel->readInt64();
463     }
464     return 0;
465 }
466 
android_os_Parcel_readFloat(jlong nativePtr)467 static jfloat android_os_Parcel_readFloat(jlong nativePtr)
468 {
469     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
470     if (parcel != NULL) {
471         return parcel->readFloat();
472     }
473     return 0;
474 }
475 
android_os_Parcel_readDouble(jlong nativePtr)476 static jdouble android_os_Parcel_readDouble(jlong nativePtr)
477 {
478     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
479     if (parcel != NULL) {
480         return parcel->readDouble();
481     }
482     return 0;
483 }
484 
android_os_Parcel_readString8(JNIEnv * env,jclass clazz,jlong nativePtr)485 static jstring android_os_Parcel_readString8(JNIEnv* env, jclass clazz, jlong nativePtr)
486 {
487     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
488     if (parcel != NULL) {
489         size_t len;
490         const char* str = parcel->readString8Inplace(&len);
491         if (str) {
492             return env->NewStringUTF(str);
493         }
494         return NULL;
495     }
496     return NULL;
497 }
498 
android_os_Parcel_readString16(JNIEnv * env,jclass clazz,jlong nativePtr)499 static jstring android_os_Parcel_readString16(JNIEnv* env, jclass clazz, jlong nativePtr)
500 {
501     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
502     if (parcel != NULL) {
503         size_t len;
504         const char16_t* str = parcel->readString16Inplace(&len);
505         if (str) {
506             return env->NewString(reinterpret_cast<const jchar*>(str), len);
507         }
508         return NULL;
509     }
510     return NULL;
511 }
512 
android_os_Parcel_readStrongBinder(JNIEnv * env,jclass clazz,jlong nativePtr)513 static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
514 {
515     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
516     if (parcel != NULL) {
517         return javaObjectForIBinder(env, parcel->readStrongBinder());
518     }
519     return NULL;
520 }
521 
android_os_Parcel_readFileDescriptor(JNIEnv * env,jclass clazz,jlong nativePtr)522 static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jclass clazz, jlong nativePtr)
523 {
524     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
525     if (parcel != NULL) {
526         int fd = parcel->readFileDescriptor();
527         if (fd < 0) return NULL;
528         fd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
529         if (fd < 0) return NULL;
530         jobject jifd = jniCreateFileDescriptor(env, fd);
531         if (jifd == NULL) {
532             close(fd);
533         }
534         return jifd;
535     }
536     return NULL;
537 }
538 
android_os_Parcel_create(JNIEnv * env,jclass clazz)539 static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
540 {
541     Parcel* parcel = new Parcel();
542     return reinterpret_cast<jlong>(parcel);
543 }
544 
android_os_Parcel_freeBuffer(JNIEnv * env,jclass clazz,jlong nativePtr)545 static void android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jlong nativePtr)
546 {
547     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
548     if (parcel != NULL) {
549         parcel->freeData();
550     }
551 }
552 
android_os_Parcel_destroy(JNIEnv * env,jclass clazz,jlong nativePtr)553 static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jlong nativePtr)
554 {
555     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
556     delete parcel;
557 }
558 
android_os_Parcel_marshall(JNIEnv * env,jclass clazz,jlong nativePtr)559 static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jclass clazz, jlong nativePtr)
560 {
561     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
562     if (parcel == NULL) {
563        return NULL;
564     }
565 
566     if (parcel->isForRpc()) {
567         jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall an RPC Parcel.");
568         return NULL;
569     }
570 
571     if (parcel->objectsCount())
572     {
573         jniThrowException(env, "java/lang/RuntimeException",
574                           "Tried to marshall a Parcel that contains objects (binders or FDs).");
575         return NULL;
576     }
577 
578     jbyteArray ret = env->NewByteArray(parcel->dataSize());
579 
580     if (ret != NULL)
581     {
582         jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
583         if (array != NULL)
584         {
585             memcpy(array, parcel->data(), parcel->dataSize());
586             env->ReleasePrimitiveArrayCritical(ret, array, 0);
587         }
588     }
589 
590     return ret;
591 }
592 
android_os_Parcel_unmarshall(JNIEnv * env,jclass clazz,jlong nativePtr,jbyteArray data,jint offset,jint length)593 static void android_os_Parcel_unmarshall(JNIEnv* env, jclass clazz, jlong nativePtr,
594                                           jbyteArray data, jint offset, jint length)
595 {
596     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
597     if (parcel == NULL || length < 0) {
598        return;
599     }
600 
601     jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
602     if (array)
603     {
604         parcel->setDataSize(length);
605         parcel->setDataPosition(0);
606 
607         void* raw = parcel->writeInplace(length);
608         memcpy(raw, (array + offset), length);
609 
610         env->ReleasePrimitiveArrayCritical(data, array, 0);
611     }
612 }
613 
android_os_Parcel_compareData(JNIEnv * env,jclass clazz,jlong thisNativePtr,jlong otherNativePtr)614 static jint android_os_Parcel_compareData(JNIEnv* env, jclass clazz, jlong thisNativePtr,
615                                           jlong otherNativePtr)
616 {
617     Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
618     LOG_ALWAYS_FATAL_IF(thisParcel == nullptr, "Should not be null");
619 
620     Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
621     LOG_ALWAYS_FATAL_IF(otherParcel == nullptr, "Should not be null");
622 
623     return thisParcel->compareData(*otherParcel);
624 }
625 
android_os_Parcel_compareDataInRange(JNIEnv * env,jclass clazz,jlong thisNativePtr,jint thisOffset,jlong otherNativePtr,jint otherOffset,jint length)626 static jboolean android_os_Parcel_compareDataInRange(JNIEnv* env, jclass clazz, jlong thisNativePtr,
627                                                      jint thisOffset, jlong otherNativePtr,
628                                                      jint otherOffset, jint length) {
629     Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
630     LOG_ALWAYS_FATAL_IF(thisParcel == nullptr, "Should not be null");
631 
632     Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
633     LOG_ALWAYS_FATAL_IF(otherParcel == nullptr, "Should not be null");
634 
635     int result;
636     status_t err =
637             thisParcel->compareDataInRange(thisOffset, *otherParcel, otherOffset, length, &result);
638     if (err != NO_ERROR) {
639         signalExceptionForError(env, clazz, err);
640         return JNI_FALSE;
641     }
642     return (result == 0) ? JNI_TRUE : JNI_FALSE;
643 }
644 
android_os_Parcel_appendFrom(JNIEnv * env,jclass clazz,jlong thisNativePtr,jlong otherNativePtr,jint offset,jint length)645 static void android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jlong thisNativePtr,
646                                           jlong otherNativePtr, jint offset, jint length)
647 {
648     Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
649     if (thisParcel == NULL) {
650        return;
651     }
652     Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
653     if (otherParcel == NULL) {
654        return;
655     }
656 
657     status_t err = thisParcel->appendFrom(otherParcel, offset, length);
658     if (err != NO_ERROR) {
659         signalExceptionForError(env, clazz, err);
660     }
661     return;
662 }
663 
android_os_Parcel_hasBinders(JNIEnv * env,jclass clazz,jlong nativePtr)664 static jboolean android_os_Parcel_hasBinders(JNIEnv* env, jclass clazz, jlong nativePtr) {
665     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
666     if (parcel != NULL) {
667         bool result;
668         status_t err = parcel->hasBinders(&result);
669         if (err != NO_ERROR) {
670             signalExceptionForError(env, clazz, err);
671             return JNI_FALSE;
672         }
673         return result ? JNI_TRUE : JNI_FALSE;
674     }
675     return JNI_FALSE;
676 }
677 
android_os_Parcel_hasBindersInRange(JNIEnv * env,jclass clazz,jlong nativePtr,jint offset,jint length)678 static jboolean android_os_Parcel_hasBindersInRange(JNIEnv* env, jclass clazz, jlong nativePtr,
679                                                     jint offset, jint length) {
680     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
681     if (parcel != NULL) {
682         bool result;
683         status_t err = parcel->hasBindersInRange(offset, length, &result);
684         if (err != NO_ERROR) {
685             signalExceptionForError(env, clazz, err);
686             return JNI_FALSE;
687         }
688         return result ? JNI_TRUE : JNI_FALSE;
689     }
690     return JNI_FALSE;
691 }
692 
android_os_Parcel_hasFileDescriptors(jlong nativePtr)693 static jboolean android_os_Parcel_hasFileDescriptors(jlong nativePtr)
694 {
695     jboolean ret = JNI_FALSE;
696     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
697     if (parcel != NULL) {
698         if (parcel->hasFileDescriptors()) {
699             ret = JNI_TRUE;
700         }
701     }
702     return ret;
703 }
704 
android_os_Parcel_hasFileDescriptorsInRange(JNIEnv * env,jclass clazz,jlong nativePtr,jint offset,jint length)705 static jboolean android_os_Parcel_hasFileDescriptorsInRange(JNIEnv* env, jclass clazz,
706                                                             jlong nativePtr, jint offset,
707                                                             jint length) {
708     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
709     if (parcel != NULL) {
710         bool result;
711         status_t err = parcel->hasFileDescriptorsInRange(offset, length, &result);
712         if (err != NO_ERROR) {
713             signalExceptionForError(env, clazz, err);
714             return JNI_FALSE;
715         }
716         return result ? JNI_TRUE : JNI_FALSE;
717     }
718     return JNI_FALSE;
719 }
720 
721 // String tries to allocate itself on the stack, within a known size, but will
722 // make a heap allocation if not.
723 template <jsize StackReserve>
724 class StackString {
725 public:
StackString(JNIEnv * env,jstring str)726     StackString(JNIEnv* env, jstring str) : mEnv(env), mJStr(str) {
727         LOG_ALWAYS_FATAL_IF(str == nullptr);
728         mSize = env->GetStringLength(str);
729         if (mSize > StackReserve) {
730             mStr = new jchar[mSize];
731         } else {
732             mStr = &mBuffer[0];
733         }
734         mEnv->GetStringRegion(str, 0, mSize, mStr);
735     }
~StackString()736     ~StackString() {
737         if (mStr != &mBuffer[0]) {
738             delete[] mStr;
739         }
740     }
str()741     const jchar* str() { return mStr; }
size()742     jsize size() { return mSize; }
743 
744 private:
745     JNIEnv* mEnv;
746     jstring mJStr;
747 
748     jchar mBuffer[StackReserve];
749     // pointer to &mBuffer[0] if string fits in mBuffer, otherwise owned
750     jchar* mStr;
751     jsize mSize;
752 };
753 
754 // This size is chosen to be longer than most interface descriptors.
755 // Ones longer than this will be allocated on the heap.
756 typedef StackString<64> InterfaceDescriptorString;
757 
android_os_Parcel_writeInterfaceToken(JNIEnv * env,jclass clazz,jlong nativePtr,jstring name)758 static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jlong nativePtr,
759                                                   jstring name)
760 {
761     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
762     if (parcel != nullptr) {
763         InterfaceDescriptorString descriptor(env, name);
764         parcel->writeInterfaceToken(reinterpret_cast<const char16_t*>(descriptor.str()),
765                                     descriptor.size());
766     }
767 }
768 
android_os_Parcel_enforceInterface(JNIEnv * env,jclass clazz,jlong nativePtr,jstring name)769 static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jlong nativePtr, jstring name)
770 {
771     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
772     if (parcel != nullptr) {
773         InterfaceDescriptorString descriptor(env, name);
774         IPCThreadState* threadState = IPCThreadState::self();
775         const int32_t oldPolicy = threadState->getStrictModePolicy();
776         const bool isValid =
777                 parcel->enforceInterface(reinterpret_cast<const char16_t*>(descriptor.str()),
778                                          descriptor.size(), threadState);
779         if (isValid) {
780             const int32_t newPolicy = threadState->getStrictModePolicy();
781             if (oldPolicy != newPolicy) {
782                 // Need to keep the Java-level thread-local strict
783                 // mode policy in sync for the libcore
784                 // enforcements, which involves an upcall back
785                 // into Java.  (We can't modify the
786                 // Parcel.enforceInterface signature, as it's
787                 // pseudo-public, and used via AIDL
788                 // auto-generation...)
789                 set_dalvik_blockguard_policy(env, newPolicy);
790             }
791             return; // everything was correct -> return silently
792         }
793     }
794 
795     // all error conditions wind up here
796     jniThrowException(env, "java/lang/SecurityException",
797             "Binder invocation to an incorrect interface");
798 }
799 
android_os_Parcel_getGlobalAllocSize(JNIEnv * env,jclass clazz)800 static jlong android_os_Parcel_getGlobalAllocSize(JNIEnv* env, jclass clazz)
801 {
802     return Parcel::getGlobalAllocSize();
803 }
804 
android_os_Parcel_getGlobalAllocCount(JNIEnv * env,jclass clazz)805 static jlong android_os_Parcel_getGlobalAllocCount(JNIEnv* env, jclass clazz)
806 {
807     return Parcel::getGlobalAllocCount();
808 }
809 
android_os_Parcel_getOpenAshmemSize(jlong nativePtr)810 static jlong android_os_Parcel_getOpenAshmemSize(jlong nativePtr)
811 {
812     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
813     if (parcel != NULL) {
814         return parcel->getOpenAshmemSize();
815     }
816     return 0;
817 }
818 
android_os_Parcel_readCallingWorkSourceUid(jlong nativePtr)819 static jint android_os_Parcel_readCallingWorkSourceUid(jlong nativePtr)
820 {
821     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
822     if (parcel != NULL) {
823         return parcel->readCallingWorkSourceUid();
824     }
825     return IPCThreadState::kUnsetWorkSource;
826 }
827 
android_os_Parcel_replaceCallingWorkSourceUid(jlong nativePtr,jint uid)828 static jboolean android_os_Parcel_replaceCallingWorkSourceUid(jlong nativePtr, jint uid)
829 {
830     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
831     if (parcel != NULL) {
832         return parcel->replaceCallingWorkSourceUid(uid);
833     }
834     return false;
835 }
836 
837 // ----------------------------------------------------------------------------
838 // clang-format off
839 static const JNINativeMethod gParcelMethods[] = {
840     // @CriticalNative
841     {"nativeMarkSensitive",       "(J)V", (void*)android_os_Parcel_markSensitive},
842     // @FastNative
843     {"nativeMarkForBinder",       "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_markForBinder},
844     // @CriticalNative
845     {"nativeIsForRpc",            "(J)Z", (void*)android_os_Parcel_isForRpc},
846     // @CriticalNative
847     {"nativeDataSize",            "(J)I", (void*)android_os_Parcel_dataSize},
848     // @CriticalNative
849     {"nativeDataAvail",           "(J)I", (void*)android_os_Parcel_dataAvail},
850     // @CriticalNative
851     {"nativeDataPosition",        "(J)I", (void*)android_os_Parcel_dataPosition},
852     // @CriticalNative
853     {"nativeDataCapacity",        "(J)I", (void*)android_os_Parcel_dataCapacity},
854     // @FastNative
855     {"nativeSetDataSize",         "(JI)V", (void*)android_os_Parcel_setDataSize},
856     // @CriticalNative
857     {"nativeSetDataPosition",     "(JI)V", (void*)android_os_Parcel_setDataPosition},
858     // @FastNative
859     {"nativeSetDataCapacity",     "(JI)V", (void*)android_os_Parcel_setDataCapacity},
860 
861     // @CriticalNative
862     {"nativePushAllowFds",        "(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
863     // @CriticalNative
864     {"nativeRestoreAllowFds",     "(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
865 
866     {"nativeWriteByteArray",      "(J[BII)V", (void*)android_os_Parcel_writeByteArray},
867     {"nativeWriteBlob",           "(J[BII)V", (void*)android_os_Parcel_writeBlob},
868     // @CriticalNative
869     {"nativeWriteInt",            "(JI)I", (void*)android_os_Parcel_writeInt},
870     // @CriticalNative
871     {"nativeWriteLong",           "(JJ)I", (void*)android_os_Parcel_writeLong},
872     // @CriticalNative
873     {"nativeWriteFloat",          "(JF)I", (void*)android_os_Parcel_writeFloat},
874     // @CriticalNative
875     {"nativeWriteDouble",         "(JD)I", (void*)android_os_Parcel_writeDouble},
876     {"nativeSignalExceptionForError", "(I)V", (void*)android_os_Parcel_nativeSignalExceptionForError},
877     // @FastNative
878     {"nativeWriteString8",        "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString8},
879     // @FastNative
880     {"nativeWriteString16",       "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString16},
881     // @FastNative
882     {"nativeWriteStrongBinder",   "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
883     // @FastNative
884     {"nativeWriteFileDescriptor", "(JLjava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor},
885 
886     {"nativeCreateByteArray",     "(J)[B", (void*)android_os_Parcel_createByteArray},
887     {"nativeReadByteArray",       "(J[BI)Z", (void*)android_os_Parcel_readByteArray},
888     {"nativeReadBlob",            "(J)[B", (void*)android_os_Parcel_readBlob},
889     // @CriticalNative
890     {"nativeReadInt",             "(J)I", (void*)android_os_Parcel_readInt},
891     // @CriticalNative
892     {"nativeReadLong",            "(J)J", (void*)android_os_Parcel_readLong},
893     // @CriticalNative
894     {"nativeReadFloat",           "(J)F", (void*)android_os_Parcel_readFloat},
895     // @CriticalNative
896     {"nativeReadDouble",          "(J)D", (void*)android_os_Parcel_readDouble},
897     // @FastNative
898     {"nativeReadString8",         "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString8},
899     // @FastNative
900     {"nativeReadString16",        "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString16},
901     // @FastNative
902     {"nativeReadStrongBinder",    "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
903     // @FastNative
904     {"nativeReadFileDescriptor",  "(J)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
905 
906     {"nativeCreate",              "()J", (void*)android_os_Parcel_create},
907     {"nativeFreeBuffer",          "(J)V", (void*)android_os_Parcel_freeBuffer},
908     {"nativeDestroy",             "(J)V", (void*)android_os_Parcel_destroy},
909 
910     {"nativeMarshall",            "(J)[B", (void*)android_os_Parcel_marshall},
911     {"nativeUnmarshall",          "(J[BII)V", (void*)android_os_Parcel_unmarshall},
912     {"nativeCompareData",         "(JJ)I", (void*)android_os_Parcel_compareData},
913     {"nativeCompareDataInRange",  "(JIJII)Z", (void*)android_os_Parcel_compareDataInRange},
914     {"nativeAppendFrom",          "(JJII)V", (void*)android_os_Parcel_appendFrom},
915     // @CriticalNative
916     {"nativeHasFileDescriptors",  "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
917     {"nativeHasFileDescriptorsInRange",  "(JII)Z", (void*)android_os_Parcel_hasFileDescriptorsInRange},
918 
919     {"nativeHasBinders",  "(J)Z", (void*)android_os_Parcel_hasBinders},
920     {"nativeHasBindersInRange",  "(JII)Z", (void*)android_os_Parcel_hasBindersInRange},
921     {"nativeWriteInterfaceToken", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
922     {"nativeEnforceInterface",    "(JLjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
923 
924     {"getGlobalAllocSize",        "()J", (void*)android_os_Parcel_getGlobalAllocSize},
925     {"getGlobalAllocCount",       "()J", (void*)android_os_Parcel_getGlobalAllocCount},
926 
927     // @CriticalNative
928     {"nativeGetOpenAshmemSize",       "(J)J", (void*)android_os_Parcel_getOpenAshmemSize},
929 
930     // @CriticalNative
931     {"nativeReadCallingWorkSourceUid", "(J)I", (void*)android_os_Parcel_readCallingWorkSourceUid},
932     // @CriticalNative
933     {"nativeReplaceCallingWorkSourceUid", "(JI)Z", (void*)android_os_Parcel_replaceCallingWorkSourceUid},
934 };
935 // clang-format on
936 
937 const char* const kParcelPathName = "android/os/Parcel";
938 
register_android_os_Parcel(JNIEnv * env)939 int register_android_os_Parcel(JNIEnv* env)
940 {
941     jclass clazz = FindClassOrDie(env, kParcelPathName);
942 
943     gParcelOffsets.clazz = MakeGlobalRefOrDie(env, clazz);
944     gParcelOffsets.mNativePtr = GetFieldIDOrDie(env, clazz, "mNativePtr", "J");
945     gParcelOffsets.obtain = GetStaticMethodIDOrDie(env, clazz, "obtain", "()Landroid/os/Parcel;");
946     gParcelOffsets.recycle = GetMethodIDOrDie(env, clazz, "recycle", "()V");
947 
948     return RegisterMethodsOrDie(env, kParcelPathName, gParcelMethods, NELEM(gParcelMethods));
949 }
950 
951 };
952