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