diff options
Diffstat (limited to 'fixContexts.cpp')
-rw-r--r-- | fixContexts.cpp | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/fixContexts.cpp b/fixContexts.cpp new file mode 100644 index 000000000..64429446e --- /dev/null +++ b/fixContexts.cpp @@ -0,0 +1,163 @@ +/* + Copyright 2012-2016 bigbiff/Dees_Troy TeamWin + This file is part of TWRP/TeamWin Recovery Project. + + TWRP is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + TWRP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TWRP. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string> +#include <unistd.h> +#include <sys/stat.h> +#include <dirent.h> +#include <errno.h> +#include <cctype> +#include "fixContexts.hpp" +#include "twrp-functions.hpp" +#include "twcommon.h" +#ifdef HAVE_SELINUX +#include "selinux/selinux.h" +#include "selinux/label.h" +#include "selinux/android.h" +#include "selinux/label.h" +#endif + +using namespace std; + +#ifdef HAVE_SELINUX +struct selabel_handle *sehandle; +struct selinux_opt selinux_options[] = { + { SELABEL_OPT_PATH, "/file_contexts" } +}; + +int fixContexts::restorecon(string entry, struct stat *sb) { + char *oldcontext, *newcontext; + + if (lgetfilecon(entry.c_str(), &oldcontext) < 0) { + LOGINFO("Couldn't get selinux context for %s\n", entry.c_str()); + return -1; + } + if (selabel_lookup(sehandle, &newcontext, entry.c_str(), sb->st_mode) < 0) { + LOGINFO("Couldn't lookup selinux context for %s\n", entry.c_str()); + return -1; + } + if (strcmp(oldcontext, newcontext) != 0) { + LOGINFO("Relabeling %s from %s to %s\n", entry.c_str(), oldcontext, newcontext); + if (lsetfilecon(entry.c_str(), newcontext) < 0) { + LOGINFO("Couldn't label %s with %s: %s\n", entry.c_str(), newcontext, strerror(errno)); + } + } + freecon(oldcontext); + freecon(newcontext); + return 0; +} + +int fixContexts::fixContextsRecursively(string name, int level) { + DIR *d; + struct dirent *de; + struct stat sb; + string path; + + if (!(d = opendir(name.c_str()))) + return -1; + if (!(de = readdir(d))) + return -1; + + do { + if (de->d_type == DT_DIR) { + if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) + continue; + path = name + "/" + de->d_name; + restorecon(path, &sb); + fixContextsRecursively(path, level + 1); + } + else { + path = name + "/" + de->d_name; + restorecon(path, &sb); + } + } while ((de = readdir(d))); + closedir(d); + return 0; +} + +int fixContexts::fixDataMediaContexts(string Mount_Point) { + DIR *d; + struct dirent *de; + struct stat sb; + + LOGINFO("Fixing media contexts on '%s'\n", Mount_Point.c_str()); + + sehandle = selabel_open(SELABEL_CTX_FILE, selinux_options, 1); + if (!sehandle) { + LOGINFO("Unable to open /file_contexts\n"); + return 0; + } + + if (TWFunc::Path_Exists(Mount_Point + "/media/0")) { + string dir = Mount_Point + "/media"; + if (!(d = opendir(dir.c_str()))) { + LOGINFO("opendir failed (%s)\n", strerror(errno)); + return -1; + } + if (!(de = readdir(d))) { + LOGINFO("readdir failed (%s)\n", strerror(errno)); + closedir(d); + return -1; + } + + do { + if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0 || de->d_type != DT_DIR) + continue; + size_t len = strlen(de->d_name); + bool is_numeric = true; + char* folder_name = de->d_name; + for (size_t i = 0; i < len; i++) { + if (!isdigit(*folder_name)) { + is_numeric = false; + break; + } + folder_name++; + } + if (is_numeric) { + dir = Mount_Point + "/media/"; + dir += de->d_name; + restorecon(dir, &sb); + fixContextsRecursively(dir, 0); + } + } while ((de = readdir(d))); + closedir(d); + } else if (TWFunc::Path_Exists(Mount_Point + "/media")) { + restorecon(Mount_Point + "/media", &sb); + fixContextsRecursively(Mount_Point + "/media", 0); + } else { + LOGINFO("fixDataMediaContexts: %s/media does not exist!\n", Mount_Point.c_str()); + return 0; + } + selabel_close(sehandle); + return 0; +} + +#else + +int fixContexts::restorecon(string entry __unused, struct stat *sb __unused) { + return -1; +} + +int fixContexts::fixContextsRecursively(string name __unused, int level __unused) { + return -1; +} + +int fixContexts::fixDataMediaContexts(string Mount_Point __unused) { + return -1; +} +#endif |