diff --git a/adb/Android.bp b/adb/Android.bp index bf71919cf..d79a97fc4 100644 --- a/adb/Android.bp +++ b/adb/Android.bp @@ -430,16 +430,10 @@ cc_library { "daemon/mdns.cpp", "daemon/reboot_service.cpp", "daemon/restart_service.cpp", - "daemon/set_verity_enable_state_service.cpp", - ], - static_libs: [ - "libavb_user", ], shared_libs: [ "libbootloader_message", "libmdnssd", - "libfec", - "libfs_mgr", "libselinux", ], }, @@ -517,6 +511,7 @@ phony { name: "adbd_system_binaries", required: [ "abb", + "set-verity-state", ] } diff --git a/adb/daemon/services.cpp b/adb/daemon/services.cpp index 181a8c5f0..e38bb0053 100644 --- a/adb/daemon/services.cpp +++ b/adb/daemon/services.cpp @@ -55,7 +55,6 @@ #include "daemon/framebuffer_service.h" #include "daemon/reboot_service.h" #include "daemon/restart_service.h" -#include "daemon/set_verity_enable_state_service.h" #include "daemon/shell_service.h" @@ -269,11 +268,11 @@ unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) { return StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone); } else if (name.starts_with("disable-verity:")) { - return create_service_thread("verity-on", std::bind(set_verity_enabled_state_service, - std::placeholders::_1, false)); + return StartSubprocess("/system/bin/disable-verity", nullptr, SubprocessType::kRaw, + SubprocessProtocol::kNone); } else if (name.starts_with("enable-verity:")) { - return create_service_thread("verity-off", std::bind(set_verity_enabled_state_service, - std::placeholders::_1, true)); + return StartSubprocess("/system/bin/enable-verity", nullptr, SubprocessType::kRaw, + SubprocessProtocol::kNone); } else if (android::base::ConsumePrefix(&name, "tcpip:")) { std::string str(name); diff --git a/adb/daemon/set_verity_enable_state_service.cpp b/adb/daemon/set_verity_enable_state_service.cpp deleted file mode 100644 index 4fbccdbd5..000000000 --- a/adb/daemon/set_verity_enable_state_service.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (C) 2014 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. - */ - -#define TRACE_TAG ADB - -#include "set_verity_enable_state_service.h" -#include "sysdeps.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "adb.h" -#include "adb_io.h" -#include "adb_unique_fd.h" - -#include "fec/io.h" - -#ifdef ALLOW_ADBD_DISABLE_VERITY -static const bool kAllowDisableVerity = true; -#else -static const bool kAllowDisableVerity = false; -#endif - -void suggest_run_adb_root(int fd) { - if (getuid() != 0) WriteFdExactly(fd, "Maybe run adb root?\n"); -} - -static bool make_block_device_writable(const std::string& dev) { - unique_fd fd(unix_open(dev, O_RDONLY | O_CLOEXEC)); - if (fd == -1) { - return false; - } - - int OFF = 0; - bool result = (ioctl(fd.get(), BLKROSET, &OFF) != -1); - return result; -} - -/* Turn verity on/off */ -static bool set_verity_enabled_state(int fd, const char* block_device, const char* mount_point, - bool enable) { - if (!make_block_device_writable(block_device)) { - WriteFdFmt(fd, "Could not make block device %s writable (%s).\n", - block_device, strerror(errno)); - return false; - } - - fec::io fh(block_device, O_RDWR); - - if (!fh) { - WriteFdFmt(fd, "Could not open block device %s (%s).\n", block_device, strerror(errno)); - suggest_run_adb_root(fd); - return false; - } - - fec_verity_metadata metadata; - - if (!fh.get_verity_metadata(metadata)) { - WriteFdExactly(fd, "Couldn't find verity metadata!\n"); - return false; - } - - if (!enable && metadata.disabled) { - WriteFdFmt(fd, "Verity already disabled on %s\n", mount_point); - return false; - } - - if (enable && !metadata.disabled) { - WriteFdFmt(fd, "Verity already enabled on %s\n", mount_point); - return false; - } - - if (!fh.set_verity_status(enable)) { - WriteFdFmt(fd, "Could not set verity %s flag on device %s with error %s\n", - enable ? "enabled" : "disabled", - block_device, strerror(errno)); - return false; - } - - auto change = false; - errno = 0; - if (enable ? fs_mgr_overlayfs_teardown(mount_point, &change) - : fs_mgr_overlayfs_setup(nullptr, mount_point, &change)) { - if (change) { - WriteFdFmt(fd, "%s overlayfs for %s\n", enable ? "disabling" : "using", mount_point); - } - } else if (errno) { - int expected_errno = enable ? EBUSY : ENOENT; - if (errno != expected_errno) { - WriteFdFmt(fd, "Overlayfs %s for %s failed with error %s\n", - enable ? "teardown" : "setup", mount_point, strerror(errno)); - } - } - WriteFdFmt(fd, "Verity %s on %s\n", enable ? "enabled" : "disabled", mount_point); - return true; -} - -/* Helper function to get A/B suffix, if any. If the device isn't - * using A/B the empty string is returned. Otherwise either "_a", - * "_b", ... is returned. - */ -static std::string get_ab_suffix() { - return android::base::GetProperty("ro.boot.slot_suffix", ""); -} - -static bool is_avb_device_locked() { - return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked"; -} - -static bool overlayfs_setup(int fd, bool enable) { - auto change = false; - errno = 0; - if (enable ? fs_mgr_overlayfs_teardown(nullptr, &change) - : fs_mgr_overlayfs_setup(nullptr, nullptr, &change)) { - if (change) { - WriteFdFmt(fd, "%s overlayfs\n", enable ? "disabling" : "using"); - } - } else if (errno) { - WriteFdFmt(fd, "Overlayfs %s failed with error %s\n", enable ? "teardown" : "setup", - strerror(errno)); - suggest_run_adb_root(fd); - } - return change; -} - -/* Use AVB to turn verity on/off */ -static bool set_avb_verity_enabled_state(int fd, AvbOps* ops, bool enable_verity) { - std::string ab_suffix = get_ab_suffix(); - bool verity_enabled; - - if (is_avb_device_locked()) { - WriteFdExactly(fd, "Device is locked. Please unlock the device first\n"); - return false; - } - - if (!avb_user_verity_get(ops, ab_suffix.c_str(), &verity_enabled)) { - WriteFdExactly(fd, "Error getting verity state. Try adb root first?\n"); - return false; - } - - if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) { - WriteFdFmt(fd, "verity is already %s\n", verity_enabled ? "enabled" : "disabled"); - return false; - } - - if (!avb_user_verity_set(ops, ab_suffix.c_str(), enable_verity)) { - WriteFdExactly(fd, "Error setting verity\n"); - return false; - } - - overlayfs_setup(fd, enable_verity); - WriteFdFmt(fd, "Successfully %s verity\n", enable_verity ? "enabled" : "disabled"); - return true; -} - -void set_verity_enabled_state_service(unique_fd fd, bool enable) { - bool any_changed = false; - - // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by - // contract, androidboot.vbmeta.digest is set by the bootloader - // when using AVB). - bool using_avb = !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty(); - - // If using AVB, dm-verity is used on any build so we want it to - // be possible to disable/enable on any build (except USER). For - // VB1.0 dm-verity is only enabled on certain builds. - if (!using_avb) { - if (!kAllowDisableVerity) { - WriteFdFmt(fd.get(), "%s-verity only works for userdebug builds\n", - enable ? "enable" : "disable"); - } - - if (!android::base::GetBoolProperty("ro.secure", false)) { - overlayfs_setup(fd.get(), enable); - WriteFdExactly(fd.get(), "verity not enabled - ENG build\n"); - return; - } - } - - // Should never be possible to disable dm-verity on a USER build - // regardless of using AVB or VB1.0. - if (!__android_log_is_debuggable()) { - WriteFdExactly(fd.get(), "verity cannot be disabled/enabled - USER build\n"); - return; - } - - if (using_avb) { - // Yep, the system is using AVB. - AvbOps* ops = avb_ops_user_new(); - if (ops == nullptr) { - WriteFdExactly(fd.get(), "Error getting AVB ops\n"); - return; - } - if (set_avb_verity_enabled_state(fd.get(), ops, enable)) { - any_changed = true; - } - avb_ops_user_free(ops); - } else { - // Not using AVB - assume VB1.0. - - // read all fstab entries at once from all sources - android::fs_mgr::Fstab fstab; - if (!android::fs_mgr::ReadDefaultFstab(&fstab)) { - WriteFdExactly(fd.get(), "Failed to read fstab\n"); - suggest_run_adb_root(fd.get()); - return; - } - - // Loop through entries looking for ones that verity manages. - for (const auto& entry : fstab) { - if (entry.fs_mgr_flags.verify) { - if (set_verity_enabled_state(fd.get(), entry.blk_device.c_str(), - entry.mount_point.c_str(), enable)) { - any_changed = true; - } - } - } - } - if (!any_changed) any_changed = overlayfs_setup(fd.get(), enable); - - if (any_changed) { - WriteFdExactly(fd.get(), "Now reboot your device for settings to take effect\n"); - } -} diff --git a/adb/daemon/set_verity_enable_state_service.h b/adb/daemon/set_verity_enable_state_service.h deleted file mode 100644 index c0ed98e87..000000000 --- a/adb/daemon/set_verity_enable_state_service.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2018 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 "adb_unique_fd.h" - -#if defined(__ANDROID__) -void set_verity_enabled_state_service(unique_fd fd, bool enable); -#endif diff --git a/set-verity-state/.clang-format b/set-verity-state/.clang-format new file mode 120000 index 000000000..fd0645fdf --- /dev/null +++ b/set-verity-state/.clang-format @@ -0,0 +1 @@ +../.clang-format-2 \ No newline at end of file diff --git a/set-verity-state/Android.bp b/set-verity-state/Android.bp new file mode 100644 index 000000000..cd8c8c57d --- /dev/null +++ b/set-verity-state/Android.bp @@ -0,0 +1,24 @@ +// Copyright 2019 The Android Open Source Project + +cc_binary { + name: "set-verity-state", + srcs: ["set-verity-state.cpp"], + shared_libs: [ + "libbase", + "libcrypto", + "libcrypto_utils", + "libcutils", + "libfec", + "libfs_mgr", + "liblog", + ], + static_libs: [ + "libavb_user", + ], + + cflags: ["-Werror"], + symlinks: [ + "enable-verity", + "disable-verity", + ], +} diff --git a/set-verity-state/set-verity-state.cpp b/set-verity-state/set-verity-state.cpp new file mode 100644 index 000000000..0a26abaa2 --- /dev/null +++ b/set-verity-state/set-verity-state.cpp @@ -0,0 +1,274 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fec/io.h" + +#ifdef ALLOW_DISABLE_VERITY +static const bool kAllowDisableVerity = true; +#else +static const bool kAllowDisableVerity = false; +#endif + +using android::base::unique_fd; + +static void suggest_run_adb_root() { + if (getuid() != 0) printf("Maybe run adb root?\n"); +} + +static bool make_block_device_writable(const std::string& dev) { + unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC)); + if (fd == -1) { + return false; + } + + int OFF = 0; + bool result = (ioctl(fd.get(), BLKROSET, &OFF) != -1); + return result; +} + +/* Turn verity on/off */ +static bool set_verity_enabled_state(const char* block_device, const char* mount_point, + bool enable) { + if (!make_block_device_writable(block_device)) { + printf("Could not make block device %s writable (%s).\n", block_device, strerror(errno)); + return false; + } + + fec::io fh(block_device, O_RDWR); + + if (!fh) { + printf("Could not open block device %s (%s).\n", block_device, strerror(errno)); + suggest_run_adb_root(); + return false; + } + + fec_verity_metadata metadata; + + if (!fh.get_verity_metadata(metadata)) { + printf("Couldn't find verity metadata!\n"); + return false; + } + + if (!enable && metadata.disabled) { + printf("Verity already disabled on %s\n", mount_point); + return false; + } + + if (enable && !metadata.disabled) { + printf("Verity already enabled on %s\n", mount_point); + return false; + } + + if (!fh.set_verity_status(enable)) { + printf("Could not set verity %s flag on device %s with error %s\n", + enable ? "enabled" : "disabled", block_device, strerror(errno)); + return false; + } + + auto change = false; + errno = 0; + if (enable ? fs_mgr_overlayfs_teardown(mount_point, &change) + : fs_mgr_overlayfs_setup(nullptr, mount_point, &change)) { + if (change) { + printf("%s overlayfs for %s\n", enable ? "disabling" : "using", mount_point); + } + } else if (errno) { + int expected_errno = enable ? EBUSY : ENOENT; + if (errno != expected_errno) { + printf("Overlayfs %s for %s failed with error %s\n", enable ? "teardown" : "setup", + mount_point, strerror(errno)); + } + } + printf("Verity %s on %s\n", enable ? "enabled" : "disabled", mount_point); + return true; +} + +/* Helper function to get A/B suffix, if any. If the device isn't + * using A/B the empty string is returned. Otherwise either "_a", + * "_b", ... is returned. + */ +static std::string get_ab_suffix() { + return android::base::GetProperty("ro.boot.slot_suffix", ""); +} + +static bool is_avb_device_locked() { + return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked"; +} + +static bool overlayfs_setup(bool enable) { + auto change = false; + errno = 0; + if (enable ? fs_mgr_overlayfs_teardown(nullptr, &change) + : fs_mgr_overlayfs_setup(nullptr, nullptr, &change)) { + if (change) { + printf("%s overlayfs\n", enable ? "disabling" : "using"); + } + } else if (errno) { + printf("Overlayfs %s failed with error %s\n", enable ? "teardown" : "setup", strerror(errno)); + suggest_run_adb_root(); + } + return change; +} + +/* Use AVB to turn verity on/off */ +static bool set_avb_verity_enabled_state(AvbOps* ops, bool enable_verity) { + std::string ab_suffix = get_ab_suffix(); + bool verity_enabled; + + if (is_avb_device_locked()) { + printf("Device is locked. Please unlock the device first\n"); + return false; + } + + if (!avb_user_verity_get(ops, ab_suffix.c_str(), &verity_enabled)) { + printf("Error getting verity state. Try adb root first?\n"); + return false; + } + + if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) { + printf("verity is already %s\n", verity_enabled ? "enabled" : "disabled"); + return false; + } + + if (!avb_user_verity_set(ops, ab_suffix.c_str(), enable_verity)) { + printf("Error setting verity\n"); + return false; + } + + overlayfs_setup(enable_verity); + printf("Successfully %s verity\n", enable_verity ? "enabled" : "disabled"); + return true; +} + +int main(int argc, char* argv[]) { + if (argc == 0) { + LOG(FATAL) << "set-verity-state called with empty argv"; + } + + std::optional enable_opt; + std::string procname = android::base::Basename(argv[0]); + if (procname == "enable-verity") { + enable_opt = true; + } else if (procname == "disable-verity") { + enable_opt = false; + } + + if (!enable_opt.has_value()) { + if (argc != 2) { + printf("usage: %s [1|0]\n", argv[0]); + return 1; + } + + if (strcmp(argv[1], "1") == 0) { + enable_opt = true; + } else if (strcmp(argv[1], "0") == 0) { + enable_opt = false; + } else { + printf("usage: %s [1|0]\n", argv[0]); + return 1; + } + } + + bool enable = enable_opt.value(); + + bool any_changed = false; + + // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by + // contract, androidboot.vbmeta.digest is set by the bootloader + // when using AVB). + bool using_avb = !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty(); + + // If using AVB, dm-verity is used on any build so we want it to + // be possible to disable/enable on any build (except USER). For + // VB1.0 dm-verity is only enabled on certain builds. + if (!using_avb) { + if (!kAllowDisableVerity) { + printf("%s only works for userdebug builds\n", argv[0]); + } + + if (!android::base::GetBoolProperty("ro.secure", false)) { + overlayfs_setup(enable); + printf("verity not enabled - ENG build\n"); + return 0; + } + } + + // Should never be possible to disable dm-verity on a USER build + // regardless of using AVB or VB1.0. + if (!__android_log_is_debuggable()) { + printf("verity cannot be disabled/enabled - USER build\n"); + return 0; + } + + if (using_avb) { + // Yep, the system is using AVB. + AvbOps* ops = avb_ops_user_new(); + if (ops == nullptr) { + printf("Error getting AVB ops\n"); + return 1; + } + if (set_avb_verity_enabled_state(ops, enable)) { + any_changed = true; + } + avb_ops_user_free(ops); + } else { + // Not using AVB - assume VB1.0. + + // read all fstab entries at once from all sources + android::fs_mgr::Fstab fstab; + if (!android::fs_mgr::ReadDefaultFstab(&fstab)) { + printf("Failed to read fstab\n"); + suggest_run_adb_root(); + return 0; + } + + // Loop through entries looking for ones that verity manages. + for (const auto& entry : fstab) { + if (entry.fs_mgr_flags.verify) { + if (set_verity_enabled_state(entry.blk_device.c_str(), entry.mount_point.c_str(), enable)) { + any_changed = true; + } + } + } + } + if (!any_changed) any_changed = overlayfs_setup(enable); + + if (any_changed) { + printf("Now reboot your device for settings to take effect\n"); + } + + return 0; +}