diff --git a/jni/Android.mk b/jni/Android.mk index 2882b8f5ce..3d4190875c 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -53,6 +53,14 @@ libwebrtc_spl \ libwebrtc_vad \ libcrypto_static - include $(BUILD_SHARED_LIBRARY) +include $(CLEAR_VARS) + +LOCAL_MODULE := native-utils +LOCAL_C_INCLUDES := $(JNI_DIR)/utils/ +LOCAL_CFLAGS += -Wall + +LOCAL_SRC_FILES := $(JNI_DIR)/utils/org_thoughtcrime_securesms_util_FileUtils.cpp + +include $(BUILD_SHARED_LIBRARY) \ No newline at end of file diff --git a/jni/utils/org_thoughtcrime_securesms_util_FileUtils.cpp b/jni/utils/org_thoughtcrime_securesms_util_FileUtils.cpp new file mode 100644 index 0000000000..ef86ac8e35 --- /dev/null +++ b/jni/utils/org_thoughtcrime_securesms_util_FileUtils.cpp @@ -0,0 +1,31 @@ +#include "org_thoughtcrime_securesms_util_FileUtils.h" + +#include +#include +#include + +jint JNICALL Java_org_thoughtcrime_securesms_util_FileUtils_getFileDescriptorOwner + (JNIEnv *env, jclass clazz, jobject fileDescriptor) +{ + jclass fdClass = env->GetObjectClass(fileDescriptor); + + if (fdClass == NULL) { + return -1; + } + + jfieldID fdFieldId = env->GetFieldID(fdClass, "descriptor", "I"); + + if (fdFieldId == NULL) { + return -1; + } + + int fd = env->GetIntField(fileDescriptor, fdFieldId); + + struct stat stat_struct; + + if (fstat(fd, &stat_struct) != 0) { + return -1; + } + + return stat_struct.st_uid; +} \ No newline at end of file diff --git a/jni/utils/org_thoughtcrime_securesms_util_FileUtils.h b/jni/utils/org_thoughtcrime_securesms_util_FileUtils.h new file mode 100644 index 0000000000..abf13b35bc --- /dev/null +++ b/jni/utils/org_thoughtcrime_securesms_util_FileUtils.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_thoughtcrime_securesms_util_FileUtils */ + +#ifndef _Included_org_thoughtcrime_securesms_util_FileUtils +#define _Included_org_thoughtcrime_securesms_util_FileUtils +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_thoughtcrime_securesms_util_FileUtils + * Method: getFileDescriptorOwner + * Signature: (Ljava/io/FileDescriptor;)I + */ +JNIEXPORT jint JNICALL Java_org_thoughtcrime_securesms_util_FileUtils_getFileDescriptorOwner + (JNIEnv *, jclass, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libs/armeabi-v7a/libnative-utils.so b/libs/armeabi-v7a/libnative-utils.so new file mode 100755 index 0000000000..1fa3ef17b5 Binary files /dev/null and b/libs/armeabi-v7a/libnative-utils.so differ diff --git a/libs/armeabi/libnative-utils.so b/libs/armeabi/libnative-utils.so new file mode 100755 index 0000000000..e8f6ea4496 Binary files /dev/null and b/libs/armeabi/libnative-utils.so differ diff --git a/libs/x86/libnative-utils.so b/libs/x86/libnative-utils.so new file mode 100755 index 0000000000..a4b0567b87 Binary files /dev/null and b/libs/x86/libnative-utils.so differ diff --git a/src/org/thoughtcrime/securesms/ShareActivity.java b/src/org/thoughtcrime/securesms/ShareActivity.java index 5dcdab0a70..c9dfbfa766 100644 --- a/src/org/thoughtcrime/securesms/ShareActivity.java +++ b/src/org/thoughtcrime/securesms/ShareActivity.java @@ -21,9 +21,15 @@ import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.AsyncTask; +import android.os.Build; import android.os.Bundle; +import android.os.ParcelFileDescriptor; +import android.os.Process; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.system.ErrnoException; +import android.system.Os; +import android.system.StructStat; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; @@ -37,9 +43,13 @@ import org.thoughtcrime.securesms.providers.PersistentBlobProvider; import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.util.DynamicLanguage; import org.thoughtcrime.securesms.util.DynamicTheme; +import org.thoughtcrime.securesms.util.FileUtils; import org.thoughtcrime.securesms.util.MediaUtil; import org.thoughtcrime.securesms.util.ViewUtil; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -193,17 +203,23 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity @Override protected Uri doInBackground(Uri... uris) { try { - if (uris.length != 1 || uris[0] == null || uris[0].getScheme().equals("file")) { + if (uris.length != 1 || uris[0] == null) { return null; } - InputStream input = context.getContentResolver().openInputStream(uris[0]); + InputStream inputStream; - if (input == null) { + if ("file".equals(uris[0].getScheme())) { + inputStream = openFileUri(uris[0]); + } else { + inputStream = context.getContentResolver().openInputStream(uris[0]); + } + + if (inputStream == null) { return null; } - return PersistentBlobProvider.getInstance(context).create(masterSecret, input, mimeType); + return PersistentBlobProvider.getInstance(context).create(masterSecret, inputStream, mimeType); } catch (IOException ioe) { Log.w(TAG, ioe); return null; @@ -216,5 +232,17 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity ViewUtil.fadeIn(fragmentContainer, 300); ViewUtil.fadeOut(progressWheel, 300); } + + private InputStream openFileUri(Uri uri) throws IOException { + FileInputStream fin = new FileInputStream(uri.getPath()); + int owner = FileUtils.getFileDescriptorOwner(fin.getFD()); + + if (owner == -1 || owner == Process.myUid()) { + fin.close(); + throw new IOException("File owned by application"); + } + + return fin; + } } } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/util/FileUtils.java b/src/org/thoughtcrime/securesms/util/FileUtils.java new file mode 100644 index 0000000000..275186f74c --- /dev/null +++ b/src/org/thoughtcrime/securesms/util/FileUtils.java @@ -0,0 +1,13 @@ +package org.thoughtcrime.securesms.util; + +import java.io.FileDescriptor; + +public class FileUtils { + + static { + System.loadLibrary("native-utils"); + } + + public static native int getFileDescriptorOwner(FileDescriptor fileDescriptor); + +}