blob: ac872ea28007c35ce2013e433423500445aede7e [file] [log] [blame]
nkk7171c6c502017-01-05 23:55:05 +02001/*
2 Copyright 2017 TeamWin
3 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
18
nkk7171c6c502017-01-05 23:55:05 +020019#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <unistd.h>
23#include <errno.h>
nkk717d1222a2017-11-06 17:27:21 +020024#include <fcntl.h>
25#include <sys/mount.h>
nkk7171c6c502017-01-05 23:55:05 +020026#include <sys/time.h>
nkk717d1222a2017-11-06 17:27:21 +020027#include <dirent.h>
28#include <fnmatch.h>
nkk7171c6c502017-01-05 23:55:05 +020029
nkk7171c6c502017-01-05 23:55:05 +020030#include <signal.h>
31#include <sys/types.h>
32#include <sys/wait.h>
nkk7171c6c502017-01-05 23:55:05 +020033
nkk717d1222a2017-11-06 17:27:21 +020034#include <fstream>
nkk7171c6c502017-01-05 23:55:05 +020035#include <string>
36#include <vector>
37#include <sstream>
38
nkk717d1222a2017-11-06 17:27:21 +020039#ifdef _USING_SHORT_SERVICE_NAMES
40#include <map>
41#endif
42
nkk7171c6c502017-01-05 23:55:05 +020043#include "../../partitions.hpp"
44#include "../../twrp-functions.hpp"
nkk7171c6c502017-01-05 23:55:05 +020045
46using namespace std;
47
48extern "C" {
49 #include <cutils/properties.h>
50}
51
nkk717d1222a2017-11-06 17:27:21 +020052#include "vold_decrypt.h"
53
54namespace {
55
nkk7171c6c502017-01-05 23:55:05 +020056/* Timeouts as defined by ServiceManager */
57
58/* The maximum amount of time to wait for a service to start or stop,
59 * in micro-seconds (really an approximation) */
60#define SLEEP_MAX_USEC 2000000 /* 2 seconds */
61/* The minimal sleeping interval between checking for the service's state
62 * when looping for SLEEP_MAX_USEC */
63#define SLEEP_MIN_USEC 200000 /* 200 msec */
64
65
nkk717d1222a2017-11-06 17:27:21 +020066/* vold response codes defined in ResponseCode.h */
67// 200 series - Requested action has been successfully completed
68#define COMMAND_OKAY 200
69#define PASSWORD_TYPE_RESULT 213
nkk7171c6c502017-01-05 23:55:05 +020070
nkk717d1222a2017-11-06 17:27:21 +020071
72#define LOGINFO(...) do { printf(__VA_ARGS__); if (fp_kmsg) { fprintf(fp_kmsg, "[VOLD_DECRYPT]I:" __VA_ARGS__); fflush(fp_kmsg); } } while (0)
73#define LOGKMSG(...) do { if (fp_kmsg) { fprintf(fp_kmsg, "[VOLD_DECRYPT]K:" __VA_ARGS__); fflush(fp_kmsg); } } while (0)
74#define LOGERROR(...) do { printf(__VA_ARGS__); if (fp_kmsg) { fprintf(fp_kmsg, "[VOLD_DECRYPT]E:" __VA_ARGS__); fflush(fp_kmsg); } } while (0)
nkk7171c6c502017-01-05 23:55:05 +020075
76FILE *fp_kmsg = NULL;
nijel82c821a82018-12-29 04:56:41 -050077int sdkver = 20;
nkk7171c6c502017-01-05 23:55:05 +020078
nkk717d1222a2017-11-06 17:27:21 +020079
80/* Debugging Functions */
nkk7171c6c502017-01-05 23:55:05 +020081#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
nkk7171c6c502017-01-05 23:55:05 +020082
nkk717d1222a2017-11-06 17:27:21 +020083#ifndef VD_STRACE_BIN
84#define VD_STRACE_BIN "/sbin/strace"
85#endif
86
87bool has_strace = false;
88pid_t pid_strace = 0;
89
90void Strace_init_Start(void) {
91 has_strace = TWFunc::Path_Exists(VD_STRACE_BIN);
92 if (!has_strace) {
93 LOGINFO("strace binary (%s) not found, disabling strace in vold_decrypt!\n", VD_STRACE_BIN);
94 return;
95 }
nkk7171c6c502017-01-05 23:55:05 +020096
97 pid_t pid;
98 switch(pid = fork())
99 {
100 case -1:
nkk717d1222a2017-11-06 17:27:21 +0200101 LOGKMSG("forking strace_init failed: %d (%s)!\n", errno, strerror(errno));
102 return;
nkk7171c6c502017-01-05 23:55:05 +0200103 case 0: // child
nkk717d1222a2017-11-06 17:27:21 +0200104 execl(VD_STRACE_BIN, "strace", "-q", "-tt", "-ff", "-v", "-y", "-s", "1000", "-o", "/tmp/strace_init.log", "-p", "1" , NULL);
105 LOGKMSG("strace_init fork failed: %d (%s)!\n", errno, strerror(errno));
nkk7171c6c502017-01-05 23:55:05 +0200106 exit(-1);
107 default:
nkk717d1222a2017-11-06 17:27:21 +0200108 LOGKMSG("Starting strace_init (pid=%d)\n", pid);
109 pid_strace = pid;
110 return;
nkk7171c6c502017-01-05 23:55:05 +0200111 }
112}
nkk717d1222a2017-11-06 17:27:21 +0200113
114void Strace_init_Stop(void) {
115 if (pid_strace > 0) {
116 LOGKMSG("Stopping strace_init (pid=%d)\n", pid_strace);
117 int timeout;
118 int status;
119 pid_t retpid = waitpid(pid_strace, &status, WNOHANG);
120
121 kill(pid_strace, SIGTERM);
122 for (timeout = 5; retpid == 0 && timeout; --timeout) {
123 sleep(1);
124 retpid = waitpid(pid_strace, &status, WNOHANG);
125 }
126 if (retpid)
127 LOGKMSG("strace_init terminated successfully\n");
128 else {
129 // SIGTERM didn't work, kill it instead
130 kill(pid_strace, SIGKILL);
131 for (timeout = 5; retpid == 0 && timeout; --timeout) {
132 sleep(1);
133 retpid = waitpid(pid_strace, &status, WNOHANG);
134 }
135 if (retpid)
136 LOGKMSG("strace_init killed successfully\n");
137 else
138 LOGKMSG("strace_init took too long to kill, may be a zombie process\n");
139 }
140 }
141}
142#endif // TW_CRYPTO_SYSTEM_VOLD_DEBUG
143
nkk7171c6c502017-01-05 23:55:05 +0200144
145/* Convert a binary key of specified length into an ascii hex string equivalent,
146 * without the leading 0x and with null termination
147 *
148 * Original code from cryptfs.c
149 */
nkk717d1222a2017-11-06 17:27:21 +0200150string convert_key_to_hex_ascii(const string& master_key) {
nkk7171c6c502017-01-05 23:55:05 +0200151 size_t i;
152 unsigned char nibble;
153 string master_key_ascii = "";
154
155 for (i = 0; i < master_key.size(); ++i) {
156 nibble = (master_key[i] >> 4) & 0xf;
157 nibble += nibble > 9 ? 0x57 : 0x30;
158 master_key_ascii += nibble;
159
160 nibble = master_key[i] & 0xf;
161 nibble += nibble > 9 ? 0x57 : 0x30;
162 master_key_ascii += nibble;
163 }
164
165 return master_key_ascii;
166}
167
nkk717d1222a2017-11-06 17:27:21 +0200168/* Helper Functions */
169#define PATH_EXISTS(path) (access(path, F_OK) >= 0)
170
171int vrename(const string& oldname, const string& newname, bool verbose = false) {
172 const char *old_name = oldname.c_str();
173 const char *new_name = newname.c_str();
174
175 if (!PATH_EXISTS(old_name))
176 return 0;
177
178 if (rename(old_name, new_name) < 0) {
179 LOGERROR("Moving %s to %s failed: %d (%s)\n", old_name, new_name, errno, strerror(errno));
180 return -1;
181 } else if (verbose)
182 LOGINFO("Renamed %s to %s\n", old_name, new_name);
183 else
184 LOGKMSG("Renamed %s to %s\n", old_name, new_name);
185 return 0;
186}
187
188int vsymlink(const string& oldname, const string& newname, bool verbose = false) {
189 const char *old_name = oldname.c_str();
190 const char *new_name = newname.c_str();
191
192 if (!PATH_EXISTS(old_name))
193 return 0;
194
195 if (symlink(old_name, new_name) < 0) {
196 LOGERROR("Symlink %s -> %s failed: %d (%s)\n", new_name, old_name, errno, strerror(errno));
197 return -1;
198 } else if (verbose)
199 LOGINFO("Symlinked %s -> %s\n", new_name, old_name);
200 else
201 LOGKMSG("Symlinked %s -> %s\n", new_name, old_name);
202 return 0;
203}
204
205
206/* Properties and Services Functions */
207string Wait_For_Property(const string& property_name, int utimeout = SLEEP_MAX_USEC, const string& expected_value = "not_empty") {
nkk7171c6c502017-01-05 23:55:05 +0200208 char prop_value[PROPERTY_VALUE_MAX];
209
210 if (expected_value == "not_empty") {
211 while (utimeout > 0) {
212 property_get(property_name.c_str(), prop_value, "error");
213 if (strcmp(prop_value, "error") != 0)
214 break;
nkk717d1222a2017-11-06 17:27:21 +0200215 LOGKMSG("waiting for %s to get set\n", property_name.c_str());
nkk7171c6c502017-01-05 23:55:05 +0200216 utimeout -= SLEEP_MIN_USEC;
217 usleep(SLEEP_MIN_USEC);;
218 }
219 }
220 else {
221 while (utimeout > 0) {
222 property_get(property_name.c_str(), prop_value, "error");
223 if (strcmp(prop_value, expected_value.c_str()) == 0)
224 break;
nkk717d1222a2017-11-06 17:27:21 +0200225 LOGKMSG("waiting for %s to change from '%s' to '%s'\n", property_name.c_str(), prop_value, expected_value.c_str());
nkk7171c6c502017-01-05 23:55:05 +0200226 utimeout -= SLEEP_MIN_USEC;
nijel82c821a82018-12-29 04:56:41 -0500227 usleep(SLEEP_MIN_USEC);
nkk7171c6c502017-01-05 23:55:05 +0200228 }
229 }
230 property_get(property_name.c_str(), prop_value, "error");
231
232 return prop_value;
233}
234
nkk717d1222a2017-11-06 17:27:21 +0200235string Get_Service_State(const string& initrc_svc) {
nkk7171c6c502017-01-05 23:55:05 +0200236 char prop_value[PROPERTY_VALUE_MAX];
237 string init_svc = "init.svc." + initrc_svc;
238 property_get(init_svc.c_str(), prop_value, "error");
nkk717d1222a2017-11-06 17:27:21 +0200239 return prop_value;
nkk7171c6c502017-01-05 23:55:05 +0200240}
241
nkk717d1222a2017-11-06 17:27:21 +0200242bool Service_Exists(const string& initrc_svc) {
243 return (Get_Service_State(initrc_svc) != "error");
nkk7171c6c502017-01-05 23:55:05 +0200244}
245
nkk717d1222a2017-11-06 17:27:21 +0200246bool Is_Service_Running(const string& initrc_svc) {
247 return (Get_Service_State(initrc_svc) == "running");
nkk7171c6c502017-01-05 23:55:05 +0200248}
249
nkk717d1222a2017-11-06 17:27:21 +0200250bool Is_Service_Stopped(const string& initrc_svc) {
251 return (Get_Service_State(initrc_svc) == "stopped");
252}
253
254bool Start_Service(const string& initrc_svc, int utimeout = SLEEP_MAX_USEC) {
nkk7171c6c502017-01-05 23:55:05 +0200255 string res = "error";
256 string init_svc = "init.svc." + initrc_svc;
257
258 property_set("ctl.start", initrc_svc.c_str());
259
nkk717d1222a2017-11-06 17:27:21 +0200260 res = Wait_For_Property(init_svc, utimeout, "running");
nkk7171c6c502017-01-05 23:55:05 +0200261
nkk717d1222a2017-11-06 17:27:21 +0200262 LOGINFO("Start service %s: %s.\n", initrc_svc.c_str(), res.c_str());
nkk7171c6c502017-01-05 23:55:05 +0200263
264 return (res == "running");
265}
266
nkk717d1222a2017-11-06 17:27:21 +0200267bool Stop_Service(const string& initrc_svc, int utimeout = SLEEP_MAX_USEC) {
nkk7171c6c502017-01-05 23:55:05 +0200268 string res = "error";
269
270 if (Service_Exists(initrc_svc)) {
271 string init_svc = "init.svc." + initrc_svc;
272 property_set("ctl.stop", initrc_svc.c_str());
nkk717d1222a2017-11-06 17:27:21 +0200273 res = Wait_For_Property(init_svc, utimeout, "stopped");
274 LOGINFO("Stop service %s: %s.\n", initrc_svc.c_str(), res.c_str());
nkk7171c6c502017-01-05 23:55:05 +0200275 }
276
277 return (res == "stopped");
278}
279
nkk717d1222a2017-11-06 17:27:21 +0200280
281/* Vendor, Firmware and fstab symlink Functions */
282bool is_Vendor_Mounted(void) {
283 static int is_mounted = -1;
284 if (is_mounted < 0)
285 is_mounted = PartitionManager.Is_Mounted_By_Path("/vendor") ? 1 : 0;
286 return is_mounted;
nkk7171c6c502017-01-05 23:55:05 +0200287}
288
nkk717d1222a2017-11-06 17:27:21 +0200289bool is_Firmware_Mounted(void) {
290 static int is_mounted = -1;
291 if (is_mounted < 0)
292 is_mounted = PartitionManager.Is_Mounted_By_Path("/firmware") ? 1 : 0;
293 return is_mounted;
294}
295
296bool will_VendorBin_Be_Symlinked(void) {
297 return (!is_Vendor_Mounted() && TWFunc::Path_Exists("/system/vendor"));
298}
299
300bool Symlink_Vendor_Folder(void) {
301 bool is_vendor_symlinked = false;
302
303 if (is_Vendor_Mounted()) {
304 LOGINFO("vendor partition mounted, skipping /vendor substitution\n");
305 }
306 else if (TWFunc::Path_Exists("/system/vendor")) {
307 LOGINFO("Symlinking vendor folder...\n");
308 if (!TWFunc::Path_Exists("/vendor") || vrename("/vendor", "/vendor-orig") == 0) {
309 TWFunc::Recursive_Mkdir("/vendor/firmware/keymaster");
nkk7137625a42017-12-08 16:37:59 +0200310 vsymlink("/system/vendor/lib64", "/vendor/lib64", true);
311 vsymlink("/system/vendor/lib", "/vendor/lib", true);
312 vsymlink("/system/vendor/bin", "/vendor/bin", true);
nkk717d1222a2017-11-06 17:27:21 +0200313 is_vendor_symlinked = true;
314 property_set("vold_decrypt.symlinked_vendor", "1");
315 }
316 }
317 return is_vendor_symlinked;
318}
319
320void Restore_Vendor_Folder(void) {
321 property_set("vold_decrypt.symlinked_vendor", "0");
322 TWFunc::removeDir("/vendor", false);
323 vrename("/vendor-orig", "/vendor");
324}
325
326bool Symlink_Firmware_Folder(void) {
327 bool is_firmware_symlinked = false;
328
329 if (is_Firmware_Mounted()) {
330 LOGINFO("firmware partition mounted, skipping /firmware substitution\n");
331 }
332 else {
333 LOGINFO("Symlinking firmware folder...\n");
334 if (!TWFunc::Path_Exists("/firmware") || vrename("/firmware", "/firmware-orig") == 0) {
335 TWFunc::Recursive_Mkdir("/firmware/image");
336 is_firmware_symlinked = true;
337 property_set("vold_decrypt.symlinked_firmware", "1");
338 }
339 }
340 return is_firmware_symlinked;
341}
342
343void Restore_Firmware_Folder(void) {
344 property_set("vold_decrypt.symlinked_firmware", "0");
345 TWFunc::removeDir("/firmware", false);
346 vrename("/firmware-orig", "/firmware");
347}
348
349int Find_Firmware_Files(const string& Path, vector<string> *FileList) {
350 int ret;
351 DIR* d;
352 struct dirent* de;
353 string FileName;
354
355 d = opendir(Path.c_str());
356 if (d == NULL) {
357 closedir(d);
358 return -1;
359 }
360 while ((de = readdir(d)) != NULL) {
361 if (de->d_type == DT_DIR) {
362 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
363 continue;
364 FileName = Path + "/" + de->d_name;
365 ret = Find_Firmware_Files(FileName, FileList);
366 if (ret < 0)
367 return -1;
368 } else if (de->d_type == DT_REG) {
369 if (fnmatch("keymaste*.*", de->d_name, 0) == 0 || fnmatch("cmnlib.*", de->d_name, 0) == 0) {
370 FileName = Path + "/" + de->d_name;
371 FileList->push_back(FileName);
372 }
373 }
374 }
375 closedir(d);
376 return 0;
377}
378
379void Symlink_Firmware_Files(bool is_vendor_symlinked, bool is_firmware_symlinked) {
380 if (!is_vendor_symlinked && !is_firmware_symlinked)
381 return;
382
383 LOGINFO("Symlinking firmware files...\n");
384
385 vector<string> FirmwareFiles;
386 Find_Firmware_Files("/system", &FirmwareFiles);
387
388 for (size_t i = 0; i < FirmwareFiles.size(); ++i) {
389 string base_name = TWFunc::Get_Filename(FirmwareFiles[i]);
390
391 if (is_firmware_symlinked)
392 vsymlink(FirmwareFiles[i], "/firmware/image/" + base_name);
393
394 if (is_vendor_symlinked) {
395 vsymlink(FirmwareFiles[i], "/vendor/firmware/" + base_name);
396 vsymlink(FirmwareFiles[i], "/vendor/firmware/keymaster/" + base_name);
397 }
398 }
399 LOGINFO("%d file(s) symlinked.\n", (int)FirmwareFiles.size());
400}
401
402// Android 8.0 fs_mgr checks for "/sbin/recovery", in which case it will
403// use /etc/recovery.fstab -> symlink it temporarily. Reference:
404// https://android.googlesource.com/platform/system/core/+/android-8.0.0_r17/fs_mgr/fs_mgr_fstab.cpp#693
405bool Symlink_Recovery_Fstab(void) {
406 bool is_fstab_symlinked = false;
407
408 if (vrename("/etc/recovery.fstab", "/etc/recovery-fstab-orig") == 0) {
409 is_fstab_symlinked = true;
410
411 // now attempt to symlink to /fstab.{ro.hardware}, but even if that
412 // fails, keep TWRP's fstab hidden since it cannot be parsed by fs_mgr
413 char prop_value[PROPERTY_VALUE_MAX];
414 property_get("ro.hardware", prop_value, "error");
415 if (strcmp(prop_value, "error")) {
416 string fstab_device = "/fstab."; fstab_device += prop_value;
417 vsymlink(fstab_device, "/etc/recovery.fstab");
418 }
419 }
420 return is_fstab_symlinked;
421}
422
423void Restore_Recovery_Fstab(void) {
424 unlink("/etc/recovery.fstab");
425 vrename("/etc/recovery-fstab-orig", "/etc/recovery.fstab");
426}
427
428
429/* Additional Services Functions */
430#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
431typedef struct {
432 string Service_Name;
433 string Service_Path;
434 string Service_Binary;
435
436 string VOLD_Service_Name;
437 string TWRP_Service_Name;
438 bool is_running;
439 bool resume;
nkk7137625a42017-12-08 16:37:59 +0200440 bool bin_exists;
441 bool svc_exists;
nkk717d1222a2017-11-06 17:27:21 +0200442} AdditionalService;
443
444typedef struct {
445 string Service_Name;
446 string Service_Path;
447 string Service_Binary;
448} RC_Service;
449
450// expand_props() courtesy of platform_system_core_init_util.cpp
451bool expand_props(const std::string& src, std::string* dst) {
452 const char* src_ptr = src.c_str();
453
454 if (!dst) {
455 return false;
456 }
457
458 /* - variables can either be $x.y or ${x.y}, in case they are only part
459 * of the string.
460 * - will accept $$ as a literal $.
461 * - no nested property expansion, i.e. ${foo.${bar}} is not supported,
462 * bad things will happen
463 * - ${x.y:-default} will return default value if property empty.
464 */
465 while (*src_ptr) {
466 const char* c;
467
468 c = strchr(src_ptr, '$');
469 if (!c) {
470 dst->append(src_ptr);
471 return true;
472 }
473
474 dst->append(src_ptr, c);
475 c++;
476
477 if (*c == '$') {
478 dst->push_back(*(c++));
479 src_ptr = c;
480 continue;
481 } else if (*c == '\0') {
482 return true;
483 }
484
485 std::string prop_name;
486 std::string def_val;
487 if (*c == '{') {
488 c++;
489 const char* end = strchr(c, '}');
490 if (!end) {
491 // failed to find closing brace, abort.
492 return false;
493 }
494 prop_name = std::string(c, end);
495 c = end + 1;
496 size_t def = prop_name.find(":-");
497 if (def < prop_name.size()) {
498 def_val = prop_name.substr(def + 2);
499 prop_name = prop_name.substr(0, def);
500 }
501 } else {
502 prop_name = c;
503 c += prop_name.size();
504 }
505
506 if (prop_name.empty()) {
507 return false;
508 }
509
510 char prop_value[PROPERTY_VALUE_MAX];
511 property_get(prop_name.c_str(), prop_value, "");
512 std::string prop_val = prop_value;
513 if (prop_val.empty()) {
514 if (def_val.empty()) {
515 return false;
516 }
517 prop_val = def_val;
518 }
519
520 dst->append(prop_val);
521 src_ptr = c;
522 }
523
524 return true;
525}
526
527string GetArgument(const string& line, size_t argument_number, bool expand_properties) {
528 size_t beg;
529 size_t end;
530 string argument;
531
532 beg = line.find_first_not_of(" \t\r");
533 if (beg == string::npos)
534 return "";
535
536 for (size_t i = 0; i < argument_number; ++i) {
537 end = line.find_first_of(" \t\r", beg);
538 if (end == string::npos)
539 return "";
540
541 beg = line.find_first_not_of(" \t\r", end);
542 if (beg == string::npos)
543 return "";
544 }
545
546 end = line.find_first_of(" \t\r", beg);
547 if (end == string::npos)
548 argument = line.substr(beg);
549 else
550 argument = line.substr(beg, end - beg); // exclude trailing whitespace
551
552 if (expand_properties) {
553 string expanded_property_argument;
554 if (expand_props(argument, &expanded_property_argument))
555 return expanded_property_argument;
556 else
557 return "";
558 } else {
559 return argument;
560 }
561}
562
563// Very simplified .rc parser to get services
564void Parse_RC_File(const string& rc_file, vector<RC_Service>& RC_Services) {
565 ifstream file;
566
567 file.open(rc_file.c_str(), ios::in);
568 if (!file.is_open())
569 return;
570
571 size_t beg; // left trim
572 size_t end; // right trim
573 bool continuation = false; // backslash continuation
574 string line; // line
575 string real_line; // trimmed line with backslash continuation removal
576 vector<string> imports; // file names of imports (we don't want to recursively do while the file is open)
577
578 while (getline(file, line)) {
579 beg = line.find_first_not_of(" \t\r");
580 end = line.find_last_not_of(" \t\r");
581 if (end == string::npos)
582 end = line.length();
583
584 if (beg == string::npos) {
585 if (continuation)
586 continuation = false;
587 else
588 continue;
589 } else if (line[end] == '\\') {
590 continuation = true;
591 real_line += line.substr(beg, end - beg); // excluding backslash
592 continue;
593 } else if (continuation) {
594 continuation = false;
595 real_line += line.substr(beg, end - beg + 1);
596 } else {
597 real_line = line.substr(beg, end - beg + 1);
598 }
599
600 if (GetArgument(real_line, 0, false) == "import") {
601 // handle: import <file>
602 string file_name = GetArgument(real_line, 1, true);
603 if (file_name.empty()) {
604 // INVALID IMPORT
605 } else
606 imports.push_back(file_name);
607 } else if (GetArgument(real_line, 0, false) == "service") {
608 // handle: service <name> <path>
609 RC_Service svc;
610
611 svc.Service_Name = GetArgument(real_line, 1, false);
612 svc.Service_Path = GetArgument(real_line, 2, true);
613
614 if (svc.Service_Name.empty() || svc.Service_Path.empty()) {
615 // INVALID SERVICE ENTRY
616 } else {
617 beg = svc.Service_Path.find_last_of("/");
618 if (beg == string::npos)
619 svc.Service_Binary = svc.Service_Path;
620 else
621 svc.Service_Binary = svc.Service_Path.substr(beg + 1);
622
623/*
624#ifdef _USING_SHORT_SERVICE_NAMES
625 if (svc.Service_Name.length() > 16) {
626 LOGERROR("WARNING: Ignoring service %s (-> %s)\n"
627 " defined in %s is greater than 16 characters and will\n"
628 " not be able to be run by init on android-7.1 or below!\n",
629 svc.Service_Name.c_str(), svc.Service_Path.c_str(), rc_file.c_str()
630 );
631 }
632 else
633#endif
634*/
635 RC_Services.push_back(svc);
636 }
637 }
638 real_line.clear();
639 }
640 file.close();
641
642 for (size_t i = 0; i < imports.size(); ++i) {
643 Parse_RC_File(imports[i], RC_Services);
644 }
645}
646
647vector<AdditionalService> Get_List_Of_Additional_Services(void) {
648 vector<AdditionalService> services;
649
650 // Additional Services needed by vold_decrypt (eg qseecomd, hwservicemanager, etc)
651 vector<string> service_names = TWFunc::Split_String(TW_CRYPTO_SYSTEM_VOLD_SERVICES, " ");
652 for (size_t i = 0; i < service_names.size(); ++i) {
653 AdditionalService svc;
654 svc.Service_Name = service_names[i];
nkk7137625a42017-12-08 16:37:59 +0200655 svc.bin_exists = false;
656 svc.svc_exists = false;
nkk717d1222a2017-11-06 17:27:21 +0200657 services.push_back(svc);
658
659#ifdef _USING_SHORT_SERVICE_NAMES
660 // Fallback code for >16 character service names which
661 // allows for multiple definitions in custom .rc files
662 if (service_names[i].length() > 12) {
663 svc.Service_Name = service_names[i].substr(0, 12); // 16-4(prefix)=12
nkk7137625a42017-12-08 16:37:59 +0200664 svc.bin_exists = false;
665 svc.svc_exists = false;
nkk717d1222a2017-11-06 17:27:21 +0200666 services.push_back(svc);
667 }
668#endif
669 }
670
671 // Read list of all services defined in all .rc files
672 vector<RC_Service> RC_Services;
673 Parse_RC_File("/init.rc", RC_Services);
674
675
676 // Cross reference Additional Services against the .rc Services and establish
677 // availability of the binaries, otherwise disable it to avoid unnecessary
678 // delays and log spam.
679 // Also check for duplicate entries between TWRP and vold_decrypt so we can
680 // stop and restart any conflicting services.
681 for (size_t i = 0; i < RC_Services.size(); ++i) {
682 string prefix = RC_Services[i].Service_Name.substr(0, 4);
683
684#ifdef _USING_SHORT_SERVICE_NAMES
685 map<string,size_t> rc_indeces;
686#endif
687
688 if (prefix != "sys_" && prefix != "ven_") {
689#ifdef _USING_SHORT_SERVICE_NAMES
690 if (RC_Services[i].Service_Name.length() > 12) {
691 // save this entry for potential binary name match
692 rc_indeces.insert(pair<string,size_t>(RC_Services[i].Service_Binary, i));
693 }
694#endif
695 continue;
696 }
697
698 for (size_t j = 0; j < services.size(); ++j) {
699 string path = RC_Services[i].Service_Path;
700 if (prefix == "ven_" && will_VendorBin_Be_Symlinked()) {
701 path = "/system" + path; // vendor is going to get symlinked to /system/vendor
702 }
703
704 if (RC_Services[i].Service_Name == prefix + services[j].Service_Name) {
nkk7137625a42017-12-08 16:37:59 +0200705 services[j].svc_exists = true;
706
nkk717d1222a2017-11-06 17:27:21 +0200707 if (!services[j].VOLD_Service_Name.empty() && TWFunc::Path_Exists(path)) {
708 // Duplicate match, log but use previous definition
709 LOGERROR("Service %s: VOLD_Service_Name already defined as %s\n", RC_Services[i].Service_Name.c_str(), services[j].VOLD_Service_Name.c_str());
710 }
711 else if (TWFunc::Path_Exists(path)) {
nkk7137625a42017-12-08 16:37:59 +0200712 services[j].bin_exists = true;
nkk717d1222a2017-11-06 17:27:21 +0200713 services[j].VOLD_Service_Name = RC_Services[i].Service_Name; // prefix + service_name
714 services[j].Service_Path = RC_Services[i].Service_Path;
715 services[j].Service_Binary = RC_Services[i].Service_Binary;
716
717 if (Service_Exists(services[j].Service_Name))
718 services[j].TWRP_Service_Name = services[j].Service_Name;
719 else if (Service_Exists("sbin" + services[j].Service_Name))
720 services[j].TWRP_Service_Name = "sbin" + services[j].Service_Name;
721 else
722 services[j].TWRP_Service_Name.clear();
723
724#ifdef _USING_SHORT_SERVICE_NAMES
725 if (services[j].TWRP_Service_Name.empty()) {
726 // Try matching Service_Binary (due to 16 character service_name limit in 7.1 and below)
727 map<string,size_t>::iterator it = rc_indeces.find(services[j].Service_Binary);
728 if (it != rc_indeces.end()) {
729 services[j].TWRP_Service_Name = RC_Services[it->second].Service_Name;
730 }
731 }
732#endif
733 }
734 break;
735 }
736 }
737 }
738
739 LOGINFO("List of additional services for vold_decrypt:\n");
740 for (size_t i = 0; i < services.size(); ++i) {
nkk7137625a42017-12-08 16:37:59 +0200741 if (!services[i].svc_exists) {
742 LOGINFO(" %s: Disabled due to lack of .rc service entry\n", services[i].Service_Name.c_str());
743 } else if (services[i].bin_exists) {
nkk717d1222a2017-11-06 17:27:21 +0200744 if (services[i].TWRP_Service_Name.empty()) {
745 LOGINFO(" %s: Enabled as %s -> %s\n",
746 services[i].Service_Name.c_str(),
747 services[i].VOLD_Service_Name.c_str(), services[i].Service_Path.c_str()
748 );
749 } else {
750 LOGINFO(" %s: Enabled as %s -> %s (temporarily replacing TWRP's %s service)\n",
751 services[i].Service_Name.c_str(),
752 services[i].VOLD_Service_Name.c_str(), services[i].Service_Path.c_str(),
753 services[i].TWRP_Service_Name.c_str()
754 );
755 }
756 }
nkk7137625a42017-12-08 16:37:59 +0200757 else {
nkk717d1222a2017-11-06 17:27:21 +0200758 LOGINFO(" %s: Disabled due to lack of matching binary\n", services[i].Service_Name.c_str());
nkk7137625a42017-12-08 16:37:59 +0200759 }
nkk717d1222a2017-11-06 17:27:21 +0200760 }
761 return services;
762}
763#endif
764
765
766/* Misc Functions */
767void Set_Needed_Properties(void) {
nkk7171c6c502017-01-05 23:55:05 +0200768 // vold won't start without ro.storage_structure on Kitkat
769 string sdkverstr = TWFunc::System_Property_Get("ro.build.version.sdk");
nkk7171c6c502017-01-05 23:55:05 +0200770 if (!sdkverstr.empty()) {
771 sdkver = atoi(sdkverstr.c_str());
772 }
773 if (sdkver <= 19) {
774 string ro_storage_structure = TWFunc::System_Property_Get("ro.storage_structure");
775 if (!ro_storage_structure.empty())
776 property_set("ro.storage_structure", ro_storage_structure.c_str());
777 }
nijel82c821a82018-12-29 04:56:41 -0500778 property_set("hwservicemanager.ready", "false");
779 property_set("sys.listeners.registered", "false");
780 property_set("vendor.sys.listeners.registered", "false");
nkk7171c6c502017-01-05 23:55:05 +0200781}
782
nijel82c821a82018-12-29 04:56:41 -0500783static unsigned int get_blkdev_size(int fd) {
784 unsigned long nr_sec;
785
786 if ( (ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
787 nr_sec = 0;
788 }
789
790 return (unsigned int) nr_sec;
791}
792
793#define CRYPT_FOOTER_OFFSET 0x4000
794static char footer[16 * 1024];
795const char* userdata_path;
796static off64_t offset;
797
798int footer_br(const string& command) {
799 int fd;
800
801 if (command == "backup") {
802 unsigned int nr_sec;
803 TWPartition* userdata = PartitionManager.Find_Partition_By_Path("/data");
804 userdata_path = userdata->Actual_Block_Device.c_str();
805 fd = open(userdata_path, O_RDONLY);
806 if (fd < 0) {
807 LOGERROR("E:footer_backup: Cannot open '%s': %s\n", userdata_path, strerror(errno));
808 return -1;
809 }
810 if ((nr_sec = get_blkdev_size(fd))) {
811 offset = ((off64_t)nr_sec * 512) - CRYPT_FOOTER_OFFSET;
812 } else {
813 LOGERROR("E:footer_br: Failed to get offset\n");
814 close(fd);
815 return -1;
816 }
817 if (lseek64(fd, offset, SEEK_SET) == -1) {
818 LOGERROR("E:footer_backup: Failed to lseek64\n");
819 close(fd);
820 return -1;
821 }
822 if (read(fd, footer, sizeof(footer)) != sizeof(footer)) {
823 LOGERROR("E:footer_br: Failed to read: %s\n", strerror(errno));
824 close(fd);
825 return -1;
826 }
827 close(fd);
828 } else if (command == "restore") {
829 fd = open(userdata_path, O_WRONLY);
830 if (fd < 0) {
831 LOGERROR("E:footer_restore: Cannot open '%s': %s\n", userdata_path, strerror(errno));
832 return -1;
833 }
834 if (lseek64(fd, offset, SEEK_SET) == -1) {
835 LOGERROR("E:footer_restore: Failed to lseek64\n");
836 close(fd);
837 return -1;
838 }
839 if (write(fd, footer, sizeof(footer)) != sizeof(footer)) {
840 LOGERROR("E:footer_br: Failed to write: %s\n", strerror(errno));
841 close(fd);
842 return -1;
843 }
844 close(fd);
845 } else {
846 LOGERROR("E:footer_br: wrong command argument: %s\n", command.c_str());
847 return -1;
848 }
849 return 0;
850}
nkk7171c6c502017-01-05 23:55:05 +0200851
nkk717d1222a2017-11-06 17:27:21 +0200852/* vdc Functions */
853typedef struct {
854 string Output; // Entire line excluding \n
855 int ResponseCode; // ResponseCode.h (int)
856 int Sequence; // Sequence (int)
857 int Message; // Message (string) but we're only interested in int
858} vdc_ReturnValues;
859
860int Exec_vdc_cryptfs(const string& command, const string& argument, vdc_ReturnValues* vdcResult) {
861 pid_t pid;
862 int status;
nkk7137625a42017-12-08 16:37:59 +0200863 int pipe_fd[2][2];
nkk717d1222a2017-11-06 17:27:21 +0200864
nkk7137625a42017-12-08 16:37:59 +0200865 vdcResult->Output.clear();
866 vdcResult->ResponseCode = vdcResult->Sequence = vdcResult->Message = -1;
867
868 for (int i = 0; i < 2; ++i) {
869 if (pipe(pipe_fd[i])) {
870 LOGERROR("exec_vdc_cryptfs: pipe() error!\n");
871 return -1;
872 }
nkk717d1222a2017-11-06 17:27:21 +0200873 }
874
nijel82c821a82018-12-29 04:56:41 -0500875 // getpwtype and checkpw commands are removed from Pie vdc, using modified vdc_pie
876 const char *cmd[] = { "/sbin/vdc_pie", "cryptfs" };
877 if (sdkver < 28)
878 cmd[0] = "/system/bin/vdc";
nkk717d1222a2017-11-06 17:27:21 +0200879 const char *env[] = { "LD_LIBRARY_PATH=/system/lib64:/system/lib", NULL };
880
nijel82c821a82018-12-29 04:56:41 -0500881 LOGINFO("sdkver: %d, using %s\n", sdkver, cmd[0]);
882
nkk717d1222a2017-11-06 17:27:21 +0200883#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
884 string log_name = "/tmp/strace_vdc_" + command;
nkk7171c6c502017-01-05 23:55:05 +0200885#endif
nkk7171c6c502017-01-05 23:55:05 +0200886
nkk717d1222a2017-11-06 17:27:21 +0200887 switch(pid = fork())
888 {
889 case -1:
890 LOGERROR("exec_vdc_cryptfs: fork failed: %d (%s)!\n", errno, strerror(errno));
891 return -1;
892
893 case 0: // child
894 fflush(stdout); fflush(stderr);
nkk7137625a42017-12-08 16:37:59 +0200895 for (int i = 0; i < 2; ++i) {
896 close(pipe_fd[i][0]);
897 dup2(pipe_fd[i][1], ((i == 0) ? STDOUT_FILENO : STDERR_FILENO));
898 close(pipe_fd[i][1]);
899 }
nkk717d1222a2017-11-06 17:27:21 +0200900
901#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
902 if (has_strace) {
903 if (argument.empty())
904 execl(VD_STRACE_BIN, "strace", "-q", "-tt", "-ff", "-v", "-y", "-s", "1000", "-o", log_name.c_str(),
905 "-E", env[0], cmd[0], cmd[1], command.c_str(), NULL);
906 else
907 execl(VD_STRACE_BIN, "strace", "-q", "-tt", "-ff", "-v", "-y", "-s", "1000", "-o", log_name.c_str(),
908 "-E", env[0], cmd[0], cmd[1], command.c_str(), argument.c_str(), NULL);
909 } else
910#endif
911 if (argument.empty())
912 execle(cmd[0], cmd[0], cmd[1], command.c_str(), NULL, env);
913 else
914 execle(cmd[0], cmd[0], cmd[1], command.c_str(), argument.c_str(), NULL, env);
915 _exit(127);
916 break;
917
918 default:
919 {
920 int timeout = 30*100;
nkk717d1222a2017-11-06 17:27:21 +0200921
nkk7137625a42017-12-08 16:37:59 +0200922 for (int i = 0; i < 2; ++i) {
923 close(pipe_fd[i][1]);
924
925 // Non-blocking read loop with timeout
926 int flags = fcntl(pipe_fd[i][0], F_GETFL, 0);
927 fcntl(pipe_fd[i][0], F_SETFL, flags | O_NONBLOCK);
928 }
nkk717d1222a2017-11-06 17:27:21 +0200929
930 char buffer[128];
931 ssize_t count;
nkk7137625a42017-12-08 16:37:59 +0200932 string strout[2];
nkk717d1222a2017-11-06 17:27:21 +0200933 pid_t retpid = waitpid(pid, &status, WNOHANG);
934 while (true) {
nkk7137625a42017-12-08 16:37:59 +0200935 for (int i = 0; i < 2; ++i) {
936 count = read(pipe_fd[i][0], buffer, sizeof(buffer));
937 if (count == -1) {
938 if (errno == EINTR)
939 continue;
940 else if (errno != EAGAIN)
941 LOGERROR("exec_vdc_cryptfs: read() error %d (%s)\n!", errno, strerror(errno));
942 } else if (count > 0) {
943 strout[i].append(buffer, count);
944 }
nkk717d1222a2017-11-06 17:27:21 +0200945 }
946
947 retpid = waitpid(pid, &status, WNOHANG);
948 if (retpid == 0 && --timeout)
949 usleep(10000);
950 else
951 break;
952 };
nkk7137625a42017-12-08 16:37:59 +0200953
954 for (int i = 0; i < 2; ++i) {
955 close(pipe_fd[i][0]);
956 }
957
958 if (!strout[0].empty()) {
959 sscanf(strout[0].c_str(), "%d %d %d", &vdcResult->ResponseCode, &vdcResult->Sequence, &vdcResult->Message);
960 vdcResult->Output = "I:" + strout[0];
961 }
962 if (!strout[1].empty()) {
963 vdcResult->Output += "E:" + strout[1];
964 }
965 std::replace(vdcResult->Output.begin(), vdcResult->Output.end(), '\n', '|');
966
967 if (!vdcResult->Output.empty() && vdcResult->Output[vdcResult->Output.length() - 1] != '|')
968 vdcResult->Output += "|";
969 vdcResult->Output += "RC=" + TWFunc::to_string(WEXITSTATUS(status));
nkk717d1222a2017-11-06 17:27:21 +0200970
971 // Error handling
972 if (retpid == 0 && timeout == 0) {
973 LOGERROR("exec_vdc_cryptfs: took too long, killing process\n");
974 kill(pid, SIGKILL);
975 for (timeout = 5; retpid == 0 && timeout; --timeout) {
976 sleep(1);
977 retpid = waitpid(pid, &status, WNOHANG);
978 }
979 if (retpid)
980 LOGINFO("exec_vdc_cryptfs: process killed successfully\n");
981 else
982 LOGERROR("exec_vdc_cryptfs: process took too long to kill, may be a zombie process\n");
983 return VD_ERR_VOLD_OPERATION_TIMEDOUT;
984 } else if (retpid > 0) {
985 if (WIFSIGNALED(status)) {
986 LOGERROR("exec_vdc_cryptfs: process ended with signal: %d\n", WTERMSIG(status)); // Seg fault or some other non-graceful termination
987 return -1;
988 }
989 } else if (retpid < 0) { // no PID returned
990 if (errno == ECHILD)
991 LOGINFO("exec_vdc_cryptfs: no child process exist\n");
992 else {
993 LOGERROR("exec_vdc_cryptfs: Unexpected error %d (%s)\n", errno, strerror(errno));
994 return -1;
995 }
996 }
nijel82c821a82018-12-29 04:56:41 -0500997 if (sdkver >= 28) {
998 return WEXITSTATUS(status);
999 }
nkk717d1222a2017-11-06 17:27:21 +02001000 return 0;
1001 }
1002 }
nkk7171c6c502017-01-05 23:55:05 +02001003}
1004
nkk717d1222a2017-11-06 17:27:21 +02001005int Run_vdc(const string& Password) {
1006 int res;
nkk7171c6c502017-01-05 23:55:05 +02001007 struct timeval t1, t2;
nkk717d1222a2017-11-06 17:27:21 +02001008 vdc_ReturnValues vdcResult;
nkk7171c6c502017-01-05 23:55:05 +02001009
nkk717d1222a2017-11-06 17:27:21 +02001010 LOGINFO("About to run vdc...\n");
nkk7171c6c502017-01-05 23:55:05 +02001011
nijel82c821a82018-12-29 04:56:41 -05001012 // Pie vdc communicates with vold directly, no socket so lets not waste time
1013 if (sdkver < 28) {
1014 // Wait for vold connection
1015 gettimeofday(&t1, NULL);
1016 t2 = t1;
1017 while ((t2.tv_sec - t1.tv_sec) < 5) {
1018 // cryptfs getpwtype returns: R1=213(PasswordTypeResult) R2=? R3="password", "pattern", "pin", "default"
1019 res = Exec_vdc_cryptfs("getpwtype", "", &vdcResult);
1020 if (vdcResult.ResponseCode == PASSWORD_TYPE_RESULT) {
1021 res = 0;
1022 break;
1023 }
1024 LOGINFO("Retrying connection to vold (Reason: %s)\n", vdcResult.Output.c_str());
1025 usleep(SLEEP_MIN_USEC); // vdc usually usleep(10000), but that causes too many unnecessary attempts
1026 gettimeofday(&t2, NULL);
nkk7171c6c502017-01-05 23:55:05 +02001027 }
nijel82c821a82018-12-29 04:56:41 -05001028
1029 if (res == 0 && (t2.tv_sec - t1.tv_sec) < 5)
1030 LOGINFO("Connected to vold: %s\n", vdcResult.Output.c_str());
1031 else if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
1032 return VD_ERR_VOLD_OPERATION_TIMEDOUT; // should never happen for getpwtype
1033 else if (res)
1034 return VD_ERR_FORK_EXECL_ERROR;
1035 else if (vdcResult.ResponseCode != -1)
1036 return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
1037 else
1038 return VD_ERR_VDC_FAILED_TO_CONNECT;
nkk7171c6c502017-01-05 23:55:05 +02001039 }
1040
nkk7171c6c502017-01-05 23:55:05 +02001041 // Input password from GUI, or default password
nkk717d1222a2017-11-06 17:27:21 +02001042 res = Exec_vdc_cryptfs("checkpw", Password, &vdcResult);
1043 if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
1044 return VD_ERR_VOLD_OPERATION_TIMEDOUT;
1045 else if (res)
1046 return VD_ERR_FORK_EXECL_ERROR;
nkk7171c6c502017-01-05 23:55:05 +02001047
nkk7137625a42017-12-08 16:37:59 +02001048 LOGINFO("vdc cryptfs result (passwd): %s\n", vdcResult.Output.c_str());
nkk717d1222a2017-11-06 17:27:21 +02001049 /*
1050 if (res == 0 && vdcResult.ResponseCode != COMMAND_OKAY)
1051 return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
1052 */
1053
nijel82c821a82018-12-29 04:56:41 -05001054 // our vdc returns vold binder op status,
1055 // we care about status.ok() only which is 0
1056 if (sdkver >= 28) {
1057 vdcResult.Message = res;
1058 }
1059
nkk717d1222a2017-11-06 17:27:21 +02001060 if (vdcResult.Message != 0) {
nkk7171c6c502017-01-05 23:55:05 +02001061 // try falling back to Lollipop hex passwords
1062 string hexPassword = convert_key_to_hex_ascii(Password);
nkk717d1222a2017-11-06 17:27:21 +02001063 res = Exec_vdc_cryptfs("checkpw", hexPassword, &vdcResult);
1064 if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
1065 return VD_ERR_VOLD_OPERATION_TIMEDOUT;
1066 else if (res)
1067 return VD_ERR_FORK_EXECL_ERROR;
1068
nkk7137625a42017-12-08 16:37:59 +02001069 LOGINFO("vdc cryptfs result (hex_pw): %s\n", vdcResult.Output.c_str());
nkk717d1222a2017-11-06 17:27:21 +02001070 /*
1071 if (res == 0 && vdcResult.ResponseCode != COMMAND_OKAY)
1072 return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
1073 */
nkk7171c6c502017-01-05 23:55:05 +02001074 }
1075
nijel82c821a82018-12-29 04:56:41 -05001076 // sdk < 28 vdc's return value is dependant upon source origin, it will either
nkk717d1222a2017-11-06 17:27:21 +02001077 // return 0 or ResponseCode, so disregard and focus on decryption instead
nijel82c821a82018-12-29 04:56:41 -05001078 // our vdc always returns 0 on success
nkk717d1222a2017-11-06 17:27:21 +02001079 if (vdcResult.Message == 0) {
nkk7171c6c502017-01-05 23:55:05 +02001080 // Decryption successful wait for crypto blk dev
nkk717d1222a2017-11-06 17:27:21 +02001081 Wait_For_Property("ro.crypto.fs_crypto_blkdev");
1082 res = VD_SUCCESS;
1083 } else if (vdcResult.ResponseCode != COMMAND_OKAY) {
1084 res = VD_ERR_VOLD_UNEXPECTED_RESPONSE;
nkk7171c6c502017-01-05 23:55:05 +02001085 } else {
nkk717d1222a2017-11-06 17:27:21 +02001086 res = VD_ERR_DECRYPTION_FAILED;
nkk7171c6c502017-01-05 23:55:05 +02001087 }
1088
1089 return res;
1090}
1091
nkk717d1222a2017-11-06 17:27:21 +02001092int Vold_Decrypt_Core(const string& Password) {
nkk7171c6c502017-01-05 23:55:05 +02001093 int res;
nkk7171c6c502017-01-05 23:55:05 +02001094 bool is_vendor_symlinked = false;
1095 bool is_firmware_symlinked = false;
nkk717d1222a2017-11-06 17:27:21 +02001096 bool is_fstab_symlinked = false;
nkk7171c6c502017-01-05 23:55:05 +02001097 bool is_vold_running = false;
1098
1099 if (Password.empty()) {
nkk717d1222a2017-11-06 17:27:21 +02001100 LOGINFO("vold_decrypt: password is empty!\n");
1101 return VD_ERR_PASSWORD_EMPTY;
nkk7171c6c502017-01-05 23:55:05 +02001102 }
1103
Captain Throwback6ac30af2018-06-21 10:57:12 -04001104 // Mount ANDROID_ROOT and check for vold and vdc
1105 if (!PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) {
nkk717d1222a2017-11-06 17:27:21 +02001106 return VD_ERR_UNABLE_TO_MOUNT_SYSTEM;
Captain Throwback6ac30af2018-06-21 10:57:12 -04001107 } else if ((!TWFunc::Path_Exists("/system/bin/vold")) && (!TWFunc::Path_Exists(PartitionManager.Get_Android_Root_Path() + "/system/bin/vold"))) {
1108 LOGINFO("ERROR: vold not found, aborting.\n");
nkk717d1222a2017-11-06 17:27:21 +02001109 return VD_ERR_MISSING_VOLD;
Captain Throwback6ac30af2018-06-21 10:57:12 -04001110 } else if ((!TWFunc::Path_Exists("/system/bin/vdc")) && (!TWFunc::Path_Exists(PartitionManager.Get_Android_Root_Path() + "/system/bin/vdc"))) {
1111 LOGINFO("ERROR: vdc not found, aborting.\n");
nkk717d1222a2017-11-06 17:27:21 +02001112 return VD_ERR_MISSING_VDC;
nkk7171c6c502017-01-05 23:55:05 +02001113 }
1114
nijel82c821a82018-12-29 04:56:41 -05001115#ifdef TW_CRYPTO_SYSTEM_VOLD_MOUNT
1116 vector<string> partitions = TWFunc::Split_String(TW_CRYPTO_SYSTEM_VOLD_MOUNT, " ");
1117 for (size_t i = 0; i < partitions.size(); ++i) {
1118 string mnt_point = "/" + partitions[i];
1119 if(PartitionManager.Find_Partition_By_Path(mnt_point)) {
1120 if (!PartitionManager.Mount_By_Path(mnt_point, true)) {
1121 LOGERROR("Unable to mount %s\n", mnt_point.c_str());
1122 return VD_ERR_UNABLE_TO_MOUNT_EXTRA;
1123 }
1124 LOGINFO("%s partition mounted\n", partitions[i].c_str());
1125 }
1126 }
1127#endif
1128
nkk7171c6c502017-01-05 23:55:05 +02001129 fp_kmsg = fopen("/dev/kmsg", "a");
1130
nkk717d1222a2017-11-06 17:27:21 +02001131 LOGINFO("TW_CRYPTO_USE_SYSTEM_VOLD := true\n");
nkk7171c6c502017-01-05 23:55:05 +02001132
nkk717d1222a2017-11-06 17:27:21 +02001133 // just cache the result to avoid unneeded duplicates in recovery.log
1134 LOGINFO("Checking existence of vendor and firmware partitions...\n");
1135 is_Vendor_Mounted();
1136 is_Firmware_Mounted();
1137
1138 LOGINFO("Attempting to use system's vold for decryption...\n");
nkk7171c6c502017-01-05 23:55:05 +02001139
1140#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
nkk717d1222a2017-11-06 17:27:21 +02001141 Strace_init_Start();
nkk7171c6c502017-01-05 23:55:05 +02001142#endif
1143
1144#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1145 vector<AdditionalService> Services = Get_List_Of_Additional_Services();
1146
1147 // Check if TWRP is running any of the services
1148 for (size_t i = 0; i < Services.size(); ++i) {
nkk717d1222a2017-11-06 17:27:21 +02001149 if (!Services[i].TWRP_Service_Name.empty() && !Is_Service_Stopped(Services[i].TWRP_Service_Name)) {
nkk7171c6c502017-01-05 23:55:05 +02001150 Services[i].resume = true;
nkk717d1222a2017-11-06 17:27:21 +02001151 Stop_Service(Services[i].TWRP_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001152 } else
1153 Services[i].resume = false;
nkk7171c6c502017-01-05 23:55:05 +02001154 }
1155#endif
1156
nkk717d1222a2017-11-06 17:27:21 +02001157 LOGINFO("Setting up folders and permissions...\n");
1158 is_fstab_symlinked = Symlink_Recovery_Fstab();
nkk7171c6c502017-01-05 23:55:05 +02001159 is_vendor_symlinked = Symlink_Vendor_Folder();
1160 is_firmware_symlinked = Symlink_Firmware_Folder();
1161 Symlink_Firmware_Files(is_vendor_symlinked, is_firmware_symlinked);
1162
nkk717d1222a2017-11-06 17:27:21 +02001163 Set_Needed_Properties();
nkk7171c6c502017-01-05 23:55:05 +02001164
1165 // Start services needed for vold decrypt
nkk717d1222a2017-11-06 17:27:21 +02001166 LOGINFO("Starting services...\n");
nkk7171c6c502017-01-05 23:55:05 +02001167#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1168 for (size_t i = 0; i < Services.size(); ++i) {
nijel82c821a82018-12-29 04:56:41 -05001169 if (Services[i].bin_exists) {
1170 if (Services[i].Service_Binary.find("keymaster") != string::npos) {
1171 Wait_For_Property("hwservicemanager.ready", 500000, "true");
1172 LOGINFO(" hwservicemanager is ready.\n");
1173 }
1174
nkk717d1222a2017-11-06 17:27:21 +02001175 Services[i].is_running = Start_Service(Services[i].VOLD_Service_Name);
nijel82c821a82018-12-29 04:56:41 -05001176
1177 if (Services[i].Service_Binary == "qseecomd") {
1178 if (Wait_For_Property("sys.listeners.registered", 500000, "true") == "true"
1179 || Wait_For_Property("vendor.sys.listeners.registered", 500000, "true") == "true")
1180 LOGINFO(" qseecomd listeners registered.\n");
1181 }
1182 }
nkk7171c6c502017-01-05 23:55:05 +02001183 }
1184#endif
1185 is_vold_running = Start_Service("sys_vold");
1186
1187 if (is_vold_running) {
nkk7171c6c502017-01-05 23:55:05 +02001188#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1189 for (size_t i = 0; i < Services.size(); ++i) {
nkk7137625a42017-12-08 16:37:59 +02001190 if (Services[i].bin_exists && !Is_Service_Running(Services[i].VOLD_Service_Name) && Services[i].resume) {
nkk7171c6c502017-01-05 23:55:05 +02001191 // if system_service has died restart the twrp_service
nkk717d1222a2017-11-06 17:27:21 +02001192 LOGINFO("%s is not running, resuming %s!\n", Services[i].VOLD_Service_Name.c_str(), Services[i].TWRP_Service_Name.c_str());
1193 Start_Service(Services[i].TWRP_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001194 }
1195 }
1196#endif
nijel82c821a82018-12-29 04:56:41 -05001197
1198 /*
1199 * Oreo and Pie vold on some devices alters footer causing
1200 * system to ask for decryption password at next boot although
1201 * password haven't changed so we save footer before and restore it
1202 * after vold operations
1203 */
1204 if (sdkver > 25) {
1205 if (footer_br("backup") == 0) {
1206 LOGINFO("footer_br: crypto footer backed up\n");
1207 res = Run_vdc(Password);
1208 if (footer_br("restore") == 0)
1209 LOGINFO("footer_br: crypto footer restored\n");
1210 else
1211 LOGERROR("footer_br: Failed to restore crypto footer\n");
1212 } else {
1213 LOGERROR("footer_br: Failed to backup crypto footer, \
1214 skipping decrypt to prevent data loss. Reboot recovery to try again...\n");
1215 res = -1;
1216 }
1217 } else {
1218 res = Run_vdc(Password);
1219 }
nkk7171c6c502017-01-05 23:55:05 +02001220
1221 if (res != 0) {
nkk717d1222a2017-11-06 17:27:21 +02001222 LOGINFO("Decryption failed\n");
nkk7171c6c502017-01-05 23:55:05 +02001223 }
1224 } else {
nkk717d1222a2017-11-06 17:27:21 +02001225 LOGINFO("Failed to start vold\n");
1226 res = VD_ERR_VOLD_FAILED_TO_START;
nkk7171c6c502017-01-05 23:55:05 +02001227 }
1228
1229 // Stop services needed for vold decrypt so /system can be unmounted
nkk717d1222a2017-11-06 17:27:21 +02001230 LOGINFO("Stopping services...\n");
nkk7171c6c502017-01-05 23:55:05 +02001231 Stop_Service("sys_vold");
1232#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1233 for (size_t i = 0; i < Services.size(); ++i) {
nkk717d1222a2017-11-06 17:27:21 +02001234 if (!Is_Service_Running(Services[i].VOLD_Service_Name) && Services[i].resume)
1235 Stop_Service(Services[i].TWRP_Service_Name);
nkk7137625a42017-12-08 16:37:59 +02001236 else if (Services[i].bin_exists)
nkk717d1222a2017-11-06 17:27:21 +02001237 Stop_Service(Services[i].VOLD_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001238 }
1239#endif
1240
1241 if (is_firmware_symlinked)
1242 Restore_Firmware_Folder();
1243 if (is_vendor_symlinked)
1244 Restore_Vendor_Folder();
nkk717d1222a2017-11-06 17:27:21 +02001245 if (is_fstab_symlinked)
1246 Restore_Recovery_Fstab();
nkk7171c6c502017-01-05 23:55:05 +02001247
Captain Throwback6ac30af2018-06-21 10:57:12 -04001248 if (!PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) {
1249 // PartitionManager failed to unmount ANDROID_ROOT, this should not happen,
nkk7171c6c502017-01-05 23:55:05 +02001250 // but in case it does, do a lazy unmount
Captain Throwback6ac30af2018-06-21 10:57:12 -04001251 LOGINFO("WARNING: '%s' could not be unmounted normally!\n", PartitionManager.Get_Android_Root_Path().c_str());
1252 umount2(PartitionManager.Get_Android_Root_Path().c_str(), MNT_DETACH);
nkk7171c6c502017-01-05 23:55:05 +02001253 }
1254
nijel82c821a82018-12-29 04:56:41 -05001255#ifdef TW_CRYPTO_SYSTEM_VOLD_MOUNT
1256 for (size_t i = 0; i < partitions.size(); ++i) {
1257 string mnt_point = "/" + partitions[i];
1258 if(PartitionManager.Is_Mounted_By_Path(mnt_point)) {
1259 if (!PartitionManager.UnMount_By_Path(mnt_point, true)) {
1260 LOGINFO("WARNING: %s partition could not be unmounted normally!\n", partitions[i].c_str());
1261 umount2(mnt_point.c_str(), MNT_DETACH);
1262 }
1263 }
1264 }
1265#endif
1266
nkk717d1222a2017-11-06 17:27:21 +02001267 LOGINFO("Finished.\n");
nkk7171c6c502017-01-05 23:55:05 +02001268
1269#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
nijel82c821a82018-12-29 04:56:41 -05001270 Set_Needed_Properties();
nkk7171c6c502017-01-05 23:55:05 +02001271 // Restart previously running services
1272 for (size_t i = 0; i < Services.size(); ++i) {
nijel82c821a82018-12-29 04:56:41 -05001273 if (Services[i].resume) {
1274 if (Services[i].Service_Binary.find("keymaster") != string::npos) {
1275 Wait_For_Property("hwservicemanager.ready", 500000, "true");
1276 LOGINFO(" hwservicemanager is ready.\n");
1277 }
1278
nkk717d1222a2017-11-06 17:27:21 +02001279 Start_Service(Services[i].TWRP_Service_Name);
nijel82c821a82018-12-29 04:56:41 -05001280
1281 if (Services[i].Service_Binary == "qseecomd") {
1282 if (Wait_For_Property("sys.listeners.registered", 500000, "true") == "true"
1283 || Wait_For_Property("vendor.sys.listeners.registered", 500000, "true") == "true")
1284 LOGINFO(" qseecomd listeners registered.\n");
1285 }
1286 }
nkk7171c6c502017-01-05 23:55:05 +02001287 }
1288#endif
1289
1290#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
nkk717d1222a2017-11-06 17:27:21 +02001291 Strace_init_Stop();
nkk7171c6c502017-01-05 23:55:05 +02001292#endif
1293
1294 // Finish up and exit
1295 if (fp_kmsg) {
1296 fflush(fp_kmsg);
1297 fclose(fp_kmsg);
1298 }
1299
nkk7171c6c502017-01-05 23:55:05 +02001300 return res;
1301}
nkk717d1222a2017-11-06 17:27:21 +02001302
1303} // namespace
1304
1305/*
1306 * Common vold Response Codes / Errors:
1307 * 406 (OpFailedStorageNotFound) -> Problem reading or parsing fstab
1308 *
1309 */
1310
1311/* Main function separated from core in case we want to return error info */
1312int vold_decrypt(const string& Password) {
1313 return Vold_Decrypt_Core(Password);
1314}