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