blob: 5587c0b1c273aaeed9b1678d029389dbf9ccf431 [file] [log] [blame]
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -04001/*
2 Copyright 2012 bigbiff/Dees_Troy 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
19#include <iostream>
20#include <fstream>
21#include <sstream>
22#include <string>
23#include <vector>
24#include <string.h>
25#include <libgen.h>
26#include <unistd.h>
27#include <sys/stat.h>
28#include <dirent.h>
29#include "gui/rapidxml.hpp"
30#include "fixPermissions.hpp"
31#include "twrp-functions.hpp"
32#include "common.h"
33
34using namespace std;
35using namespace rapidxml;
36
37int fixPermissions::fixPerms(bool enable_debug, bool remove_data_for_missing_apps) {
38 packageFile = "/data/system/packages.xml";
39 debug = enable_debug;
40 remove_data = remove_data_for_missing_apps;
41
42 if (!(TWFunc::Path_Exists(packageFile))) {
43 ui_print("Can't check permissions\n");
44 ui_print("after Factory Reset.\n");
45 ui_print("Please boot rom and try\n");
46 ui_print("again after you reboot into\n");
47 ui_print("recovery.\n");
48 return -1;
49 }
50
51 ui_print("Fixing permissions...\nLoading packages...\n");
52 if ((getPackages()) != 0) {
53 return -1;
54 }
55
56 ui_print("Fixing /system/app perissions...\n");
57 if ((fixSystemApps()) != 0) {
58 return -1;
59 }
60
61 ui_print("Fixing /data/app permisions...\n");
62 if ((fixDataApps()) != 0) {
63 return -1;
64 }
65
66 ui_print("Fixing /data/data permisions...\n");
67 if ((fixDataData()) != 0) {
68 return -1;
69 }
70 ui_print("Done fixing permissions.\n");
71 return 0;
72}
73
74int fixPermissions::pchown(string fn, int puid, int pgid) {
75 LOGI("Fixing %s, uid: %d, gid: %d\n", fn.c_str(), puid, pgid);
76 if (chown(fn.c_str(), puid, pgid) != 0) {
77 LOGE("Unable to chown '%s' %i %i\n", fn.c_str(), puid, pgid);
78 return -1;
79 }
80 return 0;
81}
82
83int fixPermissions::pchmod(string fn, string mode) {
84 long mask = 0;
85 LOGI("Fixing %s, mode: %s\n", fn.c_str(), mode.c_str());
86 for ( std::string::size_type n = 0; n < mode.length(); ++n) {
87 if (n == 0) {
88 if (mode[n] == '0')
89 continue;
90 else if (mode[n] == '1')
91 mask = S_ISVTX;
92 else if (mode[n] == '2')
93 mask = S_ISGID;
94 }
95 else if (n == 1) {
96 if (mode[n] == '7') {
97 mask |= S_IRWXU;
98 }
99 if (mode[n] == '6') {
100 mask |= S_IRUSR;
101 mask |= S_IWUSR;
102 }
103 if (mode[n] == '5') {
104 mask |= S_IRUSR;
105 mask |= S_IXUSR;
106 }
107 if (mode[n] == '4')
108 mask |= S_IRUSR;
109 if (mode[n] == '3') {
110 mask |= S_IWUSR;
111 mask |= S_IRUSR;
112 }
113 if (mode[n] == '2')
114 mask |= S_IWUSR;
115 if (mode[n] == '1')
116 mask |= S_IXUSR;
117 }
118 else if (n == 2) {
119 if (mode[n] == '7') {
120 mask |= S_IRWXG;
121 }
122 if (mode[n] == '6') {
123 mask |= S_IRGRP;
124 mask |= S_IWGRP;
125 }
126 if (mode[n] == '5') {
127 mask |= S_IRGRP;
128 mask |= S_IXGRP;
129 }
130 if (mode[n] == '4')
131 mask |= S_IRGRP;
132 if (mode[n] == '3') {
133 mask |= S_IWGRP;
134 mask |= S_IXGRP;
135 }
136 if (mode[n] == '2')
137 mask |= S_IWGRP;
138 if (mode[n] == '1')
139 mask |= S_IXGRP;
140 }
141 else if (n == 3) {
142 if (mode[n] == '7') {
143 mask |= S_IRWXO;
144 }
145 if (mode[n] == '6') {
146 mask |= S_IROTH;
147 mask |= S_IWOTH;
148 }
149 if (mode[n] == '5') {
150 mask |= S_IROTH;
151 mask |= S_IXOTH;
152 }
153 if (mode[n] == '4')
154 mask |= S_IROTH;
155 if (mode[n] == '3') {
156 mask |= S_IWOTH;
157 mask |= S_IXOTH;
158 }
159 if (mode[n] == '2')
Dees_Troy6480ce02012-10-10 10:26:54 -0400160 mask |= S_IWOTH;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400161 if (mode[n] == '1')
Dees_Troy6480ce02012-10-10 10:26:54 -0400162 mask |= S_IXOTH;
bigbiff bigbiffa0f8a592012-10-09 21:01:03 -0400163 }
164 }
165
166 if (chmod(fn.c_str(), mask) != 0) {
167 LOGE("Unable to chmod '%s' %l\n", fn.c_str(), mask);
168 return -1;
169 }
170
171 return 0;
172}
173
174int fixPermissions::removeDir(const string path) {
175 DIR *d = opendir(path.c_str());
176 int r = 0;
177 string new_path;
178
179 if (d == NULL) {
180 LOGE("Error opening '%s'\n", path.c_str());
181 return -1;
182 }
183
184 if (d) {
185 struct dirent *p;
186 while (!r && (p = readdir(d))) {
187 if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, ".."))
188 continue;
189
190 new_path = path + "/";
191 new_path.append(p->d_name);
192 if (p->d_type == DT_DIR) {
193 r = removeDir(new_path);
194 if (!r)
195 LOGI("Unable to removeDir '%s'\n", new_path.c_str());
196 } else {
197 r = unlink(new_path.c_str());
198 if (!r)
199 LOGI("Unable to unlink '%s'\n", new_path.c_str());
200 }
201 }
202 closedir(d);
203 }
204 if (!r)
205 r = rmdir(path.c_str());
206 if (!r)
207 LOGI("Unable to rmdir '%s'\n", path.c_str());
208
209 return r;
210}
211
212int fixPermissions::fixSystemApps() {
213 temp = head;
214 while (temp != NULL) {
215 if (TWFunc::Path_Exists(temp->codePath)) {
216 if (temp->appDir.compare("/system/app") == 0) {
217 if (debug) {
218 LOGI("Looking at '%s'\n", temp->codePath.c_str());
219 LOGI("Fixing permissions on '%s'\n", temp->pkgName.c_str());
220 LOGI("Directory: '%s'\n", temp->appDir.c_str());
221 LOGI("Original package owner: %d, group: %d\n", temp->uid, temp->gid);
222 }
223 if (pchown(temp->codePath, 0, 0) != 0)
224 return -1;
225 if (pchmod(temp->codePath, "0644") != 0)
226 return -1;
227 }
228 } else {
229 //Remove data directory since app isn't installed
230 if (remove_data && TWFunc::Path_Exists(temp->dDir) && temp->appDir.size() >= 9 && temp->appDir.substr(0, 9) != "/mnt/asec") {
231 if (debug)
232 LOGI("Looking at '%s', removing data dir: '%s', appDir: '%s'", temp->codePath.c_str(), temp->dDir.c_str(), temp->appDir.c_str());
233 if (removeDir(temp->dDir) != 0) {
234 LOGI("Unable to removeDir '%s'\n", temp->dDir.c_str());
235 return -1;
236 }
237 }
238 }
239 temp = temp->next;
240 }
241 return 0;
242}
243
244int fixPermissions::fixDataApps() {
245 bool fix = false;
246 int new_gid = 0;
247 string perms = "0000";
248
249 temp = head;
250 while (temp != NULL) {
251 if (TWFunc::Path_Exists(temp->codePath)) {
252 if (temp->appDir.compare("/data/app") == 0 || temp->appDir.compare("/sd-ext/app") == 0) {
253 fix = true;
254 new_gid = 1000;
255 perms = "0644";
256 } else if (temp->appDir.compare("/data/app-private") == 0 || temp->appDir.compare("/sd-ext/app-private") == 0) {
257 fix = true;
258 new_gid = temp->gid;
259 perms = "0640";
260 } else
261 fix = false;
262 if (fix) {
263 if (debug) {
264 LOGI("Looking at '%s'\n", temp->codePath.c_str());
265 LOGI("Fixing permissions on '%s'\n", temp->pkgName.c_str());
266 LOGI("Directory: '%s'\n", temp->appDir.c_str());
267 LOGI("Original package owner: %d, group: %d\n", temp->uid, temp->gid);
268 }
269 if (pchown(temp->codePath, 1000, new_gid) != 0)
270 return -1;
271 if (pchmod(temp->codePath, perms) != 0)
272 return -1;
273 }
274 } else {
275 //Remove data directory since app isn't installed
276 if (remove_data && TWFunc::Path_Exists(temp->dDir) && temp->appDir.size() >= 9 && temp->appDir.substr(0, 9) != "/mnt/asec") {
277 if (debug)
278 LOGI("Looking at '%s', removing data dir: '%s', appDir: '%s'", temp->codePath.c_str(), temp->dDir.c_str(), temp->appDir.c_str());
279 if (removeDir(temp->dDir) != 0) {
280 LOGI("Unable to removeDir '%s'\n", temp->dDir.c_str());
281 return -1;
282 }
283 }
284 }
285 temp = temp->next;
286 }
287 return 0;
288}
289
290int fixPermissions::fixAllFiles(string directory, int gid, int uid, string file_perms) {
291 vector <string> files;
292 string file;
293
294 files = listAllFiles(directory);
295 for (unsigned i = 0; i < files.size(); ++i) {
296 file = directory + "/";
297 file.append(files.at(i));
298 if (debug)
299 LOGI("Looking at file '%s'\n", file.c_str());
300 if (pchmod(file, file_perms) != 0)
301 return -1;
302 if (pchown(file, uid, gid) != 0)
303 return -1;
304 }
305 return 0;
306}
307
308int fixPermissions::fixDataData() {
309 string directory;
310
311 temp = head;
312 while (temp != NULL) {
313 if (TWFunc::Path_Exists(temp->dDir)) {
314 vector <string> dataDataDirs = listAllDirectories(temp->dDir);
315 for (unsigned n = 0; n < dataDataDirs.size(); ++n) {
316 directory = temp->dDir + "/";
317 directory.append(dataDataDirs.at(n));
318 if (debug)
319 LOGI("Looking at data directory: '%s'\n", directory.c_str());
320 if (dataDataDirs.at(n) == ".") {
321 if (pchmod(temp->dDir, "0755") != 0)
322 return -1;
323 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
324 return -1;
325 if (fixAllFiles(directory, temp->uid, temp->gid, "0755") != 0)
326 return -1;
327 }
328 else if (dataDataDirs.at(n) == "..") {
329 if (debug)
330 LOGI("Skipping ..\n");
331 continue;
332 }
333 else if (dataDataDirs.at(n) == "lib") {
334 if (pchmod(directory.c_str(), "0755") != 0)
335 return -1;
336 if (pchown(directory.c_str(), 1000, 1000) != 0)
337 return -1;
338 if (fixAllFiles(directory, temp->uid, temp->gid, "0755") != 0)
339 return -1;
340 }
341 else if (dataDataDirs.at(n) == "shared_prefs") {
342 if (pchmod(directory.c_str(), "0771") != 0)
343 return -1;
344 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
345 return -1;
346 if (fixAllFiles(directory, temp->uid, temp->gid, "0660") != 0)
347 return -1;
348 }
349 else if (dataDataDirs.at(n) == "databases") {
350 if (pchmod(directory.c_str(), "0771") != 0)
351 return -1;
352 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
353 return -1;
354 if (fixAllFiles(directory, temp->uid, temp->gid, "0660") != 0)
355 return -1;
356 }
357 else if (dataDataDirs.at(n) == "cache") {
358 if (pchmod(directory.c_str(), "0771") != 0)
359 return -1;
360 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
361 return -1;
362 if (fixAllFiles(directory, temp->uid, temp->gid, "0600") != 0)
363 return -1;
364 }
365 else {
366 if (pchmod(directory.c_str(), "0771") != 0)
367 return -1;
368 if (pchown(directory.c_str(), temp->uid, temp->gid) != 0)
369 return -1;
370 if (fixAllFiles(directory, temp->uid, temp->gid, "0755") != 0)
371 return -1;
372 }
373 }
374 }
375 temp = temp->next;
376 }
377 return 0;
378}
379
380vector <string> fixPermissions::listAllDirectories(string path) {
381 DIR *dir = opendir(path.c_str());
382 struct dirent *entry = readdir(dir);
383 vector <string> dirs;
384
385 if (dir == NULL) {
386 LOGE("Error opening '%s'\n", path.c_str());
387 return dirs;
388 }
389
390 while (entry != NULL) {
391 if (entry->d_type == DT_DIR)
392 dirs.push_back(entry->d_name);
393 entry = readdir(dir);
394 }
395 closedir(dir);
396 return dirs;
397}
398
399vector <string> fixPermissions::listAllFiles(string path) {
400 DIR *dir = opendir(path.c_str());
401 struct dirent *entry = readdir(dir);
402 vector <string> files;
403
404 if (dir == NULL) {
405 LOGE("Error opening '%s'\n", path.c_str());
406 return files;
407 }
408
409 while (entry != NULL) {
410 if (entry->d_type == DT_REG)
411 files.push_back(entry->d_name);
412 entry = readdir(dir);
413 }
414 closedir(dir);
415 return files;
416}
417
418int fixPermissions::getPackages() {
419 int len = 0;
420 bool skiploop = false;
421 vector <string> skip;
422 string dataDir;
423 string name;
424 head = NULL;
425
426 skip.push_back("/system/framework/framework-res.apk");
427 skip.push_back("/system/framework/com.htc.resources.apk");
428
429 ifstream xmlFile(packageFile.c_str());
430 xmlFile.seekg(0, ios::end);
431 len = (int) xmlFile.tellg();
432 xmlFile.seekg(0, ios::beg);
433 char xmlBuf[len + 1];
434 xmlFile.read(&xmlBuf[0], len);
435 xmlBuf[len] = '\0';
436 xml_document<> pkgDoc;
437 pkgDoc.parse<parse_full>(&xmlBuf[0]);
438
439 xml_node<> * pkgNode = pkgDoc.first_node("packages");
440 xml_node <> * next = pkgNode->first_node("package");
441
442 if (next == NULL) {
443 LOGE("No packages found to fix.\n");
444 return -1;
445 }
446
447 //Get packages
448 while (next->first_attribute("name") != NULL) {
449 package* temp = new package;
450 for (unsigned n = 0; n < skip.size(); ++n) {
451 if (skip.at(n).compare(next->first_attribute("codePath")->value()) == 0) {
452 skiploop = true;
453 break;
454 }
455 }
456
457 if (skiploop == true) {
458 if (debug)
459 LOGI("Skipping package %s\n", next->first_attribute("codePath")->value());
460 free(temp);
461 next = next->next_sibling();
462 skiploop = false;
463 continue;
464 }
465 name.append((next->first_attribute("name")->value()));
466 temp->pkgName = next->first_attribute("name")->value();
467 if (debug)
468 LOGI("Loading pkg: %s\n", next->first_attribute("name")->value());
469 temp->codePath = next->first_attribute("codePath")->value();
470 temp->app = basename(next->first_attribute("codePath")->value());
471 temp->appDir = dirname(next->first_attribute("codePath")->value());
472 dataDir.append("/data/data/");
473 dataDir.append(name);
474 temp->dDir = dataDir;
475 if ( next->first_attribute("sharedUserId") != NULL) {
476 temp->uid = atoi(next->first_attribute("sharedUserId")->value());
477 temp->gid = atoi(next->first_attribute("sharedUserId")->value());
478 }
479 else {
480 temp->uid = atoi(next->first_attribute("userId")->value());
481 temp->gid = atoi(next->first_attribute("userId")->value());
482 }
483 next = next->next_sibling();
484 name.clear();
485 dataDir.clear();
486 temp->next = head;
487 head = temp;
488 }
489 //Get updated packages
490 next = pkgNode->first_node("updated-package");
491 if (next != NULL) {
492 while (next->first_attribute("name") != NULL) {
493 package* temp = new package;
494 for (unsigned n = 0; n < skip.size(); ++n) {
495 if (skip.at(n).compare(next->first_attribute("codePath")->value()) == 0) {
496 skiploop = true;
497 break;
498 }
499 }
500
501 if (skiploop == true) {
502 if (debug)
503 LOGI("Skipping package %s\n", next->first_attribute("codePath")->value());
504 free(temp);
505 next = next->next_sibling();
506 skiploop = false;
507 continue;
508 }
509 name.append((next->first_attribute("name")->value()));
510 temp->pkgName = next->first_attribute("name")->value();
511 if (debug)
512 LOGI("Loading pkg: %s\n", next->first_attribute("name")->value());
513 temp->codePath = next->first_attribute("codePath")->value();
514 temp->app = basename(next->first_attribute("codePath")->value());
515 temp->appDir = dirname(next->first_attribute("codePath")->value());
516
517 dataDir.append("/data/data/");
518 dataDir.append(name);
519 temp->dDir = dataDir;
520 if ( next->first_attribute("sharedUserId") != NULL) {
521 temp->uid = atoi(next->first_attribute("sharedUserId")->value());
522 temp->gid = atoi(next->first_attribute("sharedUserId")->value());
523 }
524 else {
525 temp->uid = atoi(next->first_attribute("userId")->value());
526 temp->gid = atoi(next->first_attribute("userId")->value());
527 }
528 next = next->next_sibling();
529 name.clear();
530 dataDir.clear();
531 temp->next = head;
532 head = temp;
533 }
534 }
535 return 0;
536}