Ffangzhiyi18路径校验
bd33031f创建于 2024年10月29日历史提交
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;
                     }
                 }