third_party_e2fsprogs/1003-add-dac-config.patch
fangzhiyi18 bd33031fc2 路径校验
Signed-off-by: fangzhiyi18 <fangzhiyi1@huawei.com>
2024-10-29 03:27:11 +00:00

405 lines
12 KiB
Diff

diff --git a/contrib/android/dac_config.cpp b/contrib/android/dac_config.cpp
new file mode 100644
index 00000000..422e0d52
--- /dev/null
+++ b/contrib/android/dac_config.cpp
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
+ * This program 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; version 2.
+ *
+ * This program 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
+ * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
+ * Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#define __cpluscplus
+#include "dac_config.h"
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+#include <vector>
+#include <linux/capability.h>
+#include <limits.h>
+
+using namespace std;
+
+namespace {
+struct DacConfig {
+ unsigned int uid;
+ unsigned int gid;
+ unsigned int mode;
+ uint64_t capabilities;
+ string path;
+
+ DacConfig() : uid(0), gid(0), mode(0), capabilities(0), path("") {}
+ DacConfig(unsigned int m, unsigned int u, unsigned int g, uint64_t c, string p) :
+ uid(u),
+ gid(g),
+ mode(m),
+ capabilities(c),
+ path(p) {}
+
+ void SetDefault(unsigned int m, unsigned int u, unsigned int g, uint64_t c, string p)
+ {
+ this->uid = u;
+ this->gid = g;
+ this->mode = m;
+ this->capabilities = c;
+ this->path = p;
+ }
+};
+
+unordered_map<string, DacConfig> g_configMap;
+
+static string Trim(const string& s)
+{
+ if (s.size() == 0) {
+ return s;
+ }
+
+ size_t start = 0;
+ size_t end = s.size() - 1;
+
+ while (start < s.size() && isspace(s[start])) {
+ start++;
+ }
+
+ while (end >= start && isspace(s[end])) {
+ end--;
+ }
+
+ if (end < start) {
+ return "";
+ }
+
+ return s.substr(start, end - start + 1);
+}
+
+unordered_map<string, unsigned int> g_capStrCapNum = {
+ { "CAP_CHOWN", CAP_CHOWN },
+ { "CAP_DAC_OVERRIDE", CAP_DAC_OVERRIDE },
+ { "CAP_DAC_READ_SEARCH", CAP_DAC_READ_SEARCH },
+ { "CAP_FOWNER", CAP_FOWNER },
+ { "CAP_FSETID", CAP_FSETID },
+ { "CAP_KILL", CAP_KILL },
+ { "CAP_SETGID", CAP_SETGID },
+ { "CAP_SETUID", CAP_SETUID },
+ { "CAP_LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE },
+ { "CAP_NET_BIND_SERVICE", CAP_NET_BIND_SERVICE },
+ { "CAP_NET_BROADCAST", CAP_NET_BROADCAST },
+ { "CAP_NET_ADMIN", CAP_NET_ADMIN },
+ { "CAP_NET_RAW", CAP_NET_RAW },
+ { "CAP_IPC_LOCK", CAP_IPC_LOCK },
+ { "CAP_IPC_OWNER", CAP_IPC_OWNER },
+ { "CAP_SYS_MODULE", CAP_SYS_MODULE },
+ { "CAP_SYS_RAWIO", CAP_SYS_RAWIO },
+ { "CAP_SYS_CHROOT", CAP_SYS_CHROOT },
+ { "CAP_SYS_PTRACE", CAP_SYS_PTRACE },
+ { "CAP_SYS_PACCT", CAP_SYS_PACCT },
+ { "CAP_SYS_ADMIN", CAP_SYS_ADMIN },
+ { "CAP_SYS_ROOT", CAP_SYS_BOOT },
+ { "CAP_SYS_NICE", CAP_SYS_NICE },
+ { "CAP_SYS_RESOURCE", CAP_SYS_RESOURCE },
+ { "CAP_SYS_TIME", CAP_SYS_TIME },
+ { "CAP_SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG },
+ { "CAP_MKNOD", CAP_MKNOD },
+ { "CAP_LEASE", CAP_LEASE },
+ { "CAP_AUDIT_WRITE", CAP_AUDIT_WRITE },
+ { "CAP_AUDIT_CONTROL", CAP_AUDIT_CONTROL },
+ { "CAP_SETFCAP", CAP_SETFCAP },
+ { "CAP_MAC_OVERRIDE", CAP_MAC_OVERRIDE },
+ { "CAP_MAC_ADMIN", CAP_MAC_ADMIN },
+ { "CAP_SYSLOG", CAP_SYSLOG },
+ { "CAP_WAKE_ALARM", CAP_WAKE_ALARM },
+ { "CAP_BLOCK_SUSPEND", CAP_BLOCK_SUSPEND },
+};
+
+static uint64_t GetCap(string cap)
+{
+ if (isdigit(cap[0])) {
+ return stoll(cap);
+ }
+
+ stringstream ss(cap);
+ string value;
+ uint64_t c = 0;
+ while (getline(ss, value, '|')) {
+ value = Trim(value);
+ if (g_capStrCapNum.count(value)) {
+ c |= (1ULL << g_capStrCapNum[value]);
+ }
+ }
+
+ return c;
+}
+
+enum {
+ DAC_PATH_IDX = 0,
+ DAC_MODE_IDX,
+ DAC_UID_IDX,
+ DAC_GID_IDX,
+ DAC_CAP_IDX,
+ DAC_NUM
+};
+
+extern "C" {
+ int LoadDacConfig(const char* fn)
+ {
+ char resolvedPath[PATH_MAX] = {'\0'};
+ char *canonicalPath = realpath(fn, resolvedPath);
+ if (canonicalPath == nullptr) {
+ return -1;
+ }
+ ifstream readFile(canonicalPath);
+ if (readFile.fail()) {
+ return -1;
+ }
+
+ string str;
+ vector<string> values(DAC_NUM, ""); // path, mode, uid, gid, cap
+ while (getline(readFile, str)) {
+ str = Trim(str);
+ if (str.empty() || str[0] == '#') {
+ continue;
+ }
+
+ stringstream ss(str);
+ string value;
+ int i = 0;
+ while (getline(ss, value, ',')) {
+ if (i >= DAC_NUM) {
+ break;
+ }
+
+ value = Trim(value);
+ if (value.empty()) {
+ continue;
+ }
+ values[i++] = value;
+ }
+
+ if (i != DAC_NUM) {
+ continue;
+ }
+
+ int uid = 0;
+ if (isdigit(values[DAC_UID_IDX][0])) {
+ uid = stoi(values[DAC_UID_IDX]);
+ }
+
+ int gid = 0;
+ if (isdigit(values[DAC_GID_IDX][0])) {
+ gid = stoi(values[DAC_GID_IDX]);
+ }
+
+ uint64_t cap = GetCap(values[DAC_CAP_IDX]);
+ DacConfig dacConfig(stoi(values[DAC_MODE_IDX], 0, 8), uid, gid, cap, values[DAC_PATH_IDX]); // 8 oct
+ g_configMap[dacConfig.path] = dacConfig;
+ }
+
+ return 0;
+ }
+
+ void GetDacConfig(const char* path, int dir, char* targetOutPath,
+ unsigned* uid, unsigned* gid, unsigned* mode,
+ uint64_t* capabilities)
+ {
+ if (path && path[0] == '/') {
+ path++;
+ }
+
+ (void)targetOutPath;
+ string str = path;
+ string str2;
+ DacConfig dacConfig(00755, 0, 0, 0, "");
+
+ if (dir == 0) {
+ dacConfig.SetDefault(00644, 0, 0, 0, "");
+ }
+
+ if (g_configMap.count(str)) {
+ dacConfig = g_configMap[str];
+ } else if (dir == 0 && !str.empty()) {
+ for (auto i = str.size() - 1; i >= 0; i--) {
+ if (str[i] == '/') {
+ break;
+ } else {
+ str2 = str.substr(0, i) + "*";
+ if (g_configMap.count(str2)) {
+ dacConfig = g_configMap[str2];
+ break;
+ }
+ }
+ }
+ }
+
+ *uid = dacConfig.uid;
+ *gid = dacConfig.gid;
+ *mode = dacConfig.mode;
+ *capabilities = dacConfig.capabilities;
+ }
+}
+}
diff --git a/contrib/android/dac_config.h b/contrib/android/dac_config.h
new file mode 100644
index 00000000..45b89393
--- /dev/null
+++ b/contrib/android/dac_config.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
+ * This program 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; version 2.
+ *
+ * This program 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
+ * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
+ * Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __DAC_CONFIG
+#define __DAC_CONFIG
+#include <stdint.h>
+
+#ifdef __cpluscplus
+extern "C" {
+#endif
+
+int LoadDacConfig(const char* fn);
+void GetDacConfig(const char* path, int dir, char* targetOutPath,
+ unsigned* uid, unsigned* gid, unsigned* mode,
+ uint64_t* capabilities);
+
+#ifdef __cpluscplus
+}
+#endif
+#endif
diff --git a/contrib/android/perms.c b/contrib/android/perms.c
index 9c5ec05b..680d348e 100644
--- a/contrib/android/perms.c
+++ b/contrib/android/perms.c
@@ -358,16 +358,25 @@ errcode_t android_configure_fs(ext2_filsys fs, char *src_dir, char *target_out,
/* Load the FS config */
if (fs_config_file) {
+#if defined(__ANDROID__)
retval = load_canned_fs_config(fs_config_file);
+#else
+ retval = LoadDacConfig(fs_config_file);
+#endif
if (retval < 0) {
com_err(__func__, retval,
_("while loading fs_config \"%s\""),
fs_config_file);
return retval;
}
+#if defined(__ANDROID__)
fs_config_func = canned_fs_config;
} else if (mountpoint)
fs_config_func = fs_config;
+#else
+ fs_config_func = GetDacConfig;
+ }
+#endif
return __android_configure_fs(fs, src_dir, target_out, mountpoint,
fs_config_func, sehnd, fixed_time,
diff --git a/contrib/android/perms.h b/contrib/android/perms.h
index 6d6a2129..2bb0021f 100644
--- a/contrib/android/perms.h
+++ b/contrib/android/perms.h
@@ -48,11 +48,12 @@ static inline errcode_t android_configure_fs(ext2_filsys fs,
# include <selinux/label.h>
# if defined(__ANDROID__)
# include <selinux/android.h>
-# endif
# include <private/android_filesystem_config.h>
# include <private/canned_fs_config.h>
# include <private/fs_config.h>
-
+# else /* !__ANDROID__ */
+#include "dac_config.h"
+# endif
errcode_t android_configure_fs(ext2_filsys fs, char *src_dir,
char *target_out,
char *mountpoint,
--
diff --git a/contrib/android/dac_config.cpp b/contrib/android/dac_config.cpp
index 422e0d52280ff4f142b278c5fedb04790846b9ee..1c76dfd7e7d1b067941b79e73311144d548a3179 100644
--- a/contrib/android/dac_config.cpp
+++ b/contrib/android/dac_config.cpp
@@ -35,14 +35,14 @@ struct DacConfig {
string path;
DacConfig() : uid(0), gid(0), mode(0), capabilities(0), path("") {}
- DacConfig(unsigned int m, unsigned int u, unsigned int g, uint64_t c, string p) :
+ DacConfig(unsigned int m, unsigned int u, unsigned int g, uint64_t c, const string &p) :
uid(u),
gid(g),
mode(m),
capabilities(c),
path(p) {}
- void SetDefault(unsigned int m, unsigned int u, unsigned int g, uint64_t c, string p)
+ void SetDefault(unsigned int m, unsigned int u, unsigned int g, uint64_t c, const string &p)
{
this->uid = u;
this->gid = g;
@@ -198,33 +198,28 @@ extern "C" {
return 0;
}
- void GetDacConfig(const char* path, int dir, char* targetOutPath,
+ void GetDacConfig(const char* path, int dir, char*,
unsigned* uid, unsigned* gid, unsigned* mode,
uint64_t* capabilities)
{
- if (path && path[0] == '/') {
- path++;
- }
-
- (void)targetOutPath;
- string str = path;
- string str2;
+ string str = (path != nullptr && *path == '/') ? path + 1 : path;
DacConfig dacConfig(00755, 0, 0, 0, "");
if (dir == 0) {
dacConfig.SetDefault(00644, 0, 0, 0, "");
}
- if (g_configMap.count(str)) {
- dacConfig = g_configMap[str];
+ auto it = g_configMap.find(str);
+ if (it != g_configMap.end()) {
+ dacConfig = it->second;
} else if (dir == 0 && !str.empty()) {
- for (auto i = str.size() - 1; i >= 0; i--) {
+ for (int i = static_cast<int>(str.size()) - 1; i >= 0; i--) {
if (str[i] == '/') {
break;
} else {
- str2 = str.substr(0, i) + "*";
- if (g_configMap.count(str2)) {
- dacConfig = g_configMap[str2];
+ it = g_configMap.find(str.substr(0, i) + "*");
+ if (it != g_configMap.end()) {
+ dacConfig = it->second;
break;
}
}