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