Attempt to set the proper uid/gid/contexts on new files and dirs
Files and folders that we create during backups, copy log, or MTP
operations often do not have the proper uid/gid/contexts assigned.
We will attempt to read the proper contexts from the settings
storage path and assign those same contexts to any files or dirs
that we create.
Change-Id: I769f9479854122b49b499de2175e6e2d026f8afd
diff --git a/Android.mk b/Android.mk
index e909baa..2a10877 100644
--- a/Android.mk
+++ b/Android.mk
@@ -449,8 +449,8 @@
LOCAL_MODULE := libaosprecovery
LOCAL_MODULE_TAGS := eng optional
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libmincrypt/includes
-LOCAL_SRC_FILES := adb_install.cpp asn1_decoder.cpp bootloader.cpp mtdutils/mtdutils.c legacy_property_service.c verifier.cpp
-LOCAL_SHARED_LIBRARIES += libc liblog libcutils libmtdutils libfusesideload libmincrypttwrp
+LOCAL_SRC_FILES := adb_install.cpp asn1_decoder.cpp bootloader.cpp mtdutils/mtdutils.c legacy_property_service.c verifier.cpp set_metadata.c
+LOCAL_SHARED_LIBRARIES += libc liblog libcutils libmtdutils libfusesideload libmincrypttwrp libselinux
ifneq ($(BOARD_RECOVERY_BLDRMSG_OFFSET),)
LOCAL_CFLAGS += -DBOARD_RECOVERY_BLDRMSG_OFFSET=$(BOARD_RECOVERY_BLDRMSG_OFFSET)
diff --git a/data.cpp b/data.cpp
index 0d05c3d..88bc86a 100644
--- a/data.cpp
+++ b/data.cpp
@@ -46,6 +46,7 @@
#include "gui/blanktimer.hpp"
#endif
#include "find_file.hpp"
+#include "set_metadata.h"
#ifdef TW_USE_MODEL_HARDWARE_ID_FOR_DEVICE_ID
#include "cutils/properties.h"
@@ -333,6 +334,7 @@
}
}
fclose(out);
+ tw_set_default_metadata(mBackingFile.c_str());
#endif // ifdef TW_OEM_BUILD
return 0;
}
diff --git a/gui/Android.mk b/gui/Android.mk
index 479bc76..d7a605e 100644
--- a/gui/Android.mk
+++ b/gui/Android.mk
@@ -33,7 +33,7 @@
LOCAL_SRC_FILES += hardwarekeyboard.cpp
endif
-LOCAL_SHARED_LIBRARIES += libminuitwrp libc libstdc++ libminzip
+LOCAL_SHARED_LIBRARIES += libminuitwrp libc libstdc++ libminzip libaosprecovery
LOCAL_MODULE := libguitwrp
# Use this flag to create a build that simulates threaded actions like installing zips, backups, restores, and wipes for theme testing
diff --git a/gui/action.cpp b/gui/action.cpp
index 6b8565a..d72b331 100644
--- a/gui/action.cpp
+++ b/gui/action.cpp
@@ -52,6 +52,7 @@
#include "cutils/properties.h"
#include "../minadbd/adb.h"
#include "../adb_install.h"
+#include "../set_metadata.h"
int TWinstall_zip(const char* path, int* wipe_cache);
void run_script(const char *str1, const char *str2, const char *str3, const char *str4, const char *str5, const char *str6, const char *str7, int request_confirm);
@@ -503,6 +504,7 @@
PartitionManager.Mount_Current_Storage(true);
dst = DataManager::GetCurrentStoragePath() + "/recovery.log";
TWFunc::copy_file("/tmp/recovery.log", dst.c_str(), 0755);
+ tw_set_default_metadata(dst.c_str());
sync();
gui_print("Copied recovery log to %s.\n", DataManager::GetCurrentStoragePath().c_str());
} else
@@ -1222,6 +1224,12 @@
int check = 0;
std::string theme_path;
+ if (tw_get_default_metadata(DataManager::GetSettingsStoragePath().c_str()) != 0) {
+ LOGERR("Failed to get default contexts and file mode for storage files.\n");
+ } else {
+ LOGINFO("Got default contexts and file mode for storage files.\n");
+ }
+
theme_path = DataManager::GetSettingsStoragePath();
if (PartitionManager.Mount_By_Path(theme_path.c_str(), 1) < 0) {
LOGERR("Unable to mount %s during reload function startup.\n", theme_path.c_str());
diff --git a/infomanager.cpp b/infomanager.cpp
index 080fe1d..864c431 100644
--- a/infomanager.cpp
+++ b/infomanager.cpp
@@ -39,6 +39,7 @@
#include "infomanager.hpp"
#include "twcommon.h"
#include "partitions.hpp"
+#include "set_metadata.h"
using namespace std;
@@ -97,7 +98,7 @@
return -1;
PartitionManager.Mount_By_Path(File, true);
-LOGINFO("InfoManager saving '%s'\n", File.c_str());
+ LOGINFO("InfoManager saving '%s'\n", File.c_str());
FILE* out = fopen(File.c_str(), "wb");
if (!out)
return -1;
@@ -112,6 +113,7 @@
fwrite(iter->second.c_str(), 1, length, out);
}
fclose(out);
+ tw_set_default_metadata(File.c_str());
return 0;
}
diff --git a/mtp/Android.mk b/mtp/Android.mk
index 809a29a..283a283 100755
--- a/mtp/Android.mk
+++ b/mtp/Android.mk
@@ -29,7 +29,7 @@
twrpMtp.cpp \
mtp_MtpDatabase.cpp \
node.cpp
-LOCAL_SHARED_LIBRARIES += libz libc libusbhost libstdc++ libstlport libdl libcutils libutils
+LOCAL_SHARED_LIBRARIES += libz libc libusbhost libstdc++ libstlport libdl libcutils libutils libaosprecovery
ifneq ($(TW_MTP_DEVICE),)
LOCAL_CFLAGS += -DUSB_MTP_DEVICE=$(TW_MTP_DEVICE)
@@ -66,5 +66,5 @@
twrpMtp.cpp \
mtp_MtpDatabase.cpp \
node.cpp
-LOCAL_SHARED_LIBRARIES += libz libc libusbhost libstdc++ libstlport libdl libcutils libutils
+LOCAL_SHARED_LIBRARIES += libz libc libusbhost libstdc++ libstlport libdl libcutils libutils libaosprecovery
include $(BUILD_EXECUTABLE)
diff --git a/mtp/MtpServer.cpp b/mtp/MtpServer.cpp
index 66a6414..f4af2b9 100755
--- a/mtp/MtpServer.cpp
+++ b/mtp/MtpServer.cpp
@@ -26,6 +26,7 @@
#include <sys/stat.h>
#include <dirent.h>
#include "../twcommon.h"
+#include "../set_metadata.h"
#include <cutils/properties.h>
#include "MtpTypes.h"
@@ -1002,6 +1003,7 @@
return MTP_RESPONSE_GENERAL_ERROR;
}
chown((const char *)path, getuid(), mFileGroup);
+ tw_set_default_metadata((const char *)path);
// SendObject does not get sent for directories, so call endSendObject here instead
mDatabase->lockMutex();
@@ -1073,6 +1075,7 @@
ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
}
close(mfr.fd);
+ tw_set_default_metadata((const char *)mSendObjectFilePath);
if (ret < 0) {
unlink(mSendObjectFilePath);
diff --git a/partition.cpp b/partition.cpp
index d84e48f..b3c436f 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -42,6 +42,7 @@
#include "twrpDU.hpp"
#include "fixPermissions.hpp"
#include "infomanager.hpp"
+#include "set_metadata.h"
extern "C" {
#include "mtdutils/mtdutils.h"
#include "mtdutils/mounts.h"
@@ -1748,6 +1749,7 @@
Command = "dd if=" + Actual_Block_Device + " of='" + Full_FileName + "'" + " bs=" + DD_BS + " count=1";
LOGINFO("Backup command: '%s'\n", Command.c_str());
TWFunc::Exec_Cmd(Command);
+ tw_set_default_metadata(Full_FileName.c_str());
if (TWFunc::Get_File_Size(Full_FileName) == 0) {
LOGERR("Backup file size for '%s' is 0 bytes.\n", Full_FileName.c_str());
return false;
@@ -1771,6 +1773,7 @@
Command = "dump_image " + MTD_Name + " '" + Full_FileName + "'";
LOGINFO("Backup command: '%s'\n", Command.c_str());
TWFunc::Exec_Cmd(Command);
+ tw_set_default_metadata(Full_FileName.c_str());
if (TWFunc::Get_File_Size(Full_FileName) == 0) {
// Actual size may not match backup size due to bad blocks on MTD devices so just check for 0 bytes
LOGERR("Backup file size for '%s' is 0 bytes.\n", Full_FileName.c_str());
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index 437ed2f..92b2875 100644
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -38,6 +38,7 @@
#include "fixPermissions.hpp"
#include "twrpDigest.hpp"
#include "twrpDU.hpp"
+#include "set_metadata.h"
#ifdef TW_HAS_MTP
#include "mtp/mtp_MtpServer.hpp"
@@ -757,6 +758,7 @@
gui_print_color("highlight", "[BACKUP COMPLETED IN %d SECONDS]\n\n", total_time); // the end
string backup_log = Full_Backup_Path + "recovery.log";
TWFunc::copy_file("/tmp/recovery.log", backup_log, 0644);
+ tw_set_default_metadata(backup_log.c_str());
return true;
}
diff --git a/set_metadata.c b/set_metadata.c
new file mode 100644
index 0000000..f4e0de2
--- /dev/null
+++ b/set_metadata.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 The Team Win Recovery Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The purpose of these functions is to try to get and set the proper
+ * file permissions, SELinux contexts, owner, and group so that these
+ * files are accessible when we boot up to normal Android via MTP and to
+ * file manager apps. During early boot we try to read the contexts and
+ * owner / group info from /data/media or from /data/media/0 and store
+ * them in static variables. From there, we'll try to set the same
+ * contexts, owner, and group information on most files we create during
+ * operations like backups, copying the log, and MTP operations.
+ */
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "selinux/selinux.h"
+
+static security_context_t selinux_context;
+struct stat s;
+static int has_stat = 0;
+
+int tw_get_context(const char* filename) {
+ if (lgetfilecon(filename, &selinux_context) >= 0) {
+ printf("tw_get_context got selinux context: %s\n", selinux_context);
+ return 0;
+ } else {
+ printf("tw_get_context failed to get selinux context");
+ selinux_context = NULL;
+ }
+ return -1;
+}
+
+int tw_get_stat(const char* filename) {
+ if (lstat(filename, &s) == 0) {
+ has_stat = 1;
+ return 0;
+ }
+ printf("tw_get_stat failed to lstat '%s'\n", filename);
+ return -1;
+}
+
+int tw_get_default_metadata(const char* filename) {
+ if (tw_get_context(filename) == 0 && tw_get_stat(filename) == 0)
+ return 0;
+ return -1;
+}
+
+// Most of this logging is disabled to prevent log spam if we are trying
+// to set contexts and permissions on file systems that do not support
+// these types of things (e.g. vfat / FAT / FAT32).
+int tw_set_default_metadata(const char* filename) {
+ int ret = 0;
+ struct stat st;
+
+ if (selinux_context == NULL) {
+ //printf("selinux_context was null, '%s'\n", filename);
+ ret = -1;
+ } else if (lsetfilecon(filename, selinux_context) < 0) {
+ //printf("Failed to set default contexts on '%s'.\n", filename);
+ ret = -1;
+ }
+
+ if (lstat(filename, &st) == 0 && st.st_mode & S_IFREG && chmod(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) < 0) {
+ //printf("Failed to chmod '%s'\n", filename);
+ ret = -1;
+ }
+
+ if (has_stat && chown(filename, s.st_uid, s.st_gid) < 0) {
+ //printf("Failed to lchown '%s'.\n", filename);
+ ret = -1;
+ }
+ //printf("Done trying to set defaults on '%s'\n");
+ return ret;
+}
diff --git a/set_metadata.h b/set_metadata.h
new file mode 100644
index 0000000..835c31c
--- /dev/null
+++ b/set_metadata.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014 The Team Win Recovery Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The purpose of these functions is to try to get and set the proper
+ * file permissions, SELinux contexts, owner, and group so that these
+ * files are accessible when we boot up to normal Android via MTP and to
+ * file manager apps. During early boot we try to read the contexts and
+ * owner / group info from /data/media or from /data/media/0 and store
+ * them in static variables. From there, we'll try to set the same
+ * contexts, owner, and group information on most files we create during
+ * operations like backups, copying the log, and MTP operations.
+ */
+
+#ifndef _RECOVERY_SET_CONTEXTS_H
+#define _RECOVERY_SET_CONTEXTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/stat.h>
+#include "selinux/selinux.h"
+
+int tw_get_default_metadata(const char* filename);
+int tw_set_default_metadata(const char* filename);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_RECOVERY_SET_CONTEXTS_H
diff --git a/twrp-functions.cpp b/twrp-functions.cpp
index 9611424..b51024c 100644
--- a/twrp-functions.cpp
+++ b/twrp-functions.cpp
@@ -54,6 +54,7 @@
extern "C" {
#include "libcrecovery/common.h"
+ #include "set_metadata.h"
}
/* Execute a command */
@@ -406,9 +407,13 @@
while (pos != string::npos)
{
wholePath = pathCpy.substr(0, pos);
- if (mkdir(wholePath.c_str(), 0777) && errno != EEXIST) {
- LOGERR("Unable to create folder: %s (errno=%d)\n", wholePath.c_str(), errno);
- return false;
+ if (!TWFunc::Path_Exists(wholePath)) {
+ if (mkdir(wholePath.c_str(), 0777)) {
+ LOGERR("Unable to create folder: %s (errno=%d)\n", wholePath.c_str(), errno);
+ return false;
+ } else {
+ tw_set_default_metadata(wholePath.c_str());
+ }
}
pos = pathCpy.find("/", pos + 1);
diff --git a/twrp.cpp b/twrp.cpp
index a633bec..f76ab64 100644
--- a/twrp.cpp
+++ b/twrp.cpp
@@ -35,6 +35,7 @@
extern "C" {
#include "gui/gui.h"
+#include "set_metadata.h"
}
#include "twcommon.h"
#include "twrp-functions.hpp"
@@ -274,6 +275,12 @@
if (gui_startPage("decrypt") != 0) {
LOGERR("Failed to start decrypt GUI page.\n");
}
+ } else if (datamedia) {
+ if (tw_get_default_metadata(DataManager::GetSettingsStoragePath().c_str()) != 0) {
+ LOGERR("Failed to get default contexts and file mode for storage files.\n");
+ } else {
+ LOGINFO("Got default contexts and file mode for storage files.\n");
+ }
}
// Read the settings file
diff --git a/twrpDigest.cpp b/twrpDigest.cpp
index 0693c55..c3cff71 100644
--- a/twrpDigest.cpp
+++ b/twrpDigest.cpp
@@ -40,6 +40,7 @@
#include "variables.h"
#include "twrp-functions.hpp"
#include "twrpDigest.hpp"
+#include "set_metadata.h"
using namespace std;
@@ -79,6 +80,7 @@
md5string += basename((char*) md5fn.c_str());
md5string += + "\n";
TWFunc::write_file(md5file, md5string);
+ tw_set_default_metadata(md5file.c_str());
LOGINFO("MD5 for %s: %s\n", md5fn.c_str(), md5string.c_str());
return 0;
}
diff --git a/twrpTar.cpp b/twrpTar.cpp
index b5d66d3..968b6b9 100644
--- a/twrpTar.cpp
+++ b/twrpTar.cpp
@@ -21,6 +21,7 @@
#include "libtar/libtar.h"
#include "twrpTar.h"
#include "tarWrite.h"
+ #include "set_metadata.h"
}
#include <sys/types.h>
#include <sys/stat.h>
@@ -1242,6 +1243,7 @@
LOGERR("Backup file size for '%s' is 0 bytes.\n", tarfn.c_str());
return -1;
}
+ tw_set_default_metadata(tarfn.c_str());
return 0;
}