blob: 84ee01f48b29f30eed7a85d35fffc3ea5b23d52e [file] [log] [blame]
Yi-Yo Chiangad06b402022-09-21 22:10:33 +08001/*
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
17#include <getopt.h>
18#include <stdio.h>
19
20#include <android-base/file.h>
21#include <android-base/logging.h>
22#include <android-base/properties.h>
23#include <binder/ProcessState.h>
24#include <cutils/android_reboot.h>
25#include <fs_mgr_overlayfs.h>
26#include <libavb_user/libavb_user.h>
27
28#include "fs_mgr_priv_overlayfs.h"
29
30using namespace std::string_literals;
31
32namespace {
33
34void print_usage() {
35 printf("Usage:\n"
36 "\tdisable-verity\n"
37 "\tenable-verity\n"
38 "\tset-verity-state [0|1]\n"
39 "Options:\n"
40 "\t-h --help\tthis help\n"
41 "\t-R --reboot\tautomatic reboot if needed for new settings to take effect\n"
42 "\t-v --verbose\tbe noisy\n");
43}
44
45#ifdef ALLOW_DISABLE_VERITY
46const bool kAllowDisableVerity = true;
47#else
48const bool kAllowDisableVerity = false;
49#endif
50
51static bool SetupOrTeardownOverlayfs(bool enable) {
52 bool want_reboot = false;
53 if (enable) {
54 if (!fs_mgr_overlayfs_setup(nullptr, &want_reboot)) {
55 LOG(ERROR) << "Overlayfs setup failed.";
56 return want_reboot;
57 }
58 if (want_reboot) {
59 printf("enabling overlayfs\n");
60 }
61 } else {
62 auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
63 if (rv == OverlayfsTeardownResult::Error) {
64 LOG(ERROR) << "Overlayfs teardown failed.";
65 return want_reboot;
66 }
67 if (rv == OverlayfsTeardownResult::Busy) {
68 LOG(ERROR) << "Overlayfs is still active until reboot.";
69 return true;
70 }
71 if (want_reboot) {
72 printf("disabling overlayfs\n");
73 }
74 }
75 return want_reboot;
76}
77
78/* Helper function to get A/B suffix, if any. If the device isn't
79 * using A/B the empty string is returned. Otherwise either "_a",
80 * "_b", ... is returned.
81 */
82std::string get_ab_suffix() {
83 return android::base::GetProperty("ro.boot.slot_suffix", "");
84}
85
86bool is_avb_device_locked() {
87 return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked";
88}
89
90bool is_debuggable() {
91 return android::base::GetBoolProperty("ro.debuggable", false);
92}
93
94bool is_using_avb() {
95 // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
96 // contract, androidboot.vbmeta.digest is set by the bootloader
97 // when using AVB).
98 return !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
99}
100
101[[noreturn]] void reboot(const std::string& name) {
102 LOG(INFO) << "Rebooting device for new settings to take effect";
103 ::sync();
104 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot," + name);
105 ::sleep(60);
106 LOG(ERROR) << "Failed to reboot";
107 ::exit(1);
108}
109
110struct SetVerityStateResult {
111 bool success = false;
112 bool want_reboot = false;
113};
114
115/* Use AVB to turn verity on/off */
116SetVerityStateResult SetVerityState(bool enable_verity) {
117 std::string ab_suffix = get_ab_suffix();
118 bool verity_enabled = false;
119
120 if (is_avb_device_locked()) {
121 LOG(ERROR) << "Device must be bootloader unlocked to change verity state";
122 return {};
123 }
124
125 std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(),
126 &avb_ops_user_free);
127 if (!ops) {
128 LOG(ERROR) << "Error getting AVB ops";
129 return {};
130 }
131
132 if (!avb_user_verity_get(ops.get(), ab_suffix.c_str(), &verity_enabled)) {
133 LOG(ERROR) << "Error getting verity state";
134 return {};
135 }
136
137 if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
138 LOG(INFO) << "Verity is already " << (verity_enabled ? "enabled" : "disabled");
139 return {.success = true, .want_reboot = false};
140 }
141
142 if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
143 LOG(ERROR) << "Error setting verity state";
144 return {};
145 }
146
147 LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
148 return {.success = true, .want_reboot = true};
149}
150
151class MyLogger {
152 public:
153 explicit MyLogger(bool verbose) : verbose_(verbose) {}
154
155 void operator()(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
156 const char* file, unsigned int line, const char* message) {
157 // Hide log starting with '[fs_mgr]' unless it's an error.
158 if (verbose_ || severity >= android::base::ERROR || message[0] != '[') {
159 fprintf(stderr, "%s\n", message);
160 }
161 logd_(id, severity, tag, file, line, message);
162 }
163
164 private:
165 android::base::LogdLogger logd_;
166 bool verbose_;
167};
168
169} // namespace
170
171int main(int argc, char* argv[]) {
172 bool auto_reboot = false;
173 bool verbose = false;
174
175 struct option longopts[] = {
176 {"help", no_argument, nullptr, 'h'},
177 {"reboot", no_argument, nullptr, 'R'},
178 {"verbose", no_argument, nullptr, 'v'},
179 {0, 0, nullptr, 0},
180 };
181 for (int opt; (opt = ::getopt_long(argc, argv, "hRv", longopts, nullptr)) != -1;) {
182 switch (opt) {
183 case 'h':
184 print_usage();
185 return 0;
186 case 'R':
187 auto_reboot = true;
188 break;
189 case 'v':
190 verbose = true;
191 break;
192 default:
193 print_usage();
194 return 1;
195 }
196 }
197
198 android::base::InitLogging(argv, MyLogger(verbose));
199
200 bool enable_verity = false;
201 const std::string progname = getprogname();
202 if (progname == "enable-verity") {
203 enable_verity = true;
204 } else if (progname == "disable-verity") {
205 enable_verity = false;
206 } else if (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
207 // progname "set-verity-state"
208 enable_verity = (argv[optind] == "1"s);
209 } else {
210 print_usage();
211 return 1;
212 }
213
214 if (!kAllowDisableVerity || !is_debuggable()) {
215 errno = EPERM;
216 PLOG(ERROR) << "Cannot disable/enable verity on user build";
217 return 1;
218 }
219
220 if (getuid() != 0) {
221 errno = EACCES;
222 PLOG(ERROR) << "Must be running as root (adb root)";
223 return 1;
224 }
225
226 if (!is_using_avb()) {
227 LOG(ERROR) << "Expected AVB device, VB1.0 is no longer supported";
228 return 1;
229 }
230
231 int exit_code = 0;
232 bool want_reboot = false;
233
234 auto ret = SetVerityState(enable_verity);
235 if (ret.success) {
236 want_reboot |= ret.want_reboot;
237 } else {
238 exit_code = 1;
239 }
240
241 // Disable any overlayfs unconditionally if we want verity enabled.
242 // Enable overlayfs only if verity is successfully disabled or is already disabled.
243 if (enable_verity || ret.success) {
244 // Start a threadpool to service waitForService() callbacks as
245 // fs_mgr_overlayfs_* might call waitForService() to get the image service.
246 android::ProcessState::self()->startThreadPool();
247 want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
248 }
249
250 if (want_reboot) {
251 if (auto_reboot) {
252 reboot(progname);
253 }
254 printf("Reboot the device for new settings to take effect\n");
255 }
256
257 return exit_code;
258}