Don't allow expired blobs to be accessed.
Bug: 147722548 Test: atest --test-mapping apex/blobstore Change-Id: I7294124ba5ce3dcf42a0e7e9858311b1604ae185
This commit is contained in:
@@ -212,7 +212,10 @@ class BlobMetadata {
|
||||
}
|
||||
|
||||
boolean isAccessAllowedForCaller(@NonNull String callingPackage, int callingUid) {
|
||||
// TODO: verify blob is still valid (expiryTime is not elapsed)
|
||||
// Don't allow the blob to be accessed after it's expiry time has passed.
|
||||
if (getBlobHandle().isExpired()) {
|
||||
return false;
|
||||
}
|
||||
synchronized (mMetadataLock) {
|
||||
// Check if packageName already holds a lease on the blob.
|
||||
for (int i = 0, size = mLeasees.size(); i < size; ++i) {
|
||||
|
||||
@@ -1059,6 +1059,18 @@ public class BlobStoreManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
boolean isBlobAvailable(long blobId, int userId) {
|
||||
synchronized (mBlobsLock) {
|
||||
final ArrayMap<BlobHandle, BlobMetadata> userBlobs = getUserBlobsLocked(userId);
|
||||
for (BlobMetadata blobMetadata : userBlobs.values()) {
|
||||
if (blobMetadata.getBlobId() == blobId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mBlobsLock")
|
||||
private void dumpSessionsLocked(IndentingPrintWriter fout, DumpArgs dumpArgs) {
|
||||
for (int i = 0, userCount = mSessions.size(); i < userCount; ++i) {
|
||||
|
||||
@@ -46,6 +46,8 @@ class BlobStoreManagerShellCommand extends ShellCommand {
|
||||
return runDeleteBlob(pw);
|
||||
case "idle-maintenance":
|
||||
return runIdleMaintenance(pw);
|
||||
case "query-blob-existence":
|
||||
return runQueryBlobExistence(pw);
|
||||
default:
|
||||
return handleDefaultCommands(cmd);
|
||||
}
|
||||
@@ -91,6 +93,16 @@ class BlobStoreManagerShellCommand extends ShellCommand {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int runQueryBlobExistence(PrintWriter pw) {
|
||||
final ParsedArgs args = new ParsedArgs();
|
||||
if (parseOptions(pw, args) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pw.println(mService.isBlobAvailable(args.blobId, args.userId) ? 1 : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHelp() {
|
||||
final PrintWriter pw = getOutPrintWriter();
|
||||
@@ -121,6 +133,8 @@ class BlobStoreManagerShellCommand extends ShellCommand {
|
||||
pw.println(" --tag: Tag of the blob to delete.");
|
||||
pw.println("idle-maintenance");
|
||||
pw.println(" Run idle maintenance which takes care of removing stale data.");
|
||||
pw.println("query-blob-existence [-b BLOB_ID]");
|
||||
pw.println(" Prints 1 if blob exists, otherwise 0.");
|
||||
pw.println();
|
||||
}
|
||||
|
||||
@@ -147,6 +161,9 @@ class BlobStoreManagerShellCommand extends ShellCommand {
|
||||
case "--tag":
|
||||
args.tag = getNextArgRequired();
|
||||
break;
|
||||
case "-b":
|
||||
args.blobId = Long.parseLong(getNextArgRequired());
|
||||
break;
|
||||
default:
|
||||
pw.println("Error: unknown option '" + opt + "'");
|
||||
return -1;
|
||||
@@ -166,6 +183,7 @@ class BlobStoreManagerShellCommand extends ShellCommand {
|
||||
public long expiryTimeMillis;
|
||||
public CharSequence label;
|
||||
public String tag;
|
||||
public long blobId;
|
||||
|
||||
public BlobHandle getBlobHandle() {
|
||||
return BlobHandle.create(algorithm, digest, label, expiryTimeMillis, tag);
|
||||
|
||||
@@ -18,6 +18,7 @@ java_library {
|
||||
static_libs: [
|
||||
"truth-prebuilt",
|
||||
"androidx.test.uiautomator_uiautomator",
|
||||
"androidx.test.ext.junit",
|
||||
],
|
||||
sdk_version: "test_current",
|
||||
}
|
||||
@@ -42,6 +42,7 @@ public class DummyBlobData {
|
||||
private final File mFile;
|
||||
private final long mFileSize;
|
||||
private final CharSequence mLabel;
|
||||
private final long mExpiryDurationMs;
|
||||
|
||||
byte[] mFileDigest;
|
||||
long mExpiryTimeMs;
|
||||
@@ -51,6 +52,7 @@ public class DummyBlobData {
|
||||
mFile = new File(builder.getContext().getFilesDir(), builder.getFileName());
|
||||
mFileSize = builder.getFileSize();
|
||||
mLabel = builder.getLabel();
|
||||
mExpiryDurationMs = builder.getExpiryDurationMs();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
@@ -59,6 +61,7 @@ public class DummyBlobData {
|
||||
private long mFileSize = DEFAULT_SIZE_BYTES;
|
||||
private CharSequence mLabel = "Test label";
|
||||
private String mFileName = "blob_" + System.nanoTime();
|
||||
private long mExpiryDurationMs = TimeUnit.DAYS.toMillis(1);
|
||||
|
||||
public Builder(Context context) {
|
||||
mContext = context;
|
||||
@@ -104,6 +107,15 @@ public class DummyBlobData {
|
||||
return mFileName;
|
||||
}
|
||||
|
||||
public Builder setExpiryDurationMs(long durationMs) {
|
||||
mExpiryDurationMs = durationMs;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getExpiryDurationMs() {
|
||||
return mExpiryDurationMs;
|
||||
}
|
||||
|
||||
public DummyBlobData build() {
|
||||
return new DummyBlobData(this);
|
||||
}
|
||||
@@ -114,7 +126,7 @@ public class DummyBlobData {
|
||||
writeRandomData(file, mFileSize);
|
||||
}
|
||||
mFileDigest = FileUtils.digest(mFile, "SHA-256");
|
||||
mExpiryTimeMs = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1);
|
||||
mExpiryTimeMs = System.currentTimeMillis() + mExpiryDurationMs;
|
||||
}
|
||||
|
||||
public BlobHandle getBlobHandle() throws Exception {
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.android.utils.blob;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.app.blob.BlobHandle;
|
||||
import android.app.blob.BlobStoreManager;
|
||||
import android.app.blob.LeaseInfo;
|
||||
@@ -27,6 +26,7 @@ import android.content.res.Resources;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.uiautomator.UiDevice;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
@@ -149,14 +149,14 @@ public class Utils {
|
||||
assertThat(leaseInfo.getDescription()).isEqualTo(description);
|
||||
}
|
||||
|
||||
public static void triggerIdleMaintenance(Instrumentation instrumentation) throws IOException {
|
||||
runShellCmd(instrumentation, "cmd blob_store idle-maintenance");
|
||||
public static void triggerIdleMaintenance() throws IOException {
|
||||
runShellCmd("cmd blob_store idle-maintenance");
|
||||
}
|
||||
|
||||
private static String runShellCmd(Instrumentation instrumentation,
|
||||
String cmd) throws IOException {
|
||||
final UiDevice uiDevice = UiDevice.getInstance(instrumentation);
|
||||
final String result = uiDevice.executeShellCommand(cmd);
|
||||
public static String runShellCmd(String cmd) throws IOException {
|
||||
final UiDevice uiDevice = UiDevice.getInstance(
|
||||
InstrumentationRegistry.getInstrumentation());
|
||||
final String result = uiDevice.executeShellCommand(cmd).trim();
|
||||
Log.i(TAG, "Output of '" + cmd + "': '" + result + "'");
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user