• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff --git a/contrib/android/dac_config.cpp b/contrib/android/dac_config.cpp
2new file mode 100644
3index 00000000..422e0d52
4--- /dev/null
5+++ b/contrib/android/dac_config.cpp
6@@ -0,0 +1,246 @@
7+/*
8+ * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
9+ * This program is free software; you can redistribute it and/or modify
10+ * it under the terms of the GNU General Public License as published by
11+ * the Free Software Foundation; version 2.
12+ *
13+ * This program is distributed in the hope that it will be useful, but WITHOUT
14+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU General Public License along with
18+ * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
19+ * Street, Fifth Floor, Boston, MA 02110-1301, USA.
20+ */
21+
22+#define __cpluscplus
23+#include "dac_config.h"
24+
25+#include <fstream>
26+#include <iostream>
27+#include <sstream>
28+#include <string>
29+#include <unordered_map>
30+#include <vector>
31+#include <linux/capability.h>
32+#include <limits.h>
33+
34+using namespace std;
35+
36+namespace {
37+struct DacConfig {
38+    unsigned int uid;
39+    unsigned int gid;
40+    unsigned int mode;
41+    uint64_t capabilities;
42+    string path;
43+
44+    DacConfig() : uid(0), gid(0), mode(0), capabilities(0), path("") {}
45+    DacConfig(unsigned int m, unsigned int u, unsigned int g, uint64_t c, string p) :
46+        uid(u),
47+        gid(g),
48+        mode(m),
49+        capabilities(c),
50+        path(p) {}
51+
52+    void SetDefault(unsigned int m, unsigned int u, unsigned int g, uint64_t c, string p)
53+    {
54+        this->uid = u;
55+        this->gid = g;
56+        this->mode = m;
57+        this->capabilities = c;
58+        this->path = p;
59+    }
60+};
61+
62+unordered_map<string, DacConfig> g_configMap;
63+
64+static string Trim(const string& s)
65+{
66+    if (s.size() == 0) {
67+        return s;
68+    }
69+
70+    size_t start = 0;
71+    size_t end = s.size() - 1;
72+
73+    while (start < s.size() && isspace(s[start])) {
74+        start++;
75+    }
76+
77+    while (end >= start && isspace(s[end])) {
78+        end--;
79+    }
80+
81+    if (end < start) {
82+        return "";
83+    }
84+
85+    return s.substr(start, end - start + 1);
86+}
87+
88+unordered_map<string, unsigned int> g_capStrCapNum = {
89+    { "CAP_CHOWN", CAP_CHOWN },
90+    { "CAP_DAC_OVERRIDE", CAP_DAC_OVERRIDE },
91+    { "CAP_DAC_READ_SEARCH", CAP_DAC_READ_SEARCH },
92+    { "CAP_FOWNER", CAP_FOWNER },
93+    { "CAP_FSETID", CAP_FSETID },
94+    { "CAP_KILL", CAP_KILL },
95+    { "CAP_SETGID", CAP_SETGID },
96+    { "CAP_SETUID", CAP_SETUID },
97+    { "CAP_LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE },
98+    { "CAP_NET_BIND_SERVICE", CAP_NET_BIND_SERVICE },
99+    { "CAP_NET_BROADCAST", CAP_NET_BROADCAST },
100+    { "CAP_NET_ADMIN", CAP_NET_ADMIN },
101+    { "CAP_NET_RAW", CAP_NET_RAW },
102+    { "CAP_IPC_LOCK", CAP_IPC_LOCK },
103+    { "CAP_IPC_OWNER", CAP_IPC_OWNER },
104+    { "CAP_SYS_MODULE", CAP_SYS_MODULE },
105+    { "CAP_SYS_RAWIO", CAP_SYS_RAWIO },
106+    { "CAP_SYS_CHROOT", CAP_SYS_CHROOT },
107+    { "CAP_SYS_PTRACE", CAP_SYS_PTRACE },
108+    { "CAP_SYS_PACCT", CAP_SYS_PACCT },
109+    { "CAP_SYS_ADMIN", CAP_SYS_ADMIN },
110+    { "CAP_SYS_ROOT", CAP_SYS_BOOT },
111+    { "CAP_SYS_NICE", CAP_SYS_NICE },
112+    { "CAP_SYS_RESOURCE", CAP_SYS_RESOURCE },
113+    { "CAP_SYS_TIME", CAP_SYS_TIME },
114+    { "CAP_SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG },
115+    { "CAP_MKNOD", CAP_MKNOD },
116+    { "CAP_LEASE", CAP_LEASE },
117+    { "CAP_AUDIT_WRITE", CAP_AUDIT_WRITE },
118+    { "CAP_AUDIT_CONTROL", CAP_AUDIT_CONTROL },
119+    { "CAP_SETFCAP", CAP_SETFCAP },
120+    { "CAP_MAC_OVERRIDE", CAP_MAC_OVERRIDE },
121+    { "CAP_MAC_ADMIN", CAP_MAC_ADMIN },
122+    { "CAP_SYSLOG", CAP_SYSLOG },
123+    { "CAP_WAKE_ALARM", CAP_WAKE_ALARM },
124+    { "CAP_BLOCK_SUSPEND", CAP_BLOCK_SUSPEND },
125+};
126+
127+static uint64_t GetCap(string cap)
128+{
129+    if (isdigit(cap[0])) {
130+        return stoll(cap);
131+    }
132+
133+    stringstream ss(cap);
134+    string value;
135+    uint64_t c = 0;
136+    while (getline(ss, value, '|')) {
137+        value = Trim(value);
138+        if (g_capStrCapNum.count(value)) {
139+            c |= (1ULL << g_capStrCapNum[value]);
140+        }
141+    }
142+
143+    return c;
144+}
145+
146+enum {
147+    DAC_PATH_IDX = 0,
148+    DAC_MODE_IDX,
149+    DAC_UID_IDX,
150+    DAC_GID_IDX,
151+    DAC_CAP_IDX,
152+    DAC_NUM
153+};
154+
155+extern "C" {
156+    int LoadDacConfig(const char* fn)
157+    {
158+        char resolvedPath[PATH_MAX] = {'\0'};
159+        char *canonicalPath = realpath(fn, resolvedPath);
160+        if (canonicalPath == nullptr) {
161+           return -1;
162+        }
163+        ifstream readFile(canonicalPath);
164+        if (readFile.fail()) {
165+            return -1;
166+        }
167+
168+        string str;
169+        vector<string> values(DAC_NUM, ""); // path, mode, uid, gid, cap
170+        while (getline(readFile, str)) {
171+            str = Trim(str);
172+            if (str.empty() || str[0] == '#') {
173+                continue;
174+            }
175+
176+            stringstream ss(str);
177+            string value;
178+            int i = 0;
179+            while (getline(ss, value, ',')) {
180+                if (i >= DAC_NUM) {
181+                    break;
182+                }
183+
184+                value = Trim(value);
185+                if (value.empty()) {
186+                    continue;
187+                }
188+                values[i++] = value;
189+            }
190+
191+            if (i != DAC_NUM) {
192+                continue;
193+            }
194+
195+            int uid = 0;
196+            if (isdigit(values[DAC_UID_IDX][0])) {
197+                uid = stoi(values[DAC_UID_IDX]);
198+            }
199+
200+            int gid = 0;
201+            if (isdigit(values[DAC_GID_IDX][0])) {
202+                gid = stoi(values[DAC_GID_IDX]);
203+            }
204+
205+            uint64_t cap = GetCap(values[DAC_CAP_IDX]);
206+            DacConfig dacConfig(stoi(values[DAC_MODE_IDX], 0, 8), uid, gid, cap, values[DAC_PATH_IDX]); // 8 oct
207+            g_configMap[dacConfig.path] = dacConfig;
208+        }
209+
210+        return 0;
211+    }
212+
213+    void GetDacConfig(const char* path, int dir, char* targetOutPath,
214+            unsigned* uid, unsigned* gid, unsigned* mode,
215+            uint64_t* capabilities)
216+    {
217+        if (path && path[0] == '/') {
218+            path++;
219+        }
220+
221+        (void)targetOutPath;
222+        string str = path;
223+        string str2;
224+        DacConfig dacConfig(00755, 0, 0, 0, "");
225+
226+        if (dir == 0) {
227+            dacConfig.SetDefault(00644, 0, 0, 0, "");
228+        }
229+
230+        if (g_configMap.count(str)) {
231+            dacConfig = g_configMap[str];
232+        } else if (dir == 0 && !str.empty()) {
233+            for (auto i = str.size() - 1; i >= 0; i--) {
234+                if (str[i] == '/') {
235+                    break;
236+                } else {
237+                    str2 = str.substr(0, i) + "*";
238+                    if (g_configMap.count(str2)) {
239+                        dacConfig = g_configMap[str2];
240+                        break;
241+                    }
242+                }
243+            }
244+        }
245+
246+        *uid = dacConfig.uid;
247+        *gid = dacConfig.gid;
248+        *mode = dacConfig.mode;
249+        *capabilities = dacConfig.capabilities;
250+    }
251+}
252+}
253diff --git a/contrib/android/dac_config.h b/contrib/android/dac_config.h
254new file mode 100644
255index 00000000..45b89393
256--- /dev/null
257+++ b/contrib/android/dac_config.h
258@@ -0,0 +1,32 @@
259+/*
260+ * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
261+ * This program is free software; you can redistribute it and/or modify
262+ * it under the terms of the GNU General Public License as published by
263+ * the Free Software Foundation; version 2.
264+ *
265+ * This program is distributed in the hope that it will be useful, but WITHOUT
266+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
267+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
268+ *
269+ * You should have received a copy of the GNU General Public License along with
270+ * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
271+ * Street, Fifth Floor, Boston, MA 02110-1301, USA.
272+ */
273+
274+#ifndef __DAC_CONFIG
275+#define __DAC_CONFIG
276+#include <stdint.h>
277+
278+#ifdef __cpluscplus
279+extern "C" {
280+#endif
281+
282+int LoadDacConfig(const char* fn);
283+void GetDacConfig(const char* path, int dir, char* targetOutPath,
284+        unsigned* uid, unsigned* gid, unsigned* mode,
285+        uint64_t* capabilities);
286+
287+#ifdef __cpluscplus
288+}
289+#endif
290+#endif
291diff --git a/contrib/android/perms.c b/contrib/android/perms.c
292index 9c5ec05b..680d348e 100644
293--- a/contrib/android/perms.c
294+++ b/contrib/android/perms.c
295@@ -358,16 +358,25 @@ errcode_t android_configure_fs(ext2_filsys fs, char *src_dir, char *target_out,
296
297 	/* Load the FS config */
298 	if (fs_config_file) {
299+#if defined(__ANDROID__)
300 		retval = load_canned_fs_config(fs_config_file);
301+#else
302+		retval = LoadDacConfig(fs_config_file);
303+#endif
304 		if (retval < 0) {
305 			com_err(__func__, retval,
306 				_("while loading fs_config \"%s\""),
307 				fs_config_file);
308 			return retval;
309 		}
310+#if defined(__ANDROID__)
311 		fs_config_func = canned_fs_config;
312 	} else if (mountpoint)
313 		fs_config_func = fs_config;
314+#else
315+		fs_config_func = GetDacConfig;
316+	}
317+#endif
318
319 	return __android_configure_fs(fs, src_dir, target_out, mountpoint,
320 				      fs_config_func, sehnd, fixed_time,
321diff --git a/contrib/android/perms.h b/contrib/android/perms.h
322index 6d6a2129..2bb0021f 100644
323--- a/contrib/android/perms.h
324+++ b/contrib/android/perms.h
325@@ -48,11 +48,12 @@ static inline errcode_t android_configure_fs(ext2_filsys fs,
326 #  include <selinux/label.h>
327 #  if defined(__ANDROID__)
328 #   include <selinux/android.h>
329-#  endif
330 #  include <private/android_filesystem_config.h>
331 #  include <private/canned_fs_config.h>
332 #  include <private/fs_config.h>
333-
334+# else /* !__ANDROID__ */
335+#include "dac_config.h"
336+#  endif
337 errcode_t android_configure_fs(ext2_filsys fs, char *src_dir,
338 			       char *target_out,
339 			       char *mountpoint,
340--
341diff --git a/contrib/android/dac_config.cpp b/contrib/android/dac_config.cpp
342index 422e0d52280ff4f142b278c5fedb04790846b9ee..1c76dfd7e7d1b067941b79e73311144d548a3179 100644
343--- a/contrib/android/dac_config.cpp
344+++ b/contrib/android/dac_config.cpp
345@@ -35,14 +35,14 @@ struct DacConfig {
346     string path;
347
348     DacConfig() : uid(0), gid(0), mode(0), capabilities(0), path("") {}
349-    DacConfig(unsigned int m, unsigned int u, unsigned int g, uint64_t c, string p) :
350+    DacConfig(unsigned int m, unsigned int u, unsigned int g, uint64_t c, const string &p) :
351         uid(u),
352         gid(g),
353         mode(m),
354         capabilities(c),
355         path(p) {}
356
357-    void SetDefault(unsigned int m, unsigned int u, unsigned int g, uint64_t c, string p)
358+    void SetDefault(unsigned int m, unsigned int u, unsigned int g, uint64_t c, const string &p)
359     {
360         this->uid = u;
361         this->gid = g;
362@@ -198,33 +198,28 @@ extern "C" {
363         return 0;
364     }
365
366-    void GetDacConfig(const char* path, int dir, char* targetOutPath,
367+    void GetDacConfig(const char* path, int dir, char*,
368             unsigned* uid, unsigned* gid, unsigned* mode,
369             uint64_t* capabilities)
370     {
371-        if (path && path[0] == '/') {
372-            path++;
373-        }
374-
375-        (void)targetOutPath;
376-        string str = path;
377-        string str2;
378+        string str = (path != nullptr && *path == '/') ? path + 1 : path;
379         DacConfig dacConfig(00755, 0, 0, 0, "");
380
381         if (dir == 0) {
382             dacConfig.SetDefault(00644, 0, 0, 0, "");
383         }
384
385-        if (g_configMap.count(str)) {
386-            dacConfig = g_configMap[str];
387+        auto it = g_configMap.find(str);
388+        if (it != g_configMap.end()) {
389+            dacConfig = it->second;
390         } else if (dir == 0 && !str.empty()) {
391-            for (auto i = str.size() - 1; i >= 0; i--) {
392+            for (int i = static_cast<int>(str.size()) - 1; i >= 0; i--) {
393                 if (str[i] == '/') {
394                     break;
395                 } else {
396-                    str2 = str.substr(0, i) + "*";
397-                    if (g_configMap.count(str2)) {
398-                        dacConfig = g_configMap[str2];
399+                    it = g_configMap.find(str.substr(0, i) + "*");
400+                    if (it != g_configMap.end()) {
401+                        dacConfig = it->second;
402                         break;
403                     }
404                 }
405