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