Merge "fs_mgr_overlayfs: Cleanup -user build stubs"
This commit is contained in:
commit
27cf51e71c
14 changed files with 483 additions and 463 deletions
|
|
@ -254,3 +254,39 @@ cc_binary {
|
||||||
"clean_scratch_files",
|
"clean_scratch_files",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc_binary {
|
||||||
|
name: "set-verity-state",
|
||||||
|
srcs: ["set-verity-state.cpp"],
|
||||||
|
shared_libs: [
|
||||||
|
"libbase",
|
||||||
|
"libbinder",
|
||||||
|
"libcrypto",
|
||||||
|
"libcrypto_utils",
|
||||||
|
"libfs_mgr_binder",
|
||||||
|
"libutils",
|
||||||
|
],
|
||||||
|
static_libs: [
|
||||||
|
"libavb_user",
|
||||||
|
],
|
||||||
|
header_libs: [
|
||||||
|
"libcutils_headers",
|
||||||
|
],
|
||||||
|
|
||||||
|
cflags: ["-Werror"],
|
||||||
|
cppflags: [
|
||||||
|
"-DALLOW_DISABLE_VERITY=0",
|
||||||
|
],
|
||||||
|
product_variables: {
|
||||||
|
debuggable: {
|
||||||
|
cppflags: [
|
||||||
|
"-UALLOW_DISABLE_VERITY",
|
||||||
|
"-DALLOW_DISABLE_VERITY=1",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
symlinks: [
|
||||||
|
"enable-verity",
|
||||||
|
"disable-verity",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@
|
||||||
bowgotsai@google.com
|
bowgotsai@google.com
|
||||||
dvander@google.com
|
dvander@google.com
|
||||||
elsk@google.com
|
elsk@google.com
|
||||||
|
yochiang@google.com
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
#include <selinux/selinux.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -30,6 +31,7 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/swap.h>
|
#include <sys/swap.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
@ -2359,3 +2361,49 @@ bool fs_mgr_load_verity_state(int* mode) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fs_mgr_filesystem_available(const std::string& filesystem) {
|
||||||
|
std::string filesystems;
|
||||||
|
if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) return false;
|
||||||
|
return filesystems.find("\t" + filesystem + "\n") != std::string::npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fs_mgr_get_context(const std::string& mount_point) {
|
||||||
|
char* ctx = nullptr;
|
||||||
|
if (getfilecon(mount_point.c_str(), &ctx) == -1) {
|
||||||
|
PERROR << "getfilecon " << mount_point;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string context(ctx);
|
||||||
|
free(ctx);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
OverlayfsValidResult fs_mgr_overlayfs_valid() {
|
||||||
|
// Overlayfs available in the kernel, and patched for override_creds?
|
||||||
|
if (access("/sys/module/overlay/parameters/override_creds", F_OK) == 0) {
|
||||||
|
return OverlayfsValidResult::kOverrideCredsRequired;
|
||||||
|
}
|
||||||
|
if (!fs_mgr_filesystem_available("overlay")) {
|
||||||
|
return OverlayfsValidResult::kNotSupported;
|
||||||
|
}
|
||||||
|
struct utsname uts;
|
||||||
|
if (uname(&uts) == -1) {
|
||||||
|
return OverlayfsValidResult::kNotSupported;
|
||||||
|
}
|
||||||
|
int major, minor;
|
||||||
|
if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
|
||||||
|
return OverlayfsValidResult::kNotSupported;
|
||||||
|
}
|
||||||
|
if (major < 4) {
|
||||||
|
return OverlayfsValidResult::kOk;
|
||||||
|
}
|
||||||
|
if (major > 4) {
|
||||||
|
return OverlayfsValidResult::kNotSupported;
|
||||||
|
}
|
||||||
|
if (minor > 3) {
|
||||||
|
return OverlayfsValidResult::kNotSupported;
|
||||||
|
}
|
||||||
|
return OverlayfsValidResult::kOk;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@
|
||||||
#include <storage_literals/storage_literals.h>
|
#include <storage_literals/storage_literals.h>
|
||||||
|
|
||||||
#include "fs_mgr_priv.h"
|
#include "fs_mgr_priv.h"
|
||||||
|
#include "fs_mgr_priv_overlayfs.h"
|
||||||
#include "libfiemap/utility.h"
|
#include "libfiemap/utility.h"
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
@ -71,62 +72,9 @@ bool fs_mgr_access(const std::string& path) {
|
||||||
return access(path.c_str(), F_OK) == 0;
|
return access(path.c_str(), F_OK) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine if a filesystem is available
|
|
||||||
bool fs_mgr_overlayfs_filesystem_available(const std::string& filesystem) {
|
|
||||||
std::string filesystems;
|
|
||||||
if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) return false;
|
|
||||||
return filesystems.find("\t" + filesystem + "\n") != std::string::npos;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto kLowerdirOption = "lowerdir="s;
|
const auto kLowerdirOption = "lowerdir="s;
|
||||||
const auto kUpperdirOption = "upperdir="s;
|
const auto kUpperdirOption = "upperdir="s;
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
#if ALLOW_ADBD_DISABLE_VERITY == 0 // If we are a user build, provide stubs
|
|
||||||
|
|
||||||
bool fs_mgr_wants_overlayfs(FstabEntry*) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Fstab fs_mgr_overlayfs_candidate_list(const Fstab&) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fs_mgr_overlayfs_mount_all(Fstab*) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fs_mgr_overlayfs_setup(const char*, bool*, bool) {
|
|
||||||
LOG(ERROR) << "Overlayfs remounts can only be used in debuggable builds";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char*, bool*) {
|
|
||||||
return OverlayfsTeardownResult::Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fs_mgr_overlayfs_is_setup() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace android {
|
|
||||||
namespace fs_mgr {
|
|
||||||
|
|
||||||
void MapScratchPartitionIfNeeded(Fstab*, const std::function<bool(const std::set<std::string>&)>&) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void CleanupOldScratchFiles() {}
|
|
||||||
|
|
||||||
void TeardownAllOverlayForMountPoint(const std::string&) {}
|
|
||||||
|
|
||||||
} // namespace fs_mgr
|
|
||||||
} // namespace android
|
|
||||||
|
|
||||||
#else // ALLOW_ADBD_DISABLE_VERITY == 0
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
bool fs_mgr_in_recovery() {
|
bool fs_mgr_in_recovery() {
|
||||||
// Check the existence of recovery binary instead of using the compile time
|
// Check the existence of recovery binary instead of using the compile time
|
||||||
// __ANDROID_RECOVERY__ macro.
|
// __ANDROID_RECOVERY__ macro.
|
||||||
|
|
@ -234,6 +182,28 @@ bool fs_mgr_update_blk_device(FstabEntry* entry) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev) {
|
||||||
|
struct statfs fs;
|
||||||
|
if ((statfs((mount_point + "/lost+found").c_str(), &fs) == -1) ||
|
||||||
|
(fs.f_type != EXT4_SUPER_MAGIC)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
|
||||||
|
if (fd < 0) return false;
|
||||||
|
|
||||||
|
struct ext4_super_block sb;
|
||||||
|
if ((TEMP_FAILURE_RETRY(lseek64(fd, 1024, SEEK_SET)) < 0) ||
|
||||||
|
(TEMP_FAILURE_RETRY(read(fd, &sb, sizeof(sb))) < 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fs_info info;
|
||||||
|
if (ext4_parse_sb(&sb, &info) < 0) return false;
|
||||||
|
|
||||||
|
return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
|
bool fs_mgr_overlayfs_enabled(FstabEntry* entry) {
|
||||||
// readonly filesystem, can not be mount -o remount,rw
|
// readonly filesystem, can not be mount -o remount,rw
|
||||||
// for squashfs, erofs or if free space is (near) zero making such a remount
|
// for squashfs, erofs or if free space is (near) zero making such a remount
|
||||||
|
|
@ -886,10 +856,10 @@ const std::string kMkExt4("/system/bin/mke2fs");
|
||||||
|
|
||||||
// Only a suggestion for _first_ try during mounting
|
// Only a suggestion for _first_ try during mounting
|
||||||
std::string fs_mgr_overlayfs_scratch_mount_type() {
|
std::string fs_mgr_overlayfs_scratch_mount_type() {
|
||||||
if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("f2fs")) {
|
if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_filesystem_available("f2fs")) {
|
||||||
return "f2fs";
|
return "f2fs";
|
||||||
}
|
}
|
||||||
if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_overlayfs_filesystem_available("ext4")) {
|
if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_filesystem_available("ext4")) {
|
||||||
return "ext4";
|
return "ext4";
|
||||||
}
|
}
|
||||||
return "auto";
|
return "auto";
|
||||||
|
|
@ -1233,11 +1203,41 @@ bool fs_mgr_overlayfs_setup_scratch(const Fstab& fstab) {
|
||||||
return fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type);
|
return fs_mgr_overlayfs_mount_scratch(scratch_device, mnt_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fs_mgr_overlayfs_invalid() {
|
#if ALLOW_ADBD_DISABLE_VERITY
|
||||||
if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return true;
|
constexpr bool kAllowOverlayfs = true;
|
||||||
|
#else
|
||||||
|
constexpr bool kAllowOverlayfs = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// NOTE: OverlayfsSetupAllowed() must be "stricter" than OverlayfsTeardownAllowed().
|
||||||
|
// Setup is allowed only if teardown is also allowed.
|
||||||
|
bool OverlayfsSetupAllowed(bool verbose = false) {
|
||||||
|
if (!kAllowOverlayfs) {
|
||||||
|
if (verbose) {
|
||||||
|
LOG(ERROR) << "Overlayfs remounts can only be used in debuggable builds";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Check mandatory kernel patches.
|
||||||
|
if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
|
||||||
|
if (verbose) {
|
||||||
|
LOG(ERROR) << "Kernel does not support overlayfs";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// in recovery or fastbootd, not allowed!
|
// in recovery or fastbootd, not allowed!
|
||||||
return fs_mgr_in_recovery();
|
if (fs_mgr_in_recovery()) {
|
||||||
|
if (verbose) {
|
||||||
|
LOG(ERROR) << "Unsupported overlayfs setup from recovery";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool OverlayfsTeardownAllowed() {
|
||||||
|
// Never allow on non-debuggable build.
|
||||||
|
return kAllowOverlayfs;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
@ -1331,7 +1331,7 @@ static void TryMountScratch() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
|
bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
|
||||||
if (fs_mgr_overlayfs_invalid()) {
|
if (!OverlayfsSetupAllowed()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto ret = true;
|
auto ret = true;
|
||||||
|
|
@ -1352,8 +1352,7 @@ bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fs_mgr_overlayfs_setup(const char* mount_point, bool* want_reboot, bool just_disabled_verity) {
|
bool fs_mgr_overlayfs_setup(const char* mount_point, bool* want_reboot, bool just_disabled_verity) {
|
||||||
if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
|
if (!OverlayfsSetupAllowed(/*verbose=*/true)) {
|
||||||
LOG(ERROR) << "Overlayfs is not supported";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1523,7 +1522,8 @@ static bool MapDsuScratchDevice(std::string* device) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
OverlayfsTeardownResult TeardownMountsAndScratch(const char* mount_point, bool* want_reboot) {
|
static OverlayfsTeardownResult TeardownMountsAndScratch(const char* mount_point,
|
||||||
|
bool* want_reboot) {
|
||||||
bool should_destroy_scratch = false;
|
bool should_destroy_scratch = false;
|
||||||
auto rv = OverlayfsTeardownResult::Ok;
|
auto rv = OverlayfsTeardownResult::Ok;
|
||||||
for (const auto& overlay_mount_point : OverlayMountPoints()) {
|
for (const auto& overlay_mount_point : OverlayMountPoints()) {
|
||||||
|
|
@ -1555,6 +1555,10 @@ OverlayfsTeardownResult TeardownMountsAndScratch(const char* mount_point, bool*
|
||||||
|
|
||||||
// Returns false if teardown not permitted. If something is altered, set *want_reboot.
|
// Returns false if teardown not permitted. If something is altered, set *want_reboot.
|
||||||
OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point, bool* want_reboot) {
|
OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point, bool* want_reboot) {
|
||||||
|
if (!OverlayfsTeardownAllowed()) {
|
||||||
|
// Nothing to teardown.
|
||||||
|
return OverlayfsTeardownResult::Ok;
|
||||||
|
}
|
||||||
// If scratch exists, but is not mounted, lets gain access to clean
|
// If scratch exists, but is not mounted, lets gain access to clean
|
||||||
// specific override entries.
|
// specific override entries.
|
||||||
auto mount_scratch = false;
|
auto mount_scratch = false;
|
||||||
|
|
@ -1577,12 +1581,14 @@ OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point, bool*
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fs_mgr_overlayfs_is_setup() {
|
bool fs_mgr_overlayfs_is_setup() {
|
||||||
|
if (!OverlayfsSetupAllowed()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
|
if (fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) return true;
|
||||||
Fstab fstab;
|
Fstab fstab;
|
||||||
if (!ReadDefaultFstab(&fstab)) {
|
if (!ReadDefaultFstab(&fstab)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (fs_mgr_overlayfs_invalid()) return false;
|
|
||||||
for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) {
|
for (const auto& entry : fs_mgr_overlayfs_candidate_list(fstab)) {
|
||||||
if (fs_mgr_is_verity_enabled(entry)) continue;
|
if (fs_mgr_is_verity_enabled(entry)) continue;
|
||||||
if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true;
|
if (fs_mgr_overlayfs_already_mounted(fs_mgr_mount_point(entry.mount_point))) return true;
|
||||||
|
|
@ -1595,7 +1601,7 @@ namespace fs_mgr {
|
||||||
|
|
||||||
void MapScratchPartitionIfNeeded(Fstab* fstab,
|
void MapScratchPartitionIfNeeded(Fstab* fstab,
|
||||||
const std::function<bool(const std::set<std::string>&)>& init) {
|
const std::function<bool(const std::set<std::string>&)>& init) {
|
||||||
if (fs_mgr_overlayfs_invalid()) {
|
if (!OverlayfsSetupAllowed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (GetEntryForMountPoint(fstab, kScratchMountPoint) != nullptr) {
|
if (GetEntryForMountPoint(fstab, kScratchMountPoint) != nullptr) {
|
||||||
|
|
@ -1632,6 +1638,9 @@ void MapScratchPartitionIfNeeded(Fstab* fstab,
|
||||||
}
|
}
|
||||||
|
|
||||||
void CleanupOldScratchFiles() {
|
void CleanupOldScratchFiles() {
|
||||||
|
if (!OverlayfsTeardownAllowed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!ScratchIsOnData()) {
|
if (!ScratchIsOnData()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1641,6 +1650,9 @@ void CleanupOldScratchFiles() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TeardownAllOverlayForMountPoint(const std::string& mount_point) {
|
void TeardownAllOverlayForMountPoint(const std::string& mount_point) {
|
||||||
|
if (!OverlayfsTeardownAllowed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!fs_mgr_in_recovery()) {
|
if (!fs_mgr_in_recovery()) {
|
||||||
LERROR << __FUNCTION__ << "(): must be called within recovery.";
|
LERROR << __FUNCTION__ << "(): must be called within recovery.";
|
||||||
return;
|
return;
|
||||||
|
|
@ -1701,8 +1713,6 @@ void TeardownAllOverlayForMountPoint(const std::string& mount_point) {
|
||||||
} // namespace fs_mgr
|
} // namespace fs_mgr
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
||||||
#endif // ALLOW_ADBD_DISABLE_VERITY != 0
|
|
||||||
|
|
||||||
bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only) {
|
bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only) {
|
||||||
Fstab fstab;
|
Fstab fstab;
|
||||||
if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
|
if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
|
||||||
|
|
@ -1722,65 +1732,3 @@ bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overl
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev) {
|
|
||||||
struct statfs fs;
|
|
||||||
if ((statfs((mount_point + "/lost+found").c_str(), &fs) == -1) ||
|
|
||||||
(fs.f_type != EXT4_SUPER_MAGIC)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
|
|
||||||
if (fd < 0) return false;
|
|
||||||
|
|
||||||
struct ext4_super_block sb;
|
|
||||||
if ((TEMP_FAILURE_RETRY(lseek64(fd, 1024, SEEK_SET)) < 0) ||
|
|
||||||
(TEMP_FAILURE_RETRY(read(fd, &sb, sizeof(sb))) < 0)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct fs_info info;
|
|
||||||
if (ext4_parse_sb(&sb, &info) < 0) return false;
|
|
||||||
|
|
||||||
return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string fs_mgr_get_context(const std::string& mount_point) {
|
|
||||||
char* ctx = nullptr;
|
|
||||||
if (getfilecon(mount_point.c_str(), &ctx) == -1) {
|
|
||||||
PLOG(ERROR) << "getfilecon " << mount_point;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string context(ctx);
|
|
||||||
free(ctx);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
OverlayfsValidResult fs_mgr_overlayfs_valid() {
|
|
||||||
// Overlayfs available in the kernel, and patched for override_creds?
|
|
||||||
if (fs_mgr_access("/sys/module/overlay/parameters/override_creds")) {
|
|
||||||
return OverlayfsValidResult::kOverrideCredsRequired;
|
|
||||||
}
|
|
||||||
if (!fs_mgr_overlayfs_filesystem_available("overlay")) {
|
|
||||||
return OverlayfsValidResult::kNotSupported;
|
|
||||||
}
|
|
||||||
struct utsname uts;
|
|
||||||
if (uname(&uts) == -1) {
|
|
||||||
return OverlayfsValidResult::kNotSupported;
|
|
||||||
}
|
|
||||||
int major, minor;
|
|
||||||
if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
|
|
||||||
return OverlayfsValidResult::kNotSupported;
|
|
||||||
}
|
|
||||||
if (major < 4) {
|
|
||||||
return OverlayfsValidResult::kOk;
|
|
||||||
}
|
|
||||||
if (major > 4) {
|
|
||||||
return OverlayfsValidResult::kNotSupported;
|
|
||||||
}
|
|
||||||
if (minor > 3) {
|
|
||||||
return OverlayfsValidResult::kNotSupported;
|
|
||||||
}
|
|
||||||
return OverlayfsValidResult::kOk;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,16 @@ bool fs_mgr_is_f2fs(const std::string& blk_device);
|
||||||
|
|
||||||
bool fs_mgr_teardown_verity(android::fs_mgr::FstabEntry* fstab);
|
bool fs_mgr_teardown_verity(android::fs_mgr::FstabEntry* fstab);
|
||||||
|
|
||||||
|
bool fs_mgr_filesystem_available(const std::string& filesystem);
|
||||||
|
std::string fs_mgr_get_context(const std::string& mount_point);
|
||||||
|
|
||||||
|
enum class OverlayfsValidResult {
|
||||||
|
kNotSupported = 0,
|
||||||
|
kOk,
|
||||||
|
kOverrideCredsRequired,
|
||||||
|
};
|
||||||
|
OverlayfsValidResult fs_mgr_overlayfs_valid();
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace fs_mgr {
|
namespace fs_mgr {
|
||||||
bool UnmapDevice(const std::string& name);
|
bool UnmapDevice(const std::string& name);
|
||||||
|
|
|
||||||
49
fs_mgr/fs_mgr_priv_overlayfs.h
Normal file
49
fs_mgr/fs_mgr_priv_overlayfs.h
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 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 <string>
|
||||||
|
|
||||||
|
#include <fstab/fstab.h>
|
||||||
|
|
||||||
|
bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true);
|
||||||
|
bool fs_mgr_wants_overlayfs(android::fs_mgr::FstabEntry* entry);
|
||||||
|
android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab);
|
||||||
|
|
||||||
|
// If "mount_point" is non-null, set up exactly one overlay.
|
||||||
|
// If "mount_point" is null, setup any overlays.
|
||||||
|
//
|
||||||
|
// If |want_reboot| is non-null, and a reboot is needed to apply overlays, then
|
||||||
|
// it will be true on return. The caller is responsible for initializing it.
|
||||||
|
bool fs_mgr_overlayfs_setup(const char* mount_point = nullptr, bool* want_reboot = nullptr,
|
||||||
|
bool just_disabled_verity = true);
|
||||||
|
|
||||||
|
enum class OverlayfsTeardownResult {
|
||||||
|
Ok,
|
||||||
|
Busy, // Indicates that overlays are still in use.
|
||||||
|
Error
|
||||||
|
};
|
||||||
|
OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point = nullptr,
|
||||||
|
bool* want_reboot = nullptr);
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace fs_mgr {
|
||||||
|
|
||||||
|
void CleanupOldScratchFiles();
|
||||||
|
|
||||||
|
} // namespace fs_mgr
|
||||||
|
} // namespace android
|
||||||
|
|
@ -42,6 +42,8 @@
|
||||||
#include <libavb_user/libavb_user.h>
|
#include <libavb_user/libavb_user.h>
|
||||||
#include <libgsi/libgsid.h>
|
#include <libgsi/libgsid.h>
|
||||||
|
|
||||||
|
#include "fs_mgr_priv_overlayfs.h"
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
using android::fs_mgr::Fstab;
|
using android::fs_mgr::Fstab;
|
||||||
using android::fs_mgr::FstabEntry;
|
using android::fs_mgr::FstabEntry;
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
#include <android-base/logging.h>
|
#include <android-base/logging.h>
|
||||||
#include <android-base/properties.h>
|
#include <android-base/properties.h>
|
||||||
#include <fs_mgr_overlayfs.h>
|
|
||||||
#include <fs_mgr_vendor_overlay.h>
|
#include <fs_mgr_vendor_overlay.h>
|
||||||
#include <fstab/fstab.h>
|
#include <fstab/fstab.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,51 +17,21 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <fstab/fstab.h>
|
#include <fstab/fstab.h>
|
||||||
|
|
||||||
#include <set>
|
// Keep the list short and only add interfaces that must be exported public.
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
android::fs_mgr::Fstab fs_mgr_overlayfs_candidate_list(const android::fs_mgr::Fstab& fstab);
|
|
||||||
|
|
||||||
bool fs_mgr_wants_overlayfs(android::fs_mgr::FstabEntry* entry);
|
|
||||||
bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab);
|
bool fs_mgr_overlayfs_mount_all(android::fs_mgr::Fstab* fstab);
|
||||||
bool fs_mgr_overlayfs_is_setup();
|
bool fs_mgr_overlayfs_is_setup();
|
||||||
bool fs_mgr_has_shared_blocks(const std::string& mount_point, const std::string& dev);
|
|
||||||
bool fs_mgr_overlayfs_already_mounted(const std::string& mount_point, bool overlay_only = true);
|
|
||||||
std::string fs_mgr_get_context(const std::string& mount_point);
|
|
||||||
|
|
||||||
// If "mount_point" is non-null, set up exactly one overlay.
|
|
||||||
// If "mount_point" is null, setup any overlays.
|
|
||||||
//
|
|
||||||
// If |want_reboot| is non-null, and a reboot is needed to apply overlays, then
|
|
||||||
// it will be true on return. The caller is responsible for initializing it.
|
|
||||||
bool fs_mgr_overlayfs_setup(const char* mount_point = nullptr, bool* want_reboot = nullptr,
|
|
||||||
bool just_disabled_verity = true);
|
|
||||||
|
|
||||||
enum class OverlayfsTeardownResult {
|
|
||||||
Ok,
|
|
||||||
Busy, // Indicates that overlays are still in use.
|
|
||||||
Error
|
|
||||||
};
|
|
||||||
OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char* mount_point = nullptr,
|
|
||||||
bool* want_reboot = nullptr);
|
|
||||||
|
|
||||||
enum class OverlayfsValidResult {
|
|
||||||
kNotSupported = 0,
|
|
||||||
kOk,
|
|
||||||
kOverrideCredsRequired,
|
|
||||||
};
|
|
||||||
OverlayfsValidResult fs_mgr_overlayfs_valid();
|
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace fs_mgr {
|
namespace fs_mgr {
|
||||||
|
|
||||||
void MapScratchPartitionIfNeeded(Fstab* fstab,
|
void MapScratchPartitionIfNeeded(Fstab* fstab,
|
||||||
const std::function<bool(const std::set<std::string>&)>& init);
|
const std::function<bool(const std::set<std::string>&)>& init);
|
||||||
void CleanupOldScratchFiles();
|
|
||||||
|
|
||||||
// Teardown overlays of all sources (cache dir, scratch device, DSU) for |mount_point|.
|
// Teardown overlays of all sources (cache dir, scratch device, DSU) for |mount_point|.
|
||||||
// Teardown all overlays if |mount_point| is empty.
|
// Teardown all overlays if |mount_point| is empty.
|
||||||
|
|
|
||||||
258
fs_mgr/set-verity-state.cpp
Normal file
258
fs_mgr/set-verity-state.cpp
Normal file
|
|
@ -0,0 +1,258 @@
|
||||||
|
/*
|
||||||
|
* 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 <getopt.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <android-base/file.h>
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
#include <android-base/properties.h>
|
||||||
|
#include <binder/ProcessState.h>
|
||||||
|
#include <cutils/android_reboot.h>
|
||||||
|
#include <fs_mgr_overlayfs.h>
|
||||||
|
#include <libavb_user/libavb_user.h>
|
||||||
|
|
||||||
|
#include "fs_mgr_priv_overlayfs.h"
|
||||||
|
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void print_usage() {
|
||||||
|
printf("Usage:\n"
|
||||||
|
"\tdisable-verity\n"
|
||||||
|
"\tenable-verity\n"
|
||||||
|
"\tset-verity-state [0|1]\n"
|
||||||
|
"Options:\n"
|
||||||
|
"\t-h --help\tthis help\n"
|
||||||
|
"\t-R --reboot\tautomatic reboot if needed for new settings to take effect\n"
|
||||||
|
"\t-v --verbose\tbe noisy\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ALLOW_DISABLE_VERITY
|
||||||
|
const bool kAllowDisableVerity = true;
|
||||||
|
#else
|
||||||
|
const bool kAllowDisableVerity = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool SetupOrTeardownOverlayfs(bool enable) {
|
||||||
|
bool want_reboot = false;
|
||||||
|
if (enable) {
|
||||||
|
if (!fs_mgr_overlayfs_setup(nullptr, &want_reboot)) {
|
||||||
|
LOG(ERROR) << "Overlayfs setup failed.";
|
||||||
|
return want_reboot;
|
||||||
|
}
|
||||||
|
if (want_reboot) {
|
||||||
|
printf("enabling overlayfs\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
|
||||||
|
if (rv == OverlayfsTeardownResult::Error) {
|
||||||
|
LOG(ERROR) << "Overlayfs teardown failed.";
|
||||||
|
return want_reboot;
|
||||||
|
}
|
||||||
|
if (rv == OverlayfsTeardownResult::Busy) {
|
||||||
|
LOG(ERROR) << "Overlayfs is still active until reboot.";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (want_reboot) {
|
||||||
|
printf("disabling overlayfs\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return want_reboot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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.
|
||||||
|
*/
|
||||||
|
std::string get_ab_suffix() {
|
||||||
|
return android::base::GetProperty("ro.boot.slot_suffix", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_avb_device_locked() {
|
||||||
|
return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_debuggable() {
|
||||||
|
return android::base::GetBoolProperty("ro.debuggable", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_using_avb() {
|
||||||
|
// 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).
|
||||||
|
return !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[noreturn]] void reboot(const std::string& name) {
|
||||||
|
LOG(INFO) << "Rebooting device for new settings to take effect";
|
||||||
|
::sync();
|
||||||
|
android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot," + name);
|
||||||
|
::sleep(60);
|
||||||
|
LOG(ERROR) << "Failed to reboot";
|
||||||
|
::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SetVerityStateResult {
|
||||||
|
bool success = false;
|
||||||
|
bool want_reboot = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Use AVB to turn verity on/off */
|
||||||
|
SetVerityStateResult SetVerityState(bool enable_verity) {
|
||||||
|
std::string ab_suffix = get_ab_suffix();
|
||||||
|
bool verity_enabled = false;
|
||||||
|
|
||||||
|
if (is_avb_device_locked()) {
|
||||||
|
LOG(ERROR) << "Device must be bootloader unlocked to change verity state";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(),
|
||||||
|
&avb_ops_user_free);
|
||||||
|
if (!ops) {
|
||||||
|
LOG(ERROR) << "Error getting AVB ops";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!avb_user_verity_get(ops.get(), ab_suffix.c_str(), &verity_enabled)) {
|
||||||
|
LOG(ERROR) << "Error getting verity state";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
|
||||||
|
LOG(INFO) << "Verity is already " << (verity_enabled ? "enabled" : "disabled");
|
||||||
|
return {.success = true, .want_reboot = false};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
|
||||||
|
LOG(ERROR) << "Error setting verity state";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
|
||||||
|
return {.success = true, .want_reboot = true};
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyLogger {
|
||||||
|
public:
|
||||||
|
explicit MyLogger(bool verbose) : verbose_(verbose) {}
|
||||||
|
|
||||||
|
void operator()(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
|
||||||
|
const char* file, unsigned int line, const char* message) {
|
||||||
|
// Hide log starting with '[fs_mgr]' unless it's an error.
|
||||||
|
if (verbose_ || severity >= android::base::ERROR || message[0] != '[') {
|
||||||
|
fprintf(stderr, "%s\n", message);
|
||||||
|
}
|
||||||
|
logd_(id, severity, tag, file, line, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
android::base::LogdLogger logd_;
|
||||||
|
bool verbose_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
bool auto_reboot = false;
|
||||||
|
bool verbose = false;
|
||||||
|
|
||||||
|
struct option longopts[] = {
|
||||||
|
{"help", no_argument, nullptr, 'h'},
|
||||||
|
{"reboot", no_argument, nullptr, 'R'},
|
||||||
|
{"verbose", no_argument, nullptr, 'v'},
|
||||||
|
{0, 0, nullptr, 0},
|
||||||
|
};
|
||||||
|
for (int opt; (opt = ::getopt_long(argc, argv, "hRv", longopts, nullptr)) != -1;) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'h':
|
||||||
|
print_usage();
|
||||||
|
return 0;
|
||||||
|
case 'R':
|
||||||
|
auto_reboot = true;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
verbose = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
print_usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
android::base::InitLogging(argv, MyLogger(verbose));
|
||||||
|
|
||||||
|
bool enable_verity = false;
|
||||||
|
const std::string progname = getprogname();
|
||||||
|
if (progname == "enable-verity") {
|
||||||
|
enable_verity = true;
|
||||||
|
} else if (progname == "disable-verity") {
|
||||||
|
enable_verity = false;
|
||||||
|
} else if (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
|
||||||
|
// progname "set-verity-state"
|
||||||
|
enable_verity = (argv[optind] == "1"s);
|
||||||
|
} else {
|
||||||
|
print_usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kAllowDisableVerity || !is_debuggable()) {
|
||||||
|
errno = EPERM;
|
||||||
|
PLOG(ERROR) << "Cannot disable/enable verity on user build";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getuid() != 0) {
|
||||||
|
errno = EACCES;
|
||||||
|
PLOG(ERROR) << "Must be running as root (adb root)";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_using_avb()) {
|
||||||
|
LOG(ERROR) << "Expected AVB device, VB1.0 is no longer supported";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int exit_code = 0;
|
||||||
|
bool want_reboot = false;
|
||||||
|
|
||||||
|
auto ret = SetVerityState(enable_verity);
|
||||||
|
if (ret.success) {
|
||||||
|
want_reboot |= ret.want_reboot;
|
||||||
|
} else {
|
||||||
|
exit_code = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable any overlayfs unconditionally if we want verity enabled.
|
||||||
|
// Enable overlayfs only if verity is successfully disabled or is already disabled.
|
||||||
|
if (enable_verity || ret.success) {
|
||||||
|
// Start a threadpool to service waitForService() callbacks as
|
||||||
|
// fs_mgr_overlayfs_* might call waitForService() to get the image service.
|
||||||
|
android::ProcessState::self()->startThreadPool();
|
||||||
|
want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (want_reboot) {
|
||||||
|
if (auto_reboot) {
|
||||||
|
reboot(progname);
|
||||||
|
}
|
||||||
|
printf("Reboot the device for new settings to take effect\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return exit_code;
|
||||||
|
}
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
../.clang-format-2
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
// Copyright 2019 The Android Open Source Project
|
|
||||||
|
|
||||||
package {
|
|
||||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
|
||||||
}
|
|
||||||
|
|
||||||
cc_binary {
|
|
||||||
name: "set-verity-state",
|
|
||||||
srcs: ["set-verity-state.cpp"],
|
|
||||||
shared_libs: [
|
|
||||||
"libbase",
|
|
||||||
"libbinder",
|
|
||||||
"libcrypto",
|
|
||||||
"libcrypto_utils",
|
|
||||||
"libfs_mgr_binder",
|
|
||||||
"libutils",
|
|
||||||
],
|
|
||||||
static_libs: [
|
|
||||||
"libavb_user",
|
|
||||||
],
|
|
||||||
header_libs: [
|
|
||||||
"libcutils_headers",
|
|
||||||
],
|
|
||||||
|
|
||||||
cflags: ["-Werror"],
|
|
||||||
cppflags: [
|
|
||||||
"-DALLOW_DISABLE_VERITY=0",
|
|
||||||
],
|
|
||||||
product_variables: {
|
|
||||||
debuggable: {
|
|
||||||
cppflags: [
|
|
||||||
"-UALLOW_DISABLE_VERITY",
|
|
||||||
"-DALLOW_DISABLE_VERITY=1",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
symlinks: [
|
|
||||||
"enable-verity",
|
|
||||||
"disable-verity",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
dvander@google.com
|
|
||||||
yochiang@google.com
|
|
||||||
bowgotsai@google.com
|
|
||||||
|
|
@ -1,256 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 <getopt.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <android-base/file.h>
|
|
||||||
#include <android-base/logging.h>
|
|
||||||
#include <android-base/properties.h>
|
|
||||||
#include <binder/ProcessState.h>
|
|
||||||
#include <cutils/android_reboot.h>
|
|
||||||
#include <fs_mgr_overlayfs.h>
|
|
||||||
#include <libavb_user/libavb_user.h>
|
|
||||||
|
|
||||||
using namespace std::string_literals;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void print_usage() {
|
|
||||||
printf(
|
|
||||||
"Usage:\n"
|
|
||||||
"\tdisable-verity\n"
|
|
||||||
"\tenable-verity\n"
|
|
||||||
"\tset-verity-state [0|1]\n"
|
|
||||||
"Options:\n"
|
|
||||||
"\t-h --help\tthis help\n"
|
|
||||||
"\t-R --reboot\tautomatic reboot if needed for new settings to take effect\n"
|
|
||||||
"\t-v --verbose\tbe noisy\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ALLOW_DISABLE_VERITY
|
|
||||||
const bool kAllowDisableVerity = true;
|
|
||||||
#else
|
|
||||||
const bool kAllowDisableVerity = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool SetupOrTeardownOverlayfs(bool enable) {
|
|
||||||
bool want_reboot = false;
|
|
||||||
if (enable) {
|
|
||||||
if (!fs_mgr_overlayfs_setup(nullptr, &want_reboot)) {
|
|
||||||
LOG(ERROR) << "Overlayfs setup failed.";
|
|
||||||
return want_reboot;
|
|
||||||
}
|
|
||||||
if (want_reboot) {
|
|
||||||
printf("enabling overlayfs\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
|
|
||||||
if (rv == OverlayfsTeardownResult::Error) {
|
|
||||||
LOG(ERROR) << "Overlayfs teardown failed.";
|
|
||||||
return want_reboot;
|
|
||||||
}
|
|
||||||
if (rv == OverlayfsTeardownResult::Busy) {
|
|
||||||
LOG(ERROR) << "Overlayfs is still active until reboot.";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (want_reboot) {
|
|
||||||
printf("disabling overlayfs\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return want_reboot;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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.
|
|
||||||
*/
|
|
||||||
std::string get_ab_suffix() {
|
|
||||||
return android::base::GetProperty("ro.boot.slot_suffix", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_avb_device_locked() {
|
|
||||||
return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_debuggable() {
|
|
||||||
return android::base::GetBoolProperty("ro.debuggable", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_using_avb() {
|
|
||||||
// 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).
|
|
||||||
return !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[noreturn]] void reboot(const std::string& name) {
|
|
||||||
LOG(INFO) << "Rebooting device for new settings to take effect";
|
|
||||||
::sync();
|
|
||||||
android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot," + name);
|
|
||||||
::sleep(60);
|
|
||||||
LOG(ERROR) << "Failed to reboot";
|
|
||||||
::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SetVerityStateResult {
|
|
||||||
bool success = false;
|
|
||||||
bool want_reboot = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Use AVB to turn verity on/off */
|
|
||||||
SetVerityStateResult SetVerityState(bool enable_verity) {
|
|
||||||
std::string ab_suffix = get_ab_suffix();
|
|
||||||
bool verity_enabled = false;
|
|
||||||
|
|
||||||
if (is_avb_device_locked()) {
|
|
||||||
LOG(ERROR) << "Device must be bootloader unlocked to change verity state";
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(), &avb_ops_user_free);
|
|
||||||
if (!ops) {
|
|
||||||
LOG(ERROR) << "Error getting AVB ops";
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!avb_user_verity_get(ops.get(), ab_suffix.c_str(), &verity_enabled)) {
|
|
||||||
LOG(ERROR) << "Error getting verity state";
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
|
|
||||||
LOG(INFO) << "Verity is already " << (verity_enabled ? "enabled" : "disabled");
|
|
||||||
return {.success = true, .want_reboot = false};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
|
|
||||||
LOG(ERROR) << "Error setting verity state";
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
|
|
||||||
return {.success = true, .want_reboot = true};
|
|
||||||
}
|
|
||||||
|
|
||||||
class MyLogger {
|
|
||||||
public:
|
|
||||||
explicit MyLogger(bool verbose) : verbose_(verbose) {}
|
|
||||||
|
|
||||||
void operator()(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
|
|
||||||
const char* file, unsigned int line, const char* message) {
|
|
||||||
// Hide log starting with '[fs_mgr]' unless it's an error.
|
|
||||||
if (verbose_ || severity >= android::base::ERROR || message[0] != '[') {
|
|
||||||
fprintf(stderr, "%s\n", message);
|
|
||||||
}
|
|
||||||
logd_(id, severity, tag, file, line, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
android::base::LogdLogger logd_;
|
|
||||||
bool verbose_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
|
||||||
bool auto_reboot = false;
|
|
||||||
bool verbose = false;
|
|
||||||
|
|
||||||
struct option longopts[] = {
|
|
||||||
{"help", no_argument, nullptr, 'h'},
|
|
||||||
{"reboot", no_argument, nullptr, 'R'},
|
|
||||||
{"verbose", no_argument, nullptr, 'v'},
|
|
||||||
{0, 0, nullptr, 0},
|
|
||||||
};
|
|
||||||
for (int opt; (opt = ::getopt_long(argc, argv, "hRv", longopts, nullptr)) != -1;) {
|
|
||||||
switch (opt) {
|
|
||||||
case 'h':
|
|
||||||
print_usage();
|
|
||||||
return 0;
|
|
||||||
case 'R':
|
|
||||||
auto_reboot = true;
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
verbose = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
print_usage();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
android::base::InitLogging(argv, MyLogger(verbose));
|
|
||||||
|
|
||||||
bool enable_verity = false;
|
|
||||||
const std::string progname = getprogname();
|
|
||||||
if (progname == "enable-verity") {
|
|
||||||
enable_verity = true;
|
|
||||||
} else if (progname == "disable-verity") {
|
|
||||||
enable_verity = false;
|
|
||||||
} else if (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
|
|
||||||
// progname "set-verity-state"
|
|
||||||
enable_verity = (argv[optind] == "1"s);
|
|
||||||
} else {
|
|
||||||
print_usage();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!kAllowDisableVerity || !is_debuggable()) {
|
|
||||||
errno = EPERM;
|
|
||||||
PLOG(ERROR) << "Cannot disable/enable verity on user build";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getuid() != 0) {
|
|
||||||
errno = EACCES;
|
|
||||||
PLOG(ERROR) << "Must be running as root (adb root)";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_using_avb()) {
|
|
||||||
LOG(ERROR) << "Expected AVB device, VB1.0 is no longer supported";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int exit_code = 0;
|
|
||||||
bool want_reboot = false;
|
|
||||||
|
|
||||||
auto ret = SetVerityState(enable_verity);
|
|
||||||
if (ret.success) {
|
|
||||||
want_reboot |= ret.want_reboot;
|
|
||||||
} else {
|
|
||||||
exit_code = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable any overlayfs unconditionally if we want verity enabled.
|
|
||||||
// Enable overlayfs only if verity is successfully disabled or is already disabled.
|
|
||||||
if (enable_verity || ret.success) {
|
|
||||||
// Start a threadpool to service waitForService() callbacks as
|
|
||||||
// fs_mgr_overlayfs_* might call waitForService() to get the image service.
|
|
||||||
android::ProcessState::self()->startThreadPool();
|
|
||||||
want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (want_reboot) {
|
|
||||||
if (auto_reboot) {
|
|
||||||
reboot(progname);
|
|
||||||
}
|
|
||||||
printf("Reboot the device for new settings to take effect\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return exit_code;
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue