1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.pdb;
18 
19 import static com.android.internal.util.Preconditions.checkArgument;
20 
21 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
22 import static java.nio.file.StandardOpenOption.CREATE;
23 import static java.nio.file.StandardOpenOption.SYNC;
24 import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
25 import static java.nio.file.StandardOpenOption.WRITE;
26 
27 import android.Manifest;
28 import android.annotation.NonNull;
29 import android.annotation.Nullable;
30 import android.app.ActivityManager;
31 import android.content.Context;
32 import android.content.pm.PackageManager;
33 import android.content.pm.PackageManagerInternal;
34 import android.os.Binder;
35 import android.os.Build;
36 import android.os.IBinder;
37 import android.os.RemoteException;
38 import android.os.ResultReceiver;
39 import android.os.ShellCallback;
40 import android.os.ShellCommand;
41 import android.os.SystemProperties;
42 import android.os.UserHandle;
43 import android.os.UserManager;
44 import android.provider.Settings;
45 import android.security.Flags;
46 import android.service.persistentdata.IPersistentDataBlockService;
47 import android.service.persistentdata.PersistentDataBlockManager;
48 import android.text.TextUtils;
49 import android.util.Slog;
50 
51 import com.android.internal.R;
52 import com.android.internal.annotations.GuardedBy;
53 import com.android.internal.annotations.VisibleForTesting;
54 import com.android.internal.util.DumpUtils;
55 import com.android.server.LocalServices;
56 import com.android.server.SystemServerInitThreadPool;
57 import com.android.server.SystemService;
58 import com.android.server.pm.UserManagerInternal;
59 
60 import libcore.io.IoUtils;
61 
62 import java.io.DataInputStream;
63 import java.io.File;
64 import java.io.FileDescriptor;
65 import java.io.FileInputStream;
66 import java.io.FileNotFoundException;
67 import java.io.IOException;
68 import java.io.PrintWriter;
69 import java.io.RandomAccessFile;
70 import java.nio.ByteBuffer;
71 import java.nio.channels.FileChannel;
72 import java.nio.file.Files;
73 import java.nio.file.Paths;
74 import java.security.MessageDigest;
75 import java.security.NoSuchAlgorithmException;
76 import java.util.Arrays;
77 import java.util.HexFormat;
78 import java.util.concurrent.CountDownLatch;
79 import java.util.concurrent.TimeUnit;
80 
81 /**
82  * Service for reading and writing blocks to a persistent partition.
83  * This data will live across factory resets not initiated via the Settings UI.
84  * When a device is factory reset through Settings this data is wiped.
85  *
86  * Allows writing one block at a time. Namely, each time {@link IPersistentDataBlockService#write}
87  * is called, it will overwrite the data that was previously written on the block.
88  *
89  * Clients can query the size of the currently written block via
90  * {@link IPersistentDataBlockService#getDataBlockSize}
91  *
92  * Clients can read any number of bytes from the currently written block up to its total size by
93  * invoking {@link IPersistentDataBlockService#read}
94  *
95  * The persistent data block is currently laid out as follows:
96  * | ---------BEGINNING OF PARTITION-------------|
97  * | Partition digest (32 bytes)                 |
98  * | --------------------------------------------|
99  * | PARTITION_TYPE_MARKER (4 bytes)             |
100  * | --------------------------------------------|
101  * | FRP data block length (4 bytes)             |
102  * | --------------------------------------------|
103  * | FRP data (variable length; 100KB max)    |
104  * | --------------------------------------------|
105  * | ...                                         |
106  * | Empty space.                                |
107  * | ...                                         |
108  * | --------------------------------------------|
109  * | FRP secret magic (8 bytes)                  |
110  * | FRP secret (32 bytes)                       |
111  * | --------------------------------------------|
112  * | Test mode data block (10000 bytes)          |
113  * | --------------------------------------------|
114  * |     | Test mode data length (4 bytes)       |
115  * | --------------------------------------------|
116  * |     | Test mode data (variable length)      |
117  * |     | ...                                   |
118  * | --------------------------------------------|
119  * | FRP credential handle block (1000 bytes)    |
120  * | --------------------------------------------|
121  * |     | FRP credential handle length (4 bytes)|
122  * | --------------------------------------------|
123  * |     | FRP credential handle (variable len)  |
124  * |     | ...                                   |
125  * | --------------------------------------------|
126  * | OEM Unlock bit (1 byte)                     |
127  * | ---------END OF PARTITION-------------------|
128  *
129  * TODO: now that the persistent partition contains several blocks, next time someone wants a new
130  * block, we should look at adding more generic block definitions and get rid of the various raw
131  * XXX_RESERVED_SIZE and XXX_DATA_SIZE constants. That will ensure the code is easier to maintain
132  * and less likely to introduce out-of-bounds read/write.
133  */
134 public class PersistentDataBlockService extends SystemService {
135     private static final String TAG = PersistentDataBlockService.class.getSimpleName();
136 
137     private static final String GSI_SANDBOX = "/data/gsi_persistent_data";
138     private static final String GSI_RUNNING_PROP = "ro.gsid.image_running";
139 
140     private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
141     @VisibleForTesting
142     static final int HEADER_SIZE = 8;
143     // Magic number to mark block device as adhering to the format consumed by this service
144     private static final int PARTITION_TYPE_MARKER = 0x19901873;
145     /** Size of the block reserved for FRP credential, including 4 bytes for the size header. */
146     @VisibleForTesting
147     static final int FRP_CREDENTIAL_RESERVED_SIZE = 1000;
148     /** Maximum size of the FRP credential handle that can be stored. */
149     @VisibleForTesting
150     static final int MAX_FRP_CREDENTIAL_HANDLE_SIZE = FRP_CREDENTIAL_RESERVED_SIZE - 4;
151     /** Size of the FRP mode deactivation secret, in bytes */
152     @VisibleForTesting
153     static final int FRP_SECRET_SIZE = 32;
154     /** Magic value to identify the FRP secret is present. */
155     @VisibleForTesting
156     static final byte[] FRP_SECRET_MAGIC = {(byte) 0xda, (byte) 0xc2, (byte) 0xfc,
157             (byte) 0xcd, (byte) 0xb9, 0x1b, 0x09, (byte) 0x88};
158 
159     /**
160      * Size of the block reserved for Test Harness Mode data, including 4 bytes for the size header.
161      */
162     @VisibleForTesting
163     static final int TEST_MODE_RESERVED_SIZE = 10000;
164     /** Maximum size of the Test Harness Mode data that can be stored. */
165     @VisibleForTesting
166     static final int MAX_TEST_MODE_DATA_SIZE = TEST_MODE_RESERVED_SIZE - 4;
167 
168     // Limit to 100k as blocks larger than this might cause strain on Binder.
169     @VisibleForTesting
170     static final int MAX_DATA_BLOCK_SIZE = 1024 * 100;
171 
172     public static final int DIGEST_SIZE_BYTES = 32;
173     private static final String OEM_UNLOCK_PROP = "sys.oem_unlock_allowed";
174     private static final String FLASH_LOCK_PROP = "ro.boot.flash.locked";
175     private static final String FLASH_LOCK_LOCKED = "1";
176     private static final String FLASH_LOCK_UNLOCKED = "0";
177 
178     /**
179      * Path to FRP secret stored on /data.  This file enables automatic deactivation of FRP mode if
180      * it contains the current FRP secret.  When /data is wiped in an untrusted reset this file is
181      * destroyed, blocking automatic deactivation.
182      */
183     private static final String FRP_SECRET_FILE = "/data/system/frp_secret";
184 
185     /**
186      * Path to temp file used when changing the FRP secret.
187      */
188     private static final String FRP_SECRET_TMP_FILE = "/data/system/frp_secret_tmp";
189 
190     public static final String BOOTLOADER_LOCK_STATE = "ro.boot.vbmeta.device_state";
191     public static final String VERIFIED_BOOT_STATE = "ro.boot.verifiedbootstate";
192     public static final int INIT_WAIT_TIMEOUT = 10;
193 
194     private final Context mContext;
195     private final String mDataBlockFile;
196     private final boolean mIsFileBacked;
197     private final Object mLock = new Object();
198     private final CountDownLatch mInitDoneSignal = new CountDownLatch(1);
199     private final String mFrpSecretFile;
200     private final String mFrpSecretTmpFile;
201 
202     private int mAllowedUid = -1;
203     private long mBlockDeviceSize = -1; // Load lazily
204 
205     private final boolean mFrpEnforced;
206 
207     /**
208      * FRP active state.  When true (the default) we may have had an untrusted factory reset. In
209      * that case we block any updates of the persistent data block.  To exit active state, it's
210      * necessary for some caller to provide the FRP secret.
211      */
212     private boolean mFrpActive = false;
213 
214     @GuardedBy("mLock")
215     private boolean mIsWritable = true;
216 
PersistentDataBlockService(Context context)217     public PersistentDataBlockService(Context context) {
218         super(context);
219         mContext = context;
220         mFrpEnforced = Flags.frpEnforcement();
221         mFrpActive = mFrpEnforced;
222         mFrpSecretFile = FRP_SECRET_FILE;
223         mFrpSecretTmpFile = FRP_SECRET_TMP_FILE;
224         if (SystemProperties.getBoolean(GSI_RUNNING_PROP, false)) {
225             mIsFileBacked = true;
226             mDataBlockFile = GSI_SANDBOX;
227         } else {
228             mIsFileBacked = false;
229             mDataBlockFile = SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP);
230         }
231     }
232 
233     @VisibleForTesting
PersistentDataBlockService(Context context, boolean isFileBacked, String dataBlockFile, long blockDeviceSize, boolean frpEnabled, String frpSecretFile, String frpSecretTmpFile)234     PersistentDataBlockService(Context context, boolean isFileBacked, String dataBlockFile,
235             long blockDeviceSize, boolean frpEnabled, String frpSecretFile,
236             String frpSecretTmpFile) {
237         super(context);
238         mContext = context;
239         mIsFileBacked = isFileBacked;
240         mDataBlockFile = dataBlockFile;
241         mBlockDeviceSize = blockDeviceSize;
242         mFrpEnforced = frpEnabled;
243         mFrpActive = mFrpEnforced;
244         mFrpSecretFile = frpSecretFile;
245         mFrpSecretTmpFile = frpSecretTmpFile;
246     }
247 
getAllowedUid()248     private int getAllowedUid() {
249         final UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class);
250         int mainUserId = umInternal.getMainUserId();
251         if (mainUserId < 0) {
252             // If main user is not defined. Use the SYSTEM user instead.
253             mainUserId = UserHandle.USER_SYSTEM;
254         }
255         String allowedPackage = mContext.getResources()
256                 .getString(R.string.config_persistentDataPackageName);
257         int allowedUid = -1;
258         if (!TextUtils.isEmpty(allowedPackage)) {
259             try {
260                 allowedUid = mContext.getPackageManager().getPackageUidAsUser(
261                         allowedPackage, PackageManager.MATCH_SYSTEM_ONLY, mainUserId);
262             } catch (PackageManager.NameNotFoundException e) {
263                 // not expected
264                 Slog.e(TAG, "not able to find package " + allowedPackage, e);
265             }
266         }
267         return allowedUid;
268     }
269 
270     @Override
onStart()271     public void onStart() {
272         // Do init on a separate thread, will join in PHASE_ACTIVITY_MANAGER_READY
273         SystemServerInitThreadPool.submit(() -> {
274             enforceChecksumValidity();
275             if (mFrpEnforced) {
276                 automaticallyDeactivateFrpIfPossible();
277                 setOemUnlockEnabledProperty(doGetOemUnlockEnabled());
278                 setOldSettingForBackworkCompatibility(mFrpActive);
279             } else {
280                 formatIfOemUnlockEnabled();
281             }
282             publishBinderService(Context.PERSISTENT_DATA_BLOCK_SERVICE, mService);
283             signalInitDone();
284         }, TAG + ".onStart");
285     }
286 
287     @VisibleForTesting
signalInitDone()288     void signalInitDone() {
289         mInitDoneSignal.countDown();
290     }
291 
setOldSettingForBackworkCompatibility(boolean isActive)292     private void setOldSettingForBackworkCompatibility(boolean isActive) {
293         // Set the SECURE_FRP_MODE flag, for backward compatibility with clients who use it.
294         // They should switch to calling #isFrpActive().  Clear calling ID since this can happen
295         // during an app call.
296         final long callingId = Binder.clearCallingIdentity();
297         try {
298             Settings.Global.putInt(mContext.getContentResolver(),
299                     Settings.Global.SECURE_FRP_MODE, isActive ? 1 : 0);
300         } finally {
301             Binder.restoreCallingIdentity(callingId);
302         }
303     }
304 
setOemUnlockEnabledProperty(boolean oemUnlockEnabled)305     private void setOemUnlockEnabledProperty(boolean oemUnlockEnabled) {
306         setProperty(OEM_UNLOCK_PROP, oemUnlockEnabled ? "1" : "0");
307     }
308 
309     @Override
onBootPhase(int phase)310     public void onBootPhase(int phase) {
311         // Wait for initialization in onStart to finish
312         if (phase == PHASE_SYSTEM_SERVICES_READY) {
313             waitForInitDoneSignal();
314             // The user responsible for FRP should exist by now.
315             mAllowedUid = getAllowedUid();
316             LocalServices.addService(PersistentDataBlockManagerInternal.class, mInternalService);
317         }
318         super.onBootPhase(phase);
319     }
320 
waitForInitDoneSignal()321     private void waitForInitDoneSignal() {
322         try {
323             if (!mInitDoneSignal.await(INIT_WAIT_TIMEOUT, TimeUnit.SECONDS)) {
324                 throw new IllegalStateException("Service " + TAG + " init timeout");
325             }
326         } catch (InterruptedException e) {
327             Thread.currentThread().interrupt();
328             throw new IllegalStateException("Service " + TAG + " init interrupted", e);
329         }
330     }
331 
332     @VisibleForTesting
setAllowedUid(int uid)333     void setAllowedUid(int uid) {
334         mAllowedUid = uid;
335     }
336 
formatIfOemUnlockEnabled()337     private void formatIfOemUnlockEnabled() {
338         boolean enabled = doGetOemUnlockEnabled();
339         if (enabled) {
340             synchronized (mLock) {
341                 formatPartitionLocked(true);
342             }
343         }
344         setOemUnlockEnabledProperty(enabled);
345     }
346 
enforceOemUnlockReadPermission()347     private void enforceOemUnlockReadPermission() {
348         if (mContext.checkCallingOrSelfPermission(Manifest.permission.READ_OEM_UNLOCK_STATE)
349                 == PackageManager.PERMISSION_DENIED
350                 && mContext.checkCallingOrSelfPermission(Manifest.permission.OEM_UNLOCK_STATE)
351                 == PackageManager.PERMISSION_DENIED) {
352             throw new SecurityException("Can't access OEM unlock state. Requires "
353                     + "READ_OEM_UNLOCK_STATE or OEM_UNLOCK_STATE permission.");
354         }
355     }
356 
enforceOemUnlockWritePermission()357     private void enforceOemUnlockWritePermission() {
358         mContext.enforceCallingOrSelfPermission(
359                 Manifest.permission.OEM_UNLOCK_STATE,
360                 "Can't modify OEM unlock state");
361     }
362 
enforceConfigureFrpPermission()363     private void enforceConfigureFrpPermission() {
364         if (mFrpEnforced && mContext.checkCallingOrSelfPermission(
365                 Manifest.permission.CONFIGURE_FACTORY_RESET_PROTECTION)
366                 == PackageManager.PERMISSION_DENIED) {
367             throw new SecurityException(("Can't configure Factory Reset Protection. Requires "
368                     + "CONFIGURE_FACTORY_RESET_PROTECTION"));
369         }
370     }
371 
enforceUid(int callingUid)372     private void enforceUid(int callingUid) {
373         if (callingUid != mAllowedUid && callingUid != UserHandle.AID_ROOT) {
374             throw new SecurityException("uid " + callingUid + " not allowed to access PDB");
375         }
376     }
377 
enforceIsAdmin()378     private void enforceIsAdmin() {
379         final int userId = UserHandle.getCallingUserId();
380         final boolean isAdmin = UserManager.get(mContext).isUserAdmin(userId);
381         if (!isAdmin) {
382             throw new SecurityException(
383                     "Only the Admin user is allowed to change OEM unlock state");
384         }
385     }
386 
enforceUserRestriction(String userRestriction)387     private void enforceUserRestriction(String userRestriction) {
388         if (UserManager.get(mContext).hasUserRestriction(userRestriction)) {
389             throw new SecurityException(
390                     "OEM unlock is disallowed by user restriction: " + userRestriction);
391         }
392     }
393 
getTotalDataSizeLocked(DataInputStream inputStream)394     private int getTotalDataSizeLocked(DataInputStream inputStream) throws IOException {
395         // skip over checksum
396         inputStream.skipBytes(DIGEST_SIZE_BYTES);
397 
398         int totalDataSize;
399         int blockId = inputStream.readInt();
400         if (blockId == PARTITION_TYPE_MARKER) {
401             totalDataSize = inputStream.readInt();
402         } else {
403             totalDataSize = 0;
404         }
405         return totalDataSize;
406     }
407 
408     @VisibleForTesting
getBlockDeviceSize()409     long getBlockDeviceSize() {
410         synchronized (mLock) {
411             if (mBlockDeviceSize == -1) {
412                 if (mIsFileBacked) {
413                     mBlockDeviceSize = MAX_DATA_BLOCK_SIZE;
414                 } else {
415                     mBlockDeviceSize = nativeGetBlockDeviceSize(mDataBlockFile);
416                 }
417             }
418         }
419 
420         return mBlockDeviceSize;
421     }
422 
423     @VisibleForTesting
getMaximumFrpDataSize()424     int getMaximumFrpDataSize() {
425         long frpSecretSize = mFrpEnforced ? FRP_SECRET_MAGIC.length + FRP_SECRET_SIZE : 0;
426         return (int) (getTestHarnessModeDataOffset() - DIGEST_SIZE_BYTES - HEADER_SIZE
427                 - frpSecretSize);
428     }
429 
430     @VisibleForTesting
getFrpCredentialDataOffset()431     long getFrpCredentialDataOffset() {
432         return getOemUnlockDataOffset() - FRP_CREDENTIAL_RESERVED_SIZE;
433     }
434 
435     @VisibleForTesting
getFrpSecretMagicOffset()436     long getFrpSecretMagicOffset() {
437         return getFrpSecretDataOffset() - FRP_SECRET_MAGIC.length;
438     }
439 
440     @VisibleForTesting
getFrpSecretDataOffset()441     long getFrpSecretDataOffset() {
442         return getTestHarnessModeDataOffset() - FRP_SECRET_SIZE;
443     }
444 
445     @VisibleForTesting
getTestHarnessModeDataOffset()446     long getTestHarnessModeDataOffset() {
447         return getFrpCredentialDataOffset() - TEST_MODE_RESERVED_SIZE;
448     }
449 
450     @VisibleForTesting
getOemUnlockDataOffset()451     long getOemUnlockDataOffset() {
452         return getBlockDeviceSize() - 1;
453     }
454 
enforceChecksumValidity()455     private boolean enforceChecksumValidity() {
456         byte[] storedDigest = new byte[DIGEST_SIZE_BYTES];
457 
458         synchronized (mLock) {
459             byte[] digest = computeDigestLocked(storedDigest);
460             if (digest == null || !Arrays.equals(storedDigest, digest)) {
461                 Slog.i(TAG, "Formatting FRP partition...");
462                 formatPartitionLocked(false);
463                 return false;
464             }
465         }
466 
467         return true;
468     }
469 
getBlockOutputChannel()470     private FileChannel getBlockOutputChannel() throws IOException {
471         enforceFactoryResetProtectionInactive();
472         return getBlockOutputChannelIgnoringFrp();
473     }
474 
getBlockOutputChannelIgnoringFrp()475     private FileChannel getBlockOutputChannelIgnoringFrp() throws FileNotFoundException {
476         return new RandomAccessFile(mDataBlockFile, "rw").getChannel();
477     }
478 
computeAndWriteDigestLocked()479     private boolean computeAndWriteDigestLocked() {
480         byte[] digest = computeDigestLocked(null);
481         if (digest != null) {
482             try (FileChannel channel = getBlockOutputChannel()) {
483                 ByteBuffer buf = ByteBuffer.allocate(DIGEST_SIZE_BYTES);
484                 buf.put(digest);
485                 buf.flip();
486                 channel.write(buf);
487                 channel.force(true);
488             } catch (IOException e) {
489                 Slog.e(TAG, "failed to write block checksum", e);
490                 return false;
491             }
492             return true;
493         } else {
494             return false;
495         }
496     }
497 
computeDigestLocked(byte[] storedDigest)498     private byte[] computeDigestLocked(byte[] storedDigest) {
499         DataInputStream inputStream;
500         try {
501             inputStream = new DataInputStream(new FileInputStream(new File(mDataBlockFile)));
502         } catch (FileNotFoundException e) {
503             Slog.e(TAG, "partition not available?", e);
504             return null;
505         }
506 
507         MessageDigest md;
508         try {
509             md = MessageDigest.getInstance("SHA-256");
510         } catch (NoSuchAlgorithmException e) {
511             // won't ever happen -- every implementation is required to support SHA-256
512             Slog.e(TAG, "SHA-256 not supported?", e);
513             IoUtils.closeQuietly(inputStream);
514             return null;
515         }
516 
517         try {
518             if (storedDigest != null && storedDigest.length == DIGEST_SIZE_BYTES) {
519                 inputStream.read(storedDigest);
520             } else {
521                 inputStream.skipBytes(DIGEST_SIZE_BYTES);
522             }
523 
524             int read;
525             byte[] data = new byte[1024];
526             md.update(data, 0, DIGEST_SIZE_BYTES); // include 0 checksum in digest
527             while ((read = inputStream.read(data)) != -1) {
528                 md.update(data, 0, read);
529             }
530         } catch (IOException e) {
531             Slog.e(TAG, "failed to read partition", e);
532             return null;
533         } finally {
534             IoUtils.closeQuietly(inputStream);
535         }
536 
537         return md.digest();
538     }
539 
540     @VisibleForTesting
formatPartitionLocked(boolean setOemUnlockEnabled)541     void formatPartitionLocked(boolean setOemUnlockEnabled) {
542 
543         try (FileChannel channel = getBlockOutputChannelIgnoringFrp()) {
544             // Format the data selectively.
545             //
546             // 1. write header, set length = 0
547             int header_size = DIGEST_SIZE_BYTES + HEADER_SIZE;
548             ByteBuffer buf = ByteBuffer.allocate(header_size);
549             buf.put(new byte[DIGEST_SIZE_BYTES]);
550             buf.putInt(PARTITION_TYPE_MARKER);
551             buf.putInt(0);
552             buf.flip();
553             channel.write(buf);
554             channel.force(true);
555 
556             // 2. corrupt the legacy FRP data explicitly
557             int payload_size = (int) getBlockDeviceSize() - header_size;
558             if (mFrpEnforced) {
559                 buf = ByteBuffer.allocate(payload_size - TEST_MODE_RESERVED_SIZE
560                         - FRP_SECRET_MAGIC.length - FRP_SECRET_SIZE - FRP_CREDENTIAL_RESERVED_SIZE
561                         - 1);
562             } else {
563                 buf = ByteBuffer.allocate(payload_size - TEST_MODE_RESERVED_SIZE
564                         - FRP_CREDENTIAL_RESERVED_SIZE - 1);
565             }
566             channel.write(buf);
567             channel.force(true);
568 
569             // 3. Write the default FRP secret (all zeros).
570             if (mFrpEnforced) {
571                 Slog.i(TAG, "Writing FRP secret magic");
572                 channel.write(ByteBuffer.wrap(FRP_SECRET_MAGIC));
573 
574                 Slog.i(TAG, "Writing default FRP secret");
575                 channel.write(ByteBuffer.allocate(FRP_SECRET_SIZE));
576                 channel.force(true);
577 
578                 mFrpActive = false;
579             }
580 
581             // 4. skip the test mode data and leave it unformatted.
582             //    This is for a feature that enables testing.
583             channel.position(channel.position() + TEST_MODE_RESERVED_SIZE);
584 
585             // 5. wipe the FRP_CREDENTIAL explicitly
586             buf = ByteBuffer.allocate(FRP_CREDENTIAL_RESERVED_SIZE);
587             channel.write(buf);
588             channel.force(true);
589 
590             // 6. set unlock = 0 because it's a formatPartitionLocked
591             buf = ByteBuffer.allocate(FRP_CREDENTIAL_RESERVED_SIZE);
592             buf.put((byte)0);
593             buf.flip();
594             channel.write(buf);
595             channel.force(true);
596         } catch (IOException e) {
597             Slog.e(TAG, "failed to format block", e);
598             return;
599         }
600 
601         doSetOemUnlockEnabledLocked(setOemUnlockEnabled);
602         computeAndWriteDigestLocked();
603     }
604 
605     /**
606      * Try to deactivate FRP by presenting an FRP secret from the data partition, or the default
607      * secret if the secret(s) on the data partition are not present or don't work.
608      */
609     @VisibleForTesting
automaticallyDeactivateFrpIfPossible()610     boolean automaticallyDeactivateFrpIfPossible() {
611         synchronized (mLock) {
612             if (deactivateFrpWithFileSecret(mFrpSecretFile)) {
613                 return true;
614             }
615 
616             Slog.w(TAG, "Failed to deactivate with primary secret file, trying backup.");
617             if (deactivateFrpWithFileSecret(mFrpSecretTmpFile)) {
618                 // The backup file has the FRP secret, make it the primary file.
619                 moveFrpTempFileToPrimary();
620                 return true;
621             }
622 
623             Slog.w(TAG, "Failed to deactivate with backup secret file, trying default secret.");
624             if (deactivateFrp(new byte[FRP_SECRET_SIZE])) {
625                 return true;
626             }
627 
628             // We could not deactivate FRP.  It's possible that we have hit an obscure corner case,
629             // a device that once ran a version of Android that set the FRP magic and a secret,
630             // then downgraded to a version that did not know about FRP, wiping the FRP secrets
631             // files, then upgraded to a version (the current one) that does know about FRP,
632             // potentially leaving the user unable to deactivate FRP because all copies of the
633             // secret are gone.
634             //
635             // To handle this case, we check to see if we have recently upgraded from a pre-V
636             // version.  If so, we deactivate FRP and set the secret to the default value.
637             if (isUpgradingFromPreVRelease()) {
638                 Slog.w(TAG, "Upgrading from Android 14 or lower, defaulting FRP secret");
639                 writeFrpMagicAndDefaultSecret();
640                 mFrpActive = false;
641                 setOldSettingForBackworkCompatibility(mFrpActive);
642                 return true;
643             }
644 
645             Slog.e(TAG, "Did not find valid FRP secret, FRP remains active.");
646             return false;
647         }
648     }
649 
deactivateFrpWithFileSecret(String frpSecretFile)650     private boolean deactivateFrpWithFileSecret(String frpSecretFile) {
651         try {
652             return deactivateFrp(Files.readAllBytes(Paths.get(frpSecretFile)));
653         } catch (IOException e) {
654             Slog.i(TAG, "Failed to read FRP secret file: " + frpSecretFile + " "
655                     + e.getClass().getSimpleName());
656             return false;
657         }
658     }
659 
moveFrpTempFileToPrimary()660     private void moveFrpTempFileToPrimary() {
661         try {
662             Files.move(Paths.get(mFrpSecretTmpFile), Paths.get(mFrpSecretFile), REPLACE_EXISTING);
663         } catch (IOException e) {
664             Slog.e(TAG, "Error moving FRP backup file to primary (ignored)", e);
665         }
666     }
667 
668     @VisibleForTesting
isFrpActive()669     boolean isFrpActive() {
670         synchronized (mLock) {
671             // mFrpActive is initialized and automatic deactivation done (if possible) before the
672             // service is published, so there's no chance that callers could ask for the state
673             // before it has settled.
674             return mFrpActive;
675         }
676     }
677 
678     /**
679      * Write the provided secret to the FRP secret file in /data and to the persistent data block
680      * partition.
681      *
682      * Writing is a three-step process, to ensure that we can recover from a crash at any point.
683      */
updateFrpSecret(byte[] secret)684     private boolean updateFrpSecret(byte[] secret) {
685         // 1.  Write the new secret to a temporary file, and sync the write.
686         try {
687             Files.write(
688                     Paths.get(mFrpSecretTmpFile), secret, WRITE, CREATE, TRUNCATE_EXISTING, SYNC);
689         } catch (IOException e) {
690             Slog.e(TAG, "Failed to write FRP secret file", e);
691             return false;
692         }
693 
694         // 2.  Write the new secret to /persist, and sync the write.
695         if (!mInternalService.writeDataBuffer(getFrpSecretDataOffset(), ByteBuffer.wrap(secret))) {
696             return false;
697         }
698 
699         // 3.  Move the temporary file to the primary file location.  Syncing doesn't matter
700         //     here.  In the event this update doesn't complete it will get done by
701         //     #automaticallyDeactivateFrpIfPossible() during the next boot.
702         moveFrpTempFileToPrimary();
703         return true;
704     }
705 
706     /**
707      * Only for testing, activate FRP.
708      */
709     @VisibleForTesting
activateFrp()710     void activateFrp() {
711         synchronized (mLock) {
712             mFrpActive = true;
713             setOldSettingForBackworkCompatibility(mFrpActive);
714         }
715     }
716 
hasFrpSecretMagic()717     private boolean hasFrpSecretMagic() {
718         final byte[] frpMagic =
719                 readDataBlock(getFrpSecretMagicOffset(), FRP_SECRET_MAGIC.length);
720         if (frpMagic == null) {
721             // Transient read error on the partition?
722             Slog.e(TAG, "Failed to read FRP magic region.");
723             return false;
724         }
725         return Arrays.equals(frpMagic, FRP_SECRET_MAGIC);
726     }
727 
getFrpSecret()728     private byte[] getFrpSecret() {
729         return readDataBlock(getFrpSecretDataOffset(), FRP_SECRET_SIZE);
730     }
731 
deactivateFrp(byte[] secret)732     private boolean deactivateFrp(byte[] secret) {
733         if (secret == null || secret.length != FRP_SECRET_SIZE) {
734             Slog.w(TAG, "Attempted to deactivate FRP with a null or incorrectly-sized secret");
735             return false;
736         }
737 
738         synchronized (mLock) {
739             if (!hasFrpSecretMagic()) {
740                 Slog.i(TAG, "No FRP secret magic, system must have been upgraded.");
741                 writeFrpMagicAndDefaultSecret();
742             }
743         }
744 
745         final byte[] partitionSecret = getFrpSecret();
746         if (partitionSecret == null || partitionSecret.length != FRP_SECRET_SIZE) {
747             Slog.e(TAG, "Failed to read FRP secret from persistent data partition");
748             return false;
749         }
750 
751         // MessageDigest.isEqual is constant-time, to protect secret deduction by timing attack.
752         if (MessageDigest.isEqual(secret, partitionSecret)) {
753             mFrpActive = false;
754             Slog.i(TAG, "FRP secret matched, FRP deactivated.");
755             setOldSettingForBackworkCompatibility(mFrpActive);
756             return true;
757         } else {
758             Slog.e(TAG,
759                     "FRP deactivation failed with secret " + HexFormat.of().formatHex(secret));
760             return false;
761         }
762     }
763 
writeFrpMagicAndDefaultSecret()764     private void writeFrpMagicAndDefaultSecret() {
765         try (FileChannel channel = getBlockOutputChannelIgnoringFrp()) {
766             synchronized (mLock) {
767                 Slog.i(TAG, "Writing default FRP secret");
768                 channel.position(getFrpSecretDataOffset());
769                 channel.write(ByteBuffer.allocate(FRP_SECRET_SIZE));
770                 channel.force(true);
771 
772                 Slog.i(TAG, "Writing FRP secret magic");
773                 channel.position(getFrpSecretMagicOffset());
774                 channel.write(ByteBuffer.wrap(FRP_SECRET_MAGIC));
775                 channel.force(true);
776 
777                 mFrpActive = false;
778             }
779         } catch (IOException e) {
780             Slog.e(TAG, "Failed to write FRP magic and default secret", e);
781         }
782         computeAndWriteDigestLocked();
783     }
784 
785     @VisibleForTesting
readDataBlock(long offset, int length)786     byte[] readDataBlock(long offset, int length) {
787         try (DataInputStream inputStream =
788                      new DataInputStream(new FileInputStream(new File(mDataBlockFile)))) {
789             synchronized (mLock) {
790                 inputStream.skip(offset);
791                 byte[] bytes = new byte[length];
792                 inputStream.readFully(bytes);
793                 return bytes;
794             }
795         } catch (IOException e) {
796             throw new IllegalStateException("persistent partition not readable", e);
797         }
798     }
799 
doSetOemUnlockEnabledLocked(boolean enabled)800     private void doSetOemUnlockEnabledLocked(boolean enabled) {
801         try (FileChannel channel = getBlockOutputChannel()) {
802             channel.position(getBlockDeviceSize() - 1);
803 
804             ByteBuffer data = ByteBuffer.allocate(1);
805             data.put(enabled ? (byte) 1 : (byte) 0);
806             data.flip();
807             channel.write(data);
808             channel.force(true);
809         } catch (IOException e) {
810             Slog.e(TAG, "unable to access persistent partition", e);
811             return;
812         } finally {
813             setOemUnlockEnabledProperty(enabled);
814         }
815     }
816 
817     @VisibleForTesting
setProperty(String name, String value)818     void setProperty(String name, String value) {
819         SystemProperties.set(name, value);
820     }
821 
doGetOemUnlockEnabled()822     private boolean doGetOemUnlockEnabled() {
823         DataInputStream inputStream;
824         try {
825             inputStream = new DataInputStream(new FileInputStream(new File(mDataBlockFile)));
826         } catch (FileNotFoundException e) {
827             Slog.e(TAG, "partition not available");
828             return false;
829         }
830 
831         try {
832             synchronized (mLock) {
833                 inputStream.skip(getBlockDeviceSize() - 1);
834                 return inputStream.readByte() != 0;
835             }
836         } catch (IOException e) {
837             Slog.e(TAG, "unable to access persistent partition", e);
838             return false;
839         } finally {
840             IoUtils.closeQuietly(inputStream);
841         }
842     }
843 
doGetMaximumDataBlockSize()844     private long doGetMaximumDataBlockSize() {
845         final long frpSecretSize =
846                 mFrpEnforced ? (FRP_SECRET_MAGIC.length + FRP_SECRET_SIZE) : 0;
847         final long actualSize = getBlockDeviceSize() - HEADER_SIZE - DIGEST_SIZE_BYTES
848                 - TEST_MODE_RESERVED_SIZE - frpSecretSize - FRP_CREDENTIAL_RESERVED_SIZE - 1;
849         return actualSize <= MAX_DATA_BLOCK_SIZE ? actualSize : MAX_DATA_BLOCK_SIZE;
850     }
851 
nativeGetBlockDeviceSize(String path)852     private native long nativeGetBlockDeviceSize(String path);
nativeWipe(String path)853     private native int nativeWipe(String path);
854 
855     @VisibleForTesting
getInterfaceForTesting()856     IPersistentDataBlockService getInterfaceForTesting() {
857         return IPersistentDataBlockService.Stub.asInterface(mService);
858     }
859 
860     @VisibleForTesting
getInternalInterfaceForTesting()861     PersistentDataBlockManagerInternal getInternalInterfaceForTesting() {
862         return mInternalService;
863     }
864 
865     private final IBinder mService = new IPersistentDataBlockService.Stub() {
866         private int printFrpStatus(PrintWriter pw, boolean printSecrets) {
867             enforceUid(Binder.getCallingUid());
868 
869             pw.println("FRP state");
870             pw.println("=========");
871             pw.println("Enforcement enabled: " + mFrpEnforced);
872             pw.println("FRP state: " + mFrpActive);
873             printFrpDataFilesContents(pw, printSecrets);
874             printFrpSecret(pw, printSecrets);
875             pw.println("OEM unlock state: " + getOemUnlockEnabled());
876             pw.println("Bootloader lock state: " + getFlashLockState());
877             pw.println("Verified boot state: " + getVerifiedBootState());
878             pw.println("Has FRP credential handle: " + hasFrpCredentialHandle());
879             pw.println("FRP challenge block size: " + getDataBlockSize());
880             return 1;
881         }
882 
883         private void printFrpSecret(PrintWriter pw, boolean printSecret) {
884             if (hasFrpSecretMagic()) {
885                 if (printSecret) {
886                     pw.println("FRP secret in PDB: " + HexFormat.of().formatHex(
887                             readDataBlock(getFrpSecretDataOffset(), FRP_SECRET_SIZE)));
888                 } else {
889                     pw.println("FRP secret present but omitted.");
890                 }
891             } else {
892                 pw.println("FRP magic not found");
893             }
894         }
895 
896         private void printFrpDataFilesContents(PrintWriter pw, boolean printSecrets) {
897             printFrpDataFileContents(pw, mFrpSecretFile, printSecrets);
898             printFrpDataFileContents(pw, mFrpSecretTmpFile, printSecrets);
899         }
900 
901         private void printFrpDataFileContents(
902                 PrintWriter pw, String frpSecretFile, boolean printSecret) {
903             if (Files.exists(Paths.get(frpSecretFile))) {
904                 if (printSecret) {
905                     try {
906                         pw.println("FRP secret in " + frpSecretFile + ": " + HexFormat.of()
907                                 .formatHex(Files.readAllBytes(Paths.get(frpSecretFile))));
908                     } catch (IOException e) {
909                         Slog.e(TAG, "Failed to read " + frpSecretFile, e);
910                     }
911                 } else {
912                     pw.println(
913                             "FRP secret file " + frpSecretFile + " exists, contents omitted.");
914                 }
915             }
916         }
917 
918         @Override
919         public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
920                 @Nullable FileDescriptor err,
921                 @NonNull String[] args, @Nullable ShellCallback callback,
922                 @NonNull ResultReceiver resultReceiver) throws RemoteException {
923             if (!mFrpEnforced) {
924                 super.onShellCommand(in, out, err, args, callback, resultReceiver);
925                 return;
926             }
927             new ShellCommand(){
928                 @Override
929                 public int onCommand(final String cmd) {
930                     if (cmd == null) {
931                         return handleDefaultCommands(cmd);
932                     }
933 
934                     final PrintWriter pw = getOutPrintWriter();
935                     return switch (cmd) {
936                         case "status" -> printFrpStatus(pw, /* printSecrets */ !mFrpActive);
937                         case "activate" -> {
938                             activateFrp();
939                             yield printFrpStatus(pw, /* printSecrets */ !mFrpActive);
940                         }
941 
942                         case "deactivate" -> {
943                             byte[] secret = hashSecretString(getNextArg());
944                             pw.println("Attempting to deactivate with: " + HexFormat.of().formatHex(
945                                     secret));
946                             pw.println("Deactivation "
947                                     + (deactivateFrp(secret) ? "succeeded" : "failed"));
948                             yield printFrpStatus(pw, /* printSecrets */ !mFrpActive);
949                         }
950 
951                         case "auto_deactivate" -> {
952                             boolean result = automaticallyDeactivateFrpIfPossible();
953                             pw.println(
954                                     "Automatic deactivation " + (result ? "succeeded" : "failed"));
955                             yield printFrpStatus(pw, /* printSecrets */ !mFrpActive);
956                         }
957 
958                         case "set_secret" -> {
959                             byte[] secret = new byte[FRP_SECRET_SIZE];
960                             String secretString = getNextArg();
961                             if (!secretString.equals("default")) {
962                                 secret = hashSecretString(secretString);
963                             }
964                             pw.println("Setting FRP secret to: " + HexFormat.of()
965                                     .formatHex(secret) + " length: " + secret.length);
966                             setFactoryResetProtectionSecret(secret);
967                             yield printFrpStatus(pw, /* printSecrets */ !mFrpActive);
968                         }
969 
970                         default -> handleDefaultCommands(cmd);
971                     };
972                 }
973 
974                 @Override
975                 public void onHelp() {
976                     final PrintWriter pw = getOutPrintWriter();
977                     pw.println("Commands");
978                     pw.println("status: Print the FRP state and associated information.");
979                     pw.println("activate:  Put FRP into \"active\" mode.");
980                     pw.println("deactivate <secret>:  Deactivate with a hash of 'secret'.");
981                     pw.println("auto_deactivate: Deactivate with the stored secret or the default");
982                     pw.println("set_secret <secret>:  Set the stored secret to a hash of `secret`");
983                 }
984 
985                 private static byte[] hashSecretString(String secretInput) {
986                     try {
987                         // SHA-256 produces 32-byte outputs, same as the FRP secret size, so it's
988                         // a convenient way to "normalize" the length of whatever the user provided.
989                         // Also, hashing makes it difficult for an attacker to set the secret to a
990                         // known value that was randomly generated.
991                         MessageDigest md = MessageDigest.getInstance("SHA-256");
992                         return md.digest(secretInput.getBytes());
993                     } catch (NoSuchAlgorithmException e) {
994                         Slog.e(TAG, "Can't happen", e);
995                         return new byte[FRP_SECRET_SIZE];
996                     }
997                 }
998             }.exec(this, in, out, err, args, callback, resultReceiver);
999         }
1000 
1001         /**
1002          * Write the data to the persistent data block.
1003          *
1004          * @return a positive integer of the number of bytes that were written if successful,
1005          * otherwise a negative integer indicating there was a problem
1006          */
1007         @Override
1008         public int write(byte[] data) throws RemoteException {
1009             enforceUid(Binder.getCallingUid());
1010 
1011             // Need to ensure we don't write over the last byte
1012             long maxBlockSize = doGetMaximumDataBlockSize();
1013             if (data.length > maxBlockSize) {
1014                 // partition is ~500k so shouldn't be a problem to downcast
1015                 return (int) -maxBlockSize;
1016             }
1017 
1018             ByteBuffer headerAndData = ByteBuffer.allocate(
1019                     data.length + HEADER_SIZE + DIGEST_SIZE_BYTES);
1020             headerAndData.put(new byte[DIGEST_SIZE_BYTES]);
1021             headerAndData.putInt(PARTITION_TYPE_MARKER);
1022             headerAndData.putInt(data.length);
1023             headerAndData.put(data);
1024             headerAndData.flip();
1025             synchronized (mLock) {
1026                 if (!mIsWritable) {
1027                     return -1;
1028                 }
1029 
1030                 try (FileChannel channel = getBlockOutputChannel()) {
1031                     channel.write(headerAndData);
1032                     channel.force(true);
1033                 } catch (IOException e) {
1034                     Slog.e(TAG, "failed writing to the persistent data block", e);
1035                     return -1;
1036                 }
1037 
1038                 if (computeAndWriteDigestLocked()) {
1039                     return data.length;
1040                 } else {
1041                     return -1;
1042                 }
1043             }
1044         }
1045 
1046         @Override
1047         public byte[] read() {
1048             enforceUid(Binder.getCallingUid());
1049             if (!enforceChecksumValidity()) {
1050                 return new byte[0];
1051             }
1052 
1053             DataInputStream inputStream;
1054             try {
1055                 inputStream = new DataInputStream(new FileInputStream(new File(mDataBlockFile)));
1056             } catch (FileNotFoundException e) {
1057                 Slog.e(TAG, "partition not available?", e);
1058                 return null;
1059             }
1060 
1061             try {
1062                 synchronized (mLock) {
1063                     int totalDataSize = getTotalDataSizeLocked(inputStream);
1064 
1065                     if (totalDataSize == 0) {
1066                         return new byte[0];
1067                     }
1068 
1069                     byte[] data = new byte[totalDataSize];
1070                     int read = inputStream.read(data, 0, totalDataSize);
1071                     if (read < totalDataSize) {
1072                         // something went wrong, not returning potentially corrupt data
1073                         Slog.e(TAG, "failed to read entire data block. bytes read: " +
1074                                 read + "/" + totalDataSize);
1075                         return null;
1076                     }
1077                     return data;
1078                 }
1079             } catch (IOException e) {
1080                 Slog.e(TAG, "failed to read data", e);
1081                 return null;
1082             } finally {
1083                 try {
1084                     inputStream.close();
1085                 } catch (IOException e) {
1086                     Slog.e(TAG, "failed to close OutputStream");
1087                 }
1088             }
1089         }
1090 
1091         @Override
1092         public void wipe() {
1093             enforceFactoryResetProtectionInactive();
1094             enforceOemUnlockWritePermission();
1095 
1096             synchronized (mLock) {
1097                 int ret;
1098                 if (mIsFileBacked) {
1099                     try {
1100                         Files.write(Paths.get(mDataBlockFile), new byte[MAX_DATA_BLOCK_SIZE],
1101                                 TRUNCATE_EXISTING);
1102                         ret = 0;
1103                     } catch (IOException e) {
1104                         ret = -1;
1105                     }
1106                 } else {
1107                     ret = nativeWipe(mDataBlockFile);
1108                 }
1109 
1110                 if (ret < 0) {
1111                     Slog.e(TAG, "failed to wipe persistent partition");
1112                 } else {
1113                     mIsWritable = false;
1114                     Slog.i(TAG, "persistent partition now wiped and unwritable");
1115                 }
1116             }
1117         }
1118 
1119         @Override
1120         public void setOemUnlockEnabled(boolean enabled) throws SecurityException {
1121             // do not allow monkey to flip the flag
1122             if (ActivityManager.isUserAMonkey()) {
1123                 return;
1124             }
1125 
1126             enforceOemUnlockWritePermission();
1127             enforceIsAdmin();
1128 
1129             if (enabled) {
1130                 // Do not allow oem unlock to be enabled if it's disallowed by a user restriction.
1131                 enforceUserRestriction(UserManager.DISALLOW_OEM_UNLOCK);
1132                 enforceUserRestriction(UserManager.DISALLOW_FACTORY_RESET);
1133             }
1134             synchronized (mLock) {
1135                 doSetOemUnlockEnabledLocked(enabled);
1136                 computeAndWriteDigestLocked();
1137             }
1138         }
1139 
1140         @Override
1141         public boolean getOemUnlockEnabled() {
1142             enforceOemUnlockReadPermission();
1143             return doGetOemUnlockEnabled();
1144         }
1145 
1146         @Override
1147         public int getFlashLockState() {
1148             enforceOemUnlockReadPermission();
1149             String locked = SystemProperties.get(FLASH_LOCK_PROP);
1150             switch (locked) {
1151                 case FLASH_LOCK_LOCKED:
1152                     return PersistentDataBlockManager.FLASH_LOCK_LOCKED;
1153                 case FLASH_LOCK_UNLOCKED:
1154                     return PersistentDataBlockManager.FLASH_LOCK_UNLOCKED;
1155                 default:
1156                     return PersistentDataBlockManager.FLASH_LOCK_UNKNOWN;
1157             }
1158         }
1159 
1160         private static String getVerifiedBootState() {
1161             return SystemProperties.get(VERIFIED_BOOT_STATE);
1162         }
1163 
1164         @Override
1165         public int getDataBlockSize() {
1166             enforcePersistentDataBlockAccess();
1167 
1168             DataInputStream inputStream;
1169             try {
1170                 inputStream = new DataInputStream(new FileInputStream(new File(mDataBlockFile)));
1171             } catch (FileNotFoundException e) {
1172                 Slog.e(TAG, "partition not available");
1173                 return 0;
1174             }
1175 
1176             try {
1177                 synchronized (mLock) {
1178                     return getTotalDataSizeLocked(inputStream);
1179                 }
1180             } catch (IOException e) {
1181                 Slog.e(TAG, "error reading data block size");
1182                 return 0;
1183             } finally {
1184                 IoUtils.closeQuietly(inputStream);
1185             }
1186         }
1187 
1188         private void enforcePersistentDataBlockAccess() {
1189             if (mContext.checkCallingPermission(Manifest.permission.ACCESS_PDB_STATE)
1190                     != PackageManager.PERMISSION_GRANTED) {
1191                 enforceUid(Binder.getCallingUid());
1192             }
1193         }
1194 
1195         private void enforceConfigureFrpPermissionOrPersistentDataBlockAccess() {
1196             if (!mFrpEnforced) {
1197                 enforcePersistentDataBlockAccess();
1198             } else {
1199                 if (mContext.checkCallingOrSelfPermission(
1200                         Manifest.permission.CONFIGURE_FACTORY_RESET_PROTECTION)
1201                         == PackageManager.PERMISSION_DENIED) {
1202                     enforcePersistentDataBlockAccess();
1203                 }
1204             }
1205         }
1206 
1207         @Override
1208         public long getMaximumDataBlockSize() {
1209             enforceUid(Binder.getCallingUid());
1210             return doGetMaximumDataBlockSize();
1211         }
1212 
1213         @Override
1214         public boolean hasFrpCredentialHandle() {
1215             enforceConfigureFrpPermissionOrPersistentDataBlockAccess();
1216             try {
1217                 return mInternalService.getFrpCredentialHandle() != null;
1218             } catch (IllegalStateException e) {
1219                 Slog.e(TAG, "error reading frp handle", e);
1220                 throw new UnsupportedOperationException("cannot read frp credential");
1221             }
1222         }
1223 
1224         @Override
1225         public String getPersistentDataPackageName() {
1226             enforcePersistentDataBlockAccess();
1227             return mContext.getString(R.string.config_persistentDataPackageName);
1228         }
1229 
1230         @Override
1231         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1232             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
1233 
1234             pw.println("mDataBlockFile: " + mDataBlockFile);
1235             pw.println("mIsFileBacked: " + mIsFileBacked);
1236             pw.println("mInitDoneSignal: " + mInitDoneSignal);
1237             pw.println("mAllowedUid: " + mAllowedUid);
1238             pw.println("mBlockDeviceSize: " + mBlockDeviceSize);
1239             synchronized (mLock) {
1240                 pw.println("mIsWritable: " + mIsWritable);
1241             }
1242             printFrpStatus(pw, /* printSecrets */ false);
1243         }
1244 
1245         @Override
1246         public boolean isFactoryResetProtectionActive() {
1247             return isFrpActive();
1248         }
1249 
1250         @Override
1251         public boolean deactivateFactoryResetProtection(byte[] secret) {
1252             enforceConfigureFrpPermission();
1253             return deactivateFrp(secret);
1254         }
1255 
1256         @Override
1257         public boolean setFactoryResetProtectionSecret(byte[] secret) {
1258             enforceConfigureFrpPermission();
1259             enforceUid(Binder.getCallingUid());
1260             if (secret == null || secret.length != FRP_SECRET_SIZE) {
1261                 throw new IllegalArgumentException(
1262                         "Invalid FRP secret: " + HexFormat.of().formatHex(secret));
1263             }
1264             enforceFactoryResetProtectionInactive();
1265             return updateFrpSecret(secret);
1266         }
1267     };
1268 
enforceFactoryResetProtectionInactive()1269     private void enforceFactoryResetProtectionInactive() {
1270         if (mFrpEnforced && isFrpActive()) {
1271             Slog.w(TAG, "Attempt to update PDB was blocked because FRP is active.");
1272             throw new SecurityException("FRP is active");
1273         }
1274     }
1275 
1276     @VisibleForTesting
isUpgradingFromPreVRelease()1277     boolean isUpgradingFromPreVRelease() {
1278         PackageManagerInternal packageManagerInternal =
1279                 LocalServices.getService(PackageManagerInternal.class);
1280         if (packageManagerInternal == null) {
1281             Slog.e(TAG, "Unable to retrieve PackageManagerInternal");
1282             return false;
1283         }
1284 
1285         return packageManagerInternal
1286                 .isUpgradingFromLowerThan(Build.VERSION_CODES.VANILLA_ICE_CREAM);
1287     }
1288 
1289     private InternalService mInternalService = new InternalService();
1290 
1291     private class InternalService implements PersistentDataBlockManagerInternal {
1292         @Override
setFrpCredentialHandle(byte[] handle)1293         public void setFrpCredentialHandle(byte[] handle) {
1294             writeInternal(handle, getFrpCredentialDataOffset(), MAX_FRP_CREDENTIAL_HANDLE_SIZE);
1295         }
1296 
1297         @Override
getFrpCredentialHandle()1298         public byte[] getFrpCredentialHandle() {
1299             return readInternal(getFrpCredentialDataOffset(), MAX_FRP_CREDENTIAL_HANDLE_SIZE);
1300         }
1301 
1302         @Override
setTestHarnessModeData(byte[] data)1303         public void setTestHarnessModeData(byte[] data) {
1304             writeInternal(data, getTestHarnessModeDataOffset(), MAX_TEST_MODE_DATA_SIZE);
1305         }
1306 
1307         @Override
getTestHarnessModeData()1308         public byte[] getTestHarnessModeData() {
1309             byte[] data = readInternal(getTestHarnessModeDataOffset(), MAX_TEST_MODE_DATA_SIZE);
1310             if (data == null) {
1311                 return new byte[0];
1312             }
1313             return data;
1314         }
1315 
1316         @Override
clearTestHarnessModeData()1317         public void clearTestHarnessModeData() {
1318             int size = Math.min(MAX_TEST_MODE_DATA_SIZE, getTestHarnessModeData().length) + 4;
1319             writeDataBuffer(getTestHarnessModeDataOffset(), ByteBuffer.allocate(size));
1320         }
1321 
1322         @Override
getAllowedUid()1323         public int getAllowedUid() {
1324             return mAllowedUid;
1325         }
1326 
1327         @Override
deactivateFactoryResetProtectionWithoutSecret()1328         public boolean deactivateFactoryResetProtectionWithoutSecret() {
1329             synchronized (mLock) {
1330                 mFrpActive = false;
1331                 setOldSettingForBackworkCompatibility(/* isActive */ mFrpActive);
1332             }
1333             return true;
1334         }
1335 
writeInternal(byte[] data, long offset, int dataLength)1336         private void writeInternal(byte[] data, long offset, int dataLength) {
1337             checkArgument(data == null || data.length > 0, "data must be null or non-empty");
1338             checkArgument(
1339                     data == null || data.length <= dataLength,
1340                     "data must not be longer than " + dataLength);
1341 
1342             ByteBuffer dataBuffer = ByteBuffer.allocate(dataLength + 4);
1343             dataBuffer.putInt(data == null ? 0 : data.length);
1344             if (data != null) {
1345                 dataBuffer.put(data);
1346             }
1347             dataBuffer.flip();
1348 
1349             writeDataBuffer(offset, dataBuffer);
1350         }
1351 
writeDataBuffer(long offset, ByteBuffer dataBuffer)1352         private boolean writeDataBuffer(long offset, ByteBuffer dataBuffer) {
1353             synchronized (mLock) {
1354                 if (!mIsWritable) {
1355                     return false;
1356                 }
1357                 try (FileChannel channel = getBlockOutputChannel()) {
1358                     channel.position(offset);
1359                     channel.write(dataBuffer);
1360                     channel.force(true);
1361                 } catch (IOException e) {
1362                     Slog.e(TAG, "unable to access persistent partition", e);
1363                     return false;
1364                 }
1365 
1366                 return computeAndWriteDigestLocked();
1367             }
1368         }
1369 
readInternal(long offset, int maxLength)1370         private byte[] readInternal(long offset, int maxLength) {
1371             if (!enforceChecksumValidity()) {
1372                 throw new IllegalStateException("invalid checksum");
1373             }
1374 
1375             DataInputStream inputStream;
1376             try {
1377                 inputStream = new DataInputStream(
1378                         new FileInputStream(new File(mDataBlockFile)));
1379             } catch (FileNotFoundException e) {
1380                 throw new IllegalStateException("persistent partition not available");
1381             }
1382 
1383             try {
1384                 synchronized (mLock) {
1385                     inputStream.skip(offset);
1386                     int length = inputStream.readInt();
1387                     if (length <= 0 || length > maxLength) {
1388                         return null;
1389                     }
1390                     byte[] bytes = new byte[length];
1391                     inputStream.readFully(bytes);
1392                     return bytes;
1393                 }
1394             } catch (IOException e) {
1395                 throw new IllegalStateException("persistent partition not readable", e);
1396             } finally {
1397                 IoUtils.closeQuietly(inputStream);
1398             }
1399         }
1400 
1401         @Override
forceOemUnlockEnabled(boolean enabled)1402         public void forceOemUnlockEnabled(boolean enabled) {
1403             synchronized (mLock) {
1404                 doSetOemUnlockEnabledLocked(enabled);
1405                 computeAndWriteDigestLocked();
1406             }
1407         }
1408     }
1409 }
1410