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