Merge master@5428150 into git_qt-dev-plus-aosp.
Change-Id: I1c69d7c91e68fd4baba7b6510acf2a69e1a6c5d7 BUG: 129345239
This commit is contained in:
+3
-70
@@ -63,32 +63,18 @@ cc_defaults {
|
|||||||
"libbootloader_message",
|
"libbootloader_message",
|
||||||
"libcrypto",
|
"libcrypto",
|
||||||
"libcutils",
|
"libcutils",
|
||||||
"libext4_utils",
|
|
||||||
"libfs_mgr",
|
"libfs_mgr",
|
||||||
"libfusesideload",
|
|
||||||
"libhidl-gen-utils",
|
|
||||||
"libhidlbase",
|
|
||||||
"libhidltransport",
|
|
||||||
"liblog",
|
"liblog",
|
||||||
"libpng",
|
|
||||||
"libselinux",
|
|
||||||
"libtinyxml2",
|
|
||||||
"libutils",
|
|
||||||
"libz",
|
|
||||||
"libziparchive",
|
"libziparchive",
|
||||||
],
|
],
|
||||||
|
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"librecovery_fastboot",
|
"librecovery_fastboot",
|
||||||
"libminui",
|
"libminui",
|
||||||
"libpackage",
|
|
||||||
"libverifier",
|
|
||||||
"libotautil",
|
"libotautil",
|
||||||
|
|
||||||
// external dependencies
|
// external dependencies
|
||||||
"libhealthhalutils",
|
"libhealthhalutils",
|
||||||
"libvintf_recovery",
|
|
||||||
"libvintf",
|
|
||||||
"libfstab",
|
"libfstab",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@@ -102,69 +88,14 @@ cc_library_static {
|
|||||||
],
|
],
|
||||||
|
|
||||||
srcs: [
|
srcs: [
|
||||||
"adb_install.cpp",
|
|
||||||
"fsck_unshare_blocks.cpp",
|
"fsck_unshare_blocks.cpp",
|
||||||
"fuse_sdcard_install.cpp",
|
|
||||||
"install.cpp",
|
|
||||||
"recovery.cpp",
|
"recovery.cpp",
|
||||||
"roots.cpp",
|
|
||||||
],
|
],
|
||||||
|
|
||||||
shared_libs: [
|
shared_libs: [
|
||||||
|
"libinstall",
|
||||||
"librecovery_ui",
|
"librecovery_ui",
|
||||||
],
|
],
|
||||||
|
|
||||||
include_dirs: [
|
|
||||||
"system/vold",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
cc_library_static {
|
|
||||||
name: "libverifier",
|
|
||||||
recovery_available: true,
|
|
||||||
|
|
||||||
defaults: [
|
|
||||||
"recovery_defaults",
|
|
||||||
],
|
|
||||||
|
|
||||||
srcs: [
|
|
||||||
"asn1_decoder.cpp",
|
|
||||||
"verifier.cpp",
|
|
||||||
],
|
|
||||||
|
|
||||||
shared_libs: [
|
|
||||||
"libbase",
|
|
||||||
"libcrypto",
|
|
||||||
"libcrypto_utils",
|
|
||||||
"libziparchive",
|
|
||||||
],
|
|
||||||
|
|
||||||
static_libs: [
|
|
||||||
"libotautil",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
cc_library_static {
|
|
||||||
name: "libpackage",
|
|
||||||
recovery_available: true,
|
|
||||||
|
|
||||||
defaults: [
|
|
||||||
"recovery_defaults",
|
|
||||||
],
|
|
||||||
|
|
||||||
srcs: [
|
|
||||||
"package.cpp",
|
|
||||||
],
|
|
||||||
|
|
||||||
shared_libs: [
|
|
||||||
"libbase",
|
|
||||||
"libcrypto",
|
|
||||||
"libziparchive",
|
|
||||||
],
|
|
||||||
|
|
||||||
static_libs: [
|
|
||||||
"libotautil",
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cc_binary {
|
cc_binary {
|
||||||
@@ -172,6 +103,7 @@ cc_binary {
|
|||||||
recovery: true,
|
recovery: true,
|
||||||
|
|
||||||
defaults: [
|
defaults: [
|
||||||
|
"libinstall_defaults",
|
||||||
"librecovery_defaults",
|
"librecovery_defaults",
|
||||||
],
|
],
|
||||||
|
|
||||||
@@ -181,6 +113,7 @@ cc_binary {
|
|||||||
],
|
],
|
||||||
|
|
||||||
shared_libs: [
|
shared_libs: [
|
||||||
|
"libinstall",
|
||||||
"libminadbd_services",
|
"libminadbd_services",
|
||||||
"librecovery_ui",
|
"librecovery_ui",
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ static bool ReadPartitionToBuffer(const Partition& partition, FileContents* out,
|
|||||||
}
|
}
|
||||||
|
|
||||||
android::base::unique_fd dev(open(partition.name.c_str(), O_RDONLY));
|
android::base::unique_fd dev(open(partition.name.c_str(), O_RDONLY));
|
||||||
if (!dev) {
|
if (dev == -1) {
|
||||||
PLOG(ERROR) << "Failed to open eMMC partition \"" << partition << "\"";
|
PLOG(ERROR) << "Failed to open eMMC partition \"" << partition << "\"";
|
||||||
} else {
|
} else {
|
||||||
std::vector<unsigned char> buffer(partition.size);
|
std::vector<unsigned char> buffer(partition.size);
|
||||||
|
|||||||
@@ -14,11 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RECOVERY_COMMON_H
|
#pragma once
|
||||||
#define RECOVERY_COMMON_H
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -31,7 +27,6 @@ struct selabel_handle;
|
|||||||
|
|
||||||
extern struct selabel_handle* sehandle;
|
extern struct selabel_handle* sehandle;
|
||||||
extern RecoveryUI* ui;
|
extern RecoveryUI* ui;
|
||||||
extern bool modified_flash;
|
|
||||||
extern bool has_cache;
|
extern bool has_cache;
|
||||||
|
|
||||||
// The current stage, e.g. "1/2".
|
// The current stage, e.g. "1/2".
|
||||||
@@ -40,9 +35,4 @@ extern std::string stage;
|
|||||||
// The reason argument provided in "--reason=".
|
// The reason argument provided in "--reason=".
|
||||||
extern const char* reason;
|
extern const char* reason;
|
||||||
|
|
||||||
void ui_print(const char* format, ...) __printflike(1, 2);
|
|
||||||
|
|
||||||
bool is_ro_debuggable();
|
bool is_ro_debuggable();
|
||||||
|
|
||||||
bool SetUsbConfig(const std::string& state);
|
|
||||||
#endif // RECOVERY_COMMON_H
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
#include <android-base/unique_fd.h>
|
#include <android-base/unique_fd.h>
|
||||||
#include <fstab/fstab.h>
|
#include <fstab/fstab.h>
|
||||||
|
|
||||||
#include "roots.h"
|
#include "otautil/roots.h"
|
||||||
|
|
||||||
static constexpr const char* SYSTEM_E2FSCK_BIN = "/system/bin/e2fsck_static";
|
static constexpr const char* SYSTEM_E2FSCK_BIN = "/system/bin/e2fsck_static";
|
||||||
static constexpr const char* TMP_E2FSCK_BIN = "/tmp/e2fsck.bin";
|
static constexpr const char* TMP_E2FSCK_BIN = "/tmp/e2fsck.bin";
|
||||||
|
|||||||
@@ -392,7 +392,7 @@ int run_fuse_sideload(std::unique_ptr<FuseDataProvider>&& provider, const char*
|
|||||||
}
|
}
|
||||||
|
|
||||||
fd.ffd.reset(open("/dev/fuse", O_RDWR));
|
fd.ffd.reset(open("/dev/fuse", O_RDWR));
|
||||||
if (!fd.ffd) {
|
if (fd.ffd == -1) {
|
||||||
perror("open /dev/fuse");
|
perror("open /dev/fuse");
|
||||||
result = -1;
|
result = -1;
|
||||||
goto done;
|
goto done;
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
// Copyright (C) 2019 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
cc_defaults {
|
||||||
|
name: "libinstall_defaults",
|
||||||
|
|
||||||
|
defaults: [
|
||||||
|
"recovery_defaults",
|
||||||
|
],
|
||||||
|
|
||||||
|
shared_libs: [
|
||||||
|
"libbase",
|
||||||
|
"libbootloader_message",
|
||||||
|
"libcrypto",
|
||||||
|
"libext4_utils",
|
||||||
|
"libfs_mgr",
|
||||||
|
"libfusesideload",
|
||||||
|
"libhidl-gen-utils",
|
||||||
|
"libhidlbase",
|
||||||
|
"libhidltransport",
|
||||||
|
"liblog",
|
||||||
|
"libselinux",
|
||||||
|
"libtinyxml2",
|
||||||
|
"libutils",
|
||||||
|
"libz",
|
||||||
|
"libziparchive",
|
||||||
|
],
|
||||||
|
|
||||||
|
static_libs: [
|
||||||
|
"libotautil",
|
||||||
|
|
||||||
|
// external dependencies
|
||||||
|
"libvintf_recovery",
|
||||||
|
"libvintf",
|
||||||
|
"libfstab",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library {
|
||||||
|
name: "libinstall",
|
||||||
|
recovery_available: true,
|
||||||
|
|
||||||
|
defaults: [
|
||||||
|
"libinstall_defaults",
|
||||||
|
],
|
||||||
|
|
||||||
|
srcs: [
|
||||||
|
"adb_install.cpp",
|
||||||
|
"asn1_decoder.cpp",
|
||||||
|
"fuse_sdcard_install.cpp",
|
||||||
|
"install.cpp",
|
||||||
|
"package.cpp",
|
||||||
|
"verifier.cpp",
|
||||||
|
],
|
||||||
|
|
||||||
|
shared_libs: [
|
||||||
|
"librecovery_ui",
|
||||||
|
],
|
||||||
|
|
||||||
|
export_include_dirs: [
|
||||||
|
"include",
|
||||||
|
],
|
||||||
|
|
||||||
|
export_shared_lib_headers: [
|
||||||
|
"librecovery_ui",
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "adb_install.h"
|
#include "install/adb_install.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -29,12 +29,16 @@
|
|||||||
#include <android-base/logging.h>
|
#include <android-base/logging.h>
|
||||||
#include <android-base/properties.h>
|
#include <android-base/properties.h>
|
||||||
|
|
||||||
#include "common.h"
|
|
||||||
#include "fuse_sideload.h"
|
#include "fuse_sideload.h"
|
||||||
#include "install.h"
|
#include "install/install.h"
|
||||||
#include "recovery_ui/ui.h"
|
#include "recovery_ui/ui.h"
|
||||||
|
|
||||||
int apply_from_adb(bool* wipe_cache) {
|
static bool SetUsbConfig(const std::string& state) {
|
||||||
|
android::base::SetProperty("sys.usb.config", state);
|
||||||
|
return android::base::WaitForProperty("sys.usb.state", state);
|
||||||
|
}
|
||||||
|
|
||||||
|
int apply_from_adb(bool* wipe_cache, RecoveryUI* ui) {
|
||||||
// Save the usb state to restore after the sideload operation.
|
// Save the usb state to restore after the sideload operation.
|
||||||
std::string usb_state = android::base::GetProperty("sys.usb.state", "none");
|
std::string usb_state = android::base::GetProperty("sys.usb.state", "none");
|
||||||
// Clean up state and stop adbd.
|
// Clean up state and stop adbd.
|
||||||
@@ -85,7 +89,7 @@ int apply_from_adb(bool* wipe_cache) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, false, 0);
|
result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, false, 0, ui);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,9 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "asn1_decoder.h"
|
#include "private/asn1_decoder.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
int asn1_context::peek_byte() const {
|
int asn1_context::peek_byte() const {
|
||||||
if (length_ == 0) {
|
if (length_ == 0) {
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fuse_sdcard_install.h"
|
#include "install/fuse_sdcard_install.h"
|
||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -35,8 +35,8 @@
|
|||||||
#include "bootloader_message/bootloader_message.h"
|
#include "bootloader_message/bootloader_message.h"
|
||||||
#include "fuse_provider.h"
|
#include "fuse_provider.h"
|
||||||
#include "fuse_sideload.h"
|
#include "fuse_sideload.h"
|
||||||
#include "install.h"
|
#include "install/install.h"
|
||||||
#include "roots.h"
|
#include "otautil/roots.h"
|
||||||
|
|
||||||
static constexpr const char* SDCARD_ROOT = "/sdcard";
|
static constexpr const char* SDCARD_ROOT = "/sdcard";
|
||||||
// How long (in seconds) we wait for the fuse-provided package file to
|
// How long (in seconds) we wait for the fuse-provided package file to
|
||||||
@@ -184,7 +184,7 @@ int ApplyFromSdcard(Device* device, bool* wipe_cache, RecoveryUI* ui) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, false, 0 /*retry_count*/);
|
result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, false, 0 /*retry_count*/, ui);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,9 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _ADB_INSTALL_H
|
#pragma once
|
||||||
#define _ADB_INSTALL_H
|
|
||||||
|
|
||||||
int apply_from_adb(bool* wipe_cache);
|
#include <recovery_ui/ui.h>
|
||||||
|
|
||||||
#endif
|
int apply_from_adb(bool* wipe_cache, RecoveryUI* ui);
|
||||||
@@ -14,8 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RECOVERY_INSTALL_H_
|
#pragma once
|
||||||
#define RECOVERY_INSTALL_H_
|
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
@@ -26,6 +25,7 @@
|
|||||||
#include <ziparchive/zip_archive.h>
|
#include <ziparchive/zip_archive.h>
|
||||||
|
|
||||||
#include "package.h"
|
#include "package.h"
|
||||||
|
#include "recovery_ui/ui.h"
|
||||||
|
|
||||||
enum InstallResult {
|
enum InstallResult {
|
||||||
INSTALL_SUCCESS,
|
INSTALL_SUCCESS,
|
||||||
@@ -45,12 +45,12 @@ enum class OtaType {
|
|||||||
|
|
||||||
// Installs the given update package. If INSTALL_SUCCESS is returned and *wipe_cache is true on
|
// Installs the given update package. If INSTALL_SUCCESS is returned and *wipe_cache is true on
|
||||||
// exit, caller should wipe the cache partition.
|
// exit, caller should wipe the cache partition.
|
||||||
int install_package(const std::string& package, bool* wipe_cache, bool needs_mount,
|
int install_package(const std::string& package, bool* wipe_cache, bool needs_mount, int retry_count,
|
||||||
int retry_count);
|
RecoveryUI* ui);
|
||||||
|
|
||||||
// Verifies the package by ota keys. Returns true if the package is verified successfully,
|
// Verifies the package by ota keys. Returns true if the package is verified successfully,
|
||||||
// otherwise returns false.
|
// otherwise returns false.
|
||||||
bool verify_package(Package* package);
|
bool verify_package(Package* package, RecoveryUI* ui);
|
||||||
|
|
||||||
// Reads meta data file of the package; parses each line in the format "key=value"; and writes the
|
// Reads meta data file of the package; parses each line in the format "key=value"; and writes the
|
||||||
// result to |metadata|. Return true if succeed, otherwise return false.
|
// result to |metadata|. Return true if succeed, otherwise return false.
|
||||||
@@ -67,5 +67,3 @@ bool verify_package_compatibility(ZipArchiveHandle package_zip);
|
|||||||
// Mandatory checks: ota-type, pre-device and serial number(if presents)
|
// Mandatory checks: ota-type, pre-device and serial number(if presents)
|
||||||
// AB OTA specific checks: pre-build version, fingerprint, timestamp.
|
// AB OTA specific checks: pre-build version, fingerprint, timestamp.
|
||||||
int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type);
|
int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type);
|
||||||
|
|
||||||
#endif // RECOVERY_INSTALL_H_
|
|
||||||
@@ -14,8 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _RECOVERY_VERIFIER_H
|
#pragma once
|
||||||
#define _RECOVERY_VERIFIER_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -44,25 +43,20 @@ struct ECKEYDeleter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Certificate {
|
struct Certificate {
|
||||||
typedef enum {
|
typedef enum {
|
||||||
KEY_TYPE_RSA,
|
KEY_TYPE_RSA,
|
||||||
KEY_TYPE_EC,
|
KEY_TYPE_EC,
|
||||||
} KeyType;
|
} KeyType;
|
||||||
|
|
||||||
Certificate(int hash_len_,
|
Certificate(int hash_len_, KeyType key_type_, std::unique_ptr<RSA, RSADeleter>&& rsa_,
|
||||||
KeyType key_type_,
|
std::unique_ptr<EC_KEY, ECKEYDeleter>&& ec_)
|
||||||
std::unique_ptr<RSA, RSADeleter>&& rsa_,
|
: hash_len(hash_len_), key_type(key_type_), rsa(std::move(rsa_)), ec(std::move(ec_)) {}
|
||||||
std::unique_ptr<EC_KEY, ECKEYDeleter>&& ec_)
|
|
||||||
: hash_len(hash_len_),
|
|
||||||
key_type(key_type_),
|
|
||||||
rsa(std::move(rsa_)),
|
|
||||||
ec(std::move(ec_)) {}
|
|
||||||
|
|
||||||
// SHA_DIGEST_LENGTH (SHA-1) or SHA256_DIGEST_LENGTH (SHA-256)
|
// SHA_DIGEST_LENGTH (SHA-1) or SHA256_DIGEST_LENGTH (SHA-256)
|
||||||
int hash_len;
|
int hash_len;
|
||||||
KeyType key_type;
|
KeyType key_type;
|
||||||
std::unique_ptr<RSA, RSADeleter> rsa;
|
std::unique_ptr<RSA, RSADeleter> rsa;
|
||||||
std::unique_ptr<EC_KEY, ECKEYDeleter> ec;
|
std::unique_ptr<EC_KEY, ECKEYDeleter> ec;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VerifierInterface {
|
class VerifierInterface {
|
||||||
@@ -88,7 +82,8 @@ class VerifierInterface {
|
|||||||
// VERIFY_FAILURE (if any error is encountered or no key matches the signature).
|
// VERIFY_FAILURE (if any error is encountered or no key matches the signature).
|
||||||
int verify_file(VerifierInterface* package, const std::vector<Certificate>& keys);
|
int verify_file(VerifierInterface* package, const std::vector<Certificate>& keys);
|
||||||
|
|
||||||
// Checks that the RSA key has a modulus of 2048 bits long, and public exponent is 3 or 65537.
|
// Checks that the RSA key has a modulus of 2048 or 4096 bits long, and public exponent is 3 or
|
||||||
|
// 65537.
|
||||||
bool CheckRSAKey(const std::unique_ptr<RSA, RSADeleter>& rsa);
|
bool CheckRSAKey(const std::unique_ptr<RSA, RSADeleter>& rsa);
|
||||||
|
|
||||||
// Checks that the field size of the curve for the EC key is 256 bits.
|
// Checks that the field size of the curve for the EC key is 256 bits.
|
||||||
@@ -102,7 +97,5 @@ bool LoadCertificateFromBuffer(const std::vector<uint8_t>& pem_content, Certific
|
|||||||
// certificates. Returns an empty list if we fail to parse any of the entries.
|
// certificates. Returns an empty list if we fail to parse any of the entries.
|
||||||
std::vector<Certificate> LoadKeysFromZipfile(const std::string& zip_name);
|
std::vector<Certificate> LoadKeysFromZipfile(const std::string& zip_name);
|
||||||
|
|
||||||
#define VERIFY_SUCCESS 0
|
#define VERIFY_SUCCESS 0
|
||||||
#define VERIFY_FAILURE 1
|
#define VERIFY_FAILURE 1
|
||||||
|
|
||||||
#endif /* _RECOVERY_VERIFIER_H */
|
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
#ifndef ASN1_DECODER_H_
|
#ifndef ASN1_DECODER_H_
|
||||||
#define ASN1_DECODER_H_
|
#define ASN1_DECODER_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
class asn1_context {
|
class asn1_context {
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "install.h"
|
#include "install/install.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -46,19 +46,22 @@
|
|||||||
#include <android-base/unique_fd.h>
|
#include <android-base/unique_fd.h>
|
||||||
#include <vintf/VintfObjectRecovery.h>
|
#include <vintf/VintfObjectRecovery.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "install/package.h"
|
||||||
|
#include "install/verifier.h"
|
||||||
#include "otautil/error_code.h"
|
#include "otautil/error_code.h"
|
||||||
#include "otautil/paths.h"
|
#include "otautil/paths.h"
|
||||||
|
#include "otautil/roots.h"
|
||||||
#include "otautil/sysutil.h"
|
#include "otautil/sysutil.h"
|
||||||
#include "otautil/thermalutil.h"
|
#include "otautil/thermalutil.h"
|
||||||
#include "package.h"
|
#include "private/setup_commands.h"
|
||||||
#include "private/install.h"
|
|
||||||
#include "recovery_ui/ui.h"
|
#include "recovery_ui/ui.h"
|
||||||
#include "roots.h"
|
|
||||||
#include "verifier.h"
|
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
static constexpr int kRecoveryApiVersion = 3;
|
||||||
|
// Assert the version defined in code and in Android.mk are consistent.
|
||||||
|
static_assert(kRecoveryApiVersion == RECOVERY_API_VERSION, "Mismatching recovery API versions.");
|
||||||
|
|
||||||
// Default allocation of progress bar segments to operations
|
// Default allocation of progress bar segments to operations
|
||||||
static constexpr int VERIFICATION_PROGRESS_TIME = 60;
|
static constexpr int VERIFICATION_PROGRESS_TIME = 60;
|
||||||
static constexpr float VERIFICATION_PROGRESS_FRACTION = 0.25;
|
static constexpr float VERIFICATION_PROGRESS_FRACTION = 0.25;
|
||||||
@@ -323,7 +326,7 @@ static void log_max_temperature(int* max_temperature, const std::atomic<bool>& l
|
|||||||
// If the package contains an update binary, extract it and run it.
|
// If the package contains an update binary, extract it and run it.
|
||||||
static int try_update_binary(const std::string& package, ZipArchiveHandle zip, bool* wipe_cache,
|
static int try_update_binary(const std::string& package, ZipArchiveHandle zip, bool* wipe_cache,
|
||||||
std::vector<std::string>* log_buffer, int retry_count,
|
std::vector<std::string>* log_buffer, int retry_count,
|
||||||
int* max_temperature) {
|
int* max_temperature, RecoveryUI* ui) {
|
||||||
std::map<std::string, std::string> metadata;
|
std::map<std::string, std::string> metadata;
|
||||||
if (!ReadMetadataFromPackage(zip, &metadata)) {
|
if (!ReadMetadataFromPackage(zip, &metadata)) {
|
||||||
LOG(ERROR) << "Failed to parse metadata in the zip file";
|
LOG(ERROR) << "Failed to parse metadata in the zip file";
|
||||||
@@ -342,7 +345,9 @@ static int try_update_binary(const std::string& package, ZipArchiveHandle zip, b
|
|||||||
|
|
||||||
// The updater in child process writes to the pipe to communicate with recovery.
|
// The updater in child process writes to the pipe to communicate with recovery.
|
||||||
android::base::unique_fd pipe_read, pipe_write;
|
android::base::unique_fd pipe_read, pipe_write;
|
||||||
if (!android::base::Pipe(&pipe_read, &pipe_write)) {
|
// Explicitly disable O_CLOEXEC using 0 as the flags (last) parameter to Pipe
|
||||||
|
// so that the child updater process will recieve a non-closed fd.
|
||||||
|
if (!android::base::Pipe(&pipe_read, &pipe_write, 0)) {
|
||||||
PLOG(ERROR) << "Failed to create pipe for updater-recovery communication";
|
PLOG(ERROR) << "Failed to create pipe for updater-recovery communication";
|
||||||
return INSTALL_CORRUPT;
|
return INSTALL_CORRUPT;
|
||||||
}
|
}
|
||||||
@@ -567,7 +572,7 @@ bool verify_package_compatibility(ZipArchiveHandle package_zip) {
|
|||||||
|
|
||||||
static int really_install_package(const std::string& path, bool* wipe_cache, bool needs_mount,
|
static int really_install_package(const std::string& path, bool* wipe_cache, bool needs_mount,
|
||||||
std::vector<std::string>* log_buffer, int retry_count,
|
std::vector<std::string>* log_buffer, int retry_count,
|
||||||
int* max_temperature) {
|
int* max_temperature, RecoveryUI* ui) {
|
||||||
ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
|
ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
|
||||||
ui->Print("Finding update package...\n");
|
ui->Print("Finding update package...\n");
|
||||||
// Give verification half the progress bar...
|
// Give verification half the progress bar...
|
||||||
@@ -594,7 +599,7 @@ static int really_install_package(const std::string& path, bool* wipe_cache, boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify package.
|
// Verify package.
|
||||||
if (!verify_package(package.get())) {
|
if (!verify_package(package.get(), ui)) {
|
||||||
log_buffer->push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
|
log_buffer->push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
|
||||||
return INSTALL_CORRUPT;
|
return INSTALL_CORRUPT;
|
||||||
}
|
}
|
||||||
@@ -618,18 +623,19 @@ static int really_install_package(const std::string& path, bool* wipe_cache, boo
|
|||||||
ui->Print("Retry attempt: %d\n", retry_count);
|
ui->Print("Retry attempt: %d\n", retry_count);
|
||||||
}
|
}
|
||||||
ui->SetEnableReboot(false);
|
ui->SetEnableReboot(false);
|
||||||
int result = try_update_binary(path, zip, wipe_cache, log_buffer, retry_count, max_temperature);
|
int result =
|
||||||
|
try_update_binary(path, zip, wipe_cache, log_buffer, retry_count, max_temperature, ui);
|
||||||
ui->SetEnableReboot(true);
|
ui->SetEnableReboot(true);
|
||||||
ui->Print("\n");
|
ui->Print("\n");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int install_package(const std::string& path, bool* wipe_cache, bool needs_mount, int retry_count) {
|
int install_package(const std::string& path, bool* wipe_cache, bool needs_mount, int retry_count,
|
||||||
|
RecoveryUI* ui) {
|
||||||
CHECK(!path.empty());
|
CHECK(!path.empty());
|
||||||
CHECK(wipe_cache != nullptr);
|
CHECK(wipe_cache != nullptr);
|
||||||
|
|
||||||
modified_flash = true;
|
|
||||||
auto start = std::chrono::system_clock::now();
|
auto start = std::chrono::system_clock::now();
|
||||||
|
|
||||||
int start_temperature = GetMaxValueFromThermalZone();
|
int start_temperature = GetMaxValueFromThermalZone();
|
||||||
@@ -642,7 +648,7 @@ int install_package(const std::string& path, bool* wipe_cache, bool needs_mount,
|
|||||||
result = INSTALL_ERROR;
|
result = INSTALL_ERROR;
|
||||||
} else {
|
} else {
|
||||||
result = really_install_package(path, wipe_cache, needs_mount, &log_buffer, retry_count,
|
result = really_install_package(path, wipe_cache, needs_mount, &log_buffer, retry_count,
|
||||||
&max_temperature);
|
&max_temperature, ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Measure the time spent to apply OTA update in seconds.
|
// Measure the time spent to apply OTA update in seconds.
|
||||||
@@ -700,7 +706,7 @@ int install_package(const std::string& path, bool* wipe_cache, bool needs_mount,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool verify_package(Package* package) {
|
bool verify_package(Package* package, RecoveryUI* ui) {
|
||||||
static constexpr const char* CERTIFICATE_ZIP_FILE = "/system/etc/security/otacerts.zip";
|
static constexpr const char* CERTIFICATE_ZIP_FILE = "/system/etc/security/otacerts.zip";
|
||||||
std::vector<Certificate> loaded_keys = LoadKeysFromZipfile(CERTIFICATE_ZIP_FILE);
|
std::vector<Certificate> loaded_keys = LoadKeysFromZipfile(CERTIFICATE_ZIP_FILE);
|
||||||
if (loaded_keys.empty()) {
|
if (loaded_keys.empty()) {
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "package.h"
|
#include "install/package.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "verifier.h"
|
#include "install/verifier.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -36,8 +36,8 @@
|
|||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <ziparchive/zip_archive.h>
|
#include <ziparchive/zip_archive.h>
|
||||||
|
|
||||||
#include "asn1_decoder.h"
|
|
||||||
#include "otautil/print_sha1.h"
|
#include "otautil/print_sha1.h"
|
||||||
|
#include "private/asn1_decoder.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Simple version of PKCS#7 SignedData extraction. This extracts the
|
* Simple version of PKCS#7 SignedData extraction. This extracts the
|
||||||
@@ -82,10 +82,8 @@ static bool read_pkcs7(const uint8_t* pkcs7_der, size_t pkcs7_der_len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<asn1_context> signed_data_seq(signed_data_app->asn1_sequence_get());
|
std::unique_ptr<asn1_context> signed_data_seq(signed_data_app->asn1_sequence_get());
|
||||||
if (signed_data_seq == nullptr ||
|
if (signed_data_seq == nullptr || !signed_data_seq->asn1_sequence_next() ||
|
||||||
!signed_data_seq->asn1_sequence_next() ||
|
!signed_data_seq->asn1_sequence_next() || !signed_data_seq->asn1_sequence_next() ||
|
||||||
!signed_data_seq->asn1_sequence_next() ||
|
|
||||||
!signed_data_seq->asn1_sequence_next() ||
|
|
||||||
!signed_data_seq->asn1_constructed_skip_all()) {
|
!signed_data_seq->asn1_constructed_skip_all()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -96,11 +94,8 @@ static bool read_pkcs7(const uint8_t* pkcs7_der, size_t pkcs7_der_len,
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<asn1_context> sig_seq(sig_set->asn1_sequence_get());
|
std::unique_ptr<asn1_context> sig_seq(sig_set->asn1_sequence_get());
|
||||||
if (sig_seq == nullptr ||
|
if (sig_seq == nullptr || !sig_seq->asn1_sequence_next() || !sig_seq->asn1_sequence_next() ||
|
||||||
!sig_seq->asn1_sequence_next() ||
|
!sig_seq->asn1_sequence_next() || !sig_seq->asn1_sequence_next()) {
|
||||||
!sig_seq->asn1_sequence_next() ||
|
|
||||||
!sig_seq->asn1_sequence_next() ||
|
|
||||||
!sig_seq->asn1_sequence_next()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,8 +147,8 @@ int verify_file(VerifierInterface* package, const std::vector<Certificate>& keys
|
|||||||
<< " bytes from end";
|
<< " bytes from end";
|
||||||
|
|
||||||
if (signature_start > comment_size) {
|
if (signature_start > comment_size) {
|
||||||
LOG(ERROR) << "signature start: " << signature_start << " is larger than comment size: "
|
LOG(ERROR) << "signature start: " << signature_start
|
||||||
<< comment_size;
|
<< " is larger than comment size: " << comment_size;
|
||||||
return VERIFY_FAILURE;
|
return VERIFY_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,8 +184,8 @@ int verify_file(VerifierInterface* package, const std::vector<Certificate>& keys
|
|||||||
return VERIFY_FAILURE;
|
return VERIFY_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 4; i < eocd_size-3; ++i) {
|
for (size_t i = 4; i < eocd_size - 3; ++i) {
|
||||||
if (eocd[i] == 0x50 && eocd[i+1] == 0x4b && eocd[i+2] == 0x05 && eocd[i+3] == 0x06) {
|
if (eocd[i] == 0x50 && eocd[i + 1] == 0x4b && eocd[i + 2] == 0x05 && eocd[i + 3] == 0x06) {
|
||||||
// If the sequence $50 $4b $05 $06 appears anywhere after the real one, libziparchive will
|
// If the sequence $50 $4b $05 $06 appears anywhere after the real one, libziparchive will
|
||||||
// find the later (wrong) one, which could be exploitable. Fail the verification if this
|
// find the later (wrong) one, which could be exploitable. Fail the verification if this
|
||||||
// sequence occurs anywhere after the real one.
|
// sequence occurs anywhere after the real one.
|
||||||
@@ -203,8 +198,12 @@ int verify_file(VerifierInterface* package, const std::vector<Certificate>& keys
|
|||||||
bool need_sha256 = false;
|
bool need_sha256 = false;
|
||||||
for (const auto& key : keys) {
|
for (const auto& key : keys) {
|
||||||
switch (key.hash_len) {
|
switch (key.hash_len) {
|
||||||
case SHA_DIGEST_LENGTH: need_sha1 = true; break;
|
case SHA_DIGEST_LENGTH:
|
||||||
case SHA256_DIGEST_LENGTH: need_sha256 = true; break;
|
need_sha1 = true;
|
||||||
|
break;
|
||||||
|
case SHA256_DIGEST_LENGTH:
|
||||||
|
need_sha256 = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,8 +246,8 @@ int verify_file(VerifierInterface* package, const std::vector<Certificate>& keys
|
|||||||
const uint8_t* signature = eocd + eocd_size - signature_start;
|
const uint8_t* signature = eocd + eocd_size - signature_start;
|
||||||
size_t signature_size = signature_start - FOOTER_SIZE;
|
size_t signature_size = signature_start - FOOTER_SIZE;
|
||||||
|
|
||||||
LOG(INFO) << "signature (offset: " << std::hex << (length - signature_start) << ", length: "
|
LOG(INFO) << "signature (offset: " << std::hex << (length - signature_start)
|
||||||
<< signature_size << "): " << print_hex(signature, signature_size);
|
<< ", length: " << signature_size << "): " << print_hex(signature, signature_size);
|
||||||
|
|
||||||
std::vector<uint8_t> sig_der;
|
std::vector<uint8_t> sig_der;
|
||||||
if (!read_pkcs7(signature, signature_size, &sig_der)) {
|
if (!read_pkcs7(signature, signature_size, &sig_der)) {
|
||||||
@@ -373,8 +372,8 @@ bool CheckRSAKey(const std::unique_ptr<RSA, RSADeleter>& rsa) {
|
|||||||
const BIGNUM* out_e;
|
const BIGNUM* out_e;
|
||||||
RSA_get0_key(rsa.get(), &out_n, &out_e, nullptr /* private exponent */);
|
RSA_get0_key(rsa.get(), &out_n, &out_e, nullptr /* private exponent */);
|
||||||
auto modulus_bits = BN_num_bits(out_n);
|
auto modulus_bits = BN_num_bits(out_n);
|
||||||
if (modulus_bits != 2048) {
|
if (modulus_bits != 2048 && modulus_bits != 4096) {
|
||||||
LOG(ERROR) << "Modulus should be 2048 bits long, actual: " << modulus_bits;
|
LOG(ERROR) << "Modulus should be 2048 or 4096 bits long, actual: " << modulus_bits;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
+1
-1
@@ -33,7 +33,7 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "otautil/dirutil.h"
|
#include "otautil/dirutil.h"
|
||||||
#include "otautil/paths.h"
|
#include "otautil/paths.h"
|
||||||
#include "roots.h"
|
#include "otautil/roots.h"
|
||||||
|
|
||||||
static constexpr const char* LOG_FILE = "/cache/recovery/log";
|
static constexpr const char* LOG_FILE = "/cache/recovery/log";
|
||||||
static constexpr const char* LAST_INSTALL_FILE = "/cache/recovery/last_install";
|
static constexpr const char* LAST_INSTALL_FILE = "/cache/recovery/last_install";
|
||||||
|
|||||||
@@ -42,12 +42,23 @@ cc_library_static {
|
|||||||
"dirutil.cpp",
|
"dirutil.cpp",
|
||||||
"mounts.cpp",
|
"mounts.cpp",
|
||||||
"parse_install_logs.cpp",
|
"parse_install_logs.cpp",
|
||||||
|
"roots.cpp",
|
||||||
"sysutil.cpp",
|
"sysutil.cpp",
|
||||||
"thermalutil.cpp",
|
"thermalutil.cpp",
|
||||||
],
|
],
|
||||||
|
|
||||||
|
include_dirs: [
|
||||||
|
"system/vold",
|
||||||
|
],
|
||||||
|
|
||||||
|
static_libs: [
|
||||||
|
"libfstab",
|
||||||
|
],
|
||||||
|
|
||||||
shared_libs: [
|
shared_libs: [
|
||||||
"libcutils",
|
"libcutils",
|
||||||
|
"libext4_utils",
|
||||||
|
"libfs_mgr",
|
||||||
"libselinux",
|
"libselinux",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,8 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef RECOVERY_ROOTS_H_
|
#pragma once
|
||||||
#define RECOVERY_ROOTS_H_
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -58,5 +57,3 @@ int setup_install_mounts();
|
|||||||
bool logical_partitions_mapped();
|
bool logical_partitions_mapped();
|
||||||
|
|
||||||
std::string get_system_root();
|
std::string get_system_root();
|
||||||
|
|
||||||
#endif // RECOVERY_ROOTS_H_
|
|
||||||
@@ -22,6 +22,57 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "rangeset.h"
|
||||||
|
|
||||||
|
// This class holds the content of a block map file.
|
||||||
|
class BlockMapData {
|
||||||
|
public:
|
||||||
|
// A "block map" which looks like this (from uncrypt/uncrypt.cpp):
|
||||||
|
//
|
||||||
|
// /dev/block/platform/msm_sdcc.1/by-name/userdata # block device
|
||||||
|
// 49652 4096 # file size in bytes, block size
|
||||||
|
// 3 # count of block ranges
|
||||||
|
// 1000 1008 # block range 0
|
||||||
|
// 2100 2102 # ... block range 1
|
||||||
|
// 30 33 # ... block range 2
|
||||||
|
//
|
||||||
|
// Each block range represents a half-open interval; the line "30 33" reprents the blocks
|
||||||
|
// [30, 31, 32].
|
||||||
|
static BlockMapData ParseBlockMapFile(const std::string& block_map_path);
|
||||||
|
|
||||||
|
explicit operator bool() const {
|
||||||
|
return !path_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string path() const {
|
||||||
|
return path_;
|
||||||
|
}
|
||||||
|
uint64_t file_size() const {
|
||||||
|
return file_size_;
|
||||||
|
}
|
||||||
|
uint32_t block_size() const {
|
||||||
|
return block_size_;
|
||||||
|
}
|
||||||
|
RangeSet block_ranges() const {
|
||||||
|
return block_ranges_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BlockMapData() = default;
|
||||||
|
|
||||||
|
BlockMapData(const std::string& path, uint64_t file_size, uint32_t block_size,
|
||||||
|
RangeSet block_ranges)
|
||||||
|
: path_(path),
|
||||||
|
file_size_(file_size),
|
||||||
|
block_size_(block_size),
|
||||||
|
block_ranges_(std::move(block_ranges)) {}
|
||||||
|
|
||||||
|
std::string path_;
|
||||||
|
uint64_t file_size_ = 0;
|
||||||
|
uint32_t block_size_ = 0;
|
||||||
|
RangeSet block_ranges_;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use this to keep track of mapped segments.
|
* Use this to keep track of mapped segments.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "roots.h"
|
#include "otautil/roots.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -51,8 +51,6 @@ using android::fs_mgr::ReadDefaultFstab;
|
|||||||
|
|
||||||
static Fstab fstab;
|
static Fstab fstab;
|
||||||
|
|
||||||
extern struct selabel_handle* sehandle;
|
|
||||||
|
|
||||||
void load_volume_table() {
|
void load_volume_table() {
|
||||||
if (!ReadDefaultFstab(&fstab)) {
|
if (!ReadDefaultFstab(&fstab)) {
|
||||||
LOG(ERROR) << "Failed to read default fstab";
|
LOG(ERROR) << "Failed to read default fstab";
|
||||||
@@ -176,11 +174,9 @@ int format_volume(const std::string& volume, const std::string& directory) {
|
|||||||
PLOG(ERROR) << "format_volume: failed to open " << v->blk_device;
|
PLOG(ERROR) << "format_volume: failed to open " << v->blk_device;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
length =
|
length = get_file_size(fd.get(), v->length ? -v->length : CRYPT_FOOTER_OFFSET);
|
||||||
get_file_size(fd.get(), v->length ? -v->length : CRYPT_FOOTER_OFFSET);
|
|
||||||
if (length <= 0) {
|
if (length <= 0) {
|
||||||
LOG(ERROR) << "get_file_size: invalid size " << length << " for "
|
LOG(ERROR) << "get_file_size: invalid size " << length << " for " << v->blk_device;
|
||||||
<< v->blk_device;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+80
-71
@@ -18,12 +18,13 @@
|
|||||||
|
|
||||||
#include <errno.h> // TEMP_FAILURE_RETRY
|
#include <errno.h> // TEMP_FAILURE_RETRY
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdint.h> // SIZE_MAX
|
#include <inttypes.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -34,6 +35,68 @@
|
|||||||
#include <android-base/unique_fd.h>
|
#include <android-base/unique_fd.h>
|
||||||
#include <cutils/android_reboot.h>
|
#include <cutils/android_reboot.h>
|
||||||
|
|
||||||
|
BlockMapData BlockMapData::ParseBlockMapFile(const std::string& block_map_path) {
|
||||||
|
std::string content;
|
||||||
|
if (!android::base::ReadFileToString(block_map_path, &content)) {
|
||||||
|
LOG(ERROR) << "Failed to read " << block_map_path;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> lines = android::base::Split(android::base::Trim(content), "\n");
|
||||||
|
if (lines.size() < 4) {
|
||||||
|
LOG(ERROR) << "Block map file is too short: " << lines.size();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& block_dev = lines[0];
|
||||||
|
|
||||||
|
uint64_t file_size;
|
||||||
|
uint32_t blksize;
|
||||||
|
if (sscanf(lines[1].c_str(), "%" SCNu64 "%" SCNu32, &file_size, &blksize) != 2) {
|
||||||
|
LOG(ERROR) << "Failed to parse file size and block size: " << lines[1];
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_size == 0 || blksize == 0) {
|
||||||
|
LOG(ERROR) << "Invalid size in block map file: size " << file_size << ", blksize " << blksize;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t range_count;
|
||||||
|
if (sscanf(lines[2].c_str(), "%zu", &range_count) != 1) {
|
||||||
|
LOG(ERROR) << "Failed to parse block map header: " << lines[2];
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t blocks = ((file_size - 1) / blksize) + 1;
|
||||||
|
if (blocks > std::numeric_limits<uint32_t>::max() || range_count == 0 ||
|
||||||
|
lines.size() != 3 + range_count) {
|
||||||
|
LOG(ERROR) << "Invalid data in block map file: size " << file_size << ", blksize " << blksize
|
||||||
|
<< ", range_count " << range_count << ", lines " << lines.size();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
RangeSet ranges;
|
||||||
|
uint64_t remaining_blocks = blocks;
|
||||||
|
for (size_t i = 0; i < range_count; ++i) {
|
||||||
|
const std::string& line = lines[i + 3];
|
||||||
|
uint64_t start, end;
|
||||||
|
if (sscanf(line.c_str(), "%" SCNu64 "%" SCNu64, &start, &end) != 2) {
|
||||||
|
LOG(ERROR) << "failed to parse range " << i << ": " << line;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
uint64_t range_blocks = end - start;
|
||||||
|
if (end <= start || range_blocks > remaining_blocks) {
|
||||||
|
LOG(ERROR) << "Invalid range: " << start << " " << end;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
ranges.PushBack({ start, end });
|
||||||
|
remaining_blocks -= range_blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BlockMapData(block_dev, file_size, blksize, std::move(ranges));
|
||||||
|
}
|
||||||
|
|
||||||
bool MemMapping::MapFD(int fd) {
|
bool MemMapping::MapFD(int fd) {
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
if (fstat(fd, &sb) == -1) {
|
if (fstat(fd, &sb) == -1) {
|
||||||
@@ -55,115 +118,61 @@ bool MemMapping::MapFD(int fd) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A "block map" which looks like this (from uncrypt/uncrypt.cpp):
|
|
||||||
//
|
|
||||||
// /dev/block/platform/msm_sdcc.1/by-name/userdata # block device
|
|
||||||
// 49652 4096 # file size in bytes, block size
|
|
||||||
// 3 # count of block ranges
|
|
||||||
// 1000 1008 # block range 0
|
|
||||||
// 2100 2102 # ... block range 1
|
|
||||||
// 30 33 # ... block range 2
|
|
||||||
//
|
|
||||||
// Each block range represents a half-open interval; the line "30 33" reprents the blocks
|
|
||||||
// [30, 31, 32].
|
|
||||||
bool MemMapping::MapBlockFile(const std::string& filename) {
|
bool MemMapping::MapBlockFile(const std::string& filename) {
|
||||||
std::string content;
|
auto block_map_data = BlockMapData::ParseBlockMapFile(filename);
|
||||||
if (!android::base::ReadFileToString(filename, &content)) {
|
if (!block_map_data) {
|
||||||
PLOG(ERROR) << "Failed to read " << filename;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> lines = android::base::Split(android::base::Trim(content), "\n");
|
if (block_map_data.file_size() > std::numeric_limits<size_t>::max()) {
|
||||||
if (lines.size() < 4) {
|
LOG(ERROR) << "File size is too large for mmap " << block_map_data.file_size();
|
||||||
LOG(ERROR) << "Block map file is too short: " << lines.size();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size;
|
|
||||||
size_t blksize;
|
|
||||||
if (sscanf(lines[1].c_str(), "%zu %zu", &size, &blksize) != 2) {
|
|
||||||
LOG(ERROR) << "Failed to parse file size and block size: " << lines[1];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t range_count;
|
|
||||||
if (sscanf(lines[2].c_str(), "%zu", &range_count) != 1) {
|
|
||||||
LOG(ERROR) << "Failed to parse block map header: " << lines[2];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t blocks;
|
|
||||||
if (blksize != 0) {
|
|
||||||
blocks = ((size - 1) / blksize) + 1;
|
|
||||||
}
|
|
||||||
if (size == 0 || blksize == 0 || blocks > SIZE_MAX / blksize || range_count == 0 ||
|
|
||||||
lines.size() != 3 + range_count) {
|
|
||||||
LOG(ERROR) << "Invalid data in block map file: size " << size << ", blksize " << blksize
|
|
||||||
<< ", range_count " << range_count << ", lines " << lines.size();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reserve enough contiguous address space for the whole file.
|
// Reserve enough contiguous address space for the whole file.
|
||||||
|
uint32_t blksize = block_map_data.block_size();
|
||||||
|
uint64_t blocks = ((block_map_data.file_size() - 1) / blksize) + 1;
|
||||||
void* reserve = mmap(nullptr, blocks * blksize, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
void* reserve = mmap(nullptr, blocks * blksize, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||||
if (reserve == MAP_FAILED) {
|
if (reserve == MAP_FAILED) {
|
||||||
PLOG(ERROR) << "failed to reserve address space";
|
PLOG(ERROR) << "failed to reserve address space";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& block_dev = lines[0];
|
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(block_map_data.path().c_str(), O_RDONLY)));
|
||||||
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(block_dev.c_str(), O_RDONLY)));
|
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
PLOG(ERROR) << "failed to open block device " << block_dev;
|
PLOG(ERROR) << "failed to open block device " << block_map_data.path();
|
||||||
munmap(reserve, blocks * blksize);
|
munmap(reserve, blocks * blksize);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ranges_.clear();
|
ranges_.clear();
|
||||||
|
|
||||||
unsigned char* next = static_cast<unsigned char*>(reserve);
|
auto next = static_cast<unsigned char*>(reserve);
|
||||||
size_t remaining_size = blocks * blksize;
|
size_t remaining_size = blocks * blksize;
|
||||||
bool success = true;
|
for (const auto& [start, end] : block_map_data.block_ranges()) {
|
||||||
for (size_t i = 0; i < range_count; ++i) {
|
|
||||||
const std::string& line = lines[i + 3];
|
|
||||||
|
|
||||||
size_t start, end;
|
|
||||||
if (sscanf(line.c_str(), "%zu %zu\n", &start, &end) != 2) {
|
|
||||||
LOG(ERROR) << "failed to parse range " << i << ": " << line;
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
size_t range_size = (end - start) * blksize;
|
size_t range_size = (end - start) * blksize;
|
||||||
if (end <= start || (end - start) > SIZE_MAX / blksize || range_size > remaining_size) {
|
|
||||||
LOG(ERROR) << "Invalid range: " << start << " " << end;
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* range_start = mmap(next, range_size, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd,
|
void* range_start = mmap(next, range_size, PROT_READ, MAP_PRIVATE | MAP_FIXED, fd,
|
||||||
static_cast<off_t>(start) * blksize);
|
static_cast<off_t>(start) * blksize);
|
||||||
if (range_start == MAP_FAILED) {
|
if (range_start == MAP_FAILED) {
|
||||||
PLOG(ERROR) << "failed to map range " << i << ": " << line;
|
PLOG(ERROR) << "failed to map range " << start << ": " << end;
|
||||||
success = false;
|
munmap(reserve, blocks * blksize);
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
ranges_.emplace_back(MappedRange{ range_start, range_size });
|
ranges_.emplace_back(MappedRange{ range_start, range_size });
|
||||||
|
|
||||||
next += range_size;
|
next += range_size;
|
||||||
remaining_size -= range_size;
|
remaining_size -= range_size;
|
||||||
}
|
}
|
||||||
if (success && remaining_size != 0) {
|
if (remaining_size != 0) {
|
||||||
LOG(ERROR) << "Invalid ranges: remaining_size " << remaining_size;
|
LOG(ERROR) << "Invalid ranges: remaining_size " << remaining_size;
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
if (!success) {
|
|
||||||
munmap(reserve, blocks * blksize);
|
munmap(reserve, blocks * blksize);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = static_cast<unsigned char*>(reserve);
|
addr = static_cast<unsigned char*>(reserve);
|
||||||
length = size;
|
length = block_map_data.file_size();
|
||||||
|
|
||||||
LOG(INFO) << "mmapped " << range_count << " ranges";
|
LOG(INFO) << "mmapped " << block_map_data.block_ranges().size() << " ranges";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-31
@@ -24,7 +24,6 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -50,20 +49,20 @@
|
|||||||
#include <healthhalutils/HealthHalUtils.h>
|
#include <healthhalutils/HealthHalUtils.h>
|
||||||
#include <ziparchive/zip_archive.h>
|
#include <ziparchive/zip_archive.h>
|
||||||
|
|
||||||
#include "adb_install.h"
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "fsck_unshare_blocks.h"
|
#include "fsck_unshare_blocks.h"
|
||||||
#include "fuse_sdcard_install.h"
|
#include "install/adb_install.h"
|
||||||
#include "install.h"
|
#include "install/fuse_sdcard_install.h"
|
||||||
|
#include "install/install.h"
|
||||||
|
#include "install/package.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "otautil/dirutil.h"
|
#include "otautil/dirutil.h"
|
||||||
#include "otautil/error_code.h"
|
#include "otautil/error_code.h"
|
||||||
#include "otautil/paths.h"
|
#include "otautil/paths.h"
|
||||||
|
#include "otautil/roots.h"
|
||||||
#include "otautil/sysutil.h"
|
#include "otautil/sysutil.h"
|
||||||
#include "package.h"
|
|
||||||
#include "recovery_ui/screen_ui.h"
|
#include "recovery_ui/screen_ui.h"
|
||||||
#include "recovery_ui/ui.h"
|
#include "recovery_ui/ui.h"
|
||||||
#include "roots.h"
|
|
||||||
|
|
||||||
static constexpr const char* CACHE_LOG_DIR = "/cache/recovery";
|
static constexpr const char* CACHE_LOG_DIR = "/cache/recovery";
|
||||||
static constexpr const char* COMMAND_FILE = "/cache/recovery/command";
|
static constexpr const char* COMMAND_FILE = "/cache/recovery/command";
|
||||||
@@ -79,7 +78,7 @@ static constexpr const char* METADATA_ROOT = "/metadata";
|
|||||||
// into target_files.zip. Assert the version defined in code and in Android.mk are consistent.
|
// into target_files.zip. Assert the version defined in code and in Android.mk are consistent.
|
||||||
static_assert(kRecoveryApiVersion == RECOVERY_API_VERSION, "Mismatching recovery API versions.");
|
static_assert(kRecoveryApiVersion == RECOVERY_API_VERSION, "Mismatching recovery API versions.");
|
||||||
|
|
||||||
bool modified_flash = false;
|
static bool modified_flash = false;
|
||||||
std::string stage;
|
std::string stage;
|
||||||
const char* reason = nullptr;
|
const char* reason = nullptr;
|
||||||
|
|
||||||
@@ -272,12 +271,6 @@ static bool erase_volume(const char* volume) {
|
|||||||
return (result == 0);
|
return (result == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the usb config to 'state'
|
|
||||||
bool SetUsbConfig(const std::string& state) {
|
|
||||||
android::base::SetProperty("sys.usb.config", state);
|
|
||||||
return android::base::WaitForProperty("sys.usb.state", state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool yes_no(Device* device, const char* question1, const char* question2) {
|
static bool yes_no(Device* device, const char* question1, const char* question2) {
|
||||||
std::vector<std::string> headers{ question1, question2 };
|
std::vector<std::string> headers{ question1, question2 };
|
||||||
std::vector<std::string> items{ " No", " Yes" };
|
std::vector<std::string> items{ " No", " Yes" };
|
||||||
@@ -439,7 +432,7 @@ static std::unique_ptr<Package> ReadWipePackage(size_t wipe_package_size) {
|
|||||||
// 1. verify the package.
|
// 1. verify the package.
|
||||||
// 2. check metadata (ota-type, pre-device and serial number if having one).
|
// 2. check metadata (ota-type, pre-device and serial number if having one).
|
||||||
static bool CheckWipePackage(Package* wipe_package) {
|
static bool CheckWipePackage(Package* wipe_package) {
|
||||||
if (!verify_package(wipe_package)) {
|
if (!verify_package(wipe_package, ui)) {
|
||||||
LOG(ERROR) << "Failed to verify package";
|
LOG(ERROR) << "Failed to verify package";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -693,7 +686,7 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) {
|
|||||||
modified_flash = true;
|
modified_flash = true;
|
||||||
bool adb = (chosen_action == Device::APPLY_ADB_SIDELOAD);
|
bool adb = (chosen_action == Device::APPLY_ADB_SIDELOAD);
|
||||||
if (adb) {
|
if (adb) {
|
||||||
status = apply_from_adb(&should_wipe_cache);
|
status = apply_from_adb(&should_wipe_cache, ui);
|
||||||
} else {
|
} else {
|
||||||
status = ApplyFromSdcard(device, &should_wipe_cache, ui);
|
status = ApplyFromSdcard(device, &should_wipe_cache, ui);
|
||||||
}
|
}
|
||||||
@@ -746,20 +739,6 @@ static void print_property(const char* key, const char* name, void* /* cookie */
|
|||||||
printf("%s=%s\n", key, name);
|
printf("%s=%s\n", key, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_print(const char* format, ...) {
|
|
||||||
std::string buffer;
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, format);
|
|
||||||
android::base::StringAppendV(&buffer, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if (ui != nullptr) {
|
|
||||||
ui->Print("%s", buffer.c_str());
|
|
||||||
} else {
|
|
||||||
fputs(buffer.c_str(), stdout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_battery_ok(int* required_battery_level) {
|
static bool is_battery_ok(int* required_battery_level) {
|
||||||
using android::hardware::health::V1_0::BatteryStatus;
|
using android::hardware::health::V1_0::BatteryStatus;
|
||||||
using android::hardware::health::V2_0::get_health_service;
|
using android::hardware::health::V2_0::get_health_service;
|
||||||
@@ -1030,7 +1009,8 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
|
|||||||
set_retry_bootloader_message(retry_count + 1, args);
|
set_retry_bootloader_message(retry_count + 1, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = install_package(update_package, &should_wipe_cache, true, retry_count);
|
modified_flash = true;
|
||||||
|
status = install_package(update_package, &should_wipe_cache, true, retry_count, ui);
|
||||||
if (status == INSTALL_SUCCESS && should_wipe_cache) {
|
if (status == INSTALL_SUCCESS && should_wipe_cache) {
|
||||||
wipe_cache(false, device);
|
wipe_cache(false, device);
|
||||||
}
|
}
|
||||||
@@ -1096,7 +1076,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
|
|||||||
if (!sideload_auto_reboot) {
|
if (!sideload_auto_reboot) {
|
||||||
ui->ShowText(true);
|
ui->ShowText(true);
|
||||||
}
|
}
|
||||||
status = apply_from_adb(&should_wipe_cache);
|
status = apply_from_adb(&should_wipe_cache, ui);
|
||||||
if (status == INSTALL_SUCCESS && should_wipe_cache) {
|
if (status == INSTALL_SUCCESS && should_wipe_cache) {
|
||||||
if (!wipe_cache(false, device)) {
|
if (!wipe_cache(false, device)) {
|
||||||
status = INSTALL_ERROR;
|
status = INSTALL_ERROR;
|
||||||
|
|||||||
+7
-1
@@ -53,12 +53,12 @@
|
|||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "minadbd/minadbd.h"
|
#include "minadbd/minadbd.h"
|
||||||
#include "otautil/paths.h"
|
#include "otautil/paths.h"
|
||||||
|
#include "otautil/roots.h"
|
||||||
#include "otautil/sysutil.h"
|
#include "otautil/sysutil.h"
|
||||||
#include "recovery.h"
|
#include "recovery.h"
|
||||||
#include "recovery_ui/device.h"
|
#include "recovery_ui/device.h"
|
||||||
#include "recovery_ui/stub_ui.h"
|
#include "recovery_ui/stub_ui.h"
|
||||||
#include "recovery_ui/ui.h"
|
#include "recovery_ui/ui.h"
|
||||||
#include "roots.h"
|
|
||||||
|
|
||||||
static constexpr const char* COMMAND_FILE = "/cache/recovery/command";
|
static constexpr const char* COMMAND_FILE = "/cache/recovery/command";
|
||||||
static constexpr const char* LOCALE_FILE = "/cache/recovery/last_locale";
|
static constexpr const char* LOCALE_FILE = "/cache/recovery/last_locale";
|
||||||
@@ -178,6 +178,12 @@ static std::string load_locale_from_cache() {
|
|||||||
return android::base::Trim(content);
|
return android::base::Trim(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sets the usb config to 'state'.
|
||||||
|
static bool SetUsbConfig(const std::string& state) {
|
||||||
|
android::base::SetProperty("sys.usb.config", state);
|
||||||
|
return android::base::WaitForProperty("sys.usb.state", state);
|
||||||
|
}
|
||||||
|
|
||||||
static void ListenRecoverySocket(RecoveryUI* ui, std::atomic<Device::BuiltinAction>& action) {
|
static void ListenRecoverySocket(RecoveryUI* ui, std::atomic<Device::BuiltinAction>& action) {
|
||||||
android::base::unique_fd sock_fd(android_get_control_socket("recovery"));
|
android::base::unique_fd sock_fd(android_get_control_socket("recovery"));
|
||||||
if (sock_fd < 0) {
|
if (sock_fd < 0) {
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ class Device {
|
|||||||
|
|
||||||
// Performs a recovery action selected from the menu. 'menu_position' will be the index of the
|
// Performs a recovery action selected from the menu. 'menu_position' will be the index of the
|
||||||
// selected menu item, or a non-negative value returned from HandleMenuKey(). The menu will be
|
// selected menu item, or a non-negative value returned from HandleMenuKey(). The menu will be
|
||||||
// hidden when this is called; implementations can call ui_print() to print information to the
|
// hidden when this is called; implementations can call GetUI()->Print() to print information to
|
||||||
// screen. If the menu position is one of the builtin actions, you can just return the
|
// the screen. If the menu position is one of the builtin actions, you can just return the
|
||||||
// corresponding enum value. If it is an action specific to your device, you actually perform it
|
// corresponding enum value. If it is an action specific to your device, you actually perform it
|
||||||
// here and return NO_ACTION.
|
// here and return NO_ACTION.
|
||||||
virtual BuiltinAction InvokeMenuItem(size_t menu_position);
|
virtual BuiltinAction InvokeMenuItem(size_t menu_position);
|
||||||
|
|||||||
+3
-4
@@ -76,9 +76,9 @@ libapplypatch_static_libs = [
|
|||||||
librecovery_static_libs = [
|
librecovery_static_libs = [
|
||||||
"librecovery",
|
"librecovery",
|
||||||
"librecovery_fastboot",
|
"librecovery_fastboot",
|
||||||
|
"libinstall",
|
||||||
|
"librecovery_ui",
|
||||||
"libminui",
|
"libminui",
|
||||||
"libpackage",
|
|
||||||
"libverifier",
|
|
||||||
"libotautil",
|
"libotautil",
|
||||||
|
|
||||||
"libhealthhalutils",
|
"libhealthhalutils",
|
||||||
@@ -116,10 +116,9 @@ cc_test {
|
|||||||
],
|
],
|
||||||
|
|
||||||
static_libs: libapplypatch_static_libs + [
|
static_libs: libapplypatch_static_libs + [
|
||||||
|
"libinstall",
|
||||||
"librecovery_ui",
|
"librecovery_ui",
|
||||||
"libminui",
|
"libminui",
|
||||||
"libpackage",
|
|
||||||
"libverifier",
|
|
||||||
"libotautil",
|
"libotautil",
|
||||||
"libupdater",
|
"libupdater",
|
||||||
"libgtest_prod",
|
"libgtest_prod",
|
||||||
|
|||||||
@@ -32,9 +32,9 @@
|
|||||||
#include <ziparchive/zip_archive.h>
|
#include <ziparchive/zip_archive.h>
|
||||||
#include <ziparchive/zip_writer.h>
|
#include <ziparchive/zip_writer.h>
|
||||||
|
|
||||||
#include "install.h"
|
#include "install/install.h"
|
||||||
#include "otautil/paths.h"
|
#include "otautil/paths.h"
|
||||||
#include "private/install.h"
|
#include "private/setup_commands.h"
|
||||||
|
|
||||||
static void BuildZipArchive(const std::map<std::string, std::string>& file_map, int fd,
|
static void BuildZipArchive(const std::map<std::string, std::string>& file_map, int fd,
|
||||||
int compression_type) {
|
int compression_type) {
|
||||||
|
|||||||
@@ -35,9 +35,9 @@
|
|||||||
#include <ziparchive/zip_writer.h>
|
#include <ziparchive/zip_writer.h>
|
||||||
|
|
||||||
#include "common/test_constants.h"
|
#include "common/test_constants.h"
|
||||||
|
#include "install/package.h"
|
||||||
|
#include "install/verifier.h"
|
||||||
#include "otautil/sysutil.h"
|
#include "otautil/sysutil.h"
|
||||||
#include "package.h"
|
|
||||||
#include "verifier.h"
|
|
||||||
|
|
||||||
using namespace std::string_literals;
|
using namespace std::string_literals;
|
||||||
|
|
||||||
@@ -158,6 +158,17 @@ TEST(VerifierTest, LoadCertificateFromBuffer_sha256_ec256bits) {
|
|||||||
VerifyPackageWithSingleCertificate("otasigned_v5.zip", std::move(cert));
|
VerifyPackageWithSingleCertificate("otasigned_v5.zip", std::move(cert));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(VerifierTest, LoadCertificateFromBuffer_sha256_rsa4096_bits) {
|
||||||
|
Certificate cert(0, Certificate::KEY_TYPE_RSA, nullptr, nullptr);
|
||||||
|
LoadKeyFromFile(from_testdata_base("testkey_4096bits.x509.pem"), &cert);
|
||||||
|
|
||||||
|
ASSERT_EQ(SHA256_DIGEST_LENGTH, cert.hash_len);
|
||||||
|
ASSERT_EQ(Certificate::KEY_TYPE_RSA, cert.key_type);
|
||||||
|
ASSERT_EQ(nullptr, cert.ec);
|
||||||
|
|
||||||
|
VerifyPackageWithSingleCertificate("otasigned_4096bits.zip", std::move(cert));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(VerifierTest, LoadCertificateFromBuffer_check_rsa_keys) {
|
TEST(VerifierTest, LoadCertificateFromBuffer_check_rsa_keys) {
|
||||||
std::unique_ptr<RSA, RSADeleter> rsa(RSA_new());
|
std::unique_ptr<RSA, RSADeleter> rsa(RSA_new());
|
||||||
std::unique_ptr<BIGNUM, decltype(&BN_free)> exponent(BN_new(), BN_free);
|
std::unique_ptr<BIGNUM, decltype(&BN_free)> exponent(BN_new(), BN_free);
|
||||||
|
|||||||
BIN
Binary file not shown.
+35
@@ -0,0 +1,35 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIGADCCA+igAwIBAgIJAJiRMVvanGUaMA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD
|
||||||
|
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
|
||||||
|
VmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UE
|
||||||
|
AwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
|
||||||
|
Fw0xODEwMzAxMjEzNTFaFw00NjAzMTcxMjEzNTFaMIGUMQswCQYDVQQGEwJVUzET
|
||||||
|
MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
|
||||||
|
A1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UEAwwHQW5kcm9p
|
||||||
|
ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCAiIwDQYJKoZI
|
||||||
|
hvcNAQEBBQADggIPADCCAgoCggIBAL3ghKA8Gz9qOORY8gMY4wlB2tCJLDUO2tFG
|
||||||
|
LVK1UphtQMp+YEcz/0VQKVV7de7z6V4EMQ5P1HbxHOsjcKn/zXAl4YgFt7b5kZbC
|
||||||
|
bpNK4CYHEfho3j6fpYtq5d9q8rIA2kI0uZkkqPy1zXKTl2C2PjOoAnLQRk5xBVQG
|
||||||
|
M10/wYsf7yX36mSWoJJwKPp/EzVFpA+hX8HpljeIiZ6CFzKwJdqv9zO/xzfp6NsX
|
||||||
|
Tv5EGdkDxmw3qQqKgyl8dLMTZ/2zNfvVOMeZDusEPDF7A/lbU1byLWrKQdCzVb40
|
||||||
|
yc7BCSRGYwM29R/byOcgD+lslwKSGzgzNmQXICt1tXz9bSJR8qh4tlAaiRc3ZKBe
|
||||||
|
hJWIFGkGtD/cDGtDE5DbNAOz6CdSDdE2XN0Qf0cfN1RHVE6fo2FtFicRRVuFBt8M
|
||||||
|
2cbQ7bzmEvtHD6W6dsf120FH7gppXKmnhMx1WazpxR2QltbiYDTy2ZZi4paS/jDB
|
||||||
|
fL9gMCWp3Ohg2y74NGfUw5CQWQsDpcki6I7RvwClBCyOV51LHn5LE/nY4DkVrZxk
|
||||||
|
Pw0/YrTWz5J5PbdMetTuIunE4ec4lm8nZnh1ET+2MHx2+RoyF5vBs4rp1KHHRaEA
|
||||||
|
veD2AfQOWxz7kOG9+akFot7n+QoWEGdwY0mJ9jsO/IITCjv3VbD7o0OoJv1R2AW5
|
||||||
|
sK2KQ4PDAgMBAAGjUzBRMB0GA1UdDgQWBBT2EbrayXGhY6VCvSlLtRNyjW9ceDAf
|
||||||
|
BgNVHSMEGDAWgBT2EbrayXGhY6VCvSlLtRNyjW9ceDAPBgNVHRMBAf8EBTADAQH/
|
||||||
|
MA0GCSqGSIb3DQEBCwUAA4ICAQC7SsWap9zDKmuR0qMUZ6wlualnag0hUG1jZHQP
|
||||||
|
t63KO6LmNNMSuXRX60Zcq6WWzgLOyoT4HqHZZ47Jamfb4XQQcnWMMW0tJ3pDtTkz
|
||||||
|
dZILBInHJO8QPYI8Du6XWsDLSvMajq6ueBtO3NdcgsNL7eiHf3WoOtajLZxFM94Z
|
||||||
|
MESkUQOIsqHolYeTMHLTsuGkX1CK2Zw3Xn18bUSTYwZCHa6mYH00ItUBfetGCnWh
|
||||||
|
Y7bth/R15Cc+hocSB7ZsOa/R5kDyDdFDIKrnV5nH5Yd7CryrYC6Ac5UarYrxSJTq
|
||||||
|
eKPwqUlJB/tJW/lvdLt8YaURbFGzf/ZqU12zZRafYjmMjcQvfpzMoDSnbvHTA9IR
|
||||||
|
ZGO7dwhwykoSaL4/8LWde49xQUq6F2pQBRmEr+7mTzml1MaM5cWEk5emkCMXgLog
|
||||||
|
k+c56CAk1EdM1teWik7wR0TIqkkYyYJHTSg61GkXUIXrZJ6iYx2ejDg1+QTPm9rU
|
||||||
|
Yr7nP52gVkQuUAX1+xB6wKLSDizQJw8SNiUGXl5+2vwV6+0BI3/CXlQ8I/nRPBC1
|
||||||
|
oqOIkRSbE+IF7DP9QvYuNG/3bZZQ8LUVeHxqI5Mq8K2VIJZd95AIwPNMH34SaDGz
|
||||||
|
9xjG28Fq4ZkuDP0pCsHM9d2XEwK5PEVS18WW5fJ/QcJKMno4IPTB70ZBBjVzv6Y+
|
||||||
|
MYjOrw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "asn1_decoder.h"
|
#include "private/asn1_decoder.h"
|
||||||
|
|
||||||
TEST(Asn1DecoderTest, Empty_Failure) {
|
TEST(Asn1DecoderTest, Empty_Failure) {
|
||||||
uint8_t empty[] = {};
|
uint8_t empty[] = {};
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#include <ziparchive/zip_writer.h>
|
#include <ziparchive/zip_writer.h>
|
||||||
|
|
||||||
#include "common/test_constants.h"
|
#include "common/test_constants.h"
|
||||||
#include "package.h"
|
#include "install/package.h"
|
||||||
|
|
||||||
class PackageTest : public ::testing::Test {
|
class PackageTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -17,8 +17,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <android-base/file.h>
|
#include <android-base/file.h>
|
||||||
|
#include <android-base/strings.h>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "otautil/rangeset.h"
|
||||||
#include "otautil/sysutil.h"
|
#include "otautil/sysutil.h"
|
||||||
|
|
||||||
TEST(SysUtilTest, InvalidArgs) {
|
TEST(SysUtilTest, InvalidArgs) {
|
||||||
@@ -28,6 +30,65 @@ TEST(SysUtilTest, InvalidArgs) {
|
|||||||
ASSERT_FALSE(mapping.MapFile(""));
|
ASSERT_FALSE(mapping.MapFile(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(SysUtilTest, ParseBlockMapFile_smoke) {
|
||||||
|
std::vector<std::string> content = {
|
||||||
|
"/dev/abc", "49652 4096", "3", "1000 1008", "2100 2102", "30 33",
|
||||||
|
};
|
||||||
|
|
||||||
|
TemporaryFile temp_file;
|
||||||
|
ASSERT_TRUE(android::base::WriteStringToFile(android::base::Join(content, '\n'), temp_file.path));
|
||||||
|
|
||||||
|
auto block_map_data = BlockMapData::ParseBlockMapFile(temp_file.path);
|
||||||
|
ASSERT_EQ("/dev/abc", block_map_data.path());
|
||||||
|
ASSERT_EQ(49652, block_map_data.file_size());
|
||||||
|
ASSERT_EQ(4096, block_map_data.block_size());
|
||||||
|
ASSERT_EQ(RangeSet(std::vector<Range>{
|
||||||
|
{ 1000, 1008 },
|
||||||
|
{ 2100, 2102 },
|
||||||
|
{ 30, 33 },
|
||||||
|
}),
|
||||||
|
block_map_data.block_ranges());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SysUtilTest, ParseBlockMapFile_invalid_line_count) {
|
||||||
|
std::vector<std::string> content = {
|
||||||
|
"/dev/abc", "49652 4096", "2", "1000 1008", "2100 2102", "30 33",
|
||||||
|
};
|
||||||
|
|
||||||
|
TemporaryFile temp_file;
|
||||||
|
ASSERT_TRUE(android::base::WriteStringToFile(android::base::Join(content, '\n'), temp_file.path));
|
||||||
|
|
||||||
|
auto block_map_data1 = BlockMapData::ParseBlockMapFile(temp_file.path);
|
||||||
|
ASSERT_FALSE(block_map_data1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SysUtilTest, ParseBlockMapFile_invalid_size) {
|
||||||
|
std::vector<std::string> content = {
|
||||||
|
"/dev/abc",
|
||||||
|
"42949672950 4294967295",
|
||||||
|
"1",
|
||||||
|
"0 9",
|
||||||
|
};
|
||||||
|
|
||||||
|
TemporaryFile temp_file;
|
||||||
|
ASSERT_TRUE(android::base::WriteStringToFile(android::base::Join(content, '\n'), temp_file.path));
|
||||||
|
|
||||||
|
auto block_map_data = BlockMapData::ParseBlockMapFile(temp_file.path);
|
||||||
|
ASSERT_EQ("/dev/abc", block_map_data.path());
|
||||||
|
ASSERT_EQ(42949672950, block_map_data.file_size());
|
||||||
|
ASSERT_EQ(4294967295, block_map_data.block_size());
|
||||||
|
|
||||||
|
content[1] = "42949672950 4294967296";
|
||||||
|
ASSERT_TRUE(android::base::WriteStringToFile(android::base::Join(content, '\n'), temp_file.path));
|
||||||
|
auto large_block_size = BlockMapData::ParseBlockMapFile(temp_file.path);
|
||||||
|
ASSERT_FALSE(large_block_size);
|
||||||
|
|
||||||
|
content[1] = "4294967296 1";
|
||||||
|
ASSERT_TRUE(android::base::WriteStringToFile(android::base::Join(content, '\n'), temp_file.path));
|
||||||
|
auto too_many_blocks = BlockMapData::ParseBlockMapFile(temp_file.path);
|
||||||
|
ASSERT_FALSE(too_many_blocks);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(SysUtilTest, MapFileRegularFile) {
|
TEST(SysUtilTest, MapFileRegularFile) {
|
||||||
TemporaryFile temp_file1;
|
TemporaryFile temp_file1;
|
||||||
std::string content = "abc";
|
std::string content = "abc";
|
||||||
|
|||||||
Reference in New Issue
Block a user