2c9d8f6db0
This change renames the IMemory raw pointer accessors to unsecure*() to make it apparent to coders and code reviewers that the returned buffer may potentially be shared with untrusted processes, who may, after the fact, attempt to read and/or modify the contents. This may lead to hard to find security bugs and hopefully the rename makes it harder to forget. The change also attempts to fix all the callsites to make everything build correctly, but in the processes, wherever the callsite code was not obviously secure, I added a TODO requesting the owners to either document why it's secure or to change the code. Apologies in advance to the owners if there are some false positives here - I don't have enough context to reason about all the different callsites. Test: Completely syntactic change. Made sure code still builds. Change-Id: I4c555ef8c8c47cf28b42b17ad8b4021a783548cd
179 lines
5.1 KiB
C++
179 lines
5.1 KiB
C++
/*
|
|
* Copyright 2013, The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
//#define LOG_NDEBUG 0
|
|
#define LOG_TAG "MediaHTTPConnection-JNI"
|
|
#include <utils/Log.h>
|
|
|
|
#include <binder/MemoryDealer.h>
|
|
#include <media/stagefright/foundation/ADebug.h>
|
|
#include <nativehelper/ScopedLocalRef.h>
|
|
|
|
#include "android_media_MediaHTTPConnection.h"
|
|
#include "android_util_Binder.h"
|
|
|
|
#include "android_runtime/AndroidRuntime.h"
|
|
#include "jni.h"
|
|
#include <nativehelper/JNIHelp.h>
|
|
|
|
namespace android {
|
|
|
|
JMediaHTTPConnection::JMediaHTTPConnection(JNIEnv *env, jobject thiz)
|
|
: mClass(NULL),
|
|
mObject(NULL),
|
|
mByteArrayObj(NULL) {
|
|
jclass clazz = env->GetObjectClass(thiz);
|
|
CHECK(clazz != NULL);
|
|
|
|
mClass = (jclass)env->NewGlobalRef(clazz);
|
|
mObject = env->NewWeakGlobalRef(thiz);
|
|
|
|
mDealer = new MemoryDealer(kBufferSize, "MediaHTTPConnection");
|
|
mMemory = mDealer->allocate(kBufferSize);
|
|
|
|
ScopedLocalRef<jbyteArray> tmp(
|
|
env, env->NewByteArray(JMediaHTTPConnection::kBufferSize));
|
|
|
|
mByteArrayObj = (jbyteArray)env->NewGlobalRef(tmp.get());
|
|
}
|
|
|
|
JMediaHTTPConnection::~JMediaHTTPConnection() {
|
|
JNIEnv *env = AndroidRuntime::getJNIEnv();
|
|
|
|
env->DeleteGlobalRef(mByteArrayObj);
|
|
mByteArrayObj = NULL;
|
|
env->DeleteWeakGlobalRef(mObject);
|
|
mObject = NULL;
|
|
env->DeleteGlobalRef(mClass);
|
|
mClass = NULL;
|
|
}
|
|
|
|
sp<IMemory> JMediaHTTPConnection::getIMemory() {
|
|
return mMemory;
|
|
}
|
|
|
|
jbyteArray JMediaHTTPConnection::getByteArrayObj() {
|
|
return mByteArrayObj;
|
|
}
|
|
|
|
} // namespace android
|
|
|
|
using namespace android;
|
|
|
|
struct fields_t {
|
|
jfieldID context;
|
|
|
|
jmethodID readAtMethodID;
|
|
};
|
|
|
|
static fields_t gFields;
|
|
|
|
static sp<JMediaHTTPConnection> setObject(
|
|
JNIEnv *env, jobject thiz, const sp<JMediaHTTPConnection> &conn) {
|
|
sp<JMediaHTTPConnection> old =
|
|
(JMediaHTTPConnection *)env->GetLongField(thiz, gFields.context);
|
|
|
|
if (conn != NULL) {
|
|
conn->incStrong(thiz);
|
|
}
|
|
if (old != NULL) {
|
|
old->decStrong(thiz);
|
|
}
|
|
env->SetLongField(thiz, gFields.context, (jlong)conn.get());
|
|
|
|
return old;
|
|
}
|
|
|
|
static sp<JMediaHTTPConnection> getObject(JNIEnv *env, jobject thiz) {
|
|
return (JMediaHTTPConnection *)env->GetLongField(thiz, gFields.context);
|
|
}
|
|
|
|
static void android_media_MediaHTTPConnection_native_init(JNIEnv *env) {
|
|
ScopedLocalRef<jclass> clazz(
|
|
env, env->FindClass("android/media/MediaHTTPConnection"));
|
|
CHECK(clazz.get() != NULL);
|
|
|
|
gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
|
|
CHECK(gFields.context != NULL);
|
|
|
|
gFields.readAtMethodID = env->GetMethodID(clazz.get(), "readAt", "(J[BI)I");
|
|
}
|
|
|
|
static void android_media_MediaHTTPConnection_native_setup(
|
|
JNIEnv *env, jobject thiz) {
|
|
sp<JMediaHTTPConnection> conn = new JMediaHTTPConnection(env, thiz);
|
|
|
|
setObject(env, thiz, conn);
|
|
}
|
|
|
|
static void android_media_MediaHTTPConnection_native_finalize(
|
|
JNIEnv *env, jobject thiz) {
|
|
setObject(env, thiz, NULL);
|
|
}
|
|
|
|
static jobject android_media_MediaHTTPConnection_native_getIMemory(
|
|
JNIEnv *env, jobject thiz) {
|
|
sp<JMediaHTTPConnection> conn = getObject(env, thiz);
|
|
|
|
return javaObjectForIBinder(env, IInterface::asBinder(conn->getIMemory()));
|
|
}
|
|
|
|
static jint android_media_MediaHTTPConnection_native_readAt(
|
|
JNIEnv *env, jobject thiz, jlong offset, jint size) {
|
|
sp<JMediaHTTPConnection> conn = getObject(env, thiz);
|
|
if (size > JMediaHTTPConnection::kBufferSize) {
|
|
size = JMediaHTTPConnection::kBufferSize;
|
|
}
|
|
|
|
jbyteArray byteArrayObj = conn->getByteArrayObj();
|
|
|
|
jint n = env->CallIntMethod(
|
|
thiz, gFields.readAtMethodID, offset, byteArrayObj, size);
|
|
|
|
if (n > 0) {
|
|
env->GetByteArrayRegion(
|
|
byteArrayObj,
|
|
0,
|
|
n,
|
|
(jbyte *)conn->getIMemory()->unsecurePointer());
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
static const JNINativeMethod gMethods[] = {
|
|
{ "native_getIMemory", "()Landroid/os/IBinder;",
|
|
(void *)android_media_MediaHTTPConnection_native_getIMemory },
|
|
|
|
{ "native_readAt", "(JI)I",
|
|
(void *)android_media_MediaHTTPConnection_native_readAt },
|
|
|
|
{ "native_init", "()V",
|
|
(void *)android_media_MediaHTTPConnection_native_init },
|
|
|
|
{ "native_setup", "()V",
|
|
(void *)android_media_MediaHTTPConnection_native_setup },
|
|
|
|
{ "native_finalize", "()V",
|
|
(void *)android_media_MediaHTTPConnection_native_finalize },
|
|
};
|
|
|
|
int register_android_media_MediaHTTPConnection(JNIEnv *env) {
|
|
return AndroidRuntime::registerNativeMethods(env,
|
|
"android/media/MediaHTTPConnection", gMethods, NELEM(gMethods));
|
|
}
|
|
|