Only crop photos owned by Settings.
A recent security change locks down the ability for the system UID to issue Uri permission grants. This helps mitigate an entire class of confused deputy security issues. However, Settings (which runs as the system UID) was still relying on issuing Uri permission grants to the photo cropper. The simplest way to keep that working is to add the "com.android.settings.files" authority to a whitelist, and only request cropping of Uris from that location. This means that if the GET_CONTENT decides to return a Uri (instead of streaming it into mTakePictureUri), then we need to copy it ourselves locally before we can send it along to the cropper. Test: builds, boots, both take/choose photos work Bug: 33019296, 35158271 Change-Id: I2541c33e8d9452357cb9fc2e021ca74d5a43d5ff
This commit is contained in:
@@ -19,6 +19,7 @@ package com.android.settings.users;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
@@ -53,6 +54,8 @@ import com.android.settings.R;
|
|||||||
import com.android.settingslib.RestrictedLockUtils;
|
import com.android.settingslib.RestrictedLockUtils;
|
||||||
import com.android.settingslib.drawable.CircleFramedDrawable;
|
import com.android.settingslib.drawable.CircleFramedDrawable;
|
||||||
|
|
||||||
|
import libcore.io.Streams;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@@ -117,7 +120,11 @@ public class EditUserPhotoController {
|
|||||||
return true;
|
return true;
|
||||||
case REQUEST_CODE_TAKE_PHOTO:
|
case REQUEST_CODE_TAKE_PHOTO:
|
||||||
case REQUEST_CODE_CHOOSE_PHOTO:
|
case REQUEST_CODE_CHOOSE_PHOTO:
|
||||||
cropPhoto(pictureUri);
|
if (mTakePictureUri.equals(pictureUri)) {
|
||||||
|
cropPhoto();
|
||||||
|
} else {
|
||||||
|
copyAndCropPhoto(pictureUri);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -217,10 +224,31 @@ public class EditUserPhotoController {
|
|||||||
mFragment.startActivityForResult(intent, REQUEST_CODE_CHOOSE_PHOTO);
|
mFragment.startActivityForResult(intent, REQUEST_CODE_CHOOSE_PHOTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cropPhoto(Uri pictureUri) {
|
private void copyAndCropPhoto(final Uri pictureUri) {
|
||||||
|
new AsyncTask<Void, Void, Void>() {
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... params) {
|
||||||
|
final ContentResolver cr = mContext.getContentResolver();
|
||||||
|
try (InputStream in = cr.openInputStream(pictureUri);
|
||||||
|
OutputStream out = cr.openOutputStream(mTakePictureUri)) {
|
||||||
|
Streams.copy(in, out);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.w(TAG, "Failed to copy photo", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
cropPhoto();
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cropPhoto() {
|
||||||
// TODO: Use a public intent, when there is one.
|
// TODO: Use a public intent, when there is one.
|
||||||
Intent intent = new Intent("com.android.camera.action.CROP");
|
Intent intent = new Intent("com.android.camera.action.CROP");
|
||||||
intent.setDataAndType(pictureUri, "image/*");
|
intent.setDataAndType(mTakePictureUri, "image/*");
|
||||||
appendOutputExtra(intent, mCropPictureUri);
|
appendOutputExtra(intent, mCropPictureUri);
|
||||||
appendCropExtras(intent);
|
appendCropExtras(intent);
|
||||||
if (intent.resolveActivity(mContext.getPackageManager()) != null) {
|
if (intent.resolveActivity(mContext.getPackageManager()) != null) {
|
||||||
@@ -231,7 +259,7 @@ public class EditUserPhotoController {
|
|||||||
StrictMode.enableDeathOnFileUriExposure();
|
StrictMode.enableDeathOnFileUriExposure();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
onPhotoCropped(pictureUri, false);
|
onPhotoCropped(mTakePictureUri, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user