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