blob: 2b9c0ca91022b83b0def25ad8b381f32049ce0fd [file] [log] [blame]
Josh Gaof61f4142019-10-22 12:30:30 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Yi-Yo Chiang86674952022-08-17 04:12:28 +080017#include <getopt.h>
Josh Gaof61f4142019-10-22 12:30:30 -070018#include <stdio.h>
Josh Gaof61f4142019-10-22 12:30:30 -070019
20#include <android-base/file.h>
21#include <android-base/logging.h>
22#include <android-base/properties.h>
Yi-Yo Chiang1305c152022-08-10 12:53:39 +080023#include <binder/ProcessState.h>
Yi-Yo Chiang86674952022-08-17 04:12:28 +080024#include <cutils/android_reboot.h>
Josh Gaof61f4142019-10-22 12:30:30 -070025#include <fs_mgr_overlayfs.h>
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +080026#include <libavb_user/libavb_user.h>
Josh Gaof61f4142019-10-22 12:30:30 -070027
Yi-Yo Chiang7fd9d4f2022-08-08 13:36:50 +080028using namespace std::string_literals;
29
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +080030namespace {
Josh Gaof61f4142019-10-22 12:30:30 -070031
Yi-Yo Chiang86674952022-08-17 04:12:28 +080032void print_usage() {
33 printf(
34 "Usage:\n"
35 "\tdisable-verity\n"
36 "\tenable-verity\n"
37 "\tset-verity-state [0|1]\n"
38 "Options:\n"
39 "\t-h --help\tthis help\n"
40 "\t-R --reboot\tautomatic reboot if needed for new settings to take effect\n"
41 "\t-v --verbose\tbe noisy\n");
42}
43
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +080044#ifdef ALLOW_DISABLE_VERITY
45const bool kAllowDisableVerity = true;
46#else
47const bool kAllowDisableVerity = false;
48#endif
Josh Gaof61f4142019-10-22 12:30:30 -070049
David Anderson0aabcbc2022-08-05 19:31:44 -070050static bool SetupOrTeardownOverlayfs(bool enable) {
51 bool want_reboot = false;
52 if (enable) {
53 if (!fs_mgr_overlayfs_setup(nullptr, &want_reboot)) {
54 LOG(ERROR) << "Overlayfs setup failed.";
55 return want_reboot;
56 }
57 if (want_reboot) {
58 printf("enabling overlayfs\n");
59 }
60 } else {
61 auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
62 if (rv == OverlayfsTeardownResult::Error) {
63 LOG(ERROR) << "Overlayfs teardown failed.";
64 return want_reboot;
65 }
66 if (rv == OverlayfsTeardownResult::Busy) {
67 LOG(ERROR) << "Overlayfs is still active until reboot.";
68 return true;
69 }
70 if (want_reboot) {
71 printf("disabling overlayfs\n");
72 }
73 }
74 return want_reboot;
75}
76
Josh Gaof61f4142019-10-22 12:30:30 -070077/* Helper function to get A/B suffix, if any. If the device isn't
78 * using A/B the empty string is returned. Otherwise either "_a",
79 * "_b", ... is returned.
80 */
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +080081std::string get_ab_suffix() {
Josh Gaof61f4142019-10-22 12:30:30 -070082 return android::base::GetProperty("ro.boot.slot_suffix", "");
83}
84
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +080085bool is_avb_device_locked() {
Josh Gaof61f4142019-10-22 12:30:30 -070086 return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked";
87}
88
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +080089bool is_debuggable() {
90 return android::base::GetBoolProperty("ro.debuggable", false);
91}
92
93bool is_using_avb() {
94 // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
95 // contract, androidboot.vbmeta.digest is set by the bootloader
96 // when using AVB).
97 return !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
98}
99
Yi-Yo Chiang86674952022-08-17 04:12:28 +0800100[[noreturn]] void reboot(const std::string& name) {
101 LOG(INFO) << "Rebooting device for new settings to take effect";
102 ::sync();
103 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot," + name);
104 ::sleep(60);
105 LOG(ERROR) << "Failed to reboot";
106 ::exit(1);
107}
108
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800109struct SetVerityStateResult {
110 bool success = false;
111 bool want_reboot = false;
112};
113
Josh Gaof61f4142019-10-22 12:30:30 -0700114/* Use AVB to turn verity on/off */
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800115SetVerityStateResult SetVerityState(bool enable_verity) {
Josh Gaof61f4142019-10-22 12:30:30 -0700116 std::string ab_suffix = get_ab_suffix();
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800117 bool verity_enabled = false;
Josh Gaof61f4142019-10-22 12:30:30 -0700118
119 if (is_avb_device_locked()) {
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800120 LOG(ERROR) << "Device must be bootloader unlocked to change verity state";
121 return {};
Josh Gaof61f4142019-10-22 12:30:30 -0700122 }
123
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800124 std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(), &avb_ops_user_free);
125 if (!ops) {
126 LOG(ERROR) << "Error getting AVB ops";
127 return {};
128 }
129
130 if (!avb_user_verity_get(ops.get(), ab_suffix.c_str(), &verity_enabled)) {
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +0800131 LOG(ERROR) << "Error getting verity state";
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800132 return {};
Josh Gaof61f4142019-10-22 12:30:30 -0700133 }
134
135 if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800136 LOG(INFO) << "Verity is already " << (verity_enabled ? "enabled" : "disabled");
137 return {.success = true, .want_reboot = false};
Josh Gaof61f4142019-10-22 12:30:30 -0700138 }
139
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800140 if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +0800141 LOG(ERROR) << "Error setting verity state";
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800142 return {};
Josh Gaof61f4142019-10-22 12:30:30 -0700143 }
144
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +0800145 LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800146 return {.success = true, .want_reboot = true};
Josh Gaof61f4142019-10-22 12:30:30 -0700147}
148
Yi-Yo Chiang86674952022-08-17 04:12:28 +0800149class MyLogger {
150 public:
151 explicit MyLogger(bool verbose) : verbose_(verbose) {}
152
153 void operator()(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
154 const char* file, unsigned int line, const char* message) {
155 // Hide log starting with '[fs_mgr]' unless it's an error.
156 if (verbose_ || severity >= android::base::ERROR || message[0] != '[') {
157 fprintf(stderr, "%s\n", message);
158 }
159 logd_(id, severity, tag, file, line, message);
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +0800160 }
Yi-Yo Chiang86674952022-08-17 04:12:28 +0800161
162 private:
163 android::base::LogdLogger logd_;
164 bool verbose_;
165};
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +0800166
167} // namespace
168
Josh Gaof61f4142019-10-22 12:30:30 -0700169int main(int argc, char* argv[]) {
Yi-Yo Chiang86674952022-08-17 04:12:28 +0800170 bool auto_reboot = false;
171 bool verbose = false;
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +0800172
Yi-Yo Chiang86674952022-08-17 04:12:28 +0800173 struct option longopts[] = {
174 {"help", no_argument, nullptr, 'h'},
175 {"reboot", no_argument, nullptr, 'R'},
176 {"verbose", no_argument, nullptr, 'v'},
177 {0, 0, nullptr, 0},
178 };
179 for (int opt; (opt = ::getopt_long(argc, argv, "hRv", longopts, nullptr)) != -1;) {
180 switch (opt) {
181 case 'h':
182 print_usage();
183 return 0;
184 case 'R':
185 auto_reboot = true;
186 break;
187 case 'v':
188 verbose = true;
189 break;
190 default:
191 print_usage();
192 return 1;
193 }
Josh Gaof61f4142019-10-22 12:30:30 -0700194 }
195
Yi-Yo Chiang86674952022-08-17 04:12:28 +0800196 android::base::InitLogging(argv, MyLogger(verbose));
197
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800198 bool enable_verity = false;
Yi-Yo Chiang86674952022-08-17 04:12:28 +0800199 const std::string progname = getprogname();
200 if (progname == "enable-verity") {
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800201 enable_verity = true;
Yi-Yo Chiang86674952022-08-17 04:12:28 +0800202 } else if (progname == "disable-verity") {
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800203 enable_verity = false;
Yi-Yo Chiang86674952022-08-17 04:12:28 +0800204 } else if (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
205 // progname "set-verity-state"
206 enable_verity = (argv[optind] == "1"s);
Yi-Yo Chiang7fd9d4f2022-08-08 13:36:50 +0800207 } else {
Yi-Yo Chiang86674952022-08-17 04:12:28 +0800208 print_usage();
Yi-Yo Chiang7fd9d4f2022-08-08 13:36:50 +0800209 return 1;
Josh Gaof61f4142019-10-22 12:30:30 -0700210 }
211
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +0800212 if (!kAllowDisableVerity || !is_debuggable()) {
213 errno = EPERM;
214 PLOG(ERROR) << "Cannot disable/enable verity on user build";
215 return 1;
Josh Gaof61f4142019-10-22 12:30:30 -0700216 }
217
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +0800218 if (getuid() != 0) {
219 errno = EACCES;
220 PLOG(ERROR) << "Must be running as root (adb root)";
221 return 1;
Josh Gaof61f4142019-10-22 12:30:30 -0700222 }
223
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +0800224 if (!is_using_avb()) {
225 LOG(ERROR) << "Expected AVB device, VB1.0 is no longer supported";
226 return 1;
Josh Gaof61f4142019-10-22 12:30:30 -0700227 }
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +0800228
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800229 int exit_code = 0;
230 bool want_reboot = false;
231
232 auto ret = SetVerityState(enable_verity);
233 if (ret.success) {
234 want_reboot |= ret.want_reboot;
235 } else {
236 exit_code = 1;
Yi-Yo Chiang6bb1acb2022-08-08 13:36:50 +0800237 }
238
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800239 // Disable any overlayfs unconditionally if we want verity enabled.
240 // Enable overlayfs only if verity is successfully disabled or is already disabled.
241 if (enable_verity || ret.success) {
242 // Start a threadpool to service waitForService() callbacks as
243 // fs_mgr_overlayfs_* might call waitForService() to get the image service.
244 android::ProcessState::self()->startThreadPool();
David Anderson0aabcbc2022-08-05 19:31:44 -0700245 want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
Josh Gaof61f4142019-10-22 12:30:30 -0700246 }
247
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800248 if (want_reboot) {
Yi-Yo Chiang86674952022-08-17 04:12:28 +0800249 if (auto_reboot) {
250 reboot(progname);
251 }
Yi-Yo Chiang258f0232022-08-08 19:23:48 +0800252 printf("Reboot the device for new settings to take effect\n");
253 }
254
255 return exit_code;
Josh Gaof61f4142019-10-22 12:30:30 -0700256}