diff options
Diffstat (limited to 'adb/set_verity_enable_state_service.cpp')
-rw-r--r-- | adb/set_verity_enable_state_service.cpp | 134 |
1 files changed, 103 insertions, 31 deletions
diff --git a/adb/set_verity_enable_state_service.cpp b/adb/set_verity_enable_state_service.cpp index d4dd25636..253d14a0e 100644 --- a/adb/set_verity_enable_state_service.cpp +++ b/adb/set_verity_enable_state_service.cpp | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include <fcntl.h> | 21 | #include <fcntl.h> |
22 | #include <inttypes.h> | 22 | #include <inttypes.h> |
23 | #include <libavb_user/libavb_user.h> | ||
23 | #include <stdarg.h> | 24 | #include <stdarg.h> |
24 | #include <stdio.h> | 25 | #include <stdio.h> |
25 | #include <sys/stat.h> | 26 | #include <sys/stat.h> |
@@ -45,13 +46,12 @@ static const bool kAllowDisableVerity = false; | |||
45 | #endif | 46 | #endif |
46 | 47 | ||
47 | /* Turn verity on/off */ | 48 | /* Turn verity on/off */ |
48 | static int set_verity_enabled_state(int fd, const char *block_device, | 49 | static bool set_verity_enabled_state(int fd, const char* block_device, const char* mount_point, |
49 | const char* mount_point, bool enable) | 50 | bool enable) { |
50 | { | ||
51 | if (!make_block_device_writable(block_device)) { | 51 | if (!make_block_device_writable(block_device)) { |
52 | WriteFdFmt(fd, "Could not make block device %s writable (%s).\n", | 52 | WriteFdFmt(fd, "Could not make block device %s writable (%s).\n", |
53 | block_device, strerror(errno)); | 53 | block_device, strerror(errno)); |
54 | return -1; | 54 | return false; |
55 | } | 55 | } |
56 | 56 | ||
57 | fec::io fh(block_device, O_RDWR); | 57 | fec::io fh(block_device, O_RDWR); |
@@ -59,70 +59,142 @@ static int set_verity_enabled_state(int fd, const char *block_device, | |||
59 | if (!fh) { | 59 | if (!fh) { |
60 | WriteFdFmt(fd, "Could not open block device %s (%s).\n", block_device, strerror(errno)); | 60 | WriteFdFmt(fd, "Could not open block device %s (%s).\n", block_device, strerror(errno)); |
61 | WriteFdFmt(fd, "Maybe run adb root?\n"); | 61 | WriteFdFmt(fd, "Maybe run adb root?\n"); |
62 | return -1; | 62 | return false; |
63 | } | 63 | } |
64 | 64 | ||
65 | fec_verity_metadata metadata; | 65 | fec_verity_metadata metadata; |
66 | 66 | ||
67 | if (!fh.get_verity_metadata(metadata)) { | 67 | if (!fh.get_verity_metadata(metadata)) { |
68 | WriteFdFmt(fd, "Couldn't find verity metadata!\n"); | 68 | WriteFdFmt(fd, "Couldn't find verity metadata!\n"); |
69 | return -1; | 69 | return false; |
70 | } | 70 | } |
71 | 71 | ||
72 | if (!enable && metadata.disabled) { | 72 | if (!enable && metadata.disabled) { |
73 | WriteFdFmt(fd, "Verity already disabled on %s\n", mount_point); | 73 | WriteFdFmt(fd, "Verity already disabled on %s\n", mount_point); |
74 | return -1; | 74 | return false; |
75 | } | 75 | } |
76 | 76 | ||
77 | if (enable && !metadata.disabled) { | 77 | if (enable && !metadata.disabled) { |
78 | WriteFdFmt(fd, "Verity already enabled on %s\n", mount_point); | 78 | WriteFdFmt(fd, "Verity already enabled on %s\n", mount_point); |
79 | return -1; | 79 | return false; |
80 | } | 80 | } |
81 | 81 | ||
82 | if (!fh.set_verity_status(enable)) { | 82 | if (!fh.set_verity_status(enable)) { |
83 | WriteFdFmt(fd, "Could not set verity %s flag on device %s with error %s\n", | 83 | WriteFdFmt(fd, "Could not set verity %s flag on device %s with error %s\n", |
84 | enable ? "enabled" : "disabled", | 84 | enable ? "enabled" : "disabled", |
85 | block_device, strerror(errno)); | 85 | block_device, strerror(errno)); |
86 | return -1; | 86 | return false; |
87 | } | 87 | } |
88 | 88 | ||
89 | WriteFdFmt(fd, "Verity %s on %s\n", enable ? "enabled" : "disabled", mount_point); | 89 | WriteFdFmt(fd, "Verity %s on %s\n", enable ? "enabled" : "disabled", mount_point); |
90 | return 0; | 90 | return true; |
91 | } | ||
92 | |||
93 | /* Helper function to get A/B suffix, if any. If the device isn't | ||
94 | * using A/B the empty string is returned. Otherwise either "_a", | ||
95 | * "_b", ... is returned. | ||
96 | * | ||
97 | * Note that since sometime in O androidboot.slot_suffix is deprecated | ||
98 | * and androidboot.slot should be used instead. Since bootloaders may | ||
99 | * be out of sync with the OS, we check both and for extra safety | ||
100 | * prepend a leading underscore if there isn't one already. | ||
101 | */ | ||
102 | static std::string get_ab_suffix() { | ||
103 | std::string ab_suffix = android::base::GetProperty("ro.boot.slot_suffix", ""); | ||
104 | if (ab_suffix == "") { | ||
105 | ab_suffix = android::base::GetProperty("ro.boot.slot", ""); | ||
106 | } | ||
107 | if (ab_suffix.size() > 0 && ab_suffix[0] != '_') { | ||
108 | ab_suffix = std::string("_") + ab_suffix; | ||
109 | } | ||
110 | return ab_suffix; | ||
111 | } | ||
112 | |||
113 | /* Use AVB to turn verity on/off */ | ||
114 | static bool set_avb_verity_enabled_state(int fd, AvbOps* ops, bool enable_verity) { | ||
115 | std::string ab_suffix = get_ab_suffix(); | ||
116 | |||
117 | bool verity_enabled; | ||
118 | if (!avb_user_verity_get(ops, ab_suffix.c_str(), &verity_enabled)) { | ||
119 | WriteFdFmt(fd, "Error getting verity state\n"); | ||
120 | return false; | ||
121 | } | ||
122 | |||
123 | if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) { | ||
124 | WriteFdFmt(fd, "verity is already %s\n", verity_enabled ? "enabled" : "disabled"); | ||
125 | return false; | ||
126 | } | ||
127 | |||
128 | if (!avb_user_verity_set(ops, ab_suffix.c_str(), enable_verity)) { | ||
129 | WriteFdFmt(fd, "Error setting verity\n"); | ||
130 | return false; | ||
131 | } | ||
132 | |||
133 | WriteFdFmt(fd, "Successfully %s verity\n", enable_verity ? "enabled" : "disabled"); | ||
134 | return true; | ||
91 | } | 135 | } |
92 | 136 | ||
93 | void set_verity_enabled_state_service(int fd, void* cookie) { | 137 | void set_verity_enabled_state_service(int fd, void* cookie) { |
94 | unique_fd closer(fd); | 138 | unique_fd closer(fd); |
139 | bool any_changed = false; | ||
95 | 140 | ||
96 | bool enable = (cookie != NULL); | 141 | bool enable = (cookie != NULL); |
97 | if (!kAllowDisableVerity) { | ||
98 | WriteFdFmt(fd, "%s-verity only works for userdebug builds\n", | ||
99 | enable ? "enable" : "disable"); | ||
100 | } | ||
101 | 142 | ||
102 | if (!android::base::GetBoolProperty("ro.secure", false)) { | 143 | // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by |
103 | WriteFdFmt(fd, "verity not enabled - ENG build\n"); | 144 | // contract, androidboot.vbmeta.digest is set by the bootloader |
104 | return; | 145 | // when using AVB). |
146 | bool using_avb = !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty(); | ||
147 | |||
148 | // If using AVB, dm-verity is used on any build so we want it to | ||
149 | // be possible to disable/enable on any build (except USER). For | ||
150 | // VB1.0 dm-verity is only enabled on certain builds. | ||
151 | if (!using_avb) { | ||
152 | if (!kAllowDisableVerity) { | ||
153 | WriteFdFmt(fd, "%s-verity only works for userdebug builds\n", | ||
154 | enable ? "enable" : "disable"); | ||
155 | } | ||
156 | |||
157 | if (!android::base::GetBoolProperty("ro.secure", false)) { | ||
158 | WriteFdFmt(fd, "verity not enabled - ENG build\n"); | ||
159 | return; | ||
160 | } | ||
105 | } | 161 | } |
162 | |||
163 | // Should never be possible to disable dm-verity on a USER build | ||
164 | // regardless of using AVB or VB1.0. | ||
106 | if (!__android_log_is_debuggable()) { | 165 | if (!__android_log_is_debuggable()) { |
107 | WriteFdFmt(fd, "verity cannot be disabled/enabled - USER build\n"); | 166 | WriteFdFmt(fd, "verity cannot be disabled/enabled - USER build\n"); |
108 | return; | 167 | return; |
109 | } | 168 | } |
110 | 169 | ||
111 | // read all fstab entries at once from all sources | 170 | if (using_avb) { |
112 | fstab = fs_mgr_read_fstab_default(); | 171 | // Yep, the system is using AVB. |
113 | if (!fstab) { | 172 | AvbOps* ops = avb_ops_user_new(); |
114 | WriteFdFmt(fd, "Failed to read fstab\nMaybe run adb root?\n"); | 173 | if (ops == nullptr) { |
115 | return; | 174 | WriteFdFmt(fd, "Error getting AVB ops\n"); |
116 | } | 175 | return; |
176 | } | ||
177 | if (set_avb_verity_enabled_state(fd, ops, enable)) { | ||
178 | any_changed = true; | ||
179 | } | ||
180 | avb_ops_user_free(ops); | ||
181 | } else { | ||
182 | // Not using AVB - assume VB1.0. | ||
183 | |||
184 | // read all fstab entries at once from all sources | ||
185 | fstab = fs_mgr_read_fstab_default(); | ||
186 | if (!fstab) { | ||
187 | WriteFdFmt(fd, "Failed to read fstab\nMaybe run adb root?\n"); | ||
188 | return; | ||
189 | } | ||
117 | 190 | ||
118 | // Loop through entries looking for ones that vold manages. | 191 | // Loop through entries looking for ones that vold manages. |
119 | bool any_changed = false; | 192 | for (int i = 0; i < fstab->num_entries; i++) { |
120 | for (int i = 0; i < fstab->num_entries; i++) { | 193 | if (fs_mgr_is_verified(&fstab->recs[i])) { |
121 | if (fs_mgr_is_verified(&fstab->recs[i])) { | 194 | if (set_verity_enabled_state(fd, fstab->recs[i].blk_device, |
122 | if (!set_verity_enabled_state(fd, fstab->recs[i].blk_device, | 195 | fstab->recs[i].mount_point, enable)) { |
123 | fstab->recs[i].mount_point, | 196 | any_changed = true; |
124 | enable)) { | 197 | } |
125 | any_changed = true; | ||
126 | } | 198 | } |
127 | } | 199 | } |
128 | } | 200 | } |