From e827aec67096f1f7b0ccde8d250a0271a2c39c59 Mon Sep 17 00:00:00 2001 From: Howard Chen Date: Fri, 25 Dec 2020 17:32:07 +0800 Subject: [PATCH] Support copy-on-write persistent data block when running a DSU The persistent data block is protected when running a DSU. This CL adds a copy-on-write scratchpad for the persistent data block and let the test environment to have an emulated writable pdb service. Bug: 175852148 Test: gsi_tool install & pass the vts_kernel_net_tests Test: gts-tradefed run gts -m GtsOemLockServiceTestCases -t com.google.android.oemlock.gts.OemLockServiceTest Test: cts-tradefed run cts -m CtsPermission2TestCases -t android.permission2.cts.PrivappPermissionsTest Change-Id: I8af15775dbc5f8c570bd4eb4faec5036b7b43ebc --- .../server/PersistentDataBlockService.java | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java index 7bbd116d9a5a8..351e616b433b5 100644 --- a/services/core/java/com/android/server/PersistentDataBlockService.java +++ b/services/core/java/com/android/server/PersistentDataBlockService.java @@ -23,6 +23,7 @@ import android.app.ActivityManager; import android.content.Context; import android.content.pm.PackageManager; import android.os.Binder; +import android.os.FileUtils; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemProperties; @@ -37,7 +38,6 @@ import com.android.internal.annotations.GuardedBy; import libcore.io.IoUtils; -import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; @@ -45,7 +45,6 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.security.MessageDigest; @@ -105,6 +104,7 @@ import java.util.concurrent.TimeUnit; public class PersistentDataBlockService extends SystemService { private static final String TAG = PersistentDataBlockService.class.getSimpleName(); + private static final String GSI_SANDBOX = "/data/gsi_persistent_data"; private static final String GSI_RUNNING_PROP = "ro.gsid.image_running"; private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst"; @@ -131,13 +131,13 @@ public class PersistentDataBlockService extends SystemService { private static final String FLASH_LOCK_UNLOCKED = "0"; private final Context mContext; - private final String mDataBlockFile; private final boolean mIsRunningDSU; private final Object mLock = new Object(); private final CountDownLatch mInitDoneSignal = new CountDownLatch(1); private int mAllowedUid = -1; private long mBlockDeviceSize; + private String mDataBlockFile; @GuardedBy("mLock") private boolean mIsWritable = true; @@ -290,12 +290,18 @@ public class PersistentDataBlockService extends SystemService { return true; } - private OutputStream getBlockOutputStream() throws IOException { - if (mIsRunningDSU) { - Slog.i(TAG, "data is read-only when running a DSU"); - return new ByteArrayOutputStream(); - } else { + private FileOutputStream getBlockOutputStream() throws IOException { + if (!mIsRunningDSU) { return new FileOutputStream(new File(mDataBlockFile)); + } else { + File sandbox = new File(GSI_SANDBOX); + File realpdb = new File(SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP)); + if (!sandbox.exists()) { + FileUtils.copy(realpdb, sandbox); + mDataBlockFile = GSI_SANDBOX; + } + Slog.i(TAG, "PersistentDataBlock copy-on-write"); + return new FileOutputStream(sandbox); } } @@ -395,13 +401,9 @@ public class PersistentDataBlockService extends SystemService { private void doSetOemUnlockEnabledLocked(boolean enabled) { FileOutputStream outputStream; - if (mIsRunningDSU) { - Slog.i(TAG, "data is read-only when running a DSU"); - return; - } try { - outputStream = new FileOutputStream(new File(mDataBlockFile)); - } catch (FileNotFoundException e) { + outputStream = getBlockOutputStream(); + } catch (IOException e) { Slog.e(TAG, "partition not available", e); return; } @@ -564,7 +566,14 @@ public class PersistentDataBlockService extends SystemService { enforceOemUnlockWritePermission(); if (mIsRunningDSU) { - Slog.i(TAG, "data is read-only when running a DSU"); + File sandbox = new File(GSI_SANDBOX); + if (sandbox.exists()) { + if (sandbox.delete()) { + mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP); + } else { + Slog.e(TAG, "Failed to wipe sandbox persistent data block"); + } + } return; } synchronized (mLock) { @@ -725,13 +734,9 @@ public class PersistentDataBlockService extends SystemService { private void writeDataBuffer(long offset, ByteBuffer dataBuffer) { FileOutputStream outputStream; - if (mIsRunningDSU) { - Slog.i(TAG, "data is read-only when running a DSU"); - return; - } try { - outputStream = new FileOutputStream(new File(mDataBlockFile)); - } catch (FileNotFoundException e) { + outputStream = getBlockOutputStream(); + } catch (IOException e) { Slog.e(TAG, "partition not available", e); return; }