idmap2: lock down write access to /data/resouce-cache
Deny write access to /data/resource-cache for UIDs other than root and
system. While this is already handled by SELinux rules, add an
additional layer of security to explicitly prevent malicious apps from
messing with the system's idmap files.
Test: make idmap2_tests
Change-Id: Id986633558d5d02452276f05f64337a8700f148a
diff --git a/cmds/idmap2/libidmap2/FileUtils.cpp b/cmds/idmap2/libidmap2/FileUtils.cpp
index 0255727..a9b68cd 100644
--- a/cmds/idmap2/libidmap2/FileUtils.cpp
+++ b/cmds/idmap2/libidmap2/FileUtils.cpp
@@ -19,12 +19,20 @@
#include <unistd.h>
#include <cerrno>
+#include <climits>
+#include <cstdlib>
+#include <cstring>
#include <fstream>
#include <memory>
#include <string>
#include <utility>
#include <vector>
+#include "android-base/file.h"
+#include "android-base/macros.h"
+#include "android-base/stringprintf.h"
+#include "private/android_filesystem_config.h"
+
#include "idmap2/FileUtils.h"
namespace android::idmap2::utils {
@@ -77,4 +85,26 @@
return r == 0 ? std::move(str) : nullptr;
}
+#ifdef __ANDROID__
+bool UidHasWriteAccessToPath(uid_t uid, const std::string& path) {
+ // resolve symlinks and relative paths; the directories must exist
+ std::string canonical_path;
+ if (!base::Realpath(base::Dirname(path), &canonical_path)) {
+ return false;
+ }
+
+ const std::string cache_subdir = base::StringPrintf("%s/", kIdmapCacheDir);
+ if (canonical_path == kIdmapCacheDir ||
+ canonical_path.compare(0, cache_subdir.size(), cache_subdir) == 0) {
+ // limit access to /data/resource-cache to root and system
+ return uid == AID_ROOT || uid == AID_SYSTEM;
+ }
+ return true;
+}
+#else
+bool UidHasWriteAccessToPath(uid_t uid ATTRIBUTE_UNUSED, const std::string& path ATTRIBUTE_UNUSED) {
+ return true;
+}
+#endif
+
} // namespace android::idmap2::utils