blob: 7e650c20913a1f79b63b416447cfbaa18a3913ac [file] [log] [blame]
Ethan Yonkerb5fab762016-01-28 14:03:33 -06001/*
2 Copyright 2012-2016 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 <string>
20#include <unistd.h>
21#include <sys/stat.h>
22#include <dirent.h>
23#include <errno.h>
24#include <cctype>
25#include "fixContexts.hpp"
26#include "twrp-functions.hpp"
27#include "twcommon.h"
Matt Mower87413642017-01-17 21:14:46 -060028#include <selinux/selinux.h>
29#include <selinux/label.h>
30#include <selinux/android.h>
31#include <selinux/label.h>
Ethan Yonkerb5fab762016-01-28 14:03:33 -060032
33using namespace std;
34
Ethan Yonkerb5fab762016-01-28 14:03:33 -060035struct selabel_handle *sehandle;
36struct selinux_opt selinux_options[] = {
37 { SELABEL_OPT_PATH, "/file_contexts" }
38};
39
40int fixContexts::restorecon(string entry, struct stat *sb) {
41 char *oldcontext, *newcontext;
42
43 if (lgetfilecon(entry.c_str(), &oldcontext) < 0) {
44 LOGINFO("Couldn't get selinux context for %s\n", entry.c_str());
45 return -1;
46 }
47 if (selabel_lookup(sehandle, &newcontext, entry.c_str(), sb->st_mode) < 0) {
48 LOGINFO("Couldn't lookup selinux context for %s\n", entry.c_str());
49 return -1;
50 }
51 if (strcmp(oldcontext, newcontext) != 0) {
52 LOGINFO("Relabeling %s from %s to %s\n", entry.c_str(), oldcontext, newcontext);
53 if (lsetfilecon(entry.c_str(), newcontext) < 0) {
54 LOGINFO("Couldn't label %s with %s: %s\n", entry.c_str(), newcontext, strerror(errno));
55 }
56 }
57 freecon(oldcontext);
58 freecon(newcontext);
59 return 0;
60}
61
62int fixContexts::fixContextsRecursively(string name, int level) {
63 DIR *d;
64 struct dirent *de;
65 struct stat sb;
66 string path;
67
68 if (!(d = opendir(name.c_str())))
69 return -1;
70 if (!(de = readdir(d)))
71 return -1;
72
73 do {
74 if (de->d_type == DT_DIR) {
75 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
76 continue;
77 path = name + "/" + de->d_name;
78 restorecon(path, &sb);
79 fixContextsRecursively(path, level + 1);
80 }
81 else {
82 path = name + "/" + de->d_name;
83 restorecon(path, &sb);
84 }
85 } while ((de = readdir(d)));
86 closedir(d);
87 return 0;
88}
89
90int fixContexts::fixDataMediaContexts(string Mount_Point) {
91 DIR *d;
92 struct dirent *de;
93 struct stat sb;
94
95 LOGINFO("Fixing media contexts on '%s'\n", Mount_Point.c_str());
96
97 sehandle = selabel_open(SELABEL_CTX_FILE, selinux_options, 1);
98 if (!sehandle) {
99 LOGINFO("Unable to open /file_contexts\n");
100 return 0;
101 }
102
103 if (TWFunc::Path_Exists(Mount_Point + "/media/0")) {
104 string dir = Mount_Point + "/media";
105 if (!(d = opendir(dir.c_str()))) {
106 LOGINFO("opendir failed (%s)\n", strerror(errno));
107 return -1;
108 }
109 if (!(de = readdir(d))) {
110 LOGINFO("readdir failed (%s)\n", strerror(errno));
111 closedir(d);
112 return -1;
113 }
114
115 do {
116 if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0 || de->d_type != DT_DIR)
117 continue;
118 size_t len = strlen(de->d_name);
119 bool is_numeric = true;
120 char* folder_name = de->d_name;
121 for (size_t i = 0; i < len; i++) {
122 if (!isdigit(*folder_name)) {
123 is_numeric = false;
124 break;
125 }
126 folder_name++;
127 }
128 if (is_numeric) {
129 dir = Mount_Point + "/media/";
130 dir += de->d_name;
131 restorecon(dir, &sb);
132 fixContextsRecursively(dir, 0);
133 }
134 } while ((de = readdir(d)));
135 closedir(d);
136 } else if (TWFunc::Path_Exists(Mount_Point + "/media")) {
137 restorecon(Mount_Point + "/media", &sb);
138 fixContextsRecursively(Mount_Point + "/media", 0);
139 } else {
140 LOGINFO("fixDataMediaContexts: %s/media does not exist!\n", Mount_Point.c_str());
141 return 0;
142 }
143 selabel_close(sehandle);
144 return 0;
145}