blob: 2a0e1fbd59669905fd8961bc624629afda5db74b [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
bigbiffad58e1b2020-07-06 20:24:34 -040084#define VD_STRACE_BIN "/system/bin/strace"
nkk717d1222a2017-11-06 17:27:21 +020085#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
bigbiffad58e1b2020-07-06 20:24:34 -0400402// Android 8.0 fs_mgr checks for "/system/bin/recovery", in which case it will
nkk717d1222a2017-11-06 17:27:21 +0200403// 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;
bigbiffad58e1b2020-07-06 20:24:34 -0400719 else if (Service_Exists("system/bin" + services[j].Service_Name))
720 services[j].TWRP_Service_Name = "system/bin" + services[j].Service_Name;
nkk717d1222a2017-11-06 17:27:21 +0200721 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
Captain Throwback740d8522021-12-29 10:56:48 -0500783#ifdef TW_INCLUDE_LIBRESETPROP // Patch_Level_Overrides
Captain Throwback89a03cc2020-02-04 15:34:06 -0500784void Update_Patch_Level(void) {
785 // On Oreo and above, keymaster requires Android version & patch level to match installed system
786 string sdkverstr = TWFunc::System_Property_Get("ro.build.version.sdk");
787 if (!sdkverstr.empty()) {
788 sdkver = atoi(sdkverstr.c_str());
789 }
790 if (sdkver <= 25) {
791 property_set("vold_decrypt.legacy_system", "true");
792 } else {
793 LOGINFO("Current system is Oreo or above. Setting OS version and security patch level from installed system...\n");
794 property_set("vold_decrypt.legacy_system", "false");
795 }
796
797 char prop_value[PROPERTY_VALUE_MAX];
798 char legacy_system_value[PROPERTY_VALUE_MAX] = "false";
799 property_get("vold_decrypt.legacy_system", prop_value, "");
800
801 // Only set OS ver and patch level if device uses Oreo+ system
802 if (strcmp(prop_value, legacy_system_value) == 0) {
803 property_get("ro.build.version.release", prop_value, "");
804 std::string osver_orig = prop_value;
805 property_set("vold_decrypt.osver_orig", osver_orig.c_str());
806 LOGINFO("Current OS version: %s\n", osver_orig.c_str());
807
808 int error = 0;
809 std::string osver = TWFunc::System_Property_Get("ro.build.version.release");
810 if (!(osver == osver_orig)) {
811 if (!(error = TWFunc::Property_Override("ro.build.version.release", osver))) {
812 LOGINFO("Property override successful! New OS version: %s\n", osver.c_str());
813 } else {
814 LOGERROR("Property override failed, code %d\n", error);
815 return;
816 }
817 // TODO: Confirm whether we actually need to update the props in prop.default
818 std::string sed_osver = "sed -i 's/ro.build.version.release=.*/ro.build.version.release=" + osver + "/g' /prop.default";
819 TWFunc::Exec_Cmd(sed_osver);
820 property_set("vold_decrypt.osver_set", "true");
821 } else {
822 LOGINFO("Current OS version & System OS version already match. Proceeding to next step.\n");
823 property_set("vold_decrypt.osver_set", "false");
824 }
825
826 property_get("ro.build.version.security_patch", prop_value, "");
827 std::string patchlevel_orig = prop_value;
828 property_set("vold_decrypt.patchlevel_orig", patchlevel_orig.c_str());
829 LOGINFO("Current security patch level: %s\n", patchlevel_orig.c_str());
830
831 std::string patchlevel = TWFunc::System_Property_Get("ro.build.version.security_patch");
832 if (!(patchlevel == patchlevel_orig)) {
833 if (!(error = TWFunc::Property_Override("ro.build.version.security_patch", patchlevel))) {
834 LOGINFO("Property override successful! New security patch level: %s\n", patchlevel.c_str());
835 } else {
836 LOGERROR("Property override failed, code %d\n", error);
837 return;
838 }
839 // TODO: Confirm whether we actually need to update the props in prop.default
840 std::string sed_patchlevel = "sed -i 's/ro.build.version.security_patch=.*/ro.build.version.security_patch=" + patchlevel + "/g' /prop.default";
841 TWFunc::Exec_Cmd(sed_patchlevel);
842 property_set("vold_decrypt.patchlevel_set", "true");
843 } else {
844 LOGINFO("Current security patch level & System security patch level already match. Proceeding to next step.\n");
845 property_set("vold_decrypt.patchlevel_set", "false");
846 }
847 return;
848 } else {
849 LOGINFO("Current system is Nougat or older. Skipping OS version and security patch level setting...\n");
850 return;
851 }
852}
853
854void Revert_Patch_Level(void) {
855 char osver_set[PROPERTY_VALUE_MAX];
856 char patchlevel_set[PROPERTY_VALUE_MAX];
857 char osver_patchlevel_set[PROPERTY_VALUE_MAX] = "false";
858
859 property_get("vold_decrypt.osver_set", osver_set, "");
860 property_get("vold_decrypt.patchlevel_set", patchlevel_set, "");
861
862 int osver_result = strcmp(osver_set, osver_patchlevel_set);
863 int patchlevel_result = strcmp(patchlevel_set, osver_patchlevel_set);
864 if (!(osver_result == 0 && patchlevel_result == 0)) {
865 char prop_value[PROPERTY_VALUE_MAX];
866 LOGINFO("Reverting OS version and security patch level to original TWRP values...\n");
867 property_get("vold_decrypt.osver_orig", prop_value, "");
868 std::string osver_orig = prop_value;
869 property_get("ro.build.version.release", prop_value, "");
870 std::string osver = prop_value;
871
872 int error = 0;
873 if (!(osver == osver_orig)) {
874 if (!(error = TWFunc::Property_Override("ro.build.version.release", osver_orig))) {
875 LOGINFO("Property override successful! Original OS version: %s\n", osver_orig.c_str());
876 } else {
877 LOGERROR("Property override failed, code %d\n", error);
878 return;
879 }
880 // TODO: Confirm whether we actually need to update the props in prop.default
881 std::string sed_osver_orig = "sed -i 's/ro.build.version.release=.*/ro.build.version.release=" + osver_orig + "/g' /prop.default";
882 TWFunc::Exec_Cmd(sed_osver_orig);
883 }
884
885 property_get("vold_decrypt.patchlevel_orig", prop_value, "");
886 std::string patchlevel_orig = prop_value;
887 property_get("ro.build.version.security_patch", prop_value, "");
888 std::string patchlevel = prop_value;
889
890 if (!(patchlevel == patchlevel_orig)) {
891 if (!(error = TWFunc::Property_Override("ro.build.version.security_patch", patchlevel_orig))) {
892 LOGINFO("Property override successful! Original security patch level: %s\n", patchlevel_orig.c_str());
893 } else {
894 LOGERROR("Property override failed, code %d\n", error);
895 return;
896 }
897 // TODO: Confirm whether we actually need to update the props in prop.default
898 std::string sed_patchlevel_orig = "sed -i 's/ro.build.version.security_patch=.*/ro.build.version.security_patch=" + patchlevel_orig + "/g' /prop.default";
899 TWFunc::Exec_Cmd(sed_patchlevel_orig);
900 }
901 } else {
902 return;
903 }
904}
Captain Throwback740d8522021-12-29 10:56:48 -0500905#endif // Patch_Level_Overrides
Captain Throwback89a03cc2020-02-04 15:34:06 -0500906
nijel82c821a82018-12-29 04:56:41 -0500907static unsigned int get_blkdev_size(int fd) {
908 unsigned long nr_sec;
909
910 if ( (ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
911 nr_sec = 0;
912 }
913
914 return (unsigned int) nr_sec;
915}
916
917#define CRYPT_FOOTER_OFFSET 0x4000
918static char footer[16 * 1024];
919const char* userdata_path;
920static off64_t offset;
921
922int footer_br(const string& command) {
923 int fd;
924
925 if (command == "backup") {
926 unsigned int nr_sec;
927 TWPartition* userdata = PartitionManager.Find_Partition_By_Path("/data");
928 userdata_path = userdata->Actual_Block_Device.c_str();
929 fd = open(userdata_path, O_RDONLY);
930 if (fd < 0) {
931 LOGERROR("E:footer_backup: Cannot open '%s': %s\n", userdata_path, strerror(errno));
932 return -1;
933 }
934 if ((nr_sec = get_blkdev_size(fd))) {
935 offset = ((off64_t)nr_sec * 512) - CRYPT_FOOTER_OFFSET;
936 } else {
937 LOGERROR("E:footer_br: Failed to get offset\n");
938 close(fd);
939 return -1;
940 }
941 if (lseek64(fd, offset, SEEK_SET) == -1) {
942 LOGERROR("E:footer_backup: Failed to lseek64\n");
943 close(fd);
944 return -1;
945 }
946 if (read(fd, footer, sizeof(footer)) != sizeof(footer)) {
947 LOGERROR("E:footer_br: Failed to read: %s\n", strerror(errno));
948 close(fd);
949 return -1;
950 }
951 close(fd);
952 } else if (command == "restore") {
953 fd = open(userdata_path, O_WRONLY);
954 if (fd < 0) {
955 LOGERROR("E:footer_restore: Cannot open '%s': %s\n", userdata_path, strerror(errno));
956 return -1;
957 }
958 if (lseek64(fd, offset, SEEK_SET) == -1) {
959 LOGERROR("E:footer_restore: Failed to lseek64\n");
960 close(fd);
961 return -1;
962 }
963 if (write(fd, footer, sizeof(footer)) != sizeof(footer)) {
964 LOGERROR("E:footer_br: Failed to write: %s\n", strerror(errno));
965 close(fd);
966 return -1;
967 }
968 close(fd);
969 } else {
970 LOGERROR("E:footer_br: wrong command argument: %s\n", command.c_str());
971 return -1;
972 }
973 return 0;
974}
nkk7171c6c502017-01-05 23:55:05 +0200975
nkk717d1222a2017-11-06 17:27:21 +0200976/* vdc Functions */
977typedef struct {
978 string Output; // Entire line excluding \n
979 int ResponseCode; // ResponseCode.h (int)
980 int Sequence; // Sequence (int)
981 int Message; // Message (string) but we're only interested in int
982} vdc_ReturnValues;
983
984int Exec_vdc_cryptfs(const string& command, const string& argument, vdc_ReturnValues* vdcResult) {
985 pid_t pid;
986 int status;
nkk7137625a42017-12-08 16:37:59 +0200987 int pipe_fd[2][2];
nkk717d1222a2017-11-06 17:27:21 +0200988
nkk7137625a42017-12-08 16:37:59 +0200989 vdcResult->Output.clear();
990 vdcResult->ResponseCode = vdcResult->Sequence = vdcResult->Message = -1;
991
992 for (int i = 0; i < 2; ++i) {
993 if (pipe(pipe_fd[i])) {
994 LOGERROR("exec_vdc_cryptfs: pipe() error!\n");
995 return -1;
996 }
nkk717d1222a2017-11-06 17:27:21 +0200997 }
998
nijel82c821a82018-12-29 04:56:41 -0500999 // getpwtype and checkpw commands are removed from Pie vdc, using modified vdc_pie
bigbiffad58e1b2020-07-06 20:24:34 -04001000 const char *cmd[] = { "/system/bin/vdc_pie", "cryptfs" };
nijel82c821a82018-12-29 04:56:41 -05001001 if (sdkver < 28)
1002 cmd[0] = "/system/bin/vdc";
nkk717d1222a2017-11-06 17:27:21 +02001003 const char *env[] = { "LD_LIBRARY_PATH=/system/lib64:/system/lib", NULL };
1004
nijel82c821a82018-12-29 04:56:41 -05001005 LOGINFO("sdkver: %d, using %s\n", sdkver, cmd[0]);
1006
nkk717d1222a2017-11-06 17:27:21 +02001007#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
1008 string log_name = "/tmp/strace_vdc_" + command;
nkk7171c6c502017-01-05 23:55:05 +02001009#endif
nkk7171c6c502017-01-05 23:55:05 +02001010
nkk717d1222a2017-11-06 17:27:21 +02001011 switch(pid = fork())
1012 {
1013 case -1:
1014 LOGERROR("exec_vdc_cryptfs: fork failed: %d (%s)!\n", errno, strerror(errno));
1015 return -1;
1016
1017 case 0: // child
1018 fflush(stdout); fflush(stderr);
nkk7137625a42017-12-08 16:37:59 +02001019 for (int i = 0; i < 2; ++i) {
1020 close(pipe_fd[i][0]);
1021 dup2(pipe_fd[i][1], ((i == 0) ? STDOUT_FILENO : STDERR_FILENO));
1022 close(pipe_fd[i][1]);
1023 }
nkk717d1222a2017-11-06 17:27:21 +02001024
1025#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
1026 if (has_strace) {
1027 if (argument.empty())
1028 execl(VD_STRACE_BIN, "strace", "-q", "-tt", "-ff", "-v", "-y", "-s", "1000", "-o", log_name.c_str(),
1029 "-E", env[0], cmd[0], cmd[1], command.c_str(), NULL);
1030 else
1031 execl(VD_STRACE_BIN, "strace", "-q", "-tt", "-ff", "-v", "-y", "-s", "1000", "-o", log_name.c_str(),
1032 "-E", env[0], cmd[0], cmd[1], command.c_str(), argument.c_str(), NULL);
1033 } else
1034#endif
1035 if (argument.empty())
1036 execle(cmd[0], cmd[0], cmd[1], command.c_str(), NULL, env);
1037 else
1038 execle(cmd[0], cmd[0], cmd[1], command.c_str(), argument.c_str(), NULL, env);
1039 _exit(127);
1040 break;
1041
1042 default:
1043 {
1044 int timeout = 30*100;
nkk717d1222a2017-11-06 17:27:21 +02001045
nkk7137625a42017-12-08 16:37:59 +02001046 for (int i = 0; i < 2; ++i) {
1047 close(pipe_fd[i][1]);
1048
1049 // Non-blocking read loop with timeout
1050 int flags = fcntl(pipe_fd[i][0], F_GETFL, 0);
1051 fcntl(pipe_fd[i][0], F_SETFL, flags | O_NONBLOCK);
1052 }
nkk717d1222a2017-11-06 17:27:21 +02001053
1054 char buffer[128];
1055 ssize_t count;
nkk7137625a42017-12-08 16:37:59 +02001056 string strout[2];
nkk717d1222a2017-11-06 17:27:21 +02001057 pid_t retpid = waitpid(pid, &status, WNOHANG);
1058 while (true) {
nkk7137625a42017-12-08 16:37:59 +02001059 for (int i = 0; i < 2; ++i) {
1060 count = read(pipe_fd[i][0], buffer, sizeof(buffer));
1061 if (count == -1) {
1062 if (errno == EINTR)
1063 continue;
1064 else if (errno != EAGAIN)
1065 LOGERROR("exec_vdc_cryptfs: read() error %d (%s)\n!", errno, strerror(errno));
1066 } else if (count > 0) {
1067 strout[i].append(buffer, count);
1068 }
nkk717d1222a2017-11-06 17:27:21 +02001069 }
1070
1071 retpid = waitpid(pid, &status, WNOHANG);
1072 if (retpid == 0 && --timeout)
1073 usleep(10000);
1074 else
1075 break;
1076 };
nkk7137625a42017-12-08 16:37:59 +02001077
1078 for (int i = 0; i < 2; ++i) {
1079 close(pipe_fd[i][0]);
1080 }
1081
1082 if (!strout[0].empty()) {
1083 sscanf(strout[0].c_str(), "%d %d %d", &vdcResult->ResponseCode, &vdcResult->Sequence, &vdcResult->Message);
1084 vdcResult->Output = "I:" + strout[0];
1085 }
1086 if (!strout[1].empty()) {
1087 vdcResult->Output += "E:" + strout[1];
1088 }
1089 std::replace(vdcResult->Output.begin(), vdcResult->Output.end(), '\n', '|');
1090
1091 if (!vdcResult->Output.empty() && vdcResult->Output[vdcResult->Output.length() - 1] != '|')
1092 vdcResult->Output += "|";
1093 vdcResult->Output += "RC=" + TWFunc::to_string(WEXITSTATUS(status));
nkk717d1222a2017-11-06 17:27:21 +02001094
1095 // Error handling
1096 if (retpid == 0 && timeout == 0) {
1097 LOGERROR("exec_vdc_cryptfs: took too long, killing process\n");
1098 kill(pid, SIGKILL);
1099 for (timeout = 5; retpid == 0 && timeout; --timeout) {
1100 sleep(1);
1101 retpid = waitpid(pid, &status, WNOHANG);
1102 }
1103 if (retpid)
1104 LOGINFO("exec_vdc_cryptfs: process killed successfully\n");
1105 else
1106 LOGERROR("exec_vdc_cryptfs: process took too long to kill, may be a zombie process\n");
1107 return VD_ERR_VOLD_OPERATION_TIMEDOUT;
1108 } else if (retpid > 0) {
1109 if (WIFSIGNALED(status)) {
1110 LOGERROR("exec_vdc_cryptfs: process ended with signal: %d\n", WTERMSIG(status)); // Seg fault or some other non-graceful termination
1111 return -1;
1112 }
1113 } else if (retpid < 0) { // no PID returned
1114 if (errno == ECHILD)
1115 LOGINFO("exec_vdc_cryptfs: no child process exist\n");
1116 else {
1117 LOGERROR("exec_vdc_cryptfs: Unexpected error %d (%s)\n", errno, strerror(errno));
1118 return -1;
1119 }
1120 }
nijel82c821a82018-12-29 04:56:41 -05001121 if (sdkver >= 28) {
1122 return WEXITSTATUS(status);
1123 }
nkk717d1222a2017-11-06 17:27:21 +02001124 return 0;
1125 }
1126 }
nkk7171c6c502017-01-05 23:55:05 +02001127}
1128
nkk717d1222a2017-11-06 17:27:21 +02001129int Run_vdc(const string& Password) {
1130 int res;
nkk7171c6c502017-01-05 23:55:05 +02001131 struct timeval t1, t2;
nkk717d1222a2017-11-06 17:27:21 +02001132 vdc_ReturnValues vdcResult;
nkk7171c6c502017-01-05 23:55:05 +02001133
nkk717d1222a2017-11-06 17:27:21 +02001134 LOGINFO("About to run vdc...\n");
nkk7171c6c502017-01-05 23:55:05 +02001135
nijel82c821a82018-12-29 04:56:41 -05001136 // Pie vdc communicates with vold directly, no socket so lets not waste time
1137 if (sdkver < 28) {
1138 // Wait for vold connection
1139 gettimeofday(&t1, NULL);
1140 t2 = t1;
1141 while ((t2.tv_sec - t1.tv_sec) < 5) {
1142 // cryptfs getpwtype returns: R1=213(PasswordTypeResult) R2=? R3="password", "pattern", "pin", "default"
1143 res = Exec_vdc_cryptfs("getpwtype", "", &vdcResult);
1144 if (vdcResult.ResponseCode == PASSWORD_TYPE_RESULT) {
1145 res = 0;
1146 break;
1147 }
1148 LOGINFO("Retrying connection to vold (Reason: %s)\n", vdcResult.Output.c_str());
1149 usleep(SLEEP_MIN_USEC); // vdc usually usleep(10000), but that causes too many unnecessary attempts
1150 gettimeofday(&t2, NULL);
nkk7171c6c502017-01-05 23:55:05 +02001151 }
nijel82c821a82018-12-29 04:56:41 -05001152
1153 if (res == 0 && (t2.tv_sec - t1.tv_sec) < 5)
1154 LOGINFO("Connected to vold: %s\n", vdcResult.Output.c_str());
1155 else if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
1156 return VD_ERR_VOLD_OPERATION_TIMEDOUT; // should never happen for getpwtype
1157 else if (res)
1158 return VD_ERR_FORK_EXECL_ERROR;
1159 else if (vdcResult.ResponseCode != -1)
1160 return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
1161 else
1162 return VD_ERR_VDC_FAILED_TO_CONNECT;
nkk7171c6c502017-01-05 23:55:05 +02001163 }
1164
nkk7171c6c502017-01-05 23:55:05 +02001165 // Input password from GUI, or default password
nkk717d1222a2017-11-06 17:27:21 +02001166 res = Exec_vdc_cryptfs("checkpw", Password, &vdcResult);
1167 if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
1168 return VD_ERR_VOLD_OPERATION_TIMEDOUT;
1169 else if (res)
1170 return VD_ERR_FORK_EXECL_ERROR;
nkk7171c6c502017-01-05 23:55:05 +02001171
nkk7137625a42017-12-08 16:37:59 +02001172 LOGINFO("vdc cryptfs result (passwd): %s\n", vdcResult.Output.c_str());
nkk717d1222a2017-11-06 17:27:21 +02001173 /*
1174 if (res == 0 && vdcResult.ResponseCode != COMMAND_OKAY)
1175 return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
1176 */
1177
nijel82c821a82018-12-29 04:56:41 -05001178 // our vdc returns vold binder op status,
1179 // we care about status.ok() only which is 0
1180 if (sdkver >= 28) {
1181 vdcResult.Message = res;
1182 }
1183
nkk717d1222a2017-11-06 17:27:21 +02001184 if (vdcResult.Message != 0) {
nkk7171c6c502017-01-05 23:55:05 +02001185 // try falling back to Lollipop hex passwords
1186 string hexPassword = convert_key_to_hex_ascii(Password);
nkk717d1222a2017-11-06 17:27:21 +02001187 res = Exec_vdc_cryptfs("checkpw", hexPassword, &vdcResult);
1188 if (res == VD_ERR_VOLD_OPERATION_TIMEDOUT)
1189 return VD_ERR_VOLD_OPERATION_TIMEDOUT;
1190 else if (res)
1191 return VD_ERR_FORK_EXECL_ERROR;
1192
nkk7137625a42017-12-08 16:37:59 +02001193 LOGINFO("vdc cryptfs result (hex_pw): %s\n", vdcResult.Output.c_str());
nkk717d1222a2017-11-06 17:27:21 +02001194 /*
1195 if (res == 0 && vdcResult.ResponseCode != COMMAND_OKAY)
1196 return VD_ERR_VOLD_UNEXPECTED_RESPONSE;
1197 */
nkk7171c6c502017-01-05 23:55:05 +02001198 }
1199
nijel82c821a82018-12-29 04:56:41 -05001200 // sdk < 28 vdc's return value is dependant upon source origin, it will either
nkk717d1222a2017-11-06 17:27:21 +02001201 // return 0 or ResponseCode, so disregard and focus on decryption instead
nijel82c821a82018-12-29 04:56:41 -05001202 // our vdc always returns 0 on success
nkk717d1222a2017-11-06 17:27:21 +02001203 if (vdcResult.Message == 0) {
nkk7171c6c502017-01-05 23:55:05 +02001204 // Decryption successful wait for crypto blk dev
nkk717d1222a2017-11-06 17:27:21 +02001205 Wait_For_Property("ro.crypto.fs_crypto_blkdev");
1206 res = VD_SUCCESS;
1207 } else if (vdcResult.ResponseCode != COMMAND_OKAY) {
1208 res = VD_ERR_VOLD_UNEXPECTED_RESPONSE;
nkk7171c6c502017-01-05 23:55:05 +02001209 } else {
nkk717d1222a2017-11-06 17:27:21 +02001210 res = VD_ERR_DECRYPTION_FAILED;
nkk7171c6c502017-01-05 23:55:05 +02001211 }
1212
1213 return res;
1214}
1215
nkk717d1222a2017-11-06 17:27:21 +02001216int Vold_Decrypt_Core(const string& Password) {
nkk7171c6c502017-01-05 23:55:05 +02001217 int res;
nkk7171c6c502017-01-05 23:55:05 +02001218 bool is_vendor_symlinked = false;
1219 bool is_firmware_symlinked = false;
nkk717d1222a2017-11-06 17:27:21 +02001220 bool is_fstab_symlinked = false;
nkk7171c6c502017-01-05 23:55:05 +02001221 bool is_vold_running = false;
1222
1223 if (Password.empty()) {
nkk717d1222a2017-11-06 17:27:21 +02001224 LOGINFO("vold_decrypt: password is empty!\n");
1225 return VD_ERR_PASSWORD_EMPTY;
nkk7171c6c502017-01-05 23:55:05 +02001226 }
1227
Captain Throwback6ac30af2018-06-21 10:57:12 -04001228 // Mount ANDROID_ROOT and check for vold and vdc
1229 if (!PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) {
nkk717d1222a2017-11-06 17:27:21 +02001230 return VD_ERR_UNABLE_TO_MOUNT_SYSTEM;
Captain Throwback6ac30af2018-06-21 10:57:12 -04001231 } else if ((!TWFunc::Path_Exists("/system/bin/vold")) && (!TWFunc::Path_Exists(PartitionManager.Get_Android_Root_Path() + "/system/bin/vold"))) {
1232 LOGINFO("ERROR: vold not found, aborting.\n");
nkk717d1222a2017-11-06 17:27:21 +02001233 return VD_ERR_MISSING_VOLD;
Captain Throwback6ac30af2018-06-21 10:57:12 -04001234 } else if ((!TWFunc::Path_Exists("/system/bin/vdc")) && (!TWFunc::Path_Exists(PartitionManager.Get_Android_Root_Path() + "/system/bin/vdc"))) {
1235 LOGINFO("ERROR: vdc not found, aborting.\n");
nkk717d1222a2017-11-06 17:27:21 +02001236 return VD_ERR_MISSING_VDC;
nkk7171c6c502017-01-05 23:55:05 +02001237 }
1238
nijel82c821a82018-12-29 04:56:41 -05001239#ifdef TW_CRYPTO_SYSTEM_VOLD_MOUNT
1240 vector<string> partitions = TWFunc::Split_String(TW_CRYPTO_SYSTEM_VOLD_MOUNT, " ");
1241 for (size_t i = 0; i < partitions.size(); ++i) {
1242 string mnt_point = "/" + partitions[i];
1243 if(PartitionManager.Find_Partition_By_Path(mnt_point)) {
1244 if (!PartitionManager.Mount_By_Path(mnt_point, true)) {
1245 LOGERROR("Unable to mount %s\n", mnt_point.c_str());
1246 return VD_ERR_UNABLE_TO_MOUNT_EXTRA;
1247 }
1248 LOGINFO("%s partition mounted\n", partitions[i].c_str());
1249 }
1250 }
1251#endif
1252
nkk7171c6c502017-01-05 23:55:05 +02001253 fp_kmsg = fopen("/dev/kmsg", "a");
1254
nkk717d1222a2017-11-06 17:27:21 +02001255 LOGINFO("TW_CRYPTO_USE_SYSTEM_VOLD := true\n");
nkk7171c6c502017-01-05 23:55:05 +02001256
nkk717d1222a2017-11-06 17:27:21 +02001257 // just cache the result to avoid unneeded duplicates in recovery.log
1258 LOGINFO("Checking existence of vendor and firmware partitions...\n");
1259 is_Vendor_Mounted();
1260 is_Firmware_Mounted();
1261
1262 LOGINFO("Attempting to use system's vold for decryption...\n");
nkk7171c6c502017-01-05 23:55:05 +02001263
1264#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
nkk717d1222a2017-11-06 17:27:21 +02001265 Strace_init_Start();
nkk7171c6c502017-01-05 23:55:05 +02001266#endif
1267
1268#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1269 vector<AdditionalService> Services = Get_List_Of_Additional_Services();
1270
1271 // Check if TWRP is running any of the services
1272 for (size_t i = 0; i < Services.size(); ++i) {
nkk717d1222a2017-11-06 17:27:21 +02001273 if (!Services[i].TWRP_Service_Name.empty() && !Is_Service_Stopped(Services[i].TWRP_Service_Name)) {
nkk7171c6c502017-01-05 23:55:05 +02001274 Services[i].resume = true;
nkk717d1222a2017-11-06 17:27:21 +02001275 Stop_Service(Services[i].TWRP_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001276 } else
1277 Services[i].resume = false;
nkk7171c6c502017-01-05 23:55:05 +02001278 }
1279#endif
1280
nkk717d1222a2017-11-06 17:27:21 +02001281 LOGINFO("Setting up folders and permissions...\n");
1282 is_fstab_symlinked = Symlink_Recovery_Fstab();
nkk7171c6c502017-01-05 23:55:05 +02001283 is_vendor_symlinked = Symlink_Vendor_Folder();
1284 is_firmware_symlinked = Symlink_Firmware_Folder();
1285 Symlink_Firmware_Files(is_vendor_symlinked, is_firmware_symlinked);
1286
nkk717d1222a2017-11-06 17:27:21 +02001287 Set_Needed_Properties();
Captain Throwback89a03cc2020-02-04 15:34:06 -05001288#ifdef TW_INCLUDE_LIBRESETPROP
1289 Update_Patch_Level();
1290#endif
nkk7171c6c502017-01-05 23:55:05 +02001291
1292 // Start services needed for vold decrypt
nkk717d1222a2017-11-06 17:27:21 +02001293 LOGINFO("Starting services...\n");
nkk7171c6c502017-01-05 23:55:05 +02001294#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1295 for (size_t i = 0; i < Services.size(); ++i) {
nijel82c821a82018-12-29 04:56:41 -05001296 if (Services[i].bin_exists) {
1297 if (Services[i].Service_Binary.find("keymaster") != string::npos) {
1298 Wait_For_Property("hwservicemanager.ready", 500000, "true");
1299 LOGINFO(" hwservicemanager is ready.\n");
1300 }
1301
nkk717d1222a2017-11-06 17:27:21 +02001302 Services[i].is_running = Start_Service(Services[i].VOLD_Service_Name);
nijel82c821a82018-12-29 04:56:41 -05001303
1304 if (Services[i].Service_Binary == "qseecomd") {
1305 if (Wait_For_Property("sys.listeners.registered", 500000, "true") == "true"
1306 || Wait_For_Property("vendor.sys.listeners.registered", 500000, "true") == "true")
1307 LOGINFO(" qseecomd listeners registered.\n");
1308 }
1309 }
nkk7171c6c502017-01-05 23:55:05 +02001310 }
1311#endif
1312 is_vold_running = Start_Service("sys_vold");
1313
1314 if (is_vold_running) {
nkk7171c6c502017-01-05 23:55:05 +02001315#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1316 for (size_t i = 0; i < Services.size(); ++i) {
nkk7137625a42017-12-08 16:37:59 +02001317 if (Services[i].bin_exists && !Is_Service_Running(Services[i].VOLD_Service_Name) && Services[i].resume) {
nkk7171c6c502017-01-05 23:55:05 +02001318 // if system_service has died restart the twrp_service
nkk717d1222a2017-11-06 17:27:21 +02001319 LOGINFO("%s is not running, resuming %s!\n", Services[i].VOLD_Service_Name.c_str(), Services[i].TWRP_Service_Name.c_str());
1320 Start_Service(Services[i].TWRP_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001321 }
1322 }
1323#endif
nijel82c821a82018-12-29 04:56:41 -05001324
1325 /*
1326 * Oreo and Pie vold on some devices alters footer causing
1327 * system to ask for decryption password at next boot although
1328 * password haven't changed so we save footer before and restore it
1329 * after vold operations
1330 */
1331 if (sdkver > 25) {
1332 if (footer_br("backup") == 0) {
1333 LOGINFO("footer_br: crypto footer backed up\n");
1334 res = Run_vdc(Password);
1335 if (footer_br("restore") == 0)
1336 LOGINFO("footer_br: crypto footer restored\n");
1337 else
1338 LOGERROR("footer_br: Failed to restore crypto footer\n");
1339 } else {
1340 LOGERROR("footer_br: Failed to backup crypto footer, \
1341 skipping decrypt to prevent data loss. Reboot recovery to try again...\n");
1342 res = -1;
1343 }
1344 } else {
1345 res = Run_vdc(Password);
1346 }
nkk7171c6c502017-01-05 23:55:05 +02001347
1348 if (res != 0) {
nkk717d1222a2017-11-06 17:27:21 +02001349 LOGINFO("Decryption failed\n");
nkk7171c6c502017-01-05 23:55:05 +02001350 }
1351 } else {
nkk717d1222a2017-11-06 17:27:21 +02001352 LOGINFO("Failed to start vold\n");
1353 res = VD_ERR_VOLD_FAILED_TO_START;
nkk7171c6c502017-01-05 23:55:05 +02001354 }
Captain Throwback89a03cc2020-02-04 15:34:06 -05001355#ifdef TW_INCLUDE_LIBRESETPROP
1356 Revert_Patch_Level();
1357#endif
nkk7171c6c502017-01-05 23:55:05 +02001358 // Stop services needed for vold decrypt so /system can be unmounted
nkk717d1222a2017-11-06 17:27:21 +02001359 LOGINFO("Stopping services...\n");
nkk7171c6c502017-01-05 23:55:05 +02001360 Stop_Service("sys_vold");
1361#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
1362 for (size_t i = 0; i < Services.size(); ++i) {
nkk717d1222a2017-11-06 17:27:21 +02001363 if (!Is_Service_Running(Services[i].VOLD_Service_Name) && Services[i].resume)
1364 Stop_Service(Services[i].TWRP_Service_Name);
nkk7137625a42017-12-08 16:37:59 +02001365 else if (Services[i].bin_exists)
nkk717d1222a2017-11-06 17:27:21 +02001366 Stop_Service(Services[i].VOLD_Service_Name);
nkk7171c6c502017-01-05 23:55:05 +02001367 }
1368#endif
1369
1370 if (is_firmware_symlinked)
1371 Restore_Firmware_Folder();
1372 if (is_vendor_symlinked)
1373 Restore_Vendor_Folder();
nkk717d1222a2017-11-06 17:27:21 +02001374 if (is_fstab_symlinked)
1375 Restore_Recovery_Fstab();
nkk7171c6c502017-01-05 23:55:05 +02001376
Captain Throwback6ac30af2018-06-21 10:57:12 -04001377 if (!PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true)) {
1378 // PartitionManager failed to unmount ANDROID_ROOT, this should not happen,
nkk7171c6c502017-01-05 23:55:05 +02001379 // but in case it does, do a lazy unmount
Captain Throwback6ac30af2018-06-21 10:57:12 -04001380 LOGINFO("WARNING: '%s' could not be unmounted normally!\n", PartitionManager.Get_Android_Root_Path().c_str());
1381 umount2(PartitionManager.Get_Android_Root_Path().c_str(), MNT_DETACH);
nkk7171c6c502017-01-05 23:55:05 +02001382 }
1383
nijel82c821a82018-12-29 04:56:41 -05001384#ifdef TW_CRYPTO_SYSTEM_VOLD_MOUNT
1385 for (size_t i = 0; i < partitions.size(); ++i) {
1386 string mnt_point = "/" + partitions[i];
1387 if(PartitionManager.Is_Mounted_By_Path(mnt_point)) {
1388 if (!PartitionManager.UnMount_By_Path(mnt_point, true)) {
1389 LOGINFO("WARNING: %s partition could not be unmounted normally!\n", partitions[i].c_str());
1390 umount2(mnt_point.c_str(), MNT_DETACH);
1391 }
1392 }
1393 }
1394#endif
1395
nkk717d1222a2017-11-06 17:27:21 +02001396 LOGINFO("Finished.\n");
nkk7171c6c502017-01-05 23:55:05 +02001397
1398#ifdef TW_CRYPTO_SYSTEM_VOLD_SERVICES
nijel82c821a82018-12-29 04:56:41 -05001399 Set_Needed_Properties();
nkk7171c6c502017-01-05 23:55:05 +02001400 // Restart previously running services
1401 for (size_t i = 0; i < Services.size(); ++i) {
nijel82c821a82018-12-29 04:56:41 -05001402 if (Services[i].resume) {
1403 if (Services[i].Service_Binary.find("keymaster") != string::npos) {
1404 Wait_For_Property("hwservicemanager.ready", 500000, "true");
1405 LOGINFO(" hwservicemanager is ready.\n");
1406 }
1407
nkk717d1222a2017-11-06 17:27:21 +02001408 Start_Service(Services[i].TWRP_Service_Name);
nijel82c821a82018-12-29 04:56:41 -05001409
1410 if (Services[i].Service_Binary == "qseecomd") {
1411 if (Wait_For_Property("sys.listeners.registered", 500000, "true") == "true"
1412 || Wait_For_Property("vendor.sys.listeners.registered", 500000, "true") == "true")
1413 LOGINFO(" qseecomd listeners registered.\n");
1414 }
1415 }
nkk7171c6c502017-01-05 23:55:05 +02001416 }
1417#endif
1418
1419#ifdef TW_CRYPTO_SYSTEM_VOLD_DEBUG
nkk717d1222a2017-11-06 17:27:21 +02001420 Strace_init_Stop();
nkk7171c6c502017-01-05 23:55:05 +02001421#endif
1422
1423 // Finish up and exit
1424 if (fp_kmsg) {
1425 fflush(fp_kmsg);
1426 fclose(fp_kmsg);
1427 }
1428
nkk7171c6c502017-01-05 23:55:05 +02001429 return res;
1430}
nkk717d1222a2017-11-06 17:27:21 +02001431
1432} // namespace
1433
1434/*
1435 * Common vold Response Codes / Errors:
1436 * 406 (OpFailedStorageNotFound) -> Problem reading or parsing fstab
1437 *
1438 */
1439
1440/* Main function separated from core in case we want to return error info */
1441int vold_decrypt(const string& Password) {
1442 return Vold_Decrypt_Core(Password);
1443}