blob: ded4e7b6761a3822c8f1c5a28697d4a587af628b [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");
nkk7137625a42017-12-08 16:37:59 +0200309 vsymlink("/system/vendor/lib64", "/vendor/lib64", true);
310 vsymlink("/system/vendor/lib", "/vendor/lib", true);
311 vsymlink("/system/vendor/bin", "/vendor/bin", true);
nkk717d1222a2017-11-06 17:27:21 +0200312 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;
nkk7137625a42017-12-08 16:37:59 +0200439 bool bin_exists;
440 bool svc_exists;
nkk717d1222a2017-11-06 17:27:21 +0200441} AdditionalService;
442
443typedef struct {
444 string Service_Name;
445 string Service_Path;
446 string Service_Binary;
447} RC_Service;
448
449// expand_props() courtesy of platform_system_core_init_util.cpp
450bool expand_props(const std::string& src, std::string* dst) {
451 const char* src_ptr = src.c_str();
452
453 if (!dst) {
454 return false;
455 }
456
457 /* - variables can either be $x.y or ${x.y}, in case they are only part
458 * of the string.
459 * - will accept $$ as a literal $.
460 * - no nested property expansion, i.e. ${foo.${bar}} is not supported,
461 * bad things will happen
462 * - ${x.y:-default} will return default value if property empty.
463 */
464 while (*src_ptr) {
465 const char* c;
466
467 c = strchr(src_ptr, '$');
468 if (!c) {
469 dst->append(src_ptr);
470 return true;
471 }
472
473 dst->append(src_ptr, c);
474 c++;
475
476 if (*c == '$') {
477 dst->push_back(*(c++));
478 src_ptr = c;
479 continue;
480 } else if (*c == '\0') {
481 return true;
482 }
483
484 std::string prop_name;
485 std::string def_val;
486 if (*c == '{') {
487 c++;
488 const char* end = strchr(c, '}');
489 if (!end) {
490 // failed to find closing brace, abort.
491 return false;
492 }
493 prop_name = std::string(c, end);
494 c = end + 1;
495 size_t def = prop_name.find(":-");
496 if (def < prop_name.size()) {
497 def_val = prop_name.substr(def + 2);
498 prop_name = prop_name.substr(0, def);
499 }
500 } else {
501 prop_name = c;
502 c += prop_name.size();
503 }
504
505 if (prop_name.empty()) {
506 return false;
507 }
508
509 char prop_value[PROPERTY_VALUE_MAX];
510 property_get(prop_name.c_str(), prop_value, "");
511 std::string prop_val = prop_value;
512 if (prop_val.empty()) {
513 if (def_val.empty()) {
514 return false;
515 }
516 prop_val = def_val;
517 }
518
519 dst->append(prop_val);
520 src_ptr = c;
521 }
522
523 return true;
524}
525
526string GetArgument(const string& line, size_t argument_number, bool expand_properties) {
527 size_t beg;
528 size_t end;
529 string argument;
530
531 beg = line.find_first_not_of(" \t\r");
532 if (beg == string::npos)
533 return "";
534
535 for (size_t i = 0; i < argument_number; ++i) {
536 end = line.find_first_of(" \t\r", beg);
537 if (end == string::npos)
538 return "";
539
540 beg = line.find_first_not_of(" \t\r", end);
541 if (beg == string::npos)
542 return "";
543 }
544
545 end = line.find_first_of(" \t\r", beg);
546 if (end == string::npos)
547 argument = line.substr(beg);
548 else
549 argument = line.substr(beg, end - beg); // exclude trailing whitespace
550
551 if (expand_properties) {
552 string expanded_property_argument;
553 if (expand_props(argument, &expanded_property_argument))
554 return expanded_property_argument;
555 else
556 return "";
557 } else {
558 return argument;
559 }
560}
561
562// Very simplified .rc parser to get services
563void Parse_RC_File(const string& rc_file, vector<RC_Service>& RC_Services) {
564 ifstream file;
565
566 file.open(rc_file.c_str(), ios::in);
567 if (!file.is_open())
568 return;
569
570 size_t beg; // left trim
571 size_t end; // right trim
572 bool continuation = false; // backslash continuation
573 string line; // line
574 string real_line; // trimmed line with backslash continuation removal
575 vector<string> imports; // file names of imports (we don't want to recursively do while the file is open)
576
577 while (getline(file, line)) {
578 beg = line.find_first_not_of(" \t\r");
579 end = line.find_last_not_of(" \t\r");
580 if (end == string::npos)
581 end = line.length();
582
583 if (beg == string::npos) {
584 if (continuation)
585 continuation = false;
586 else
587 continue;
588 } else if (line[end] == '\\') {
589 continuation = true;
590 real_line += line.substr(beg, end - beg); // excluding backslash
591 continue;
592 } else if (continuation) {
593 continuation = false;
594 real_line += line.substr(beg, end - beg + 1);
595 } else {
596 real_line = line.substr(beg, end - beg + 1);
597 }
598
599 if (GetArgument(real_line, 0, false) == "import") {
600 // handle: import <file>
601 string file_name = GetArgument(real_line, 1, true);
602 if (file_name.empty()) {
603 // INVALID IMPORT
604 } else
605 imports.push_back(file_name);
606 } else if (GetArgument(real_line, 0, false) == "service") {
607 // handle: service <name> <path>
608 RC_Service svc;
609
610 svc.Service_Name = GetArgument(real_line, 1, false);
611 svc.Service_Path = GetArgument(real_line, 2, true);
612
613 if (svc.Service_Name.empty() || svc.Service_Path.empty()) {
614 // INVALID SERVICE ENTRY
615 } else {
616 beg = svc.Service_Path.find_last_of("/");
617 if (beg == string::npos)
618 svc.Service_Binary = svc.Service_Path;
619 else
620 svc.Service_Binary = svc.Service_Path.substr(beg + 1);
621
622/*
623#ifdef _USING_SHORT_SERVICE_NAMES
624 if (svc.Service_Name.length() > 16) {
625 LOGERROR("WARNING: Ignoring service %s (-> %s)\n"
626 " defined in %s is greater than 16 characters and will\n"
627 " not be able to be run by init on android-7.1 or below!\n",
628 svc.Service_Name.c_str(), svc.Service_Path.c_str(), rc_file.c_str()
629 );
630 }
631 else
632#endif
633*/
634 RC_Services.push_back(svc);
635 }
636 }
637 real_line.clear();
638 }
639 file.close();
640
641 for (size_t i = 0; i < imports.size(); ++i) {
642 Parse_RC_File(imports[i], RC_Services);
643 }
644}
645
646vector<AdditionalService> Get_List_Of_Additional_Services(void) {
647 vector<AdditionalService> services;
648
649 // Additional Services needed by vold_decrypt (eg qseecomd, hwservicemanager, etc)
650 vector<string> service_names = TWFunc::Split_String(TW_CRYPTO_SYSTEM_VOLD_SERVICES, " ");
651 for (size_t i = 0; i < service_names.size(); ++i) {
652 AdditionalService svc;
653 svc.Service_Name = service_names[i];
nkk7137625a42017-12-08 16:37:59 +0200654 svc.bin_exists = false;
655 svc.svc_exists = false;
nkk717d1222a2017-11-06 17:27:21 +0200656 services.push_back(svc);
657
658#ifdef _USING_SHORT_SERVICE_NAMES
659 // Fallback code for >16 character service names which
660 // allows for multiple definitions in custom .rc files
661 if (service_names[i].length() > 12) {
662 svc.Service_Name = service_names[i].substr(0, 12); // 16-4(prefix)=12
nkk7137625a42017-12-08 16:37:59 +0200663 svc.bin_exists = false;
664 svc.svc_exists = false;
nkk717d1222a2017-11-06 17:27:21 +0200665 services.push_back(svc);
666 }
667#endif
668 }
669
670 // Read list of all services defined in all .rc files
671 vector<RC_Service> RC_Services;
672 Parse_RC_File("/init.rc", RC_Services);
673
674
675 // Cross reference Additional Services against the .rc Services and establish
676 // availability of the binaries, otherwise disable it to avoid unnecessary
677 // delays and log spam.
678 // Also check for duplicate entries between TWRP and vold_decrypt so we can
679 // stop and restart any conflicting services.
680 for (size_t i = 0; i < RC_Services.size(); ++i) {
681 string prefix = RC_Services[i].Service_Name.substr(0, 4);
682
683#ifdef _USING_SHORT_SERVICE_NAMES
684 map<string,size_t> rc_indeces;
685#endif
686
687 if (prefix != "sys_" && prefix != "ven_") {
688#ifdef _USING_SHORT_SERVICE_NAMES
689 if (RC_Services[i].Service_Name.length() > 12) {
690 // save this entry for potential binary name match
691 rc_indeces.insert(pair<string,size_t>(RC_Services[i].Service_Binary, i));
692 }
693#endif
694 continue;
695 }
696
697 for (size_t j = 0; j < services.size(); ++j) {
698 string path = RC_Services[i].Service_Path;
699 if (prefix == "ven_" && will_VendorBin_Be_Symlinked()) {
700 path = "/system" + path; // vendor is going to get symlinked to /system/vendor
701 }
702
703 if (RC_Services[i].Service_Name == prefix + services[j].Service_Name) {
nkk7137625a42017-12-08 16:37:59 +0200704 services[j].svc_exists = true;
705
nkk717d1222a2017-11-06 17:27:21 +0200706 if (!services[j].VOLD_Service_Name.empty() && TWFunc::Path_Exists(path)) {
707 // Duplicate match, log but use previous definition
708 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());
709 }
710 else if (TWFunc::Path_Exists(path)) {
nkk7137625a42017-12-08 16:37:59 +0200711 services[j].bin_exists = true;
nkk717d1222a2017-11-06 17:27:21 +0200712 services[j].VOLD_Service_Name = RC_Services[i].Service_Name; // prefix + service_name
713 services[j].Service_Path = RC_Services[i].Service_Path;
714 services[j].Service_Binary = RC_Services[i].Service_Binary;
715
716 if (Service_Exists(services[j].Service_Name))
717 services[j].TWRP_Service_Name = services[j].Service_Name;
718 else if (Service_Exists("sbin" + services[j].Service_Name))
719 services[j].TWRP_Service_Name = "sbin" + services[j].Service_Name;
720 else
721 services[j].TWRP_Service_Name.clear();
722
723#ifdef _USING_SHORT_SERVICE_NAMES
724 if (services[j].TWRP_Service_Name.empty()) {
725 // Try matching Service_Binary (due to 16 character service_name limit in 7.1 and below)
726 map<string,size_t>::iterator it = rc_indeces.find(services[j].Service_Binary);
727 if (it != rc_indeces.end()) {
728 services[j].TWRP_Service_Name = RC_Services[it->second].Service_Name;
729 }
730 }
731#endif
732 }
733 break;
734 }
735 }
736 }
737
738 LOGINFO("List of additional services for vold_decrypt:\n");
739 for (size_t i = 0; i < services.size(); ++i) {
nkk7137625a42017-12-08 16:37:59 +0200740 if (!services[i].svc_exists) {
741 LOGINFO(" %s: Disabled due to lack of .rc service entry\n", services[i].Service_Name.c_str());
742 } else if (services[i].bin_exists) {
nkk717d1222a2017-11-06 17:27:21 +0200743 if (services[i].TWRP_Service_Name.empty()) {
744 LOGINFO(" %s: Enabled as %s -> %s\n",
745 services[i].Service_Name.c_str(),
746 services[i].VOLD_Service_Name.c_str(), services[i].Service_Path.c_str()
747 );
748 } else {
749 LOGINFO(" %s: Enabled as %s -> %s (temporarily replacing TWRP's %s service)\n",
750 services[i].Service_Name.c_str(),
751 services[i].VOLD_Service_Name.c_str(), services[i].Service_Path.c_str(),
752 services[i].TWRP_Service_Name.c_str()
753 );
754 }
755 }
nkk7137625a42017-12-08 16:37:59 +0200756 else {
nkk717d1222a2017-11-06 17:27:21 +0200757 LOGINFO(" %s: Disabled due to lack of matching binary\n", services[i].Service_Name.c_str());
nkk7137625a42017-12-08 16:37:59 +0200758 }
nkk717d1222a2017-11-06 17:27:21 +0200759 }
760 return services;
761}
762#endif
763
764
765/* Misc Functions */
766void Set_Needed_Properties(void) {
nkk7171c6c502017-01-05 23:55:05 +0200767 // vold won't start without ro.storage_structure on Kitkat
768 string sdkverstr = TWFunc::System_Property_Get("ro.build.version.sdk");
769 int sdkver = 20;
770 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 }
778}
779
nkk7171c6c502017-01-05 23:55:05 +0200780
nkk717d1222a2017-11-06 17:27:21 +0200781/* vdc Functions */
782typedef struct {
783 string Output; // Entire line excluding \n
784 int ResponseCode; // ResponseCode.h (int)
785 int Sequence; // Sequence (int)
786 int Message; // Message (string) but we're only interested in int
787} vdc_ReturnValues;
788
789int Exec_vdc_cryptfs(const string& command, const string& argument, vdc_ReturnValues* vdcResult) {
790 pid_t pid;
791 int status;
nkk7137625a42017-12-08 16:37:59 +0200792 int pipe_fd[2][2];
nkk717d1222a2017-11-06 17:27:21 +0200793
nkk7137625a42017-12-08 16:37:59 +0200794 vdcResult->Output.clear();
795 vdcResult->ResponseCode = vdcResult->Sequence = vdcResult->Message = -1;
796
797 for (int i = 0; i < 2; ++i) {
798 if (pipe(pipe_fd[i])) {
799 LOGERROR("exec_vdc_cryptfs: pipe() error!\n");
800 return -1;
801 }
nkk717d1222a2017-11-06 17:27:21 +0200802 }
803
804 const char *cmd[] = { "/system/bin/vdc", "cryptfs" };
805 const char *env[] = { "LD_LIBRARY_PATH=/system/lib64:/system/lib", NULL };
806
807#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
808 string log_name = "/tmp/strace_vdc_" + command;
nkk7171c6c502017-01-05 23:55:05 +0200809#endif
nkk7171c6c502017-01-05 23:55:05 +0200810
nkk717d1222a2017-11-06 17:27:21 +0200811 switch(pid = fork())
812 {
813 case -1:
814 LOGERROR("exec_vdc_cryptfs: fork failed: %d (%s)!\n", errno, strerror(errno));
815 return -1;
816
817 case 0: // child
818 fflush(stdout); fflush(stderr);
nkk7137625a42017-12-08 16:37:59 +0200819 for (int i = 0; i < 2; ++i) {
820 close(pipe_fd[i][0]);
821 dup2(pipe_fd[i][1], ((i == 0) ? STDOUT_FILENO : STDERR_FILENO));
822 close(pipe_fd[i][1]);
823 }
nkk717d1222a2017-11-06 17:27:21 +0200824
825#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
826 if (has_strace) {
827 if (argument.empty())
828 execl(VD_STRACE_BIN, "strace", "-q", "-tt", "-ff", "-v", "-y", "-s", "1000", "-o", log_name.c_str(),
829 "-E", env[0], cmd[0], cmd[1], command.c_str(), NULL);
830 else
831 execl(VD_STRACE_BIN, "strace", "-q", "-tt", "-ff", "-v", "-y", "-s", "1000", "-o", log_name.c_str(),
832 "-E", env[0], cmd[0], cmd[1], command.c_str(), argument.c_str(), NULL);
833 } else
834#endif
835 if (argument.empty())
836 execle(cmd[0], cmd[0], cmd[1], command.c_str(), NULL, env);
837 else
838 execle(cmd[0], cmd[0], cmd[1], command.c_str(), argument.c_str(), NULL, env);
839 _exit(127);
840 break;
841
842 default:
843 {
844 int timeout = 30*100;
nkk717d1222a2017-11-06 17:27:21 +0200845
nkk7137625a42017-12-08 16:37:59 +0200846 for (int i = 0; i < 2; ++i) {
847 close(pipe_fd[i][1]);
848
849 // Non-blocking read loop with timeout
850 int flags = fcntl(pipe_fd[i][0], F_GETFL, 0);
851 fcntl(pipe_fd[i][0], F_SETFL, flags | O_NONBLOCK);
852 }
nkk717d1222a2017-11-06 17:27:21 +0200853
854 char buffer[128];
855 ssize_t count;
nkk7137625a42017-12-08 16:37:59 +0200856 string strout[2];
nkk717d1222a2017-11-06 17:27:21 +0200857 pid_t retpid = waitpid(pid, &status, WNOHANG);
858 while (true) {
nkk7137625a42017-12-08 16:37:59 +0200859 for (int i = 0; i < 2; ++i) {
860 count = read(pipe_fd[i][0], buffer, sizeof(buffer));
861 if (count == -1) {
862 if (errno == EINTR)
863 continue;
864 else if (errno != EAGAIN)
865 LOGERROR("exec_vdc_cryptfs: read() error %d (%s)\n!", errno, strerror(errno));
866 } else if (count > 0) {
867 strout[i].append(buffer, count);
868 }
nkk717d1222a2017-11-06 17:27:21 +0200869 }
870
871 retpid = waitpid(pid, &status, WNOHANG);
872 if (retpid == 0 && --timeout)
873 usleep(10000);
874 else
875 break;
876 };
nkk7137625a42017-12-08 16:37:59 +0200877
878 for (int i = 0; i < 2; ++i) {
879 close(pipe_fd[i][0]);
880 }
881
882 if (!strout[0].empty()) {
883 sscanf(strout[0].c_str(), "%d %d %d", &vdcResult->ResponseCode, &vdcResult->Sequence, &vdcResult->Message);
884 vdcResult->Output = "I:" + strout[0];
885 }
886 if (!strout[1].empty()) {
887 vdcResult->Output += "E:" + strout[1];
888 }
889 std::replace(vdcResult->Output.begin(), vdcResult->Output.end(), '\n', '|');
890
891 if (!vdcResult->Output.empty() && vdcResult->Output[vdcResult->Output.length() - 1] != '|')
892 vdcResult->Output += "|";
893 vdcResult->Output += "RC=" + TWFunc::to_string(WEXITSTATUS(status));
nkk717d1222a2017-11-06 17:27:21 +0200894
895 // Error handling
896 if (retpid == 0 && timeout == 0) {
897 LOGERROR("exec_vdc_cryptfs: took too long, killing process\n");
898 kill(pid, SIGKILL);
899 for (timeout = 5; retpid == 0 && timeout; --timeout) {
900 sleep(1);
901 retpid = waitpid(pid, &status, WNOHANG);
902 }
903 if (retpid)
904 LOGINFO("exec_vdc_cryptfs: process killed successfully\n");
905 else
906 LOGERROR("exec_vdc_cryptfs: process took too long to kill, may be a zombie process\n");
907 return VD_ERR_VOLD_OPERATION_TIMEDOUT;
908 } else if (retpid > 0) {
909 if (WIFSIGNALED(status)) {
910 LOGERROR("exec_vdc_cryptfs: process ended with signal: %d\n", WTERMSIG(status)); // Seg fault or some other non-graceful termination
911 return -1;
912 }
913 } else if (retpid < 0) { // no PID returned
914 if (errno == ECHILD)
915 LOGINFO("exec_vdc_cryptfs: no child process exist\n");
916 else {
917 LOGERROR("exec_vdc_cryptfs: Unexpected error %d (%s)\n", errno, strerror(errno));
918 return -1;
919 }
920 }
921 return 0;
922 }
923 }
nkk7171c6c502017-01-05 23:55:05 +0200924}
925
nkk717d1222a2017-11-06 17:27:21 +0200926int Run_vdc(const string& Password) {
927 int res;
nkk7171c6c502017-01-05 23:55:05 +0200928 struct timeval t1, t2;
nkk717d1222a2017-11-06 17:27:21 +0200929 vdc_ReturnValues vdcResult;
nkk7171c6c502017-01-05 23:55:05 +0200930
nkk717d1222a2017-11-06 17:27:21 +0200931 LOGINFO("About to run vdc...\n");
nkk7171c6c502017-01-05 23:55:05 +0200932
933 // Wait for vold connection
934 gettimeofday(&t1, NULL);
935 t2 = t1;
936 while ((t2.tv_sec - t1.tv_sec) < 5) {
nkk7171c6c502017-01-05 23:55:05 +0200937 // cryptfs getpwtype returns: R1=213(PasswordTypeResult) R2=? R3="password", "pattern", "pin", "default"
nkk717d1222a2017-11-06 17:27:21 +0200938 res = Exec_vdc_cryptfs("getpwtype", "", &vdcResult);
939 if (vdcResult.ResponseCode == PASSWORD_TYPE_RESULT) {
nkk7171c6c502017-01-05 23:55:05 +0200940 res = 0;
941 break;
942 }
nkk717d1222a2017-11-06 17:27:21 +0200943 LOGINFO("Retrying connection to vold (Reason: %s)\n", vdcResult.Output.c_str());
nkk7171c6c502017-01-05 23:55:05 +0200944 usleep(SLEEP_MIN_USEC); // vdc usually usleep(10000), but that causes too many unnecessary attempts
945 gettimeofday(&t2, NULL);
946 }
947
nkk717d1222a2017-11-06 17:27:21 +0200948 if (res == 0 && (t2.tv_sec - t1.tv_sec) < 5)
nkk7137625a42017-12-08 16:37:59 +0200949 LOGINFO("Connected to vold: %s\n", vdcResult.Output.c_str());
nkk717d1222a2017-11-06 17:27:21 +0200950 else if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
951 return VD_ERR_VOLD_OPERATION_TIMEDOUT; // should never happen for getpwtype
952 else if (res)
953 return VD_ERR_FORK_EXECL_ERROR;
954 else if (vdcResult.ResponseCode != -1)
955 return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
956 else
957 return VD_ERR_VDC_FAILED_TO_CONNECT;
nkk7171c6c502017-01-05 23:55:05 +0200958
nkk7171c6c502017-01-05 23:55:05 +0200959
960 // Input password from GUI, or default password
nkk717d1222a2017-11-06 17:27:21 +0200961 res = Exec_vdc_cryptfs("checkpw", Password, &vdcResult);
962 if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
963 return VD_ERR_VOLD_OPERATION_TIMEDOUT;
964 else if (res)
965 return VD_ERR_FORK_EXECL_ERROR;
nkk7171c6c502017-01-05 23:55:05 +0200966
nkk7137625a42017-12-08 16:37:59 +0200967 LOGINFO("vdc cryptfs result (passwd): %s\n", vdcResult.Output.c_str());
nkk717d1222a2017-11-06 17:27:21 +0200968 /*
969 if (res == 0 && vdcResult.ResponseCode != COMMAND_OKAY)
970 return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
971 */
972
973 if (vdcResult.Message != 0) {
nkk7171c6c502017-01-05 23:55:05 +0200974 // try falling back to Lollipop hex passwords
975 string hexPassword = convert_key_to_hex_ascii(Password);
nkk717d1222a2017-11-06 17:27:21 +0200976 res = Exec_vdc_cryptfs("checkpw", hexPassword, &vdcResult);
977 if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
978 return VD_ERR_VOLD_OPERATION_TIMEDOUT;
979 else if (res)
980 return VD_ERR_FORK_EXECL_ERROR;
981
nkk7137625a42017-12-08 16:37:59 +0200982 LOGINFO("vdc cryptfs result (hex_pw): %s\n", vdcResult.Output.c_str());
nkk717d1222a2017-11-06 17:27:21 +0200983 /*
984 if (res == 0 && vdcResult.ResponseCode != COMMAND_OKAY)
985 return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
986 */
nkk7171c6c502017-01-05 23:55:05 +0200987 }
988
989 // vdc's return value is dependant upon source origin, it will either
nkk717d1222a2017-11-06 17:27:21 +0200990 // return 0 or ResponseCode, so disregard and focus on decryption instead
991 if (vdcResult.Message == 0) {
nkk7171c6c502017-01-05 23:55:05 +0200992 // Decryption successful wait for crypto blk dev
nkk717d1222a2017-11-06 17:27:21 +0200993 Wait_For_Property("ro.crypto.fs_crypto_blkdev");
994 res = VD_SUCCESS;
995 } else if (vdcResult.ResponseCode != COMMAND_OKAY) {
996 res = VD_ERR_VOLD_UNEXPECTED_RESPONSE;
nkk7171c6c502017-01-05 23:55:05 +0200997 } else {
nkk717d1222a2017-11-06 17:27:21 +0200998 res = VD_ERR_DECRYPTION_FAILED;
nkk7171c6c502017-01-05 23:55:05 +0200999 }
1000
1001 return res;
1002}
1003
nkk717d1222a2017-11-06 17:27:21 +02001004int Vold_Decrypt_Core(const string& Password) {
nkk7171c6c502017-01-05 23:55:05 +02001005 int res;
nkk7171c6c502017-01-05 23:55:05 +02001006 bool is_vendor_symlinked = false;
1007 bool is_firmware_symlinked = false;
nkk717d1222a2017-11-06 17:27:21 +02001008 bool is_fstab_symlinked = false;
nkk7171c6c502017-01-05 23:55:05 +02001009 bool is_vold_running = false;
1010
1011 if (Password.empty()) {
nkk717d1222a2017-11-06 17:27:21 +02001012 LOGINFO("vold_decrypt: password is empty!\n");
1013 return VD_ERR_PASSWORD_EMPTY;
nkk7171c6c502017-01-05 23:55:05 +02001014 }
1015
1016 // Mount system and check for vold and vdc
1017 if (!PartitionManager.Mount_By_Path("/system", true)) {
nkk717d1222a2017-11-06 17:27:21 +02001018 return VD_ERR_UNABLE_TO_MOUNT_SYSTEM;
nkk7171c6c502017-01-05 23:55:05 +02001019 } else if (!TWFunc::Path_Exists("/system/bin/vold")) {
nkk717d1222a2017-11-06 17:27:21 +02001020 LOGINFO("ERROR: /system/bin/vold not found, aborting.\n");
1021 return VD_ERR_MISSING_VOLD;
nkk7171c6c502017-01-05 23:55:05 +02001022 } else if (!TWFunc::Path_Exists("/system/bin/vdc")) {
nkk717d1222a2017-11-06 17:27:21 +02001023 LOGINFO("ERROR: /system/bin/vdc not found, aborting.\n");
1024 return VD_ERR_MISSING_VDC;
nkk7171c6c502017-01-05 23:55:05 +02001025 }
1026
1027 fp_kmsg = fopen("/dev/kmsg", "a");
1028
nkk717d1222a2017-11-06 17:27:21 +02001029 LOGINFO("TW_CRYPTO_USE_SYSTEM_VOLD := true\n");
nkk7171c6c502017-01-05 23:55:05 +02001030
nkk717d1222a2017-11-06 17:27:21 +02001031 // just cache the result to avoid unneeded duplicates in recovery.log
1032 LOGINFO("Checking existence of vendor and firmware partitions...\n");
1033 is_Vendor_Mounted();
1034 is_Firmware_Mounted();
1035
1036 LOGINFO("Attempting to use system's vold for decryption...\n");
nkk7171c6c502017-01-05 23:55:05 +02001037
1038#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
nkk717d1222a2017-11-06 17:27:21 +02001039 Strace_init_Start();
nkk7171c6c502017-01-05 23:55:05 +02001040#endif
1041
1042#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1043 vector<AdditionalService> Services = Get_List_Of_Additional_Services();
1044
1045 // Check if TWRP is running any of the services
1046 for (size_t i = 0; i < Services.size(); ++i) {
nkk717d1222a2017-11-06 17:27:21 +02001047 if (!Services[i].TWRP_Service_Name.empty() && !Is_Service_Stopped(Services[i].TWRP_Service_Name)) {
nkk7171c6c502017-01-05 23:55:05 +02001048 Services[i].resume = true;
nkk717d1222a2017-11-06 17:27:21 +02001049 Stop_Service(Services[i].TWRP_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001050 } else
1051 Services[i].resume = false;
nkk7171c6c502017-01-05 23:55:05 +02001052 }
1053#endif
1054
nkk717d1222a2017-11-06 17:27:21 +02001055 LOGINFO("Setting up folders and permissions...\n");
1056 is_fstab_symlinked = Symlink_Recovery_Fstab();
nkk7171c6c502017-01-05 23:55:05 +02001057 is_vendor_symlinked = Symlink_Vendor_Folder();
1058 is_firmware_symlinked = Symlink_Firmware_Folder();
1059 Symlink_Firmware_Files(is_vendor_symlinked, is_firmware_symlinked);
1060
nkk717d1222a2017-11-06 17:27:21 +02001061 Set_Needed_Properties();
nkk7171c6c502017-01-05 23:55:05 +02001062
1063 // Start services needed for vold decrypt
nkk717d1222a2017-11-06 17:27:21 +02001064 LOGINFO("Starting services...\n");
nkk7171c6c502017-01-05 23:55:05 +02001065#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1066 for (size_t i = 0; i < Services.size(); ++i) {
nkk7137625a42017-12-08 16:37:59 +02001067 if (Services[i].bin_exists)
nkk717d1222a2017-11-06 17:27:21 +02001068 Services[i].is_running = Start_Service(Services[i].VOLD_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001069 }
1070#endif
1071 is_vold_running = Start_Service("sys_vold");
1072
1073 if (is_vold_running) {
nkk7171c6c502017-01-05 23:55:05 +02001074#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1075 for (size_t i = 0; i < Services.size(); ++i) {
nkk7137625a42017-12-08 16:37:59 +02001076 if (Services[i].bin_exists && !Is_Service_Running(Services[i].VOLD_Service_Name) && Services[i].resume) {
nkk7171c6c502017-01-05 23:55:05 +02001077 // if system_service has died restart the twrp_service
nkk717d1222a2017-11-06 17:27:21 +02001078 LOGINFO("%s is not running, resuming %s!\n", Services[i].VOLD_Service_Name.c_str(), Services[i].TWRP_Service_Name.c_str());
1079 Start_Service(Services[i].TWRP_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001080 }
1081 }
1082#endif
nkk717d1222a2017-11-06 17:27:21 +02001083 res = Run_vdc(Password);
nkk7171c6c502017-01-05 23:55:05 +02001084
1085 if (res != 0) {
nkk717d1222a2017-11-06 17:27:21 +02001086 LOGINFO("Decryption failed\n");
nkk7171c6c502017-01-05 23:55:05 +02001087 }
1088 } else {
nkk717d1222a2017-11-06 17:27:21 +02001089 LOGINFO("Failed to start vold\n");
1090 res = VD_ERR_VOLD_FAILED_TO_START;
nkk7171c6c502017-01-05 23:55:05 +02001091 }
1092
1093 // Stop services needed for vold decrypt so /system can be unmounted
nkk717d1222a2017-11-06 17:27:21 +02001094 LOGINFO("Stopping services...\n");
nkk7171c6c502017-01-05 23:55:05 +02001095 Stop_Service("sys_vold");
1096#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1097 for (size_t i = 0; i < Services.size(); ++i) {
nkk717d1222a2017-11-06 17:27:21 +02001098 if (!Is_Service_Running(Services[i].VOLD_Service_Name) && Services[i].resume)
1099 Stop_Service(Services[i].TWRP_Service_Name);
nkk7137625a42017-12-08 16:37:59 +02001100 else if (Services[i].bin_exists)
nkk717d1222a2017-11-06 17:27:21 +02001101 Stop_Service(Services[i].VOLD_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001102 }
1103#endif
1104
1105 if (is_firmware_symlinked)
1106 Restore_Firmware_Folder();
1107 if (is_vendor_symlinked)
1108 Restore_Vendor_Folder();
nkk717d1222a2017-11-06 17:27:21 +02001109 if (is_fstab_symlinked)
1110 Restore_Recovery_Fstab();
nkk7171c6c502017-01-05 23:55:05 +02001111
1112 if (!PartitionManager.UnMount_By_Path("/system", true)) {
1113 // PartitionManager failed to unmount /system, this should not happen,
1114 // but in case it does, do a lazy unmount
nkk717d1222a2017-11-06 17:27:21 +02001115 LOGINFO("WARNING: system could not be unmounted normally!\n");
1116 umount2("/system", MNT_DETACH);
nkk7171c6c502017-01-05 23:55:05 +02001117 }
1118
nkk717d1222a2017-11-06 17:27:21 +02001119 LOGINFO("Finished.\n");
nkk7171c6c502017-01-05 23:55:05 +02001120
1121#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1122 // Restart previously running services
1123 for (size_t i = 0; i < Services.size(); ++i) {
1124 if (Services[i].resume)
nkk717d1222a2017-11-06 17:27:21 +02001125 Start_Service(Services[i].TWRP_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001126 }
1127#endif
1128
1129#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
nkk717d1222a2017-11-06 17:27:21 +02001130 Strace_init_Stop();
nkk7171c6c502017-01-05 23:55:05 +02001131#endif
1132
1133 // Finish up and exit
1134 if (fp_kmsg) {
1135 fflush(fp_kmsg);
1136 fclose(fp_kmsg);
1137 }
1138
nkk7171c6c502017-01-05 23:55:05 +02001139 return res;
1140}
nkk717d1222a2017-11-06 17:27:21 +02001141
1142} // namespace
1143
1144/*
1145 * Common vold Response Codes / Errors:
1146 * 406 (OpFailedStorageNotFound) -> Problem reading or parsing fstab
1147 *
1148 */
1149
1150/* Main function separated from core in case we want to return error info */
1151int vold_decrypt(const string& Password) {
1152 return Vold_Decrypt_Core(Password);
1153}