Merge "Changing FlashTask to take in apply_vbmeta"
diff --git a/debuggerd/crasher/arm/crashglue.S b/debuggerd/crasher/arm/crashglue.S
index 8649056..6f41b21 100644
--- a/debuggerd/crasher/arm/crashglue.S
+++ b/debuggerd/crasher/arm/crashglue.S
@@ -1,6 +1,10 @@
.globl crash1
.type crash1, %function
crash1:
+ .cfi_startproc
+ push {lr}
+ .cfi_def_cfa_offset 4
+ .cfi_rel_offset lr, 0
ldr r0, =0xa5a50000
ldr r1, =0xa5a50001
ldr r2, =0xa5a50002
@@ -52,11 +56,16 @@
mov lr, #0
ldr lr, [lr]
b .
+ .cfi_endproc
.globl crashnostack
.type crashnostack, %function
crashnostack:
+ .cfi_startproc
+ mov r1, sp
+ .cfi_def_cfa_register r1
mov sp, #0
mov r0, #0
ldr r0, [r0]
b .
+ .cfi_endproc
diff --git a/debuggerd/crasher/arm64/crashglue.S b/debuggerd/crasher/arm64/crashglue.S
index e58b542..014c98c 100644
--- a/debuggerd/crasher/arm64/crashglue.S
+++ b/debuggerd/crasher/arm64/crashglue.S
@@ -1,6 +1,11 @@
.globl crash1
.type crash1, %function
crash1:
+ .cfi_startproc
+ stp x29, x30, [sp, -16]!
+ .cfi_def_cfa_offset 16
+ .cfi_rel_offset x29, 0
+ .cfi_rel_offset x30, 8
ldr x0, =0xa5a50000
ldr x1, =0xa5a50001
ldr x2, =0xa5a50002
@@ -68,12 +73,17 @@
mov x30, xzr
ldr x30, [x30]
b .
+ .cfi_endproc
.globl crashnostack
.type crashnostack, %function
crashnostack:
+ .cfi_startproc
+ mov x1, sp
+ .cfi_def_cfa_register x1
mov x0, xzr
add sp, x0, xzr
ldr x0, [x0]
b .
+ .cfi_endproc
diff --git a/debuggerd/crasher/x86/crashglue.S b/debuggerd/crasher/x86/crashglue.S
index 59df432..ffbd816 100644
--- a/debuggerd/crasher/x86/crashglue.S
+++ b/debuggerd/crasher/x86/crashglue.S
@@ -11,5 +11,9 @@
crashnostack:
- movl $0, %ebp
- jmp *%ebp
+ .cfi_startproc
+ movl %esp, %eax
+ .cfi_def_cfa_register %eax
+ movl $0, %esp
+ movl (%esp), %ebx
+ .cfi_endproc
diff --git a/debuggerd/crasher/x86_64/crashglue.S b/debuggerd/crasher/x86_64/crashglue.S
index 4d2a5c0..7e22118 100644
--- a/debuggerd/crasher/x86_64/crashglue.S
+++ b/debuggerd/crasher/x86_64/crashglue.S
@@ -11,5 +11,9 @@
crashnostack:
- movl $0, %ebp
- jmp *%rbp
+ .cfi_startproc
+ movq %rsp, %rax
+ .cfi_def_cfa_register %rax
+ movq $0, %rsp
+ movq (%rsp), %rbx
+ .cfi_endproc
diff --git a/fs_mgr/TEST_MAPPING b/fs_mgr/TEST_MAPPING
index b6710d5..db27cf0 100644
--- a/fs_mgr/TEST_MAPPING
+++ b/fs_mgr/TEST_MAPPING
@@ -28,9 +28,6 @@
"name": "vabc_legacy_tests"
},
{
- "name": "libsnapshot_fuzzer_test"
- },
- {
"name": "cow_api_test"
}
],
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index c2f435f..3bfa4d5 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -366,80 +366,6 @@
gtest: false,
}
-cc_defaults {
- name: "libsnapshot_fuzzer_defaults",
- defaults: [
- "libsnapshot_cow_defaults",
- ],
- native_coverage : true,
- srcs: [
- // Compile the protobuf definition again with type full.
- "android/snapshot/snapshot_fuzz.proto",
- "update_engine/update_metadata.proto",
- "fuzz_utils.cpp",
- "snapshot_fuzz.cpp",
- "snapshot_fuzz_utils.cpp",
-
- // Compile libsnapshot sources directly to avoid dependency
- // to update_metadata-protos
- ":libsnapshot_sources",
- ],
- static_libs: [
- "libbase",
- "libbrotli",
- "libc++fs",
- "libchrome",
- "libcrypto_static",
- "libcutils",
- "libext2_uuid",
- "libext4_utils",
- "libfstab",
- "libfs_mgr",
- "libgtest", // from libsnapshot_test_helpers
- "libgmock", // from libsnapshot_test_helpers
- "liblog",
- "liblp",
- "libsnapshot_cow",
- "libsnapshot_test_helpers",
- "libprotobuf-mutator",
- "libz",
- ],
- header_libs: [
- "libfiemap_headers",
- "libstorage_literals_headers",
- "libupdate_engine_headers",
- ],
- proto: {
- type: "full",
- canonical_path_from_root: false,
- local_include_dirs: ["."],
- },
-}
-
-cc_fuzz {
- name: "libsnapshot_fuzzer",
- defaults: ["libsnapshot_fuzzer_defaults"],
- corpus: ["corpus/*"],
- fuzz_config: {
- cc: ["android-virtual-ab+bugs@google.com"],
- componentid: 30545,
- hotlists: ["1646452"],
- fuzz_on_haiku_host: false,
- fuzz_on_haiku_device: true,
- },
-}
-
-cc_test {
- name: "libsnapshot_fuzzer_test",
- defaults: ["libsnapshot_fuzzer_defaults"],
- data: ["corpus/*"],
- test_suites: [
- "device-tests",
- ],
- auto_gen_config: true,
- require_root: true,
-}
-
cc_test {
name: "cow_api_test",
defaults: [
diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto
deleted file mode 100644
index a55b42a..0000000
--- a/fs_mgr/libsnapshot/android/snapshot/snapshot_fuzz.proto
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (C) 2020 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.
-
-syntax = "proto3";
-package android.snapshot;
-
-import "update_engine/update_metadata.proto";
-
-// Controls the behavior of IDeviceInfo.
-// Next: 6
-message FuzzDeviceInfoData {
- bool slot_suffix_is_a = 1;
- bool is_overlayfs_setup = 2;
- bool allow_set_boot_control_merge_status = 3;
- bool allow_set_slot_as_unbootable = 4;
- bool is_recovery = 5;
-}
-
-// Controls the behavior of the test SnapshotManager.
-// Next: 2
-message FuzzSnapshotManagerData {
- bool is_local_image_manager = 1;
-}
-
-// A simplified version of CreateLogicalPartitionParams for fuzzing.
-// Next: 9
-message CreateLogicalPartitionParamsProto {
- bool use_correct_super = 1;
- string block_device = 2;
- bool has_metadata_slot = 3;
- uint32 metadata_slot = 4;
- string partition_name = 5;
- bool force_writable = 6;
- int64 timeout_millis = 7;
- string device_name = 8;
-}
-
-// Mimics the API of ISnapshotManager. Defines one action on the snapshot
-// manager.
-// Next: 18
-message SnapshotManagerActionProto {
- message NoArgs {}
- message ProcessUpdateStateArgs {
- bool has_before_cancel = 1;
- bool fail_before_cancel = 2;
- }
- message CreateLogicalAndSnapshotPartitionsArgs {
- bool use_correct_super = 1;
- string super = 2;
- int64 timeout_millis = 3;
- }
- message RecoveryCreateSnapshotDevicesArgs {
- bool has_metadata_device_object = 1;
- bool metadata_mounted = 2;
- }
- reserved 18 to 9999;
- oneof value {
- NoArgs begin_update = 1;
- NoArgs cancel_update = 2;
- bool finished_snapshot_writes = 3;
- NoArgs initiate_merge = 4;
- ProcessUpdateStateArgs process_update_state = 5;
- bool get_update_state = 6;
- chromeos_update_engine.DeltaArchiveManifest create_update_snapshots = 7;
- CreateLogicalPartitionParamsProto map_update_snapshot = 8;
- string unmap_update_snapshot = 9;
- NoArgs need_snapshots_in_first_stage_mount = 10;
- CreateLogicalAndSnapshotPartitionsArgs create_logical_and_snapshot_partitions = 11;
- bool handle_imminent_data_wipe = 12;
- NoArgs recovery_create_snapshot_devices = 13;
- RecoveryCreateSnapshotDevicesArgs recovery_create_snapshot_devices_with_metadata = 14;
- NoArgs dump = 15;
- NoArgs ensure_metadata_mounted = 16;
- NoArgs get_snapshot_merge_stats_instance = 17;
-
- // Test directives that has nothing to do with ISnapshotManager API surface.
- NoArgs switch_slot = 10000;
- }
-}
-
-// Includes all data that needs to be fuzzed.
-message SnapshotFuzzData {
- FuzzDeviceInfoData device_info_data = 1;
- FuzzSnapshotManagerData manager_data = 2;
-
- // If true:
- // - if super_data is empty, create empty super partition metadata.
- // - otherwise, create super partition metadata accordingly.
- // If false, no valid super partition metadata (it is zeroed)
- bool is_super_metadata_valid = 3;
- chromeos_update_engine.DeltaArchiveManifest super_data = 4;
-
- // Whether the directory that mocks /metadata/ota/snapshot is created.
- bool has_metadata_snapshots_dir = 5;
-
- // More data used to prep the test before running actions.
- reserved 6 to 9999;
- repeated SnapshotManagerActionProto actions = 10000;
-}
diff --git a/fs_mgr/libsnapshot/corpus/avoid-io-in-fuzzer.txt b/fs_mgr/libsnapshot/corpus/avoid-io-in-fuzzer.txt
deleted file mode 100644
index c474f4c..0000000
--- a/fs_mgr/libsnapshot/corpus/avoid-io-in-fuzzer.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-device_info_data {
- allow_set_slot_as_unbootable: true
- is_recovery: true
-}
-is_super_metadata_valid: true
-super_data {
- partitions {
- partition_name: "sys_a"
- new_partition_info {
- size: 3145728
- }
- }
- partitions {
- partition_name: "vnnd_"
- new_partition_info {
- size: 3145728
- }
- }
- partitions {
- partition_name: "prd_a"
- new_partition_info {
- }
- }
- dynamic_partition_metadata {
- groups {
- name: "group_google_dp_a"
- size: 34375467008
- partition_names: "sys_a"
- partition_names: "vnd_a"
- partition_names: "prd_a"
- }
- }
-}
-has_metadata_snapshots_dir: true
-actions {
- handle_imminent_data_wipe: true
-}
-actions {
- begin_update {
- }
-}
diff --git a/fs_mgr/libsnapshot/corpus/launch_device.txt b/fs_mgr/libsnapshot/corpus/launch_device.txt
deleted file mode 100644
index 55a7f2c..0000000
--- a/fs_mgr/libsnapshot/corpus/launch_device.txt
+++ /dev/null
@@ -1,161 +0,0 @@
-device_info_data {
- slot_suffix_is_a: true
- is_overlayfs_setup: false
- allow_set_boot_control_merge_status: true
- allow_set_slot_as_unbootable: true
- is_recovery: false
-}
-manager_data {
- is_local_image_manager: false
-}
-is_super_metadata_valid: true
-super_data {
- partitions {
- partition_name: "sys_a"
- new_partition_info {
- size: 3145728
- }
- }
- partitions {
- partition_name: "vnd_a"
- new_partition_info {
- size: 3145728
- }
- }
- partitions {
- partition_name: "prd_a"
- new_partition_info {
- size: 3145728
- }
- }
- dynamic_partition_metadata {
- groups {
- name: "group_google_dp_a"
- size: 15728640
- partition_names: "sys_a"
- partition_names: "vnd_a"
- partition_names: "prd_a"
- }
- }
-}
-has_metadata_snapshots_dir: true
-actions {
- begin_update {
- }
-}
-actions {
- create_update_snapshots {
- partitions {
- partition_name: "sys"
- new_partition_info {
- size: 3878912
- }
- operations {
- type: ZERO,
- dst_extents {
- start_block: 0
- num_blocks: 947
- }
- }
- }
- partitions {
- partition_name: "vnd"
- new_partition_info {
- size: 3878912
- }
- operations {
- type: ZERO,
- dst_extents {
- start_block: 0
- num_blocks: 947
- }
- }
- }
- partitions {
- partition_name: "prd"
- new_partition_info {
- size: 3878912
- }
- operations {
- type: ZERO,
- dst_extents {
- start_block: 0
- num_blocks: 947
- }
- }
- }
- dynamic_partition_metadata {
- groups {
- name: "group_google_dp"
- size: 15728640
- partition_names: "sys"
- partition_names: "vnd"
- partition_names: "prd"
- }
- }
- }
-}
-actions {
- map_update_snapshot {
- use_correct_super: true
- has_metadata_slot: true
- metadata_slot: 1
- partition_name: "sys_b"
- force_writable: true
- timeout_millis: 3000
- }
-}
-actions {
- map_update_snapshot {
- use_correct_super: true
- has_metadata_slot: true
- metadata_slot: 1
- partition_name: "vnd_b"
- force_writable: true
- timeout_millis: 3000
- }
-}
-actions {
- map_update_snapshot {
- use_correct_super: true
- has_metadata_slot: true
- metadata_slot: 1
- partition_name: "prd_b"
- force_writable: true
- timeout_millis: 3000
- }
-}
-actions {
- finished_snapshot_writes: false
-}
-actions {
- unmap_update_snapshot: "sys_b"
-}
-actions {
- unmap_update_snapshot: "vnd_b"
-}
-actions {
- unmap_update_snapshot: "prd_b"
-}
-actions {
- switch_slot {
- }
-}
-actions {
- need_snapshots_in_first_stage_mount {
- }
-}
-actions {
- create_logical_and_snapshot_partitions {
- use_correct_super: true
- timeout_millis: 5000
- }
-}
-actions {
- initiate_merge {
- }
-}
-actions {
- process_update_state {
- }
-}
diff --git a/fs_mgr/libsnapshot/fuzz.sh b/fs_mgr/libsnapshot/fuzz.sh
deleted file mode 100755
index 5995cef..0000000
--- a/fs_mgr/libsnapshot/fuzz.sh
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/bin/bash
-PROJECT_PATH=system/core/fs_mgr/libsnapshot
-FUZZ_TARGET=libsnapshot_fuzzer
-TARGET_ARCH=$(get_build_var TARGET_ARCH)
-FUZZ_BINARY=/data/fuzz/${TARGET_ARCH}/${FUZZ_TARGET}/${FUZZ_TARGET}
-DEVICE_INIT_CORPUS_DIR=/data/fuzz/${TARGET_ARCH}/${FUZZ_TARGET}/corpus
-DEVICE_GENERATED_CORPUS_DIR=/data/local/tmp/${FUZZ_TARGET}/corpus
-DEVICE_GCOV_DIR=/data/local/tmp/${FUZZ_TARGET}/gcov
-HOST_SCRATCH_DIR=/tmp/${FUZZ_TARGET}
-GCOV_TOOL=${HOST_SCRATCH_DIR}/llvm-gcov
-
-build_normal() (
- pushd $(gettop)
- NATIVE_COVERAGE="" NATIVE_LINE_COVERAGE="" NATIVE_COVERAGE_PATHS="" m ${FUZZ_TARGET}
- ret=$?
- popd
- return ${ret}
-)
-
-build_cov() {
- pushd $(gettop)
- NATIVE_COVERAGE="true" NATIVE_LINE_COVERAGE="true" NATIVE_COVERAGE_PATHS="${PROJECT_PATH}" m ${FUZZ_TARGET}
- ret=$?
- popd
- return ${ret}
-}
-
-prepare_device() {
- adb root && adb remount &&
- adb shell mkdir -p ${DEVICE_GENERATED_CORPUS_DIR} &&
- adb shell rm -rf ${DEVICE_GCOV_DIR} &&
- adb shell mkdir -p ${DEVICE_GCOV_DIR}
-}
-
-push_binary() {
- adb push ${ANDROID_PRODUCT_OUT}/${FUZZ_BINARY} ${FUZZ_BINARY} &&
- adb push ${ANDROID_PRODUCT_OUT}/${DEVICE_INIT_CORPUS_DIR} $(dirname ${FUZZ_BINARY})
-}
-
-prepare_host() {
- which lcov || {
- echo "please run:";
- echo " sudo apt-get install lcov ";
- return 1;
- }
- rm -rf ${HOST_SCRATCH_DIR} &&
- mkdir -p ${HOST_SCRATCH_DIR}
-}
-
-# run_snapshot_fuzz -runs=10000
-generate_corpus() {
- [[ "$@" ]] || { echo "run with -runs=X"; return 1; }
-
- prepare_device &&
- build_normal &&
- push_binary &&
- adb shell ${FUZZ_BINARY} "$@" ${DEVICE_INIT_CORPUS_DIR} ${DEVICE_GENERATED_CORPUS_DIR}
-}
-
-run_snapshot_fuzz() {
- prepare_device &&
- build_cov &&
- push_binary &&
- adb shell GCOV_PREFIX=${DEVICE_GCOV_DIR} GCOV_PREFIX_STRIP=3 \
- ${FUZZ_BINARY} \
- -runs=0 \
- ${DEVICE_INIT_CORPUS_DIR} ${DEVICE_GENERATED_CORPUS_DIR}
-}
-
-show_fuzz_result() {
- prepare_host &&
- unzip -o -j -d ${HOST_SCRATCH_DIR} ${ANDROID_PRODUCT_OUT}/coverage/data/fuzz/${TARGET_ARCH}/${FUZZ_TARGET}/${FUZZ_TARGET}.zip &&
- adb shell find ${DEVICE_GCOV_DIR} -type f | xargs -I {} adb pull {} ${HOST_SCRATCH_DIR} &&
- ls ${HOST_SCRATCH_DIR} &&
- cat > ${GCOV_TOOL} <<< '
-#!/bin/bash
-exec llvm-cov gcov "$@"
-' &&
- chmod +x ${GCOV_TOOL} &&
- lcov --directory ${HOST_SCRATCH_DIR} --base-directory $(gettop) --gcov-tool ${GCOV_TOOL} --capture -o ${HOST_SCRATCH_DIR}/report.cov &&
- genhtml ${HOST_SCRATCH_DIR}/report.cov -o ${HOST_SCRATCH_DIR}/html &&
- echo file://$(realpath ${HOST_SCRATCH_DIR}/html/index.html)
-}
-
-# run_snapshot_fuzz -runs=10000
-run_snapshot_fuzz_all() {
- generate_corpus "$@" &&
- run_snapshot_fuzz &&
- show_fuzz_result
-}
diff --git a/fs_mgr/libsnapshot/fuzz_utils.cpp b/fs_mgr/libsnapshot/fuzz_utils.cpp
deleted file mode 100644
index 0263f7e..0000000
--- a/fs_mgr/libsnapshot/fuzz_utils.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2020 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.
-
-#include "fuzz_utils.h"
-
-#include <android-base/logging.h>
-
-namespace android::fuzz {
-
-void CheckInternal(bool value, std::string_view msg) {
- CHECK(value) << msg;
-}
-
-const google::protobuf::OneofDescriptor* GetProtoValueDescriptor(
- const google::protobuf::Descriptor* action_desc) {
- CHECK(action_desc);
- CHECK(action_desc->oneof_decl_count() == 1)
- << action_desc->oneof_decl_count() << " oneof fields found in " << action_desc->name()
- << "; only one is expected.";
- auto* oneof_value_desc = action_desc->oneof_decl(0);
- CHECK(oneof_value_desc);
- CHECK(oneof_value_desc->name() == "value")
- << "oneof field has name " << oneof_value_desc->name();
- return oneof_value_desc;
-}
-
-} // namespace android::fuzz
diff --git a/fs_mgr/libsnapshot/fuzz_utils.h b/fs_mgr/libsnapshot/fuzz_utils.h
deleted file mode 100644
index 20b13b2..0000000
--- a/fs_mgr/libsnapshot/fuzz_utils.h
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright (C) 2020 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.
-
-#pragma once
-
-#include <map>
-#include <string>
-#include <string_view>
-
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>
-
-// Utilities for using a protobuf definition to fuzz APIs in a class.
-// Terms:
-// The "fuzzed class" is the C++ class definition whose functions are fuzzed.
-// The "fuzzed object" is an instantiated object of the fuzzed class. It is
-// typically created and destroyed for each test run.
-// An "action" is an operation on the fuzzed object that may mutate its state.
-// This typically involves one function call into the fuzzed object.
-
-namespace android::fuzz {
-
-// CHECK(value) << msg
-void CheckInternal(bool value, std::string_view msg);
-
-// Get the oneof descriptor inside Action
-const google::protobuf::OneofDescriptor* GetProtoValueDescriptor(
- const google::protobuf::Descriptor* action_desc);
-
-template <typename Class>
-using FunctionMapImpl =
- std::map<int, std::function<void(Class*, const google::protobuf::Message& action_proto,
- const google::protobuf::FieldDescriptor* field_desc)>>;
-
-template <typename Class>
-class FunctionMap : public FunctionMapImpl<Class> {
- public:
- void CheckEmplace(typename FunctionMapImpl<Class>::key_type key,
- typename FunctionMapImpl<Class>::mapped_type&& value) {
- auto [it, inserted] = this->emplace(key, std::move(value));
- CheckInternal(inserted,
- "Multiple implementation registered for tag number " + std::to_string(key));
- }
-};
-
-template <typename Action>
-int CheckConsistency() {
- const auto* function_map = Action::GetFunctionMap();
- const auto* action_value_desc = GetProtoValueDescriptor(Action::Proto::GetDescriptor());
-
- for (int field_index = 0; field_index < action_value_desc->field_count(); ++field_index) {
- const auto* field_desc = action_value_desc->field(field_index);
- CheckInternal(function_map->find(field_desc->number()) != function_map->end(),
- "Missing impl for function " + field_desc->camelcase_name());
- }
- return 0;
-}
-
-// Get the field descriptor for the oneof field in the action message. If no oneof field is set,
-// return nullptr.
-template <typename Action>
-const google::protobuf::FieldDescriptor* GetValueFieldDescriptor(
- const typename Action::Proto& action_proto) {
- static auto* action_value_desc = GetProtoValueDescriptor(Action::Proto::GetDescriptor());
-
- auto* action_refl = Action::Proto::GetReflection();
- if (!action_refl->HasOneof(action_proto, action_value_desc)) {
- return nullptr;
- }
- return action_refl->GetOneofFieldDescriptor(action_proto, action_value_desc);
-}
-
-template <typename Action>
-void ExecuteActionProto(typename Action::ClassType* module,
- const typename Action::Proto& action_proto) {
- const auto* field_desc = GetValueFieldDescriptor<Action>(action_proto);
- if (field_desc == nullptr) return;
- auto number = field_desc->number();
- const auto& map = *Action::GetFunctionMap();
- auto it = map.find(number);
- CheckInternal(it != map.end(), "Missing impl for function " + field_desc->camelcase_name());
- const auto& func = it->second;
- func(module, action_proto, field_desc);
-}
-
-template <typename Action>
-void ExecuteAllActionProtos(
- typename Action::ClassType* module,
- const google::protobuf::RepeatedPtrField<typename Action::Proto>& action_protos) {
- for (const auto& proto : action_protos) {
- ExecuteActionProto<Action>(module, proto);
- }
-}
-
-// Safely cast message to T. Returns a pointer to message if cast successfully, otherwise nullptr.
-template <typename T>
-const T* SafeCast(const google::protobuf::Message& message) {
- if (message.GetDescriptor() != T::GetDescriptor()) {
- return nullptr;
- }
- return static_cast<const T*>(&message);
-}
-
-// Cast message to const T&. Abort if type mismatch.
-template <typename T>
-const T& CheckedCast(const google::protobuf::Message& message) {
- const auto* ptr = SafeCast<T>(message);
- CheckInternal(ptr, "Cannot cast " + message.GetDescriptor()->name() + " to " +
- T::GetDescriptor()->name());
- return *ptr;
-}
-
-// A templated way to a primitive field from a message using reflection.
-template <typename T>
-struct PrimitiveGetter;
-#define FUZZ_DEFINE_PRIMITIVE_GETTER(type, func_name) \
- template <> \
- struct PrimitiveGetter<type> { \
- static constexpr const auto fp = &google::protobuf::Reflection::func_name; \
- }
-
-FUZZ_DEFINE_PRIMITIVE_GETTER(bool, GetBool);
-FUZZ_DEFINE_PRIMITIVE_GETTER(uint32_t, GetUInt32);
-FUZZ_DEFINE_PRIMITIVE_GETTER(int32_t, GetInt32);
-FUZZ_DEFINE_PRIMITIVE_GETTER(uint64_t, GetUInt64);
-FUZZ_DEFINE_PRIMITIVE_GETTER(int64_t, GetInt64);
-FUZZ_DEFINE_PRIMITIVE_GETTER(double, GetDouble);
-FUZZ_DEFINE_PRIMITIVE_GETTER(float, GetFloat);
-
-// ActionPerformer extracts arguments from the protobuf message, and then call FuzzFunction
-// with these arguments.
-template <typename FuzzFunction, typename Signature, typename Enabled = void>
-struct ActionPerformerImpl; // undefined
-
-template <typename FuzzFunction, typename MessageProto>
-struct ActionPerformerImpl<
- FuzzFunction, void(const MessageProto&),
- typename std::enable_if_t<std::is_base_of_v<google::protobuf::Message, MessageProto>>> {
- static typename FuzzFunction::ReturnType Invoke(
- typename FuzzFunction::ClassType* module, const google::protobuf::Message& action_proto,
- const google::protobuf::FieldDescriptor* field_desc) {
- const MessageProto& arg = CheckedCast<std::remove_reference_t<MessageProto>>(
- action_proto.GetReflection()->GetMessage(action_proto, field_desc));
- return FuzzFunction::ImplBody(module, arg);
- }
-};
-
-template <typename FuzzFunction, typename Primitive>
-struct ActionPerformerImpl<FuzzFunction, void(Primitive),
- typename std::enable_if_t<std::is_arithmetic_v<Primitive>>> {
- static typename FuzzFunction::ReturnType Invoke(
- typename FuzzFunction::ClassType* module, const google::protobuf::Message& action_proto,
- const google::protobuf::FieldDescriptor* field_desc) {
- Primitive arg = std::invoke(PrimitiveGetter<Primitive>::fp, action_proto.GetReflection(),
- action_proto, field_desc);
- return FuzzFunction::ImplBody(module, arg);
- }
-};
-
-template <typename FuzzFunction>
-struct ActionPerformerImpl<FuzzFunction, void()> {
- static typename FuzzFunction::ReturnType Invoke(typename FuzzFunction::ClassType* module,
- const google::protobuf::Message&,
- const google::protobuf::FieldDescriptor*) {
- return FuzzFunction::ImplBody(module);
- }
-};
-
-template <typename FuzzFunction>
-struct ActionPerformerImpl<FuzzFunction, void(const std::string&)> {
- static typename FuzzFunction::ReturnType Invoke(
- typename FuzzFunction::ClassType* module, const google::protobuf::Message& action_proto,
- const google::protobuf::FieldDescriptor* field_desc) {
- std::string scratch;
- const std::string& arg = action_proto.GetReflection()->GetStringReference(
- action_proto, field_desc, &scratch);
- return FuzzFunction::ImplBody(module, arg);
- }
-};
-
-template <typename FuzzFunction>
-struct ActionPerformer : ActionPerformerImpl<FuzzFunction, typename FuzzFunction::Signature> {};
-
-} // namespace android::fuzz
-
-// Fuzz existing C++ class, ClassType, with a collection of functions under the name Action.
-//
-// Prerequisite: ActionProto must be defined in Protobuf to describe possible actions:
-// message FooActionProto {
-// message NoArgs {}
-// oneof value {
-// bool do_foo = 1;
-// NoArgs do_bar = 1;
-// }
-// }
-// Use it to fuzz a C++ class Foo by doing the following:
-// FUZZ_CLASS(Foo, FooAction)
-// After linking functions of Foo to FooAction, execute all actions by:
-// FooAction::ExecuteAll(foo_object, action_protos)
-#define FUZZ_CLASS(Class, Action) \
- class Action { \
- public: \
- using Proto = Action##Proto; \
- using ClassType = Class; \
- using FunctionMap = android::fuzz::FunctionMap<Class>; \
- static FunctionMap* GetFunctionMap() { \
- static Action::FunctionMap map; \
- return ↦ \
- } \
- static void ExecuteAll(Class* module, \
- const google::protobuf::RepeatedPtrField<Proto>& action_protos) { \
- [[maybe_unused]] static int consistent = android::fuzz::CheckConsistency<Action>(); \
- android::fuzz::ExecuteAllActionProtos<Action>(module, action_protos); \
- } \
- }
-
-#define FUZZ_FUNCTION_CLASS_NAME(Action, FunctionName) Action##_##FunctionName
-#define FUZZ_FUNCTION_TAG_NAME(FunctionName) k##FunctionName
-
-// Implement an action defined in protobuf. Example:
-// message FooActionProto {
-// oneof value {
-// bool do_foo = 1;
-// }
-// }
-// class Foo { public: void DoAwesomeFoo(bool arg); };
-// FUZZ_OBJECT(FooAction, Foo);
-// FUZZ_FUNCTION(FooAction, DoFoo, void, IFoo* module, bool arg) {
-// module->DoAwesomeFoo(arg);
-// }
-// The name DoFoo is the camel case name of the action in protobuf definition of FooActionProto.
-#define FUZZ_FUNCTION(Action, FunctionName, Return, ModuleArg, ...) \
- class FUZZ_FUNCTION_CLASS_NAME(Action, FunctionName) { \
- public: \
- using ActionType = Action; \
- using ClassType = Action::ClassType; \
- using ReturnType = Return; \
- using Signature = void(__VA_ARGS__); \
- static constexpr const char name[] = #FunctionName; \
- static constexpr const auto tag = \
- Action::Proto::ValueCase::FUZZ_FUNCTION_TAG_NAME(FunctionName); \
- static ReturnType ImplBody(ModuleArg, ##__VA_ARGS__); \
- \
- private: \
- static bool registered_; \
- }; \
- auto FUZZ_FUNCTION_CLASS_NAME(Action, FunctionName)::registered_ = ([] { \
- auto tag = FUZZ_FUNCTION_CLASS_NAME(Action, FunctionName)::tag; \
- auto func = &::android::fuzz::ActionPerformer<FUZZ_FUNCTION_CLASS_NAME( \
- Action, FunctionName)>::Invoke; \
- Action::GetFunctionMap()->CheckEmplace(tag, func); \
- return true; \
- })(); \
- Return FUZZ_FUNCTION_CLASS_NAME(Action, FunctionName)::ImplBody(ModuleArg, ##__VA_ARGS__)
-
-// Implement a simple action by linking it to the function with the same name. Example:
-// message FooActionProto {
-// message NoArgs {}
-// oneof value {
-// NoArgs do_bar = 1;
-// }
-// }
-// class Foo { public void DoBar(); };
-// FUZZ_OBJECT(FooAction, Foo);
-// FUZZ_FUNCTION(FooAction, DoBar);
-// The name DoBar is the camel case name of the action in protobuf definition of FooActionProto, and
-// also the name of the function of Foo.
-#define FUZZ_SIMPLE_FUNCTION(Action, FunctionName) \
- FUZZ_FUNCTION(Action, FunctionName, \
- decltype(std::declval<Action::ClassType>().FunctionName()), \
- Action::ClassType* module) { \
- return module->FunctionName(); \
- }
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index f655522..64637c2 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -2901,6 +2901,20 @@
}
}
+std::ostream& operator<<(std::ostream& os, MergePhase phase) {
+ switch (phase) {
+ case MergePhase::NO_MERGE:
+ return os << "none";
+ case MergePhase::FIRST_PHASE:
+ return os << "first";
+ case MergePhase::SECOND_PHASE:
+ return os << "second";
+ default:
+ LOG(ERROR) << "Unknown merge phase: " << static_cast<uint32_t>(phase);
+ return os << "unknown(" << static_cast<uint32_t>(phase) << ")";
+ }
+}
+
UpdateState SnapshotManager::ReadUpdateState(LockedFile* lock) {
SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock);
return status.state();
@@ -3761,7 +3775,7 @@
auto update_status = ReadSnapshotUpdateStatus(file.get());
- ss << "Update state: " << ReadUpdateState(file.get()) << std::endl;
+ ss << "Update state: " << update_status.state() << std::endl;
ss << "Using snapuserd: " << update_status.using_snapuserd() << std::endl;
ss << "Using userspace snapshots: " << update_status.userspace_snapshots() << std::endl;
ss << "Using io_uring: " << update_status.io_uring_enabled() << std::endl;
@@ -3776,6 +3790,17 @@
<< std::endl;
ss << "Source build fingerprint: " << update_status.source_build_fingerprint() << std::endl;
+ if (update_status.state() == UpdateState::Merging) {
+ ss << "Merge completion: ";
+ if (!EnsureSnapuserdConnected()) {
+ ss << "N/A";
+ } else {
+ ss << snapuserd_client_->GetMergePercent() << "%";
+ }
+ ss << std::endl;
+ ss << "Merge phase: " << update_status.merge_phase() << std::endl;
+ }
+
bool ok = true;
std::vector<std::string> snapshots;
if (!ListSnapshots(file.get(), &snapshots)) {
@@ -3798,6 +3823,7 @@
ss << " allocated sectors: " << status.sectors_allocated() << std::endl;
ss << " metadata sectors: " << status.metadata_sectors() << std::endl;
ss << " compression: " << status.compression_algorithm() << std::endl;
+ ss << " merge phase: " << DecideMergePhase(status) << std::endl;
}
os << ss.rdbuf();
return ok;
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz.cpp b/fs_mgr/libsnapshot/snapshot_fuzz.cpp
deleted file mode 100644
index aced3ed..0000000
--- a/fs_mgr/libsnapshot/snapshot_fuzz.cpp
+++ /dev/null
@@ -1,352 +0,0 @@
-// Copyright (C) 2020 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.
-
-#include <stddef.h>
-#include <stdint.h>
-#include <sysexits.h>
-
-#include <functional>
-#include <sstream>
-#include <tuple>
-
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/result.h>
-#include <gtest/gtest.h>
-#include <src/libfuzzer/libfuzzer_macro.h>
-#include <storage_literals/storage_literals.h>
-
-#include "fuzz_utils.h"
-#include "snapshot_fuzz_utils.h"
-
-using android::base::Error;
-using android::base::GetBoolProperty;
-using android::base::LogId;
-using android::base::LogSeverity;
-using android::base::ReadFileToString;
-using android::base::Result;
-using android::base::SetLogger;
-using android::base::StderrLogger;
-using android::base::StdioLogger;
-using android::fs_mgr::CreateLogicalPartitionParams;
-using android::fuzz::CheckedCast;
-using android::snapshot::SnapshotFuzzData;
-using android::snapshot::SnapshotFuzzEnv;
-using chromeos_update_engine::DeltaArchiveManifest;
-using google::protobuf::FieldDescriptor;
-using google::protobuf::Message;
-using google::protobuf::RepeatedPtrField;
-
-// Avoid linking to libgsi since it needs disk I/O.
-namespace android::gsi {
-bool IsGsiRunning() {
- LOG(FATAL) << "Called IsGsiRunning";
- __builtin_unreachable();
-}
-std::string GetDsuSlot(const std::string& install_dir) {
- LOG(FATAL) << "Called GetDsuSlot(" << install_dir << ")";
- __builtin_unreachable();
-}
-} // namespace android::gsi
-
-namespace android::snapshot {
-
-const SnapshotFuzzData* current_data = nullptr;
-const SnapshotTestModule* current_module = nullptr;
-
-SnapshotFuzzEnv* GetSnapshotFuzzEnv();
-
-FUZZ_CLASS(ISnapshotManager, SnapshotManagerAction);
-
-using ProcessUpdateStateArgs = SnapshotManagerAction::Proto::ProcessUpdateStateArgs;
-using CreateLogicalAndSnapshotPartitionsArgs =
- SnapshotManagerAction::Proto::CreateLogicalAndSnapshotPartitionsArgs;
-using RecoveryCreateSnapshotDevicesArgs =
- SnapshotManagerAction::Proto::RecoveryCreateSnapshotDevicesArgs;
-
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, BeginUpdate);
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, CancelUpdate);
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, InitiateMerge);
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, NeedSnapshotsInFirstStageMount);
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, RecoveryCreateSnapshotDevices);
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, EnsureMetadataMounted);
-FUZZ_SIMPLE_FUNCTION(SnapshotManagerAction, GetSnapshotMergeStatsInstance);
-
-#define SNAPSHOT_FUZZ_FUNCTION(FunctionName, ReturnType, ...) \
- FUZZ_FUNCTION(SnapshotManagerAction, FunctionName, ReturnType, ISnapshotManager* snapshot, \
- ##__VA_ARGS__)
-
-SNAPSHOT_FUZZ_FUNCTION(FinishedSnapshotWrites, bool, bool wipe) {
- return snapshot->FinishedSnapshotWrites(wipe);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(ProcessUpdateState, bool, const ProcessUpdateStateArgs& args) {
- std::function<bool()> before_cancel;
- if (args.has_before_cancel()) {
- before_cancel = [&]() { return args.fail_before_cancel(); };
- }
- return snapshot->ProcessUpdateState({}, before_cancel);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(GetUpdateState, UpdateState, bool has_progress_arg) {
- double progress;
- return snapshot->GetUpdateState(has_progress_arg ? &progress : nullptr);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(HandleImminentDataWipe, bool, bool has_callback) {
- std::function<void()> callback;
- if (has_callback) {
- callback = []() {};
- }
- return snapshot->HandleImminentDataWipe(callback);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(Dump, bool) {
- std::stringstream ss;
- return snapshot->Dump(ss);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(CreateUpdateSnapshots, bool, const DeltaArchiveManifest& manifest) {
- return snapshot->CreateUpdateSnapshots(manifest);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(UnmapUpdateSnapshot, bool, const std::string& name) {
- return snapshot->UnmapUpdateSnapshot(name);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(CreateLogicalAndSnapshotPartitions, bool,
- const CreateLogicalAndSnapshotPartitionsArgs& args) {
- const std::string* super;
- if (args.use_correct_super()) {
- super = &GetSnapshotFuzzEnv()->super();
- } else {
- super = &args.super();
- }
- return snapshot->CreateLogicalAndSnapshotPartitions(
- *super, std::chrono::milliseconds(args.timeout_millis()));
-}
-
-SNAPSHOT_FUZZ_FUNCTION(RecoveryCreateSnapshotDevicesWithMetadata, CreateResult,
- const RecoveryCreateSnapshotDevicesArgs& args) {
- std::unique_ptr<AutoDevice> device;
- if (args.has_metadata_device_object()) {
- device = std::make_unique<NoOpAutoDevice>(args.metadata_mounted());
- }
- return snapshot->RecoveryCreateSnapshotDevices(device);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(MapUpdateSnapshot, bool,
- const CreateLogicalPartitionParamsProto& params_proto) {
- auto partition_opener = std::make_unique<TestPartitionOpener>(GetSnapshotFuzzEnv()->super());
- CreateLogicalPartitionParams params;
- if (params_proto.use_correct_super()) {
- params.block_device = GetSnapshotFuzzEnv()->super();
- } else {
- params.block_device = params_proto.block_device();
- }
- if (params_proto.has_metadata_slot()) {
- params.metadata_slot = params_proto.metadata_slot();
- }
- params.partition_name = params_proto.partition_name();
- params.force_writable = params_proto.force_writable();
- params.timeout_ms = std::chrono::milliseconds(params_proto.timeout_millis());
- params.device_name = params_proto.device_name();
- params.partition_opener = partition_opener.get();
- std::string path;
- return snapshot->MapUpdateSnapshot(params, &path);
-}
-
-SNAPSHOT_FUZZ_FUNCTION(SwitchSlot, void) {
- (void)snapshot;
- CHECK(current_module != nullptr);
- CHECK(current_module->device_info != nullptr);
- current_module->device_info->SwitchSlot();
-}
-
-// During global init, log all messages to stdio. This is only done once.
-int AllowLoggingDuringGlobalInit() {
- SetLogger(&StdioLogger);
- return 0;
-}
-
-// Only log fatal messages during tests.
-void FatalOnlyLogger(LogId logid, LogSeverity severity, const char* tag, const char* file,
- unsigned int line, const char* message) {
- if (severity == LogSeverity::FATAL) {
- StderrLogger(logid, severity, tag, file, line, message);
-
- // If test fails by a LOG(FATAL) or CHECK(), log the corpus. If it abort()'s, there's
- // nothing else we can do.
- StderrLogger(logid, severity, tag, __FILE__, __LINE__,
- "Attempting to dump current corpus:");
- if (current_data == nullptr) {
- StderrLogger(logid, severity, tag, __FILE__, __LINE__, "Current corpus is nullptr.");
- } else {
- std::string content;
- if (!google::protobuf::TextFormat::PrintToString(*current_data, &content)) {
- StderrLogger(logid, severity, tag, __FILE__, __LINE__,
- "Failed to print corpus to string.");
- } else {
- StderrLogger(logid, severity, tag, __FILE__, __LINE__, content.c_str());
- }
- }
- }
-}
-// Stop logging (except fatal messages) after global initialization. This is only done once.
-int StopLoggingAfterGlobalInit() {
- (void)GetSnapshotFuzzEnv();
- [[maybe_unused]] static protobuf_mutator::protobuf::LogSilencer log_silencer;
- SetLogger(&FatalOnlyLogger);
- return 0;
-}
-
-SnapshotFuzzEnv* GetSnapshotFuzzEnv() {
- [[maybe_unused]] static auto allow_logging = AllowLoggingDuringGlobalInit();
- static SnapshotFuzzEnv env;
- return &env;
-}
-
-SnapshotTestModule SetUpTest(const SnapshotFuzzData& snapshot_fuzz_data) {
- current_data = &snapshot_fuzz_data;
-
- auto env = GetSnapshotFuzzEnv();
- env->CheckSoftReset();
-
- auto test_module = env->CheckCreateSnapshotManager(snapshot_fuzz_data);
- current_module = &test_module;
- CHECK(test_module.snapshot);
- return test_module;
-}
-
-void TearDownTest() {
- current_module = nullptr;
- current_data = nullptr;
-}
-
-} // namespace android::snapshot
-
-DEFINE_PROTO_FUZZER(const SnapshotFuzzData& snapshot_fuzz_data) {
- using namespace android::snapshot;
-
- [[maybe_unused]] static auto stop_logging = StopLoggingAfterGlobalInit();
- auto test_module = SetUpTest(snapshot_fuzz_data);
- SnapshotManagerAction::ExecuteAll(test_module.snapshot.get(), snapshot_fuzz_data.actions());
- TearDownTest();
-}
-
-namespace android::snapshot {
-
-// Work-around to cast a 'void' value to Result<void>.
-template <typename T>
-struct GoodResult {
- template <typename F>
- static Result<T> Cast(F&& f) {
- return f();
- }
-};
-
-template <>
-struct GoodResult<void> {
- template <typename F>
- static Result<void> Cast(F&& f) {
- f();
- return {};
- }
-};
-
-class LibsnapshotFuzzerTest : public ::testing::Test {
- protected:
- static void SetUpTestCase() {
- // Do initialization once.
- (void)GetSnapshotFuzzEnv();
- }
- void SetUp() override {
- bool is_virtual_ab = GetBoolProperty("ro.virtual_ab.enabled", false);
- if (!is_virtual_ab) GTEST_SKIP() << "Test only runs on Virtual A/B devices.";
- }
- void SetUpFuzzData(const std::string& fn) {
- auto path = android::base::GetExecutableDirectory() + "/corpus/"s + fn;
- std::string proto_text;
- ASSERT_TRUE(ReadFileToString(path, &proto_text));
- snapshot_fuzz_data_ = std::make_unique<SnapshotFuzzData>();
- ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(proto_text,
- snapshot_fuzz_data_.get()));
- test_module_ = android::snapshot::SetUpTest(*snapshot_fuzz_data_);
- }
- void TearDown() override { android::snapshot::TearDownTest(); }
- template <typename FuzzFunction>
- Result<typename FuzzFunction::ReturnType> Execute(int action_index) {
- if (action_index >= snapshot_fuzz_data_->actions_size()) {
- return Error() << "Index " << action_index << " is out of bounds ("
- << snapshot_fuzz_data_->actions_size() << " actions in corpus";
- }
- const auto& action_proto = snapshot_fuzz_data_->actions(action_index);
- const auto* field_desc =
- android::fuzz::GetValueFieldDescriptor<typename FuzzFunction::ActionType>(
- action_proto);
- if (field_desc == nullptr) {
- return Error() << "Action at index " << action_index << " has no value defined.";
- }
- if (FuzzFunction::tag != field_desc->number()) {
- return Error() << "Action at index " << action_index << " is expected to be "
- << FuzzFunction::name << ", but it is " << field_desc->name()
- << " in corpus.";
- }
- return GoodResult<typename FuzzFunction::ReturnType>::Cast([&]() {
- return android::fuzz::ActionPerformer<FuzzFunction>::Invoke(test_module_.snapshot.get(),
- action_proto, field_desc);
- });
- }
-
- std::unique_ptr<SnapshotFuzzData> snapshot_fuzz_data_;
- SnapshotTestModule test_module_;
-};
-
-#define SNAPSHOT_FUZZ_FN_NAME(name) FUZZ_FUNCTION_CLASS_NAME(SnapshotManagerAction, name)
-
-MATCHER_P(ResultIs, expected, "") {
- if (!arg.ok()) {
- *result_listener << arg.error();
- return false;
- }
- *result_listener << "expected: " << expected;
- return arg.value() == expected;
-}
-
-#define ASSERT_RESULT_TRUE(actual) ASSERT_THAT(actual, ResultIs(true))
-
-// Check that launch_device.txt is executed correctly.
-TEST_F(LibsnapshotFuzzerTest, LaunchDevice) {
- SetUpFuzzData("launch_device.txt");
-
- int i = 0;
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(BeginUpdate)>(i++));
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(CreateUpdateSnapshots)>(i++));
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(MapUpdateSnapshot)>(i++)) << "sys_b";
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(MapUpdateSnapshot)>(i++)) << "vnd_b";
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(MapUpdateSnapshot)>(i++)) << "prd_b";
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(FinishedSnapshotWrites)>(i++));
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(UnmapUpdateSnapshot)>(i++)) << "sys_b";
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(UnmapUpdateSnapshot)>(i++)) << "vnd_b";
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(UnmapUpdateSnapshot)>(i++)) << "prd_b";
- ASSERT_RESULT_OK(Execute<SNAPSHOT_FUZZ_FN_NAME(SwitchSlot)>(i++));
- ASSERT_EQ("_b", test_module_.device_info->GetSlotSuffix());
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(NeedSnapshotsInFirstStageMount)>(i++));
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(CreateLogicalAndSnapshotPartitions)>(i++));
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(InitiateMerge)>(i++));
- ASSERT_RESULT_TRUE(Execute<SNAPSHOT_FUZZ_FN_NAME(ProcessUpdateState)>(i++));
- ASSERT_EQ(i, snapshot_fuzz_data_->actions_size()) << "Not all actions are executed.";
-}
-
-} // namespace android::snapshot
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp b/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp
deleted file mode 100644
index 54c6a00..0000000
--- a/fs_mgr/libsnapshot/snapshot_fuzz_utils.cpp
+++ /dev/null
@@ -1,513 +0,0 @@
-// Copyright (C) 2020 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.
-
-#include <ftw.h>
-#include <inttypes.h>
-#include <sys/mman.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sysexits.h>
-
-#include <chrono>
-#include <string>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <fs_mgr.h>
-#include <libsnapshot/auto_device.h>
-#include <libsnapshot/snapshot.h>
-#include <storage_literals/storage_literals.h>
-
-#include "snapshot_fuzz_utils.h"
-#include "utility.h"
-
-// Prepends the errno string, but it is good enough.
-#ifndef PCHECK
-#define PCHECK(x) CHECK(x) << strerror(errno) << ": "
-#endif
-
-using namespace android::storage_literals;
-using namespace std::chrono_literals;
-using namespace std::string_literals;
-
-using android::base::Basename;
-using android::base::ReadFileToString;
-using android::base::SetProperty;
-using android::base::Split;
-using android::base::StartsWith;
-using android::base::StringPrintf;
-using android::base::unique_fd;
-using android::base::WriteStringToFile;
-using android::dm::DeviceMapper;
-using android::dm::DmTarget;
-using android::dm::LoopControl;
-using android::fiemap::IImageManager;
-using android::fiemap::ImageManager;
-using android::fs_mgr::BlockDeviceInfo;
-using android::fs_mgr::FstabEntry;
-using android::fs_mgr::IPartitionOpener;
-using chromeos_update_engine::DynamicPartitionMetadata;
-
-static const char MNT_DIR[] = "/mnt";
-static const char BLOCK_SYSFS[] = "/sys/block";
-
-static const char FAKE_ROOT_NAME[] = "snapshot_fuzz";
-static const auto SUPER_IMAGE_SIZE = 16_MiB;
-static const auto DATA_IMAGE_SIZE = 16_MiB;
-static const auto FAKE_ROOT_SIZE = 64_MiB;
-
-namespace android::snapshot {
-
-bool Mkdir(const std::string& path) {
- if (mkdir(path.c_str(), 0750) == -1 && errno != EEXIST) {
- PLOG(ERROR) << "Cannot create " << path;
- return false;
- }
- return true;
-}
-
-bool RmdirRecursive(const std::string& path) {
- auto callback = [](const char* child, const struct stat*, int file_type, struct FTW*) -> int {
- switch (file_type) {
- case FTW_D:
- case FTW_DP:
- case FTW_DNR:
- if (rmdir(child) == -1) {
- PLOG(ERROR) << "rmdir " << child;
- return -1;
- }
- return 0;
- case FTW_NS:
- default:
- if (rmdir(child) != -1) break;
- [[fallthrough]];
- case FTW_F:
- case FTW_SL:
- case FTW_SLN:
- if (unlink(child) == -1) {
- PLOG(ERROR) << "unlink " << child;
- return -1;
- }
- return 0;
- }
- return 0;
- };
-
- return nftw(path.c_str(), callback, 128, FTW_DEPTH | FTW_MOUNT | FTW_PHYS) == 0;
-}
-
-std::string GetLinearBaseDeviceString(const DeviceMapper::TargetInfo& target) {
- if (target.spec.target_type != "linear"s) return {};
- auto tokens = Split(target.data, " ");
- CHECK_EQ(2, tokens.size());
- return tokens[0];
-}
-
-std::vector<std::string> GetSnapshotBaseDeviceStrings(const DeviceMapper::TargetInfo& target) {
- if (target.spec.target_type != "snapshot"s && target.spec.target_type != "snapshot-merge"s)
- return {};
- auto tokens = Split(target.data, " ");
- CHECK_EQ(4, tokens.size());
- return {tokens[0], tokens[1]};
-}
-
-bool ShouldDeleteLoopDevice(const std::string& node) {
- std::string backing_file;
- if (ReadFileToString(StringPrintf("%s/loop/backing_file", node.data()), &backing_file)) {
- if (StartsWith(backing_file, std::string(MNT_DIR) + "/" + FAKE_ROOT_NAME)) {
- return true;
- }
- }
- return false;
-}
-
-std::vector<DeviceMapper::TargetInfo> GetTableInfoIfExists(const std::string& dev_name) {
- auto& dm = DeviceMapper::Instance();
- std::vector<DeviceMapper::TargetInfo> table;
- if (!dm.GetTableInfo(dev_name, &table)) {
- PCHECK(errno == ENODEV || errno == ENXIO);
- return {};
- }
- return table;
-}
-
-std::set<std::string> GetAllBaseDeviceStrings(const std::string& child_dev) {
- std::set<std::string> ret;
- for (const auto& child_target : GetTableInfoIfExists(child_dev)) {
- auto snapshot_bases = GetSnapshotBaseDeviceStrings(child_target);
- ret.insert(snapshot_bases.begin(), snapshot_bases.end());
-
- auto linear_base = GetLinearBaseDeviceString(child_target);
- if (!linear_base.empty()) {
- ret.insert(linear_base);
- }
- }
- return ret;
-}
-
-using PropertyList = std::set<std::string>;
-void InsertProperty(const char* key, const char* /*name*/, void* cookie) {
- reinterpret_cast<PropertyList*>(cookie)->insert(key);
-}
-
-// Attempt to delete all devices that is based on dev_name, including itself.
-void CheckDeleteDeviceMapperTree(const std::string& dev_name, bool known_allow_delete = false,
- uint64_t depth = 100) {
- CHECK(depth > 0) << "Reaching max depth when deleting " << dev_name
- << ". There may be devices referencing itself. Check `dmctl list devices -v`.";
-
- auto& dm = DeviceMapper::Instance();
- auto table = GetTableInfoIfExists(dev_name);
- if (table.empty()) {
- PCHECK(dm.DeleteDeviceIfExists(dev_name)) << dev_name;
- return;
- }
-
- if (!known_allow_delete) {
- for (const auto& target : table) {
- auto base_device_string = GetLinearBaseDeviceString(target);
- if (base_device_string.empty()) continue;
- if (ShouldDeleteLoopDevice(
- StringPrintf("/sys/dev/block/%s", base_device_string.data()))) {
- known_allow_delete = true;
- break;
- }
- }
- }
- if (!known_allow_delete) {
- return;
- }
-
- std::string dev_string;
- PCHECK(dm.GetDeviceString(dev_name, &dev_string));
-
- std::vector<DeviceMapper::DmBlockDevice> devices;
- PCHECK(dm.GetAvailableDevices(&devices));
- for (const auto& child_dev : devices) {
- auto child_bases = GetAllBaseDeviceStrings(child_dev.name());
- if (child_bases.find(dev_string) != child_bases.end()) {
- CheckDeleteDeviceMapperTree(child_dev.name(), true /* known_allow_delete */, depth - 1);
- }
- }
-
- PCHECK(dm.DeleteDeviceIfExists(dev_name)) << dev_name;
-}
-
-// Attempt to clean up residues from previous runs.
-void CheckCleanupDeviceMapperDevices() {
- auto& dm = DeviceMapper::Instance();
- std::vector<DeviceMapper::DmBlockDevice> devices;
- PCHECK(dm.GetAvailableDevices(&devices));
-
- for (const auto& dev : devices) {
- CheckDeleteDeviceMapperTree(dev.name());
- }
-}
-
-void CheckUmount(const std::string& path) {
- PCHECK(TEMP_FAILURE_RETRY(umount(path.data()) == 0) || errno == ENOENT || errno == EINVAL)
- << path;
-}
-
-void CheckDetachLoopDevices(const std::set<std::string>& exclude_names = {}) {
- // ~SnapshotFuzzEnv automatically does the following.
- std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(BLOCK_SYSFS), closedir);
- PCHECK(dir != nullptr) << BLOCK_SYSFS;
- LoopControl loop_control;
- dirent* dp;
- while ((dp = readdir(dir.get())) != nullptr) {
- if (exclude_names.find(dp->d_name) != exclude_names.end()) {
- continue;
- }
- if (!ShouldDeleteLoopDevice(StringPrintf("%s/%s", BLOCK_SYSFS, dp->d_name).data())) {
- continue;
- }
- PCHECK(loop_control.Detach(StringPrintf("/dev/block/%s", dp->d_name).data()));
- }
-}
-
-void CheckUmountAll() {
- CheckUmount(std::string(MNT_DIR) + "/snapshot_fuzz_data");
- CheckUmount(std::string(MNT_DIR) + "/" + FAKE_ROOT_NAME);
-}
-
-class AutoDeleteDir : public AutoDevice {
- public:
- static std::unique_ptr<AutoDeleteDir> New(const std::string& path) {
- if (!Mkdir(path)) {
- return std::unique_ptr<AutoDeleteDir>(new AutoDeleteDir(""));
- }
- return std::unique_ptr<AutoDeleteDir>(new AutoDeleteDir(path));
- }
- ~AutoDeleteDir() {
- if (!HasDevice()) return;
- PCHECK(rmdir(name_.c_str()) == 0 || errno == ENOENT) << name_;
- }
-
- private:
- AutoDeleteDir(const std::string& path) : AutoDevice(path) {}
-};
-
-class AutoUnmount : public AutoDevice {
- public:
- ~AutoUnmount() {
- if (!HasDevice()) return;
- CheckUmount(name_);
- }
- AutoUnmount(const std::string& path) : AutoDevice(path) {}
-};
-
-class AutoUnmountTmpfs : public AutoUnmount {
- public:
- static std::unique_ptr<AutoUnmount> New(const std::string& path, uint64_t size) {
- if (mount("tmpfs", path.c_str(), "tmpfs", 0,
- (void*)StringPrintf("size=%" PRIu64, size).data()) == -1) {
- PLOG(ERROR) << "Cannot mount " << path;
- return std::unique_ptr<AutoUnmount>(new AutoUnmount(""));
- }
- return std::unique_ptr<AutoUnmount>(new AutoUnmount(path));
- }
- private:
- using AutoUnmount::AutoUnmount;
-};
-
-// A directory on tmpfs. Upon destruct, it is unmounted and deleted.
-class AutoMemBasedDir : public AutoDevice {
- public:
- static std::unique_ptr<AutoMemBasedDir> New(const std::string& name, uint64_t size) {
- auto ret = std::unique_ptr<AutoMemBasedDir>(new AutoMemBasedDir(name));
- ret->auto_delete_mount_dir_ = AutoDeleteDir::New(ret->mount_path());
- if (!ret->auto_delete_mount_dir_->HasDevice()) {
- return std::unique_ptr<AutoMemBasedDir>(new AutoMemBasedDir(""));
- }
- ret->auto_umount_mount_point_ = AutoUnmountTmpfs::New(ret->mount_path(), size);
- if (!ret->auto_umount_mount_point_->HasDevice()) {
- return std::unique_ptr<AutoMemBasedDir>(new AutoMemBasedDir(""));
- }
- // tmp_path() and persist_path does not need to be deleted upon destruction, hence it is
- // not wrapped with AutoDeleteDir.
- if (!Mkdir(ret->tmp_path())) {
- return std::unique_ptr<AutoMemBasedDir>(new AutoMemBasedDir(""));
- }
- if (!Mkdir(ret->persist_path())) {
- return std::unique_ptr<AutoMemBasedDir>(new AutoMemBasedDir(""));
- }
- return ret;
- }
- // Return the temporary scratch directory.
- std::string tmp_path() const {
- CHECK(HasDevice());
- return mount_path() + "/tmp";
- }
- // Return the temporary scratch directory.
- std::string persist_path() const {
- CHECK(HasDevice());
- return mount_path() + "/persist";
- }
- // Delete all contents in tmp_path() and start over. tmp_path() itself is re-created.
- void CheckSoftReset() {
- PCHECK(RmdirRecursive(tmp_path()));
- PCHECK(Mkdir(tmp_path()));
- }
-
- private:
- AutoMemBasedDir(const std::string& name) : AutoDevice(name) {}
- std::string mount_path() const {
- CHECK(HasDevice());
- return MNT_DIR + "/"s + name_;
- }
- std::unique_ptr<AutoDeleteDir> auto_delete_mount_dir_;
- std::unique_ptr<AutoUnmount> auto_umount_mount_point_;
-};
-
-SnapshotFuzzEnv::SnapshotFuzzEnv() {
- CheckCleanupDeviceMapperDevices();
- CheckDetachLoopDevices();
- CheckUmountAll();
-
- fake_root_ = AutoMemBasedDir::New(FAKE_ROOT_NAME, FAKE_ROOT_SIZE);
- CHECK(fake_root_ != nullptr);
- CHECK(fake_root_->HasDevice());
- loop_control_ = std::make_unique<LoopControl>();
-
- fake_data_mount_point_ = MNT_DIR + "/snapshot_fuzz_data"s;
- auto_delete_data_mount_point_ = AutoDeleteDir::New(fake_data_mount_point_);
- CHECK(auto_delete_data_mount_point_ != nullptr);
- CHECK(auto_delete_data_mount_point_->HasDevice());
-
- const auto& fake_persist_path = fake_root_->persist_path();
- mapped_super_ = CheckMapImage(fake_persist_path + "/super.img", SUPER_IMAGE_SIZE,
- loop_control_.get(), &fake_super_);
- mapped_data_ = CheckMapImage(fake_persist_path + "/data.img", DATA_IMAGE_SIZE,
- loop_control_.get(), &fake_data_block_device_);
- mounted_data_ = CheckMountFormatData(fake_data_block_device_, fake_data_mount_point_);
-}
-
-SnapshotFuzzEnv::~SnapshotFuzzEnv() {
- CheckCleanupDeviceMapperDevices();
- mounted_data_ = nullptr;
- auto_delete_data_mount_point_ = nullptr;
- mapped_data_ = nullptr;
- mapped_super_ = nullptr;
- CheckDetachLoopDevices();
- loop_control_ = nullptr;
- fake_root_ = nullptr;
- CheckUmountAll();
-}
-
-void CheckZeroFill(const std::string& file, size_t size) {
- std::string zeros(size, '\0');
- PCHECK(WriteStringToFile(zeros, file)) << "Cannot write zeros to " << file;
-}
-
-void SnapshotFuzzEnv::CheckSoftReset() {
- fake_root_->CheckSoftReset();
- CheckZeroFill(super(), SUPER_IMAGE_SIZE);
- CheckCleanupDeviceMapperDevices();
- CheckDetachLoopDevices({Basename(fake_super_), Basename(fake_data_block_device_)});
-}
-
-std::unique_ptr<IImageManager> SnapshotFuzzEnv::CheckCreateFakeImageManager() {
- auto metadata_dir = fake_root_->tmp_path() + "/images_manager_metadata";
- auto data_dir = fake_data_mount_point_ + "/image_manager_data";
- PCHECK(Mkdir(metadata_dir));
- PCHECK(Mkdir(data_dir));
- return SnapshotFuzzImageManager::Open(metadata_dir, data_dir);
-}
-
-// Helper to create a loop device for a file.
-static void CheckCreateLoopDevice(LoopControl* control, const std::string& file,
- const std::chrono::milliseconds& timeout_ms, std::string* path) {
- static constexpr int kOpenFlags = O_RDWR | O_NOFOLLOW | O_CLOEXEC;
- android::base::unique_fd file_fd(open(file.c_str(), kOpenFlags));
- PCHECK(file_fd >= 0) << "Could not open file: " << file;
- CHECK(control->Attach(file_fd, timeout_ms, path))
- << "Could not create loop device for: " << file;
-}
-
-class AutoDetachLoopDevice : public AutoDevice {
- public:
- AutoDetachLoopDevice(LoopControl* control, const std::string& device)
- : AutoDevice(device), control_(control) {}
- ~AutoDetachLoopDevice() { PCHECK(control_->Detach(name_)) << name_; }
-
- private:
- LoopControl* control_;
-};
-
-std::unique_ptr<AutoDevice> SnapshotFuzzEnv::CheckMapImage(const std::string& img_path,
- uint64_t size, LoopControl* control,
- std::string* mapped_path) {
- CheckZeroFill(img_path, size);
- CheckCreateLoopDevice(control, img_path, 1s, mapped_path);
-
- return std::make_unique<AutoDetachLoopDevice>(control, *mapped_path);
-}
-
-SnapshotTestModule SnapshotFuzzEnv::CheckCreateSnapshotManager(const SnapshotFuzzData& data) {
- SnapshotTestModule ret;
- auto partition_opener = std::make_unique<TestPartitionOpener>(super());
- ret.opener = partition_opener.get();
- CheckWriteSuperMetadata(data, *partition_opener);
- auto metadata_dir = fake_root_->tmp_path() + "/snapshot_metadata";
- PCHECK(Mkdir(metadata_dir));
- if (data.has_metadata_snapshots_dir()) {
- PCHECK(Mkdir(metadata_dir + "/snapshots"));
- }
-
- ret.device_info = new SnapshotFuzzDeviceInfo(this, data.device_info_data(),
- std::move(partition_opener), metadata_dir);
- auto snapshot = SnapshotManager::New(ret.device_info /* takes ownership */);
- ret.snapshot = std::move(snapshot);
-
- return ret;
-}
-
-const std::string& SnapshotFuzzEnv::super() const {
- return fake_super_;
-}
-
-void SnapshotFuzzEnv::CheckWriteSuperMetadata(const SnapshotFuzzData& data,
- const IPartitionOpener& opener) {
- if (!data.is_super_metadata_valid()) {
- // Leave it zero.
- return;
- }
-
- BlockDeviceInfo super_device("super", SUPER_IMAGE_SIZE, 0, 0, 4096);
- std::vector<BlockDeviceInfo> devices = {super_device};
- auto builder = MetadataBuilder::New(devices, "super", 65536, 2);
- CHECK(builder != nullptr);
-
- // Attempt to create a super partition metadata using proto. All errors are ignored.
- for (const auto& group_proto : data.super_data().dynamic_partition_metadata().groups()) {
- (void)builder->AddGroup(group_proto.name(), group_proto.size());
- for (const auto& partition_name : group_proto.partition_names()) {
- (void)builder->AddPartition(partition_name, group_proto.name(),
- LP_PARTITION_ATTR_READONLY);
- }
- }
-
- for (const auto& partition_proto : data.super_data().partitions()) {
- auto p = builder->FindPartition(partition_proto.partition_name());
- if (p == nullptr) continue;
- (void)builder->ResizePartition(p, partition_proto.new_partition_info().size());
- }
-
- auto metadata = builder->Export();
- // metadata may be nullptr if it is not valid (e.g. partition name too long).
- // In this case, just use empty super partition data.
- if (metadata == nullptr) {
- builder = MetadataBuilder::New(devices, "super", 65536, 2);
- CHECK(builder != nullptr);
- metadata = builder->Export();
- CHECK(metadata != nullptr);
- }
- CHECK(FlashPartitionTable(opener, super(), *metadata.get()));
-}
-
-std::unique_ptr<AutoDevice> SnapshotFuzzEnv::CheckMountFormatData(const std::string& blk_device,
- const std::string& mount_point) {
- FstabEntry entry{
- .blk_device = blk_device,
- .length = static_cast<off64_t>(DATA_IMAGE_SIZE),
- .fs_type = "ext4",
- .mount_point = mount_point,
- };
- CHECK(0 == fs_mgr_do_format(entry));
- CHECK(0 == fs_mgr_do_mount_one(entry));
- return std::make_unique<AutoUnmount>(mount_point);
-}
-
-SnapshotFuzzImageManager::~SnapshotFuzzImageManager() {
- // Remove relevant gsid.mapped_images.* props.
- for (const auto& name : mapped_) {
- CHECK(UnmapImageIfExists(name)) << "Cannot unmap " << name;
- }
-}
-
-bool SnapshotFuzzImageManager::MapImageDevice(const std::string& name,
- const std::chrono::milliseconds& timeout_ms,
- std::string* path) {
- if (impl_->MapImageDevice(name, timeout_ms, path)) {
- mapped_.insert(name);
- return true;
- }
- return false;
-}
-
-} // namespace android::snapshot
diff --git a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h b/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
deleted file mode 100644
index eb8246a..0000000
--- a/fs_mgr/libsnapshot/snapshot_fuzz_utils.h
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright (C) 2020 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.
-
-#include <memory>
-#include <set>
-#include <string>
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-#include <android/snapshot/snapshot_fuzz.pb.h>
-#include <libdm/loop_control.h>
-#include <libfiemap/image_manager.h>
-#include <liblp/liblp.h>
-#include <libsnapshot/auto_device.h>
-#include <libsnapshot/test_helpers.h>
-
-// libsnapshot-specific code for fuzzing. Defines fake classes that are depended
-// by SnapshotManager.
-
-#include "android/snapshot/snapshot_fuzz.pb.h"
-#include "libsnapshot/snapshot.h"
-
-namespace android::snapshot {
-
-class AutoMemBasedDir;
-class SnapshotFuzzDeviceInfo;
-
-class NoOpAutoDevice : public AutoDevice {
- public:
- NoOpAutoDevice(bool mounted) : AutoDevice(mounted ? "no_op" : "") {}
-};
-
-struct SnapshotTestModule {
- std::unique_ptr<ISnapshotManager> snapshot;
- SnapshotFuzzDeviceInfo* device_info = nullptr;
- TestPartitionOpener* opener = nullptr;
-};
-
-// Prepare test environment. This has a heavy overhead and should be done once.
-class SnapshotFuzzEnv {
- public:
- // Check if test should run at all.
- static bool ShouldSkipTest();
-
- // Initialize the environment.
- SnapshotFuzzEnv();
- ~SnapshotFuzzEnv();
-
- // Soft reset part of the environment before running the next test.
- // Abort if fails.
- void CheckSoftReset();
-
- // Create a snapshot manager for this test run.
- // Client is responsible for maintaining the lifetime of |data| over the life time of
- // ISnapshotManager.
- SnapshotTestModule CheckCreateSnapshotManager(const SnapshotFuzzData& data);
-
- std::unique_ptr<android::fiemap::IImageManager> CheckCreateFakeImageManager();
-
- // Return path to super partition.
- const std::string& super() const;
-
- private:
- std::unique_ptr<AutoMemBasedDir> fake_root_;
- std::unique_ptr<android::dm::LoopControl> loop_control_;
- std::string fake_data_mount_point_;
- std::unique_ptr<AutoDevice> auto_delete_data_mount_point_;
- std::unique_ptr<AutoDevice> mapped_super_;
- std::string fake_super_;
- std::unique_ptr<AutoDevice> mapped_data_;
- std::string fake_data_block_device_;
- std::unique_ptr<AutoDevice> mounted_data_;
-
- static std::unique_ptr<AutoDevice> CheckMapImage(const std::string& fake_persist_path,
- uint64_t size,
- android::dm::LoopControl* control,
- std::string* mapped_path);
- static std::unique_ptr<AutoDevice> CheckMountFormatData(const std::string& blk_device,
- const std::string& mount_point);
-
- void CheckWriteSuperMetadata(const SnapshotFuzzData& proto,
- const android::fs_mgr::IPartitionOpener& opener);
-};
-
-class SnapshotFuzzDeviceInfo : public ISnapshotManager::IDeviceInfo {
- public:
- using MergeStatus = ISnapshotManager::IDeviceInfo::MergeStatus;
- // Client is responsible for maintaining the lifetime of |data|.
- SnapshotFuzzDeviceInfo(SnapshotFuzzEnv* env, const FuzzDeviceInfoData& data,
- std::unique_ptr<TestPartitionOpener>&& partition_opener,
- const std::string& metadata_dir)
- : env_(env),
- data_(&data),
- partition_opener_(std::move(partition_opener)),
- metadata_dir_(metadata_dir),
- dm_(android::dm::DeviceMapper::Instance()) {}
-
- // Following APIs are mocked.
- std::string GetMetadataDir() const override { return metadata_dir_; }
- std::string GetSuperDevice(uint32_t) const override {
- // TestPartitionOpener can recognize this.
- return "super";
- }
- const android::fs_mgr::IPartitionOpener& GetPartitionOpener() const override {
- return *partition_opener_;
- }
-
- // Following APIs are fuzzed.
- std::string GetSlotSuffix() const override { return CurrentSlotIsA() ? "_a" : "_b"; }
- std::string GetOtherSlotSuffix() const override { return CurrentSlotIsA() ? "_b" : "_a"; }
- bool IsOverlayfsSetup() const override { return data_->is_overlayfs_setup(); }
- bool SetBootControlMergeStatus(MergeStatus) override {
- return data_->allow_set_boot_control_merge_status();
- }
- bool SetSlotAsUnbootable(unsigned int) override {
- return data_->allow_set_slot_as_unbootable();
- }
- bool IsRecovery() const override { return data_->is_recovery(); }
- bool IsFirstStageInit() const override { return false; }
- android::dm::IDeviceMapper& GetDeviceMapper() override { return dm_; }
- std::unique_ptr<IImageManager> OpenImageManager() const {
- return env_->CheckCreateFakeImageManager();
- }
-
- void SwitchSlot() { switched_slot_ = !switched_slot_; }
-
- private:
- SnapshotFuzzEnv* env_;
- const FuzzDeviceInfoData* data_;
- std::unique_ptr<TestPartitionOpener> partition_opener_;
- std::string metadata_dir_;
- bool switched_slot_ = false;
- android::dm::DeviceMapper& dm_;
-
- bool CurrentSlotIsA() const { return data_->slot_suffix_is_a() != switched_slot_; }
-};
-
-// A spy class on ImageManager implementation. Upon destruction, unmaps all images
-// map through this object.
-class SnapshotFuzzImageManager : public android::fiemap::IImageManager {
- public:
- static std::unique_ptr<SnapshotFuzzImageManager> Open(const std::string& metadata_dir,
- const std::string& data_dir) {
- auto impl = android::fiemap::ImageManager::Open(metadata_dir, data_dir);
- if (impl == nullptr) return nullptr;
- return std::unique_ptr<SnapshotFuzzImageManager>(
- new SnapshotFuzzImageManager(std::move(impl)));
- }
-
- ~SnapshotFuzzImageManager();
-
- // Spied APIs.
- bool MapImageDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms,
- std::string* path) override;
-
- // Other functions call through.
- android::fiemap::FiemapStatus CreateBackingImage(
- const std::string& name, uint64_t size, int flags,
- std::function<bool(uint64_t, uint64_t)>&& on_progress) override {
- return impl_->CreateBackingImage(name, size, flags, std::move(on_progress));
- }
- bool DeleteBackingImage(const std::string& name) override {
- return impl_->DeleteBackingImage(name);
- }
- bool UnmapImageDevice(const std::string& name) override {
- return impl_->UnmapImageDevice(name);
- }
- bool BackingImageExists(const std::string& name) override {
- return impl_->BackingImageExists(name);
- }
- bool IsImageMapped(const std::string& name) override { return impl_->IsImageMapped(name); }
- bool MapImageWithDeviceMapper(const IPartitionOpener& opener, const std::string& name,
- std::string* dev) override {
- return impl_->MapImageWithDeviceMapper(opener, name, dev);
- }
- bool GetMappedImageDevice(const std::string& name, std::string* device) override {
- return impl_->GetMappedImageDevice(name, device);
- }
- bool MapAllImages(const std::function<bool(std::set<std::string>)>& init) override {
- return impl_->MapAllImages(init);
- }
- bool DisableImage(const std::string& name) override { return impl_->DisableImage(name); }
- bool RemoveDisabledImages() override { return impl_->RemoveDisabledImages(); }
- std::vector<std::string> GetAllBackingImages() override { return impl_->GetAllBackingImages(); }
- android::fiemap::FiemapStatus ZeroFillNewImage(const std::string& name,
- uint64_t bytes) override {
- return impl_->ZeroFillNewImage(name, bytes);
- }
- bool RemoveAllImages() override { return impl_->RemoveAllImages(); }
- bool UnmapImageIfExists(const std::string& name) override {
- return impl_->UnmapImageIfExists(name);
- }
- bool IsImageDisabled(const std::string& name) override { return impl_->IsImageDisabled(name); }
-
- private:
- std::unique_ptr<android::fiemap::IImageManager> impl_;
- std::set<std::string> mapped_;
-
- SnapshotFuzzImageManager(std::unique_ptr<android::fiemap::IImageManager>&& impl)
- : impl_(std::move(impl)) {}
-};
-
-} // namespace android::snapshot
diff --git a/fs_mgr/libsnapshot/snapuserd/Android.bp b/fs_mgr/libsnapshot/snapuserd/Android.bp
index a67e37c..9261482 100644
--- a/fs_mgr/libsnapshot/snapuserd/Android.bp
+++ b/fs_mgr/libsnapshot/snapuserd/Android.bp
@@ -25,8 +25,6 @@
],
cflags: [
"-D_FILE_OFFSET_BITS=64",
- "-Wall",
- "-Werror",
],
export_include_dirs: ["include"],
srcs: [
@@ -54,6 +52,39 @@
vendor_ramdisk_available: true,
}
+cc_library_static {
+ name: "libsnapuserd",
+ defaults: [
+ "fs_mgr_defaults",
+ ],
+ srcs: [
+ "dm-snapshot-merge/snapuserd.cpp",
+ "dm-snapshot-merge/snapuserd_worker.cpp",
+ "dm-snapshot-merge/snapuserd_readahead.cpp",
+ "snapuserd_buffer.cpp",
+ "user-space-merge/snapuserd_core.cpp",
+ "user-space-merge/snapuserd_dm_user.cpp",
+ "user-space-merge/snapuserd_merge.cpp",
+ "user-space-merge/snapuserd_readahead.cpp",
+ "user-space-merge/snapuserd_transitions.cpp",
+ "user-space-merge/snapuserd_verify.cpp",
+ ],
+ static_libs: [
+ "libbase",
+ "libdm",
+ "libext4_utils",
+ "libsnapshot_cow",
+ "liburing",
+ ],
+ include_dirs: ["bionic/libc/kernel"],
+ header_libs: [
+ "libstorage_literals_headers",
+ ],
+ ramdisk_available: true,
+ vendor_ramdisk_available: true,
+ recovery_available: true,
+}
+
cc_defaults {
name: "snapuserd_defaults",
defaults: [
@@ -61,23 +92,8 @@
],
srcs: [
"dm-snapshot-merge/snapuserd_server.cpp",
- "dm-snapshot-merge/snapuserd.cpp",
- "dm-snapshot-merge/snapuserd_worker.cpp",
- "dm-snapshot-merge/snapuserd_readahead.cpp",
"snapuserd_daemon.cpp",
- "snapuserd_buffer.cpp",
- "user-space-merge/snapuserd_core.cpp",
- "user-space-merge/snapuserd_dm_user.cpp",
- "user-space-merge/snapuserd_merge.cpp",
- "user-space-merge/snapuserd_readahead.cpp",
- "user-space-merge/snapuserd_transitions.cpp",
"user-space-merge/snapuserd_server.cpp",
- "user-space-merge/snapuserd_verify.cpp",
- ],
-
- cflags: [
- "-Wall",
- "-Werror",
],
static_libs: [
@@ -90,6 +106,7 @@
"liblog",
"libsnapshot_cow",
"libsnapshot_snapuserd",
+ "libsnapuserd",
"libz",
"liblz4",
"libext4_utils",
@@ -125,7 +142,6 @@
],
ramdisk_available: false,
vendor_ramdisk_available: true,
- recovery_available: true,
}
// This target will install to /system/bin/snapuserd_ramdisk
@@ -158,10 +174,6 @@
"dm-snapshot-merge/snapuserd_worker.cpp",
"snapuserd_buffer.cpp",
],
- cflags: [
- "-Wall",
- "-Werror",
- ],
shared_libs: [
"libbase",
"liblog",
@@ -197,10 +209,6 @@
srcs: [
"user-space-merge/snapuserd_test.cpp",
],
- cflags: [
- "-Wall",
- "-Werror",
- ],
shared_libs: [
"libbase",
"liblog",
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
index 492c43f..2c201ff 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
@@ -31,30 +31,21 @@
using android::base::unique_fd;
SnapshotHandler::SnapshotHandler(std::string misc_name, std::string cow_device,
- std::string backing_device, std::string base_path_merge) {
+ std::string backing_device, std::string base_path_merge,
+ int num_worker_threads, bool use_iouring,
+ bool perform_verification) {
misc_name_ = std::move(misc_name);
cow_device_ = std::move(cow_device);
backing_store_device_ = std::move(backing_device);
control_device_ = "/dev/dm-user/" + misc_name_;
base_path_merge_ = std::move(base_path_merge);
+ num_worker_threads_ = num_worker_threads;
+ is_io_uring_enabled_ = use_iouring;
+ perform_verification_ = perform_verification;
}
bool SnapshotHandler::InitializeWorkers() {
- int num_worker_threads = kNumWorkerThreads;
-
- // We will need multiple worker threads only during
- // device boot after OTA. For all other purposes,
- // one thread is sufficient. We don't want to consume
- // unnecessary memory especially during OTA install phase
- // when daemon will be up during entire post install phase.
- //
- // During boot up, we need multiple threads primarily for
- // update-verification.
- if (is_socket_present_) {
- num_worker_threads = 1;
- }
-
- for (int i = 0; i < num_worker_threads; i++) {
+ for (int i = 0; i < num_worker_threads_; i++) {
std::unique_ptr<Worker> wt =
std::make_unique<Worker>(cow_device_, backing_store_device_, control_device_,
misc_name_, base_path_merge_, GetSharedPtr());
@@ -331,19 +322,11 @@
std::async(std::launch::async, &Worker::RunThread, worker_threads_[i].get()));
}
- bool partition_verification = true;
-
- // We don't want to read the blocks during first stage init or
- // during post-install phase.
- if (android::base::EndsWith(misc_name_, "-init") || is_socket_present_) {
- partition_verification = false;
- }
-
std::future<bool> merge_thread =
std::async(std::launch::async, &Worker::RunMergeThread, merge_thread_.get());
// Now that the worker threads are up, scan the partitions.
- if (partition_verification) {
+ if (perform_verification_) {
update_verify_->VerifyUpdatePartition();
}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
index 42237ef..777aa07 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
@@ -301,7 +301,8 @@
class SnapshotHandler : public std::enable_shared_from_this<SnapshotHandler> {
public:
SnapshotHandler(std::string misc_name, std::string cow_device, std::string backing_device,
- std::string base_path_merge);
+ std::string base_path_merge, int num_workers, bool use_iouring,
+ bool perform_verification);
bool InitCowDevice();
bool Start();
@@ -369,8 +370,6 @@
// Total number of blocks to be merged in a given read-ahead buffer region
void SetMergedBlockCountForNextCommit(int x) { total_ra_blocks_merged_ = x; }
int GetTotalBlocksToMerge() { return total_ra_blocks_merged_; }
- void SetSocketPresent(bool socket) { is_socket_present_ = socket; }
- void SetIouringEnabled(bool io_uring_enabled) { is_io_uring_enabled_ = io_uring_enabled; }
bool MergeInitiated() { return merge_initiated_; }
bool MergeMonitored() { return merge_monitored_; }
double GetMergePercentage() { return merge_completion_percentage_; }
@@ -441,9 +440,10 @@
bool merge_initiated_ = false;
bool merge_monitored_ = false;
bool attached_ = false;
- bool is_socket_present_;
bool is_io_uring_enabled_ = false;
bool scratch_space_ = false;
+ int num_worker_threads_ = kNumWorkerThreads;
+ bool perform_verification_ = true;
std::unique_ptr<struct io_uring> ring_;
std::unique_ptr<UpdateVerify> update_verify_;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
index d437d32..b7ce210 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
@@ -29,6 +29,7 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/scopeguard.h>
+#include <android-base/strings.h>
#include <fs_mgr/file_wait.h>
#include <snapuserd/snapuserd_client.h>
#include "snapuserd_server.h"
@@ -101,7 +102,7 @@
JoinAllThreads();
}
-UserSnapshotDmUserHandler::UserSnapshotDmUserHandler(std::shared_ptr<SnapshotHandler> snapuserd)
+HandlerThread::HandlerThread(std::shared_ptr<SnapshotHandler> snapuserd)
: snapuserd_(snapuserd), misc_name_(snapuserd_->GetMiscName()) {}
bool UserSnapshotServer::Sendmsg(android::base::borrowed_fd fd, const std::string& msg) {
@@ -307,7 +308,7 @@
}
}
-void UserSnapshotServer::RunThread(std::shared_ptr<UserSnapshotDmUserHandler> handler) {
+void UserSnapshotServer::RunThread(std::shared_ptr<HandlerThread> handler) {
LOG(INFO) << "Entering thread for handler: " << handler->misc_name();
if (!handler->snapuserd()->Start()) {
@@ -428,7 +429,7 @@
void UserSnapshotServer::JoinAllThreads() {
// Acquire the thread list within the lock.
- std::vector<std::shared_ptr<UserSnapshotDmUserHandler>> dm_users;
+ std::vector<std::shared_ptr<HandlerThread>> dm_users;
{
std::lock_guard<std::mutex> guard(lock_);
dm_users = std::move(dm_users_);
@@ -483,25 +484,42 @@
SetTerminating();
}
-std::shared_ptr<UserSnapshotDmUserHandler> UserSnapshotServer::AddHandler(
- const std::string& misc_name, const std::string& cow_device_path,
- const std::string& backing_device, const std::string& base_path_merge) {
+std::shared_ptr<HandlerThread> UserSnapshotServer::AddHandler(const std::string& misc_name,
+ const std::string& cow_device_path,
+ const std::string& backing_device,
+ const std::string& base_path_merge) {
+ // We will need multiple worker threads only during
+ // device boot after OTA. For all other purposes,
+ // one thread is sufficient. We don't want to consume
+ // unnecessary memory especially during OTA install phase
+ // when daemon will be up during entire post install phase.
+ //
+ // During boot up, we need multiple threads primarily for
+ // update-verification.
+ int num_worker_threads = kNumWorkerThreads;
+ if (is_socket_present_) {
+ num_worker_threads = 1;
+ }
+
+ bool perform_verification = true;
+ if (android::base::EndsWith(misc_name, "-init") || is_socket_present_) {
+ perform_verification = false;
+ }
+
auto snapuserd = std::make_shared<SnapshotHandler>(misc_name, cow_device_path, backing_device,
- base_path_merge);
+ base_path_merge, num_worker_threads,
+ io_uring_enabled_, perform_verification);
if (!snapuserd->InitCowDevice()) {
LOG(ERROR) << "Failed to initialize Snapuserd";
return nullptr;
}
- snapuserd->SetSocketPresent(is_socket_present_);
- snapuserd->SetIouringEnabled(io_uring_enabled_);
-
if (!snapuserd->InitializeWorkers()) {
LOG(ERROR) << "Failed to initialize workers";
return nullptr;
}
- auto handler = std::make_shared<UserSnapshotDmUserHandler>(snapuserd);
+ auto handler = std::make_shared<HandlerThread>(snapuserd);
{
std::lock_guard<std::mutex> lock(lock_);
if (FindHandler(&lock, misc_name) != dm_users_.end()) {
@@ -513,7 +531,7 @@
return handler;
}
-bool UserSnapshotServer::StartHandler(const std::shared_ptr<UserSnapshotDmUserHandler>& handler) {
+bool UserSnapshotServer::StartHandler(const std::shared_ptr<HandlerThread>& handler) {
if (handler->snapuserd()->IsAttached()) {
LOG(ERROR) << "Handler already attached";
return false;
@@ -526,7 +544,7 @@
}
bool UserSnapshotServer::StartMerge(std::lock_guard<std::mutex>* proof_of_lock,
- const std::shared_ptr<UserSnapshotDmUserHandler>& handler) {
+ const std::shared_ptr<HandlerThread>& handler) {
CHECK(proof_of_lock);
if (!handler->snapuserd()->IsAttached()) {
@@ -568,8 +586,7 @@
}
}
-std::string UserSnapshotServer::GetMergeStatus(
- const std::shared_ptr<UserSnapshotDmUserHandler>& handler) {
+std::string UserSnapshotServer::GetMergeStatus(const std::shared_ptr<HandlerThread>& handler) {
return handler->snapuserd()->GetMergeStatus();
}
@@ -604,7 +621,7 @@
}
bool UserSnapshotServer::RemoveAndJoinHandler(const std::string& misc_name) {
- std::shared_ptr<UserSnapshotDmUserHandler> handler;
+ std::shared_ptr<HandlerThread> handler;
{
std::lock_guard<std::mutex> lock(lock_);
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
index c2af61f..12c3903 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
@@ -54,9 +54,9 @@
INVALID,
};
-class UserSnapshotDmUserHandler {
+class HandlerThread {
public:
- explicit UserSnapshotDmUserHandler(std::shared_ptr<SnapshotHandler> snapuserd);
+ explicit HandlerThread(std::shared_ptr<SnapshotHandler> snapuserd);
void FreeResources() {
// Each worker thread holds a reference to snapuserd.
@@ -99,9 +99,9 @@
std::mutex lock_;
- using HandlerList = std::vector<std::shared_ptr<UserSnapshotDmUserHandler>>;
+ using HandlerList = std::vector<std::shared_ptr<HandlerThread>>;
HandlerList dm_users_;
- std::queue<std::shared_ptr<UserSnapshotDmUserHandler>> merge_handlers_;
+ std::queue<std::shared_ptr<HandlerThread>> merge_handlers_;
void AddWatchedFd(android::base::borrowed_fd fd, int events);
void AcceptClient();
@@ -118,13 +118,13 @@
bool IsTerminating() { return terminating_; }
- void RunThread(std::shared_ptr<UserSnapshotDmUserHandler> handler);
+ void RunThread(std::shared_ptr<HandlerThread> handler);
void MonitorMerge();
void JoinAllThreads();
bool StartWithSocket(bool start_listening);
- // Find a UserSnapshotDmUserHandler within a lock.
+ // Find a HandlerThread within a lock.
HandlerList::iterator FindHandler(std::lock_guard<std::mutex>* proof_of_lock,
const std::string& misc_name);
@@ -143,14 +143,14 @@
bool RunForSocketHandoff();
bool WaitForSocket();
- std::shared_ptr<UserSnapshotDmUserHandler> AddHandler(const std::string& misc_name,
- const std::string& cow_device_path,
- const std::string& backing_device,
- const std::string& base_path_merge);
- bool StartHandler(const std::shared_ptr<UserSnapshotDmUserHandler>& handler);
+ std::shared_ptr<HandlerThread> AddHandler(const std::string& misc_name,
+ const std::string& cow_device_path,
+ const std::string& backing_device,
+ const std::string& base_path_merge);
+ bool StartHandler(const std::shared_ptr<HandlerThread>& handler);
bool StartMerge(std::lock_guard<std::mutex>* proof_of_lock,
- const std::shared_ptr<UserSnapshotDmUserHandler>& handler);
- std::string GetMergeStatus(const std::shared_ptr<UserSnapshotDmUserHandler>& handler);
+ const std::shared_ptr<HandlerThread>& handler);
+ std::string GetMergeStatus(const std::shared_ptr<HandlerThread>& handler);
void WakeupMonitorMergeThread();
void SetTerminating() { terminating_ = true; }
diff --git a/init/Android.bp b/init/Android.bp
index 1aba4b3..7b52903 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -502,11 +502,13 @@
"libbase",
"libcutils",
"libselinux",
- "libhidl-gen-utils",
"liblog",
"libprocessgroup",
"libprotobuf-cpp-lite",
],
+ static_libs: [
+ "libhidl-gen-utils",
+ ],
}
cc_library_static {
diff --git a/init/service.cpp b/init/service.cpp
index 8456d1e..35beaad 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -453,6 +453,7 @@
// disable services requiring the console. For older kernels and boot
// images, not setting this at all will fall back to the old behavior
if (GetProperty("ro.boot.serialconsole", "") == "0") {
+ flags_ |= SVC_DISABLED;
return {};
}
diff --git a/init/test_kill_services/init_kill_services_test.cpp b/init/test_kill_services/init_kill_services_test.cpp
index 66a3328..5355703 100644
--- a/init/test_kill_services/init_kill_services_test.cpp
+++ b/init/test_kill_services/init_kill_services_test.cpp
@@ -29,8 +29,8 @@
const std::string initial_pid = GetProperty(pid_prop, "");
- EXPECT_EQ("running", GetProperty(status_prop, "")) << status_prop;
- EXPECT_NE("", initial_pid) << pid_prop;
+ ASSERT_EQ("running", GetProperty(status_prop, "")) << status_prop;
+ ASSERT_NE("", initial_pid) << pid_prop;
EXPECT_EQ(0, system(("kill -9 " + initial_pid).c_str()));
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 38f19ff..f7af08b 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -446,6 +446,14 @@
static int KillProcessGroup(uid_t uid, int initialPid, int signal, int retries,
int* max_processes) {
+ if (uid < 0) {
+ LOG(ERROR) << __func__ << ": invalid UID " << uid;
+ return -1;
+ }
+ if (initialPid <= 0) {
+ LOG(ERROR) << __func__ << ": invalid PID " << initialPid;
+ return -1;
+ }
std::string hierarchy_root_path;
if (CgroupsAvailable()) {
CgroupGetControllerPath(CGROUPV2_CONTROLLER_NAME, &hierarchy_root_path);
diff --git a/trusty/trusty-base.mk b/trusty/trusty-base.mk
index 5a3a320..1986c73 100644
--- a/trusty/trusty-base.mk
+++ b/trusty/trusty-base.mk
@@ -39,7 +39,6 @@
$(LOCAL_KEYMINT_PRODUCT_PACKAGE) \
android.hardware.gatekeeper-service.trusty \
trusty_apploader \
- RemoteProvisioner
PRODUCT_PROPERTY_OVERRIDES += \
ro.hardware.keystore_desede=true \