• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 <errno.h>
18 #include <fcntl.h>
19 #include <inttypes.h>
20 #include <libavb_user/libavb_user.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <sys/mount.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 
27 #include <android-base/file.h>
28 #include <android-base/logging.h>
29 #include <android-base/properties.h>
30 #include <android-base/stringprintf.h>
31 #include <android-base/unique_fd.h>
32 #include <fs_mgr.h>
33 #include <fs_mgr_overlayfs.h>
34 #include <fstab/fstab.h>
35 #include <log/log_properties.h>
36 
37 #include "fec/io.h"
38 
39 #ifdef ALLOW_DISABLE_VERITY
40 static const bool kAllowDisableVerity = true;
41 #else
42 static const bool kAllowDisableVerity = false;
43 #endif
44 
45 using android::base::unique_fd;
46 
suggest_run_adb_root()47 static void suggest_run_adb_root() {
48   if (getuid() != 0) printf("Maybe run adb root?\n");
49 }
50 
make_block_device_writable(const std::string & dev)51 static bool make_block_device_writable(const std::string& dev) {
52   unique_fd fd(open(dev.c_str(), O_RDONLY | O_CLOEXEC));
53   if (fd == -1) {
54     return false;
55   }
56 
57   int OFF = 0;
58   bool result = (ioctl(fd.get(), BLKROSET, &OFF) != -1);
59   return result;
60 }
61 
62 /* Turn verity on/off */
set_verity_enabled_state(const char * block_device,const char * mount_point,bool enable)63 static bool set_verity_enabled_state(const char* block_device, const char* mount_point,
64                                      bool enable) {
65   if (!make_block_device_writable(block_device)) {
66     printf("Could not make block device %s writable (%s).\n", block_device, strerror(errno));
67     return false;
68   }
69 
70   fec::io fh(block_device, O_RDWR);
71 
72   if (!fh) {
73     printf("Could not open block device %s (%s).\n", block_device, strerror(errno));
74     suggest_run_adb_root();
75     return false;
76   }
77 
78   fec_verity_metadata metadata;
79 
80   if (!fh.get_verity_metadata(metadata)) {
81     printf("Couldn't find verity metadata!\n");
82     return false;
83   }
84 
85   if (!enable && metadata.disabled) {
86     printf("Verity already disabled on %s\n", mount_point);
87     return false;
88   }
89 
90   if (enable && !metadata.disabled) {
91     printf("Verity already enabled on %s\n", mount_point);
92     return false;
93   }
94 
95   if (!fh.set_verity_status(enable)) {
96     printf("Could not set verity %s flag on device %s with error %s\n",
97            enable ? "enabled" : "disabled", block_device, strerror(errno));
98     return false;
99   }
100 
101   auto change = false;
102   errno = 0;
103   if (enable ? fs_mgr_overlayfs_teardown(mount_point, &change)
104              : fs_mgr_overlayfs_setup(nullptr, mount_point, &change)) {
105     if (change) {
106       printf("%s overlayfs for %s\n", enable ? "disabling" : "using", mount_point);
107     }
108   } else if (errno) {
109     int expected_errno = enable ? EBUSY : ENOENT;
110     if (errno != expected_errno) {
111       printf("Overlayfs %s for %s failed with error %s\n", enable ? "teardown" : "setup",
112              mount_point, strerror(errno));
113     }
114   }
115   printf("Verity %s on %s\n", enable ? "enabled" : "disabled", mount_point);
116   return true;
117 }
118 
119 /* Helper function to get A/B suffix, if any. If the device isn't
120  * using A/B the empty string is returned. Otherwise either "_a",
121  * "_b", ... is returned.
122  */
get_ab_suffix()123 static std::string get_ab_suffix() {
124   return android::base::GetProperty("ro.boot.slot_suffix", "");
125 }
126 
is_avb_device_locked()127 static bool is_avb_device_locked() {
128   return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked";
129 }
130 
overlayfs_setup(bool enable)131 static bool overlayfs_setup(bool enable) {
132   auto change = false;
133   errno = 0;
134   if (enable ? fs_mgr_overlayfs_teardown(nullptr, &change)
135              : fs_mgr_overlayfs_setup(nullptr, nullptr, &change)) {
136     if (change) {
137       printf("%s overlayfs\n", enable ? "disabling" : "using");
138     }
139   } else if (errno) {
140     printf("Overlayfs %s failed with error %s\n", enable ? "teardown" : "setup", strerror(errno));
141     suggest_run_adb_root();
142   }
143   return change;
144 }
145 
146 /* Use AVB to turn verity on/off */
set_avb_verity_enabled_state(AvbOps * ops,bool enable_verity)147 static bool set_avb_verity_enabled_state(AvbOps* ops, bool enable_verity) {
148   std::string ab_suffix = get_ab_suffix();
149   bool verity_enabled;
150 
151   if (is_avb_device_locked()) {
152     printf("Device is locked. Please unlock the device first\n");
153     return false;
154   }
155 
156   if (!avb_user_verity_get(ops, ab_suffix.c_str(), &verity_enabled)) {
157     printf("Error getting verity state. Try adb root first?\n");
158     return false;
159   }
160 
161   if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
162     printf("verity is already %s\n", verity_enabled ? "enabled" : "disabled");
163     return false;
164   }
165 
166   if (!avb_user_verity_set(ops, ab_suffix.c_str(), enable_verity)) {
167     printf("Error setting verity\n");
168     return false;
169   }
170 
171   overlayfs_setup(enable_verity);
172   printf("Successfully %s verity\n", enable_verity ? "enabled" : "disabled");
173   return true;
174 }
175 
main(int argc,char * argv[])176 int main(int argc, char* argv[]) {
177   if (argc == 0) {
178     LOG(FATAL) << "set-verity-state called with empty argv";
179   }
180 
181   std::optional<bool> enable_opt;
182   std::string procname = android::base::Basename(argv[0]);
183   if (procname == "enable-verity") {
184     enable_opt = true;
185   } else if (procname == "disable-verity") {
186     enable_opt = false;
187   }
188 
189   if (!enable_opt.has_value()) {
190     if (argc != 2) {
191       printf("usage: %s [1|0]\n", argv[0]);
192       return 1;
193     }
194 
195     if (strcmp(argv[1], "1") == 0) {
196       enable_opt = true;
197     } else if (strcmp(argv[1], "0") == 0) {
198       enable_opt = false;
199     } else {
200       printf("usage: %s [1|0]\n", argv[0]);
201       return 1;
202     }
203   }
204 
205   bool enable = enable_opt.value();
206 
207   bool any_changed = false;
208 
209   // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
210   // contract, androidboot.vbmeta.digest is set by the bootloader
211   // when using AVB).
212   bool using_avb = !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
213 
214   // If using AVB, dm-verity is used on any build so we want it to
215   // be possible to disable/enable on any build (except USER). For
216   // VB1.0 dm-verity is only enabled on certain builds.
217   if (!using_avb) {
218     if (!kAllowDisableVerity) {
219       printf("%s only works for userdebug builds\n", argv[0]);
220     }
221 
222     if (!android::base::GetBoolProperty("ro.secure", false)) {
223       overlayfs_setup(enable);
224       printf("verity not enabled - ENG build\n");
225       return 0;
226     }
227   }
228 
229   // Should never be possible to disable dm-verity on a USER build
230   // regardless of using AVB or VB1.0.
231   if (!__android_log_is_debuggable()) {
232     printf("verity cannot be disabled/enabled - USER build\n");
233     return 0;
234   }
235 
236   if (using_avb) {
237     // Yep, the system is using AVB.
238     AvbOps* ops = avb_ops_user_new();
239     if (ops == nullptr) {
240       printf("Error getting AVB ops\n");
241       return 1;
242     }
243     if (set_avb_verity_enabled_state(ops, enable)) {
244       any_changed = true;
245     }
246     avb_ops_user_free(ops);
247   } else {
248     // Not using AVB - assume VB1.0.
249 
250     // read all fstab entries at once from all sources
251     android::fs_mgr::Fstab fstab;
252     if (!android::fs_mgr::ReadDefaultFstab(&fstab)) {
253       printf("Failed to read fstab\n");
254       suggest_run_adb_root();
255       return 0;
256     }
257 
258     // Loop through entries looking for ones that verity manages.
259     for (const auto& entry : fstab) {
260       if (entry.fs_mgr_flags.verify) {
261         if (set_verity_enabled_state(entry.blk_device.c_str(), entry.mount_point.c_str(), enable)) {
262           any_changed = true;
263         }
264       }
265     }
266   }
267   if (!any_changed) any_changed = overlayfs_setup(enable);
268 
269   if (any_changed) {
270     printf("Now reboot your device for settings to take effect\n");
271   }
272 
273   return 0;
274 }
275