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