blob: f6e6e348236703357824b77828c8c20a4c2599d0 [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;
nkk7171c6c502017-01-05 23:55:05 +020077
nkk717d1222a2017-11-06 17:27:21 +020078
79/* Debugging Functions */
nkk7171c6c502017-01-05 23:55:05 +020080#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
nkk7171c6c502017-01-05 23:55:05 +020081
nkk717d1222a2017-11-06 17:27:21 +020082#ifndef VD_STRACE_BIN
83#define VD_STRACE_BIN "/sbin/strace"
84#endif
85
86bool has_strace = false;
87pid_t pid_strace = 0;
88
89void Strace_init_Start(void) {
90 has_strace = TWFunc::Path_Exists(VD_STRACE_BIN);
91 if (!has_strace) {
92 LOGINFO("strace binary (%s) not found, disabling strace in vold_decrypt!\n", VD_STRACE_BIN);
93 return;
94 }
nkk7171c6c502017-01-05 23:55:05 +020095
96 pid_t pid;
97 switch(pid = fork())
98 {
99 case -1:
nkk717d1222a2017-11-06 17:27:21 +0200100 LOGKMSG("forking strace_init failed: %d (%s)!\n", errno, strerror(errno));
101 return;
nkk7171c6c502017-01-05 23:55:05 +0200102 case 0: // child
nkk717d1222a2017-11-06 17:27:21 +0200103 execl(VD_STRACE_BIN, "strace", "-q", "-tt", "-ff", "-v", "-y", "-s", "1000", "-o", "/tmp/strace_init.log", "-p", "1" , NULL);
104 LOGKMSG("strace_init fork failed: %d (%s)!\n", errno, strerror(errno));
nkk7171c6c502017-01-05 23:55:05 +0200105 exit(-1);
106 default:
nkk717d1222a2017-11-06 17:27:21 +0200107 LOGKMSG("Starting strace_init (pid=%d)\n", pid);
108 pid_strace = pid;
109 return;
nkk7171c6c502017-01-05 23:55:05 +0200110 }
111}
nkk717d1222a2017-11-06 17:27:21 +0200112
113void Strace_init_Stop(void) {
114 if (pid_strace > 0) {
115 LOGKMSG("Stopping strace_init (pid=%d)\n", pid_strace);
116 int timeout;
117 int status;
118 pid_t retpid = waitpid(pid_strace, &status, WNOHANG);
119
120 kill(pid_strace, SIGTERM);
121 for (timeout = 5; retpid == 0 && timeout; --timeout) {
122 sleep(1);
123 retpid = waitpid(pid_strace, &status, WNOHANG);
124 }
125 if (retpid)
126 LOGKMSG("strace_init terminated successfully\n");
127 else {
128 // SIGTERM didn't work, kill it instead
129 kill(pid_strace, SIGKILL);
130 for (timeout = 5; retpid == 0 && timeout; --timeout) {
131 sleep(1);
132 retpid = waitpid(pid_strace, &status, WNOHANG);
133 }
134 if (retpid)
135 LOGKMSG("strace_init killed successfully\n");
136 else
137 LOGKMSG("strace_init took too long to kill, may be a zombie process\n");
138 }
139 }
140}
141#endif // TW_CRYPTO_SYSTEM_VOLD_DEBUG
142
nkk7171c6c502017-01-05 23:55:05 +0200143
144/* Convert a binary key of specified length into an ascii hex string equivalent,
145 * without the leading 0x and with null termination
146 *
147 * Original code from cryptfs.c
148 */
nkk717d1222a2017-11-06 17:27:21 +0200149string convert_key_to_hex_ascii(const string& master_key) {
nkk7171c6c502017-01-05 23:55:05 +0200150 size_t i;
151 unsigned char nibble;
152 string master_key_ascii = "";
153
154 for (i = 0; i < master_key.size(); ++i) {
155 nibble = (master_key[i] >> 4) & 0xf;
156 nibble += nibble > 9 ? 0x57 : 0x30;
157 master_key_ascii += nibble;
158
159 nibble = master_key[i] & 0xf;
160 nibble += nibble > 9 ? 0x57 : 0x30;
161 master_key_ascii += nibble;
162 }
163
164 return master_key_ascii;
165}
166
nkk717d1222a2017-11-06 17:27:21 +0200167/* Helper Functions */
168#define PATH_EXISTS(path) (access(path, F_OK) >= 0)
169
170int vrename(const string& oldname, const string& newname, bool verbose = false) {
171 const char *old_name = oldname.c_str();
172 const char *new_name = newname.c_str();
173
174 if (!PATH_EXISTS(old_name))
175 return 0;
176
177 if (rename(old_name, new_name) < 0) {
178 LOGERROR("Moving %s to %s failed: %d (%s)\n", old_name, new_name, errno, strerror(errno));
179 return -1;
180 } else if (verbose)
181 LOGINFO("Renamed %s to %s\n", old_name, new_name);
182 else
183 LOGKMSG("Renamed %s to %s\n", old_name, new_name);
184 return 0;
185}
186
187int vsymlink(const string& oldname, const string& newname, bool verbose = false) {
188 const char *old_name = oldname.c_str();
189 const char *new_name = newname.c_str();
190
191 if (!PATH_EXISTS(old_name))
192 return 0;
193
194 if (symlink(old_name, new_name) < 0) {
195 LOGERROR("Symlink %s -> %s failed: %d (%s)\n", new_name, old_name, errno, strerror(errno));
196 return -1;
197 } else if (verbose)
198 LOGINFO("Symlinked %s -> %s\n", new_name, old_name);
199 else
200 LOGKMSG("Symlinked %s -> %s\n", new_name, old_name);
201 return 0;
202}
203
204
205/* Properties and Services Functions */
206string Wait_For_Property(const string& property_name, int utimeout = SLEEP_MAX_USEC, const string& expected_value = "not_empty") {
nkk7171c6c502017-01-05 23:55:05 +0200207 char prop_value[PROPERTY_VALUE_MAX];
208
209 if (expected_value == "not_empty") {
210 while (utimeout > 0) {
211 property_get(property_name.c_str(), prop_value, "error");
212 if (strcmp(prop_value, "error") != 0)
213 break;
nkk717d1222a2017-11-06 17:27:21 +0200214 LOGKMSG("waiting for %s to get set\n", property_name.c_str());
nkk7171c6c502017-01-05 23:55:05 +0200215 utimeout -= SLEEP_MIN_USEC;
216 usleep(SLEEP_MIN_USEC);;
217 }
218 }
219 else {
220 while (utimeout > 0) {
221 property_get(property_name.c_str(), prop_value, "error");
222 if (strcmp(prop_value, expected_value.c_str()) == 0)
223 break;
nkk717d1222a2017-11-06 17:27:21 +0200224 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 +0200225 utimeout -= SLEEP_MIN_USEC;
226 usleep(SLEEP_MIN_USEC);;
227 }
228 }
229 property_get(property_name.c_str(), prop_value, "error");
230
231 return prop_value;
232}
233
nkk717d1222a2017-11-06 17:27:21 +0200234string Get_Service_State(const string& initrc_svc) {
nkk7171c6c502017-01-05 23:55:05 +0200235 char prop_value[PROPERTY_VALUE_MAX];
236 string init_svc = "init.svc." + initrc_svc;
237 property_get(init_svc.c_str(), prop_value, "error");
nkk717d1222a2017-11-06 17:27:21 +0200238 return prop_value;
nkk7171c6c502017-01-05 23:55:05 +0200239}
240
nkk717d1222a2017-11-06 17:27:21 +0200241bool Service_Exists(const string& initrc_svc) {
242 return (Get_Service_State(initrc_svc) != "error");
nkk7171c6c502017-01-05 23:55:05 +0200243}
244
nkk717d1222a2017-11-06 17:27:21 +0200245bool Is_Service_Running(const string& initrc_svc) {
246 return (Get_Service_State(initrc_svc) == "running");
nkk7171c6c502017-01-05 23:55:05 +0200247}
248
nkk717d1222a2017-11-06 17:27:21 +0200249bool Is_Service_Stopped(const string& initrc_svc) {
250 return (Get_Service_State(initrc_svc) == "stopped");
251}
252
253bool Start_Service(const string& initrc_svc, int utimeout = SLEEP_MAX_USEC) {
nkk7171c6c502017-01-05 23:55:05 +0200254 string res = "error";
255 string init_svc = "init.svc." + initrc_svc;
256
257 property_set("ctl.start", initrc_svc.c_str());
258
nkk717d1222a2017-11-06 17:27:21 +0200259 res = Wait_For_Property(init_svc, utimeout, "running");
nkk7171c6c502017-01-05 23:55:05 +0200260
nkk717d1222a2017-11-06 17:27:21 +0200261 LOGINFO("Start service %s: %s.\n", initrc_svc.c_str(), res.c_str());
nkk7171c6c502017-01-05 23:55:05 +0200262
263 return (res == "running");
264}
265
nkk717d1222a2017-11-06 17:27:21 +0200266bool Stop_Service(const string& initrc_svc, int utimeout = SLEEP_MAX_USEC) {
nkk7171c6c502017-01-05 23:55:05 +0200267 string res = "error";
268
269 if (Service_Exists(initrc_svc)) {
270 string init_svc = "init.svc." + initrc_svc;
271 property_set("ctl.stop", initrc_svc.c_str());
nkk717d1222a2017-11-06 17:27:21 +0200272 res = Wait_For_Property(init_svc, utimeout, "stopped");
273 LOGINFO("Stop service %s: %s.\n", initrc_svc.c_str(), res.c_str());
nkk7171c6c502017-01-05 23:55:05 +0200274 }
275
276 return (res == "stopped");
277}
278
nkk717d1222a2017-11-06 17:27:21 +0200279
280/* Vendor, Firmware and fstab symlink Functions */
281bool is_Vendor_Mounted(void) {
282 static int is_mounted = -1;
283 if (is_mounted < 0)
284 is_mounted = PartitionManager.Is_Mounted_By_Path("/vendor") ? 1 : 0;
285 return is_mounted;
nkk7171c6c502017-01-05 23:55:05 +0200286}
287
nkk717d1222a2017-11-06 17:27:21 +0200288bool is_Firmware_Mounted(void) {
289 static int is_mounted = -1;
290 if (is_mounted < 0)
291 is_mounted = PartitionManager.Is_Mounted_By_Path("/firmware") ? 1 : 0;
292 return is_mounted;
293}
294
295bool will_VendorBin_Be_Symlinked(void) {
296 return (!is_Vendor_Mounted() && TWFunc::Path_Exists("/system/vendor"));
297}
298
299bool Symlink_Vendor_Folder(void) {
300 bool is_vendor_symlinked = false;
301
302 if (is_Vendor_Mounted()) {
303 LOGINFO("vendor partition mounted, skipping /vendor substitution\n");
304 }
305 else if (TWFunc::Path_Exists("/system/vendor")) {
306 LOGINFO("Symlinking vendor folder...\n");
307 if (!TWFunc::Path_Exists("/vendor") || vrename("/vendor", "/vendor-orig") == 0) {
308 TWFunc::Recursive_Mkdir("/vendor/firmware/keymaster");
309 vsymlink("/system/vendor/lib64", "/vendor/lib64");
310 vsymlink("/system/vendor/lib", "/vendor/lib");
311 vsymlink("/system/vendor/bin", "/vendor/bin");
312 is_vendor_symlinked = true;
313 property_set("vold_decrypt.symlinked_vendor", "1");
314 }
315 }
316 return is_vendor_symlinked;
317}
318
319void Restore_Vendor_Folder(void) {
320 property_set("vold_decrypt.symlinked_vendor", "0");
321 TWFunc::removeDir("/vendor", false);
322 vrename("/vendor-orig", "/vendor");
323}
324
325bool Symlink_Firmware_Folder(void) {
326 bool is_firmware_symlinked = false;
327
328 if (is_Firmware_Mounted()) {
329 LOGINFO("firmware partition mounted, skipping /firmware substitution\n");
330 }
331 else {
332 LOGINFO("Symlinking firmware folder...\n");
333 if (!TWFunc::Path_Exists("/firmware") || vrename("/firmware", "/firmware-orig") == 0) {
334 TWFunc::Recursive_Mkdir("/firmware/image");
335 is_firmware_symlinked = true;
336 property_set("vold_decrypt.symlinked_firmware", "1");
337 }
338 }
339 return is_firmware_symlinked;
340}
341
342void Restore_Firmware_Folder(void) {
343 property_set("vold_decrypt.symlinked_firmware", "0");
344 TWFunc::removeDir("/firmware", false);
345 vrename("/firmware-orig", "/firmware");
346}
347
348int Find_Firmware_Files(const string& Path, vector<string> *FileList) {
349 int ret;
350 DIR* d;
351 struct dirent* de;
352 string FileName;
353
354 d = opendir(Path.c_str());
355 if (d == NULL) {
356 closedir(d);
357 return -1;
358 }
359 while ((de = readdir(d)) != NULL) {
360 if (de->d_type == DT_DIR) {
361 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
362 continue;
363 FileName = Path + "/" + de->d_name;
364 ret = Find_Firmware_Files(FileName, FileList);
365 if (ret < 0)
366 return -1;
367 } else if (de->d_type == DT_REG) {
368 if (fnmatch("keymaste*.*", de->d_name, 0) == 0 || fnmatch("cmnlib.*", de->d_name, 0) == 0) {
369 FileName = Path + "/" + de->d_name;
370 FileList->push_back(FileName);
371 }
372 }
373 }
374 closedir(d);
375 return 0;
376}
377
378void Symlink_Firmware_Files(bool is_vendor_symlinked, bool is_firmware_symlinked) {
379 if (!is_vendor_symlinked && !is_firmware_symlinked)
380 return;
381
382 LOGINFO("Symlinking firmware files...\n");
383
384 vector<string> FirmwareFiles;
385 Find_Firmware_Files("/system", &FirmwareFiles);
386
387 for (size_t i = 0; i < FirmwareFiles.size(); ++i) {
388 string base_name = TWFunc::Get_Filename(FirmwareFiles[i]);
389
390 if (is_firmware_symlinked)
391 vsymlink(FirmwareFiles[i], "/firmware/image/" + base_name);
392
393 if (is_vendor_symlinked) {
394 vsymlink(FirmwareFiles[i], "/vendor/firmware/" + base_name);
395 vsymlink(FirmwareFiles[i], "/vendor/firmware/keymaster/" + base_name);
396 }
397 }
398 LOGINFO("%d file(s) symlinked.\n", (int)FirmwareFiles.size());
399}
400
401// Android 8.0 fs_mgr checks for "/sbin/recovery", in which case it will
402// use /etc/recovery.fstab -> symlink it temporarily. Reference:
403// https://android.googlesource.com/platform/system/core/+/android-8.0.0_r17/fs_mgr/fs_mgr_fstab.cpp#693
404bool Symlink_Recovery_Fstab(void) {
405 bool is_fstab_symlinked = false;
406
407 if (vrename("/etc/recovery.fstab", "/etc/recovery-fstab-orig") == 0) {
408 is_fstab_symlinked = true;
409
410 // now attempt to symlink to /fstab.{ro.hardware}, but even if that
411 // fails, keep TWRP's fstab hidden since it cannot be parsed by fs_mgr
412 char prop_value[PROPERTY_VALUE_MAX];
413 property_get("ro.hardware", prop_value, "error");
414 if (strcmp(prop_value, "error")) {
415 string fstab_device = "/fstab."; fstab_device += prop_value;
416 vsymlink(fstab_device, "/etc/recovery.fstab");
417 }
418 }
419 return is_fstab_symlinked;
420}
421
422void Restore_Recovery_Fstab(void) {
423 unlink("/etc/recovery.fstab");
424 vrename("/etc/recovery-fstab-orig", "/etc/recovery.fstab");
425}
426
427
428/* Additional Services Functions */
429#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
430typedef struct {
431 string Service_Name;
432 string Service_Path;
433 string Service_Binary;
434
435 string VOLD_Service_Name;
436 string TWRP_Service_Name;
437 bool is_running;
438 bool resume;
439 bool exists;
440} AdditionalService;
441
442typedef struct {
443 string Service_Name;
444 string Service_Path;
445 string Service_Binary;
446} RC_Service;
447
448// expand_props() courtesy of platform_system_core_init_util.cpp
449bool expand_props(const std::string& src, std::string* dst) {
450 const char* src_ptr = src.c_str();
451
452 if (!dst) {
453 return false;
454 }
455
456 /* - variables can either be $x.y or ${x.y}, in case they are only part
457 * of the string.
458 * - will accept $$ as a literal $.
459 * - no nested property expansion, i.e. ${foo.${bar}} is not supported,
460 * bad things will happen
461 * - ${x.y:-default} will return default value if property empty.
462 */
463 while (*src_ptr) {
464 const char* c;
465
466 c = strchr(src_ptr, '$');
467 if (!c) {
468 dst->append(src_ptr);
469 return true;
470 }
471
472 dst->append(src_ptr, c);
473 c++;
474
475 if (*c == '$') {
476 dst->push_back(*(c++));
477 src_ptr = c;
478 continue;
479 } else if (*c == '\0') {
480 return true;
481 }
482
483 std::string prop_name;
484 std::string def_val;
485 if (*c == '{') {
486 c++;
487 const char* end = strchr(c, '}');
488 if (!end) {
489 // failed to find closing brace, abort.
490 return false;
491 }
492 prop_name = std::string(c, end);
493 c = end + 1;
494 size_t def = prop_name.find(":-");
495 if (def < prop_name.size()) {
496 def_val = prop_name.substr(def + 2);
497 prop_name = prop_name.substr(0, def);
498 }
499 } else {
500 prop_name = c;
501 c += prop_name.size();
502 }
503
504 if (prop_name.empty()) {
505 return false;
506 }
507
508 char prop_value[PROPERTY_VALUE_MAX];
509 property_get(prop_name.c_str(), prop_value, "");
510 std::string prop_val = prop_value;
511 if (prop_val.empty()) {
512 if (def_val.empty()) {
513 return false;
514 }
515 prop_val = def_val;
516 }
517
518 dst->append(prop_val);
519 src_ptr = c;
520 }
521
522 return true;
523}
524
525string GetArgument(const string& line, size_t argument_number, bool expand_properties) {
526 size_t beg;
527 size_t end;
528 string argument;
529
530 beg = line.find_first_not_of(" \t\r");
531 if (beg == string::npos)
532 return "";
533
534 for (size_t i = 0; i < argument_number; ++i) {
535 end = line.find_first_of(" \t\r", beg);
536 if (end == string::npos)
537 return "";
538
539 beg = line.find_first_not_of(" \t\r", end);
540 if (beg == string::npos)
541 return "";
542 }
543
544 end = line.find_first_of(" \t\r", beg);
545 if (end == string::npos)
546 argument = line.substr(beg);
547 else
548 argument = line.substr(beg, end - beg); // exclude trailing whitespace
549
550 if (expand_properties) {
551 string expanded_property_argument;
552 if (expand_props(argument, &expanded_property_argument))
553 return expanded_property_argument;
554 else
555 return "";
556 } else {
557 return argument;
558 }
559}
560
561// Very simplified .rc parser to get services
562void Parse_RC_File(const string& rc_file, vector<RC_Service>& RC_Services) {
563 ifstream file;
564
565 file.open(rc_file.c_str(), ios::in);
566 if (!file.is_open())
567 return;
568
569 size_t beg; // left trim
570 size_t end; // right trim
571 bool continuation = false; // backslash continuation
572 string line; // line
573 string real_line; // trimmed line with backslash continuation removal
574 vector<string> imports; // file names of imports (we don't want to recursively do while the file is open)
575
576 while (getline(file, line)) {
577 beg = line.find_first_not_of(" \t\r");
578 end = line.find_last_not_of(" \t\r");
579 if (end == string::npos)
580 end = line.length();
581
582 if (beg == string::npos) {
583 if (continuation)
584 continuation = false;
585 else
586 continue;
587 } else if (line[end] == '\\') {
588 continuation = true;
589 real_line += line.substr(beg, end - beg); // excluding backslash
590 continue;
591 } else if (continuation) {
592 continuation = false;
593 real_line += line.substr(beg, end - beg + 1);
594 } else {
595 real_line = line.substr(beg, end - beg + 1);
596 }
597
598 if (GetArgument(real_line, 0, false) == "import") {
599 // handle: import <file>
600 string file_name = GetArgument(real_line, 1, true);
601 if (file_name.empty()) {
602 // INVALID IMPORT
603 } else
604 imports.push_back(file_name);
605 } else if (GetArgument(real_line, 0, false) == "service") {
606 // handle: service <name> <path>
607 RC_Service svc;
608
609 svc.Service_Name = GetArgument(real_line, 1, false);
610 svc.Service_Path = GetArgument(real_line, 2, true);
611
612 if (svc.Service_Name.empty() || svc.Service_Path.empty()) {
613 // INVALID SERVICE ENTRY
614 } else {
615 beg = svc.Service_Path.find_last_of("/");
616 if (beg == string::npos)
617 svc.Service_Binary = svc.Service_Path;
618 else
619 svc.Service_Binary = svc.Service_Path.substr(beg + 1);
620
621/*
622#ifdef _USING_SHORT_SERVICE_NAMES
623 if (svc.Service_Name.length() > 16) {
624 LOGERROR("WARNING: Ignoring service %s (-> %s)\n"
625 " defined in %s is greater than 16 characters and will\n"
626 " not be able to be run by init on android-7.1 or below!\n",
627 svc.Service_Name.c_str(), svc.Service_Path.c_str(), rc_file.c_str()
628 );
629 }
630 else
631#endif
632*/
633 RC_Services.push_back(svc);
634 }
635 }
636 real_line.clear();
637 }
638 file.close();
639
640 for (size_t i = 0; i < imports.size(); ++i) {
641 Parse_RC_File(imports[i], RC_Services);
642 }
643}
644
645vector<AdditionalService> Get_List_Of_Additional_Services(void) {
646 vector<AdditionalService> services;
647
648 // Additional Services needed by vold_decrypt (eg qseecomd, hwservicemanager, etc)
649 vector<string> service_names = TWFunc::Split_String(TW_CRYPTO_SYSTEM_VOLD_SERVICES, " ");
650 for (size_t i = 0; i < service_names.size(); ++i) {
651 AdditionalService svc;
652 svc.Service_Name = service_names[i];
653 svc.exists = false;
654 services.push_back(svc);
655
656#ifdef _USING_SHORT_SERVICE_NAMES
657 // Fallback code for >16 character service names which
658 // allows for multiple definitions in custom .rc files
659 if (service_names[i].length() > 12) {
660 svc.Service_Name = service_names[i].substr(0, 12); // 16-4(prefix)=12
661 svc.exists = false;
662 services.push_back(svc);
663 }
664#endif
665 }
666
667 // Read list of all services defined in all .rc files
668 vector<RC_Service> RC_Services;
669 Parse_RC_File("/init.rc", RC_Services);
670
671
672 // Cross reference Additional Services against the .rc Services and establish
673 // availability of the binaries, otherwise disable it to avoid unnecessary
674 // delays and log spam.
675 // Also check for duplicate entries between TWRP and vold_decrypt so we can
676 // stop and restart any conflicting services.
677 for (size_t i = 0; i < RC_Services.size(); ++i) {
678 string prefix = RC_Services[i].Service_Name.substr(0, 4);
679
680#ifdef _USING_SHORT_SERVICE_NAMES
681 map<string,size_t> rc_indeces;
682#endif
683
684 if (prefix != "sys_" && prefix != "ven_") {
685#ifdef _USING_SHORT_SERVICE_NAMES
686 if (RC_Services[i].Service_Name.length() > 12) {
687 // save this entry for potential binary name match
688 rc_indeces.insert(pair<string,size_t>(RC_Services[i].Service_Binary, i));
689 }
690#endif
691 continue;
692 }
693
694 for (size_t j = 0; j < services.size(); ++j) {
695 string path = RC_Services[i].Service_Path;
696 if (prefix == "ven_" && will_VendorBin_Be_Symlinked()) {
697 path = "/system" + path; // vendor is going to get symlinked to /system/vendor
698 }
699
700 if (RC_Services[i].Service_Name == prefix + services[j].Service_Name) {
701 if (!services[j].VOLD_Service_Name.empty() && TWFunc::Path_Exists(path)) {
702 // Duplicate match, log but use previous definition
703 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());
704 }
705 else if (TWFunc::Path_Exists(path)) {
706 services[j].exists = true;
707 services[j].VOLD_Service_Name = RC_Services[i].Service_Name; // prefix + service_name
708 services[j].Service_Path = RC_Services[i].Service_Path;
709 services[j].Service_Binary = RC_Services[i].Service_Binary;
710
711 if (Service_Exists(services[j].Service_Name))
712 services[j].TWRP_Service_Name = services[j].Service_Name;
713 else if (Service_Exists("sbin" + services[j].Service_Name))
714 services[j].TWRP_Service_Name = "sbin" + services[j].Service_Name;
715 else
716 services[j].TWRP_Service_Name.clear();
717
718#ifdef _USING_SHORT_SERVICE_NAMES
719 if (services[j].TWRP_Service_Name.empty()) {
720 // Try matching Service_Binary (due to 16 character service_name limit in 7.1 and below)
721 map<string,size_t>::iterator it = rc_indeces.find(services[j].Service_Binary);
722 if (it != rc_indeces.end()) {
723 services[j].TWRP_Service_Name = RC_Services[it->second].Service_Name;
724 }
725 }
726#endif
727 }
728 break;
729 }
730 }
731 }
732
733 LOGINFO("List of additional services for vold_decrypt:\n");
734 for (size_t i = 0; i < services.size(); ++i) {
735 if (services[i].exists) {
736 if (services[i].TWRP_Service_Name.empty()) {
737 LOGINFO(" %s: Enabled as %s -> %s\n",
738 services[i].Service_Name.c_str(),
739 services[i].VOLD_Service_Name.c_str(), services[i].Service_Path.c_str()
740 );
741 } else {
742 LOGINFO(" %s: Enabled as %s -> %s (temporarily replacing TWRP's %s service)\n",
743 services[i].Service_Name.c_str(),
744 services[i].VOLD_Service_Name.c_str(), services[i].Service_Path.c_str(),
745 services[i].TWRP_Service_Name.c_str()
746 );
747 }
748 }
749 else
750 LOGINFO(" %s: Disabled due to lack of matching binary\n", services[i].Service_Name.c_str());
751 }
752 return services;
753}
754#endif
755
756
757/* Misc Functions */
758void Set_Needed_Properties(void) {
nkk7171c6c502017-01-05 23:55:05 +0200759 // vold won't start without ro.storage_structure on Kitkat
760 string sdkverstr = TWFunc::System_Property_Get("ro.build.version.sdk");
761 int sdkver = 20;
762 if (!sdkverstr.empty()) {
763 sdkver = atoi(sdkverstr.c_str());
764 }
765 if (sdkver <= 19) {
766 string ro_storage_structure = TWFunc::System_Property_Get("ro.storage_structure");
767 if (!ro_storage_structure.empty())
768 property_set("ro.storage_structure", ro_storage_structure.c_str());
769 }
770}
771
nkk7171c6c502017-01-05 23:55:05 +0200772
nkk717d1222a2017-11-06 17:27:21 +0200773/* vdc Functions */
774typedef struct {
775 string Output; // Entire line excluding \n
776 int ResponseCode; // ResponseCode.h (int)
777 int Sequence; // Sequence (int)
778 int Message; // Message (string) but we're only interested in int
779} vdc_ReturnValues;
780
781int Exec_vdc_cryptfs(const string& command, const string& argument, vdc_ReturnValues* vdcResult) {
782 pid_t pid;
783 int status;
784 int pipe_fd[2];
785 vdcResult->Output.clear();
786
787 if (pipe(pipe_fd)) {
788 LOGERROR("exec_vdc_cryptfs: pipe() error!\n");
789 return -1;
790 }
791
792 const char *cmd[] = { "/system/bin/vdc", "cryptfs" };
793 const char *env[] = { "LD_LIBRARY_PATH=/system/lib64:/system/lib", NULL };
794
795#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
796 string log_name = "/tmp/strace_vdc_" + command;
nkk7171c6c502017-01-05 23:55:05 +0200797#endif
nkk7171c6c502017-01-05 23:55:05 +0200798
nkk717d1222a2017-11-06 17:27:21 +0200799 switch(pid = fork())
800 {
801 case -1:
802 LOGERROR("exec_vdc_cryptfs: fork failed: %d (%s)!\n", errno, strerror(errno));
803 return -1;
804
805 case 0: // child
806 fflush(stdout); fflush(stderr);
807 close(pipe_fd[0]);
808 dup2(pipe_fd[1], STDOUT_FILENO);
809 dup2(pipe_fd[1], STDERR_FILENO);
810 close(pipe_fd[1]);
811
812#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
813 if (has_strace) {
814 if (argument.empty())
815 execl(VD_STRACE_BIN, "strace", "-q", "-tt", "-ff", "-v", "-y", "-s", "1000", "-o", log_name.c_str(),
816 "-E", env[0], cmd[0], cmd[1], command.c_str(), NULL);
817 else
818 execl(VD_STRACE_BIN, "strace", "-q", "-tt", "-ff", "-v", "-y", "-s", "1000", "-o", log_name.c_str(),
819 "-E", env[0], cmd[0], cmd[1], command.c_str(), argument.c_str(), NULL);
820 } else
821#endif
822 if (argument.empty())
823 execle(cmd[0], cmd[0], cmd[1], command.c_str(), NULL, env);
824 else
825 execle(cmd[0], cmd[0], cmd[1], command.c_str(), argument.c_str(), NULL, env);
826 _exit(127);
827 break;
828
829 default:
830 {
831 int timeout = 30*100;
832 vdcResult->Output.clear();
833 close(pipe_fd[1]);
834
835 // Non-blocking read loop with timeout
836 int flags = fcntl(pipe_fd[0], F_GETFL, 0);
837 fcntl(pipe_fd[0], F_SETFL, flags | O_NONBLOCK);
838
839 char buffer[128];
840 ssize_t count;
841 pid_t retpid = waitpid(pid, &status, WNOHANG);
842 while (true) {
843 count = read(pipe_fd[0], buffer, sizeof(buffer));
844 if (count == -1) {
845 if (errno == EINTR)
846 continue;
847 else if (errno != EAGAIN)
848 LOGERROR("exec_vdc_cryptfs: read() error %d (%s)\n!", errno, strerror(errno));
849 } else if (count > 0) {
850 vdcResult->Output.append(buffer, count);
851 }
852
853 retpid = waitpid(pid, &status, WNOHANG);
854 if (retpid == 0 && --timeout)
855 usleep(10000);
856 else
857 break;
858 };
859 close(pipe_fd[0]);
860 if (vdcResult->Output.length() > 0 && vdcResult->Output[vdcResult->Output.length() - 1] == '\n')
861 vdcResult->Output.erase(vdcResult->Output.length() - 1);
862 vdcResult->ResponseCode = vdcResult->Sequence = vdcResult->Message = -1;
863 sscanf(vdcResult->Output.c_str(), "%d %d %d", &vdcResult->ResponseCode, &vdcResult->Sequence, &vdcResult->Message);
864
865 // Error handling
866 if (retpid == 0 && timeout == 0) {
867 LOGERROR("exec_vdc_cryptfs: took too long, killing process\n");
868 kill(pid, SIGKILL);
869 for (timeout = 5; retpid == 0 && timeout; --timeout) {
870 sleep(1);
871 retpid = waitpid(pid, &status, WNOHANG);
872 }
873 if (retpid)
874 LOGINFO("exec_vdc_cryptfs: process killed successfully\n");
875 else
876 LOGERROR("exec_vdc_cryptfs: process took too long to kill, may be a zombie process\n");
877 return VD_ERR_VOLD_OPERATION_TIMEDOUT;
878 } else if (retpid > 0) {
879 if (WIFSIGNALED(status)) {
880 LOGERROR("exec_vdc_cryptfs: process ended with signal: %d\n", WTERMSIG(status)); // Seg fault or some other non-graceful termination
881 return -1;
882 }
883 } else if (retpid < 0) { // no PID returned
884 if (errno == ECHILD)
885 LOGINFO("exec_vdc_cryptfs: no child process exist\n");
886 else {
887 LOGERROR("exec_vdc_cryptfs: Unexpected error %d (%s)\n", errno, strerror(errno));
888 return -1;
889 }
890 }
891 return 0;
892 }
893 }
nkk7171c6c502017-01-05 23:55:05 +0200894}
895
nkk717d1222a2017-11-06 17:27:21 +0200896int Run_vdc(const string& Password) {
897 int res;
nkk7171c6c502017-01-05 23:55:05 +0200898 struct timeval t1, t2;
nkk717d1222a2017-11-06 17:27:21 +0200899 vdc_ReturnValues vdcResult;
nkk7171c6c502017-01-05 23:55:05 +0200900
nkk717d1222a2017-11-06 17:27:21 +0200901 LOGINFO("About to run vdc...\n");
nkk7171c6c502017-01-05 23:55:05 +0200902
903 // Wait for vold connection
904 gettimeofday(&t1, NULL);
905 t2 = t1;
906 while ((t2.tv_sec - t1.tv_sec) < 5) {
nkk7171c6c502017-01-05 23:55:05 +0200907 // cryptfs getpwtype returns: R1=213(PasswordTypeResult) R2=? R3="password", "pattern", "pin", "default"
nkk717d1222a2017-11-06 17:27:21 +0200908 res = Exec_vdc_cryptfs("getpwtype", "", &vdcResult);
909 if (vdcResult.ResponseCode == PASSWORD_TYPE_RESULT) {
910 char str_res[4 + sizeof(int) + 1];
911 snprintf(str_res, sizeof(str_res), "ret=%d", res);
912 vdcResult.Output += str_res;
nkk7171c6c502017-01-05 23:55:05 +0200913 res = 0;
914 break;
915 }
nkk717d1222a2017-11-06 17:27:21 +0200916 LOGINFO("Retrying connection to vold (Reason: %s)\n", vdcResult.Output.c_str());
nkk7171c6c502017-01-05 23:55:05 +0200917 usleep(SLEEP_MIN_USEC); // vdc usually usleep(10000), but that causes too many unnecessary attempts
918 gettimeofday(&t2, NULL);
919 }
920
nkk717d1222a2017-11-06 17:27:21 +0200921 if (res == 0 && (t2.tv_sec - t1.tv_sec) < 5)
922 LOGINFO("Connected to vold (%s)\n", vdcResult.Output.c_str());
923 else if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
924 return VD_ERR_VOLD_OPERATION_TIMEDOUT; // should never happen for getpwtype
925 else if (res)
926 return VD_ERR_FORK_EXECL_ERROR;
927 else if (vdcResult.ResponseCode != -1)
928 return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
929 else
930 return VD_ERR_VDC_FAILED_TO_CONNECT;
nkk7171c6c502017-01-05 23:55:05 +0200931
nkk7171c6c502017-01-05 23:55:05 +0200932
933 // Input password from GUI, or default password
nkk717d1222a2017-11-06 17:27:21 +0200934 res = Exec_vdc_cryptfs("checkpw", Password, &vdcResult);
935 if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
936 return VD_ERR_VOLD_OPERATION_TIMEDOUT;
937 else if (res)
938 return VD_ERR_FORK_EXECL_ERROR;
nkk7171c6c502017-01-05 23:55:05 +0200939
nkk717d1222a2017-11-06 17:27:21 +0200940 LOGINFO("vdc cryptfs result (passwd): %s (ret=%d)\n", vdcResult.Output.c_str(), res);
941 /*
942 if (res == 0 && vdcResult.ResponseCode != COMMAND_OKAY)
943 return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
944 */
945
946 if (vdcResult.Message != 0) {
nkk7171c6c502017-01-05 23:55:05 +0200947 // try falling back to Lollipop hex passwords
948 string hexPassword = convert_key_to_hex_ascii(Password);
nkk717d1222a2017-11-06 17:27:21 +0200949 res = Exec_vdc_cryptfs("checkpw", hexPassword, &vdcResult);
950 if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
951 return VD_ERR_VOLD_OPERATION_TIMEDOUT;
952 else if (res)
953 return VD_ERR_FORK_EXECL_ERROR;
954
955 LOGINFO("vdc cryptfs result (hex_pw): %s (ret=%d)\n", vdcResult.Output.c_str(), res);
956 /*
957 if (res == 0 && vdcResult.ResponseCode != COMMAND_OKAY)
958 return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
959 */
nkk7171c6c502017-01-05 23:55:05 +0200960 }
961
962 // vdc's return value is dependant upon source origin, it will either
nkk717d1222a2017-11-06 17:27:21 +0200963 // return 0 or ResponseCode, so disregard and focus on decryption instead
964 if (vdcResult.Message == 0) {
nkk7171c6c502017-01-05 23:55:05 +0200965 // Decryption successful wait for crypto blk dev
nkk717d1222a2017-11-06 17:27:21 +0200966 Wait_For_Property("ro.crypto.fs_crypto_blkdev");
967 res = VD_SUCCESS;
968 } else if (vdcResult.ResponseCode != COMMAND_OKAY) {
969 res = VD_ERR_VOLD_UNEXPECTED_RESPONSE;
nkk7171c6c502017-01-05 23:55:05 +0200970 } else {
nkk717d1222a2017-11-06 17:27:21 +0200971 res = VD_ERR_DECRYPTION_FAILED;
nkk7171c6c502017-01-05 23:55:05 +0200972 }
973
974 return res;
975}
976
nkk717d1222a2017-11-06 17:27:21 +0200977int Vold_Decrypt_Core(const string& Password) {
nkk7171c6c502017-01-05 23:55:05 +0200978 int res;
nkk7171c6c502017-01-05 23:55:05 +0200979 bool is_vendor_symlinked = false;
980 bool is_firmware_symlinked = false;
nkk717d1222a2017-11-06 17:27:21 +0200981 bool is_fstab_symlinked = false;
nkk7171c6c502017-01-05 23:55:05 +0200982 bool is_vold_running = false;
983
984 if (Password.empty()) {
nkk717d1222a2017-11-06 17:27:21 +0200985 LOGINFO("vold_decrypt: password is empty!\n");
986 return VD_ERR_PASSWORD_EMPTY;
nkk7171c6c502017-01-05 23:55:05 +0200987 }
988
989 // Mount system and check for vold and vdc
990 if (!PartitionManager.Mount_By_Path("/system", true)) {
nkk717d1222a2017-11-06 17:27:21 +0200991 return VD_ERR_UNABLE_TO_MOUNT_SYSTEM;
nkk7171c6c502017-01-05 23:55:05 +0200992 } else if (!TWFunc::Path_Exists("/system/bin/vold")) {
nkk717d1222a2017-11-06 17:27:21 +0200993 LOGINFO("ERROR: /system/bin/vold not found, aborting.\n");
994 return VD_ERR_MISSING_VOLD;
nkk7171c6c502017-01-05 23:55:05 +0200995 } else if (!TWFunc::Path_Exists("/system/bin/vdc")) {
nkk717d1222a2017-11-06 17:27:21 +0200996 LOGINFO("ERROR: /system/bin/vdc not found, aborting.\n");
997 return VD_ERR_MISSING_VDC;
nkk7171c6c502017-01-05 23:55:05 +0200998 }
999
1000 fp_kmsg = fopen("/dev/kmsg", "a");
1001
nkk717d1222a2017-11-06 17:27:21 +02001002 LOGINFO("TW_CRYPTO_USE_SYSTEM_VOLD := true\n");
nkk7171c6c502017-01-05 23:55:05 +02001003
nkk717d1222a2017-11-06 17:27:21 +02001004 // just cache the result to avoid unneeded duplicates in recovery.log
1005 LOGINFO("Checking existence of vendor and firmware partitions...\n");
1006 is_Vendor_Mounted();
1007 is_Firmware_Mounted();
1008
1009 LOGINFO("Attempting to use system's vold for decryption...\n");
nkk7171c6c502017-01-05 23:55:05 +02001010
1011#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
nkk717d1222a2017-11-06 17:27:21 +02001012 Strace_init_Start();
nkk7171c6c502017-01-05 23:55:05 +02001013#endif
1014
1015#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1016 vector<AdditionalService> Services = Get_List_Of_Additional_Services();
1017
1018 // Check if TWRP is running any of the services
1019 for (size_t i = 0; i < Services.size(); ++i) {
nkk717d1222a2017-11-06 17:27:21 +02001020 if (!Services[i].TWRP_Service_Name.empty() && !Is_Service_Stopped(Services[i].TWRP_Service_Name)) {
nkk7171c6c502017-01-05 23:55:05 +02001021 Services[i].resume = true;
nkk717d1222a2017-11-06 17:27:21 +02001022 Stop_Service(Services[i].TWRP_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001023 } else
1024 Services[i].resume = false;
nkk7171c6c502017-01-05 23:55:05 +02001025 }
1026#endif
1027
nkk717d1222a2017-11-06 17:27:21 +02001028 LOGINFO("Setting up folders and permissions...\n");
1029 is_fstab_symlinked = Symlink_Recovery_Fstab();
nkk7171c6c502017-01-05 23:55:05 +02001030 is_vendor_symlinked = Symlink_Vendor_Folder();
1031 is_firmware_symlinked = Symlink_Firmware_Folder();
1032 Symlink_Firmware_Files(is_vendor_symlinked, is_firmware_symlinked);
1033
nkk717d1222a2017-11-06 17:27:21 +02001034 Set_Needed_Properties();
nkk7171c6c502017-01-05 23:55:05 +02001035
1036 // Start services needed for vold decrypt
nkk717d1222a2017-11-06 17:27:21 +02001037 LOGINFO("Starting services...\n");
nkk7171c6c502017-01-05 23:55:05 +02001038#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1039 for (size_t i = 0; i < Services.size(); ++i) {
nkk717d1222a2017-11-06 17:27:21 +02001040 if (Services[i].exists)
1041 Services[i].is_running = Start_Service(Services[i].VOLD_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001042 }
1043#endif
1044 is_vold_running = Start_Service("sys_vold");
1045
1046 if (is_vold_running) {
nkk7171c6c502017-01-05 23:55:05 +02001047#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1048 for (size_t i = 0; i < Services.size(); ++i) {
nkk717d1222a2017-11-06 17:27:21 +02001049 if (Services[i].exists && !Is_Service_Running(Services[i].VOLD_Service_Name) && Services[i].resume) {
nkk7171c6c502017-01-05 23:55:05 +02001050 // if system_service has died restart the twrp_service
nkk717d1222a2017-11-06 17:27:21 +02001051 LOGINFO("%s is not running, resuming %s!\n", Services[i].VOLD_Service_Name.c_str(), Services[i].TWRP_Service_Name.c_str());
1052 Start_Service(Services[i].TWRP_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001053 }
1054 }
1055#endif
nkk717d1222a2017-11-06 17:27:21 +02001056 res = Run_vdc(Password);
nkk7171c6c502017-01-05 23:55:05 +02001057
1058 if (res != 0) {
nkk717d1222a2017-11-06 17:27:21 +02001059 LOGINFO("Decryption failed\n");
nkk7171c6c502017-01-05 23:55:05 +02001060 }
1061 } else {
nkk717d1222a2017-11-06 17:27:21 +02001062 LOGINFO("Failed to start vold\n");
1063 res = VD_ERR_VOLD_FAILED_TO_START;
nkk7171c6c502017-01-05 23:55:05 +02001064 }
1065
1066 // Stop services needed for vold decrypt so /system can be unmounted
nkk717d1222a2017-11-06 17:27:21 +02001067 LOGINFO("Stopping services...\n");
nkk7171c6c502017-01-05 23:55:05 +02001068 Stop_Service("sys_vold");
1069#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1070 for (size_t i = 0; i < Services.size(); ++i) {
nkk717d1222a2017-11-06 17:27:21 +02001071 if (!Is_Service_Running(Services[i].VOLD_Service_Name) && Services[i].resume)
1072 Stop_Service(Services[i].TWRP_Service_Name);
1073 else if (Services[i].exists)
1074 Stop_Service(Services[i].VOLD_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001075 }
1076#endif
1077
1078 if (is_firmware_symlinked)
1079 Restore_Firmware_Folder();
1080 if (is_vendor_symlinked)
1081 Restore_Vendor_Folder();
nkk717d1222a2017-11-06 17:27:21 +02001082 if (is_fstab_symlinked)
1083 Restore_Recovery_Fstab();
nkk7171c6c502017-01-05 23:55:05 +02001084
1085 if (!PartitionManager.UnMount_By_Path("/system", true)) {
1086 // PartitionManager failed to unmount /system, this should not happen,
1087 // but in case it does, do a lazy unmount
nkk717d1222a2017-11-06 17:27:21 +02001088 LOGINFO("WARNING: system could not be unmounted normally!\n");
1089 umount2("/system", MNT_DETACH);
nkk7171c6c502017-01-05 23:55:05 +02001090 }
1091
nkk717d1222a2017-11-06 17:27:21 +02001092 LOGINFO("Finished.\n");
nkk7171c6c502017-01-05 23:55:05 +02001093
1094#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1095 // Restart previously running services
1096 for (size_t i = 0; i < Services.size(); ++i) {
1097 if (Services[i].resume)
nkk717d1222a2017-11-06 17:27:21 +02001098 Start_Service(Services[i].TWRP_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001099 }
1100#endif
1101
1102#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
nkk717d1222a2017-11-06 17:27:21 +02001103 Strace_init_Stop();
nkk7171c6c502017-01-05 23:55:05 +02001104#endif
1105
1106 // Finish up and exit
1107 if (fp_kmsg) {
1108 fflush(fp_kmsg);
1109 fclose(fp_kmsg);
1110 }
1111
nkk7171c6c502017-01-05 23:55:05 +02001112 return res;
1113}
nkk717d1222a2017-11-06 17:27:21 +02001114
1115} // namespace
1116
1117/*
1118 * Common vold Response Codes / Errors:
1119 * 406 (OpFailedStorageNotFound) -> Problem reading or parsing fstab
1120 *
1121 */
1122
1123/* Main function separated from core in case we want to return error info */
1124int vold_decrypt(const string& Password) {
1125 return Vold_Decrypt_Core(Password);
1126}