diff --git a/services/param/adapter/param_dac.c b/services/param/adapter/param_dac.c index adaca666f..ea824a3ff 100644 --- a/services/param/adapter/param_dac.c +++ b/services/param/adapter/param_dac.c @@ -25,6 +25,7 @@ #include "param_utils.h" #include "param_base.h" +#define MAX_MEMBER_IN_GROUP 128 #define MAX_BUF_SIZE 1024 #define INVALID_MODE 0550 #ifdef STARTUP_INIT_TEST @@ -124,30 +125,76 @@ static int FreeLocalSecurityLabel(ParamSecurityLabel *srcLabel) return 0; } +static int DacGetGroupMember(gid_t gid, uid_t *member, uint32_t *memberSize) +{ + uint32_t inputLen = *memberSize; + *memberSize = 0; + struct group *data = getgrgid(gid); + if (data == NULL || data->gr_mem == NULL) { + return 0; + } + int i = 0; + int memIndex = 0; + while (data->gr_mem[i]) { + uid_t uid; + GetUserIdByName(&uid, data->gr_mem[i]); + if (INVALID_UID(uid)) { + i++; + continue; + } + if ((memIndex + 1) > inputLen) { + PARAM_LOGE("Not enough memory for uid member %u", gid); + break; + } + member[memIndex++] = uid; + i++; + } + uid_t uid = 0; + GetUserIdByName(&uid, data->gr_name); + if (!INVALID_UID(uid) && ((memIndex + 1) < inputLen)) { + member[memIndex++] = uid; + } + *memberSize = memIndex; + return 0; +} + static int LoadOneParam_(const uint32_t *context, const char *name, const char *value) { - ParamAuditData auditData = {0}; - auditData.dacData.gid = -1; - auditData.dacData.uid = -1; - auditData.name = name; - int ret = GetParamDacData(&auditData.dacData, value); + ParamAuditData *auditData = (ParamAuditData *)context; + auditData->dacData.gid = -1; + auditData->dacData.uid = -1; + auditData->name = name; + int ret = GetParamDacData(&auditData->dacData, value); PARAM_CHECK(ret == 0, return -1, "Failed to get param info %d %s", ret, name); - if (INVALID_UID(auditData.dacData.gid) || INVALID_UID(auditData.dacData.uid)) { - PARAM_LOGW("Invalid dac for '%s' gid %d uid %d", name, auditData.dacData.gid, auditData.dacData.uid); + if (INVALID_UID(auditData->dacData.gid) || INVALID_UID(auditData->dacData.uid)) { + PARAM_LOGW("Invalid dac for '%s' gid %d uid %d", name, auditData->dacData.gid, auditData->dacData.uid); } - AddSecurityLabel(&auditData); + // get uid from group + auditData->memberNum = MAX_MEMBER_IN_GROUP; + ret = DacGetGroupMember(auditData->dacData.gid, auditData->members, &auditData->memberNum); + if (ret != 0) { + auditData->memberNum = 1; + auditData->members[0] = auditData->dacData.gid; + } + AddSecurityLabel(auditData); return 0; } static int LoadParamLabels(const char *fileName) { + ParamAuditData *auditData = (ParamAuditData *)calloc(1, + sizeof(ParamAuditData) + sizeof(uid_t) * MAX_MEMBER_IN_GROUP); + if (auditData == NULL) { + PARAM_LOGE("Failed to alloc memory %s", fileName); + return 0; + } uint32_t infoCount = 0; FILE *fp = fopen(fileName, "r"); const uint32_t buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10; // 10 size char *buff = (char *)calloc(1, buffSize); while (fp != NULL && buff != NULL && fgets(buff, buffSize, fp) != NULL) { buff[buffSize - 1] = '\0'; - int ret = SplitParamString(buff, NULL, 0, LoadOneParam_, NULL); + int ret = SplitParamString(buff, NULL, 0, LoadOneParam_, (const uint32_t *)auditData); if (ret != 0) { PARAM_LOGE("Failed to split string %s fileName %s", buff, fileName); continue; @@ -161,6 +208,9 @@ static int LoadParamLabels(const char *fileName) if (buff != NULL) { free(buff); } + if (auditData != NULL) { + free(auditData); + } return 0; } @@ -237,127 +287,3 @@ INIT_LOCAL_API int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit) } return ret; } - -static void AddGroupUser(const char *userName, gid_t gid) -{ - if (userName == NULL || strlen(userName) == 0) { - return; - } - uid_t uid = 0; - GetUserIdByName(&uid, userName); - PARAM_LOGV("Add group user '%s' gid %d uid %d", userName, gid, uid); - if (INVALID_UID(gid) || INVALID_UID(uid)) { - PARAM_LOGW("Invalid user for '%s' gid %d uid %d", userName, gid, uid); - return; - } - char buffer[USER_BUFFER_LEN] = {0}; - int ret = PARAM_SPRINTF(buffer, sizeof(buffer), GROUP_FORMAT, gid, uid); - PARAM_CHECK(ret >= 0, return, "Failed to format name for %d.%d", gid, uid); - (void)AddParamEntry(WORKSPACE_INDEX_BASE, PARAM_TYPE_STRING, buffer, "1"); -} - -#ifdef PARAM_DECODE_GROUPID_FROM_FILE -static char *UserNameTrim(char *str) -{ - if (str == NULL) { - return NULL; - } - size_t len = strlen(str); - if (str == NULL || len == 0) { - return NULL; - } - char *end = str + len - 1; - while (end >= str && (*end == ' ' || *end == '\t' || *end == '\n' || *end == '\r')) { - *end = '\0'; - end--; - } - len = strlen(str); - char *head = str; - end = str + strlen(str); - while (head < end && (*head == ' ' || *head == '\t' || *head == '\n' || *head == '\r')) { - *head = '\0'; - head++; - } - if (strlen(str) == 0) { - return NULL; - } - return head; -} - -static void LoadGroupUser_(void) -{ - // decode group file - FILE *fp = fopen(GROUP_FILE_PATH, "r"); - const uint32_t buffSize = 1024; // 1024 max buffer for decode - char *buff = (char *)calloc(1, buffSize); - while (fp != NULL && buff != NULL && fgets(buff, buffSize, fp) != NULL) { - buff[buffSize - 1] = '\0'; - // deviceprivate:x:1053:root,shell,system,samgr,hdf_devmgr,deviceinfo,dsoftbus,dms,account - char *buffer = UserNameTrim(buff); - PARAM_CHECK(buffer != NULL, continue, "Invalid buffer %s", buff); - - PARAM_LOGV("LoadGroupUser_ '%s'", buffer); - // group name - char *groupName = strtok(buffer, ":"); - groupName = UserNameTrim(groupName); - PARAM_CHECK(groupName != NULL, continue, "Invalid group name %s", buff); - gid_t gid = -1; - GetGroupIdByName(&gid, groupName); - - // skip x - (void)strtok(NULL, ":"); - char *strGid = strtok(NULL, ":"); - char *userName = strGid + strlen(strGid) + 1; - userName = UserNameTrim(userName); - PARAM_LOGV("LoadGroupUser_ %s userName '%s'", groupName, userName); - if (userName == NULL) { - AddGroupUser(groupName, gid); - continue; - } - char *tmp = strtok(userName, ","); - while (tmp != NULL) { - PARAM_LOGV("LoadGroupUser_ %s userName '%s'", groupName, tmp); - AddGroupUser(UserNameTrim(tmp), gid); - userName = tmp + strlen(tmp) + 1; - tmp = strtok(NULL, ","); - } - // last username - if (userName != NULL) { - AddGroupUser(UserNameTrim(userName), gid); - } - } - if (fp != NULL) { - (void)fclose(fp); - } - if (buff != NULL) { - free(buff); - } - return; -} -#else -static void LoadGroupUser_(void) -{ - struct group *data = NULL; - while ((data = getgrent()) != NULL) { - if (data->gr_name == NULL || data->gr_mem == NULL) { - continue; - } - if (data->gr_mem[0] == NULL) { // default user in group - AddGroupUser(data->gr_name, data->gr_gid); - continue; - } - int index = 0; - while (data->gr_mem[index]) { // user in this group - AddGroupUser(data->gr_mem[index], data->gr_gid); - index++; - } - } - endgrent(); -} -#endif - -INIT_LOCAL_API void LoadGroupUser(void) -{ - PARAM_LOGV("LoadGroupUser "); - LoadGroupUser_(); -} diff --git a/services/param/adapter/param_selinux.c b/services/param/adapter/param_selinux.c index 597490794..5820d5248 100644 --- a/services/param/adapter/param_selinux.c +++ b/services/param/adapter/param_selinux.c @@ -234,6 +234,8 @@ static void HandleSelinuxLabelForPermission(const ParameterNode *paramNode, int auditData.dacData.paramType = node->type; auditData.selinuxIndex = labelIndex; auditData.name = paramNode->paraName; + auditData.memberNum = 1; + auditData.members[0] = node->gid; AddSecurityLabel(&auditData); } diff --git a/services/param/base/param_base.c b/services/param/base/param_base.c index 6348a3920..7b064d3c2 100644 --- a/services/param/base/param_base.c +++ b/services/param/base/param_base.c @@ -124,9 +124,8 @@ static int CheckNeedInit(int onlyRead, const PARAM_WORKSPACE_OPS *ops) INIT_INNER_API int InitParamWorkSpace(int onlyRead, const PARAM_WORKSPACE_OPS *ops) { - if (CheckNeedInit(onlyRead, ops) == 0) { - return 0; - } + PARAM_ONLY_CHECK(CheckNeedInit(onlyRead, ops) != 0, return 0); + paramMutexEnvInit(); g_paramWorkSpace.maxLabelIndex = PARAM_DEF_SELINUX_LABEL; if (!PARAM_TEST_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_INIT)) { @@ -151,8 +150,6 @@ INIT_INNER_API int InitParamWorkSpace(int onlyRead, const PARAM_WORKSPACE_OPS *o PARAM_CHECK(ret == 0, return -1, "Failed to add dac workspace"); #endif if (onlyRead == 0) { - // load user info for dac - LoadGroupUser(); // add default dac policy ParamAuditData auditData = {0}; auditData.name = "#"; @@ -160,6 +157,8 @@ INIT_INNER_API int InitParamWorkSpace(int onlyRead, const PARAM_WORKSPACE_OPS *o auditData.dacData.uid = DAC_DEFAULT_USER; auditData.dacData.mode = DAC_DEFAULT_MODE; // 0774 default mode auditData.dacData.paramType = PARAM_TYPE_STRING; + auditData.memberNum = 1; + auditData.members[0] = DAC_DEFAULT_GROUP; #ifdef PARAM_SUPPORT_SELINUX auditData.selinuxIndex = INVALID_SELINUX_INDEX; #endif @@ -364,14 +363,12 @@ STATIC_INLINE int ReadParamWithCheck(WorkSpace **workspace, const char *name, ui return ret; } -static int CheckUserInGroup(WorkSpace *space, gid_t groupId, uid_t uid) +static int CheckUserInGroup(WorkSpace *space, const ParamSecurityNode *node, uid_t uid) { - char buffer[USER_BUFFER_LEN] = {0}; - int ret = PARAM_SPRINTF(buffer, sizeof(buffer), GROUP_FORMAT, groupId, uid); - PARAM_CHECK(ret >= 0, return -1, "Failed to format name for "GROUP_FORMAT, groupId, uid); - ParamNode *node = GetParamNode(WORKSPACE_INDEX_BASE, buffer); - if (node != NULL) { - return 0; + for (uint32_t i = 0; i < node->memberNum; i++) { + if (node->members[i] == uid) { + return 0; + } } return -1; } @@ -436,7 +433,7 @@ STATIC_INLINE int DacCheckParamPermission(const ParamLabelIndex *labelIndex, return DAC_RESULT_PERMISSION; } // 4, check user in group - if (CheckUserInGroup(space, node->gid, srcLabel->cred.uid) == 0) { + if (CheckUserInGroup(space, node, srcLabel->cred.uid) == 0) { localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_GROUP_START; if ((node->mode & localMode) != 0) { return DAC_RESULT_PERMISSION; diff --git a/services/param/base/param_trie.c b/services/param/base/param_trie.c index b270b7696..a3ba0d307 100644 --- a/services/param/base/param_trie.c +++ b/services/param/base/param_trie.c @@ -237,7 +237,7 @@ INIT_LOCAL_API uint32_t AddParamSecurityNode(WorkSpace *workSpace, const ParamAu { PARAM_CHECK(CheckWorkSpace(workSpace) == 0, return 0, "Invalid workSpace"); PARAM_CHECK(auditData != NULL, return 0, "Invalid auditData"); - uint32_t realLen = sizeof(ParamSecurityNode); + uint32_t realLen = sizeof(ParamSecurityNode) + sizeof(uid_t) * auditData->memberNum; PARAM_CHECK((workSpace->area->currOffset + realLen) < workSpace->area->dataSize, return 0, "Failed to allocate currOffset %u, dataSize %u datalen %u", workSpace->area->currOffset, workSpace->area->dataSize, realLen); @@ -251,6 +251,13 @@ INIT_LOCAL_API uint32_t AddParamSecurityNode(WorkSpace *workSpace, const ParamAu #else node->selinuxIndex = 0; #endif + if (auditData->memberNum > 0) { + // copy member + int ret = PARAM_MEMCPY(node->members, + realLen - sizeof(ParamSecurityNode), auditData->members, auditData->memberNum * sizeof(uid_t)); + PARAM_CHECK(ret == 0, return 0, "Failed to copy members"); + } + node->memberNum = auditData->memberNum; uint32_t offset = workSpace->area->currOffset; workSpace->area->currOffset += realLen; workSpace->area->securityNodeCount++; diff --git a/services/param/include/param_common.h b/services/param/include/param_common.h index 32386923c..fc4b2cef1 100644 --- a/services/param/include/param_common.h +++ b/services/param/include/param_common.h @@ -87,6 +87,8 @@ typedef struct { uint16_t mode; uint8_t type; uint8_t length; + uint32_t memberNum; + uid_t members[0]; } ParamSecurityNode; typedef struct { diff --git a/services/param/include/param_security.h b/services/param/include/param_security.h index c82b95c70..17fcd72ce 100644 --- a/services/param/include/param_security.h +++ b/services/param/include/param_security.h @@ -88,6 +88,8 @@ typedef struct { char label[SELINUX_CONTENT_LEN]; uint32_t selinuxIndex; #endif + uint32_t memberNum; + uid_t members[1]; } ParamAuditData; struct WorkSpace_; @@ -127,7 +129,6 @@ INIT_LOCAL_API int RegisterSecuritySelinuxOps(ParamSecurityOps *ops, int isInit) #endif INIT_LOCAL_API ParamSecurityOps *GetParamSecurityOps(int type); -INIT_LOCAL_API void LoadGroupUser(void); INIT_LOCAL_API int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit); INIT_LOCAL_API int RegisterSecurityOps(int onlyRead); diff --git a/services/param/liteos/param_litedac.c b/services/param/liteos/param_litedac.c index 1c2cafe1e..ef9de763f 100644 --- a/services/param/liteos/param_litedac.c +++ b/services/param/liteos/param_litedac.c @@ -81,7 +81,3 @@ INIT_LOCAL_API int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit) } return ret; } - -INIT_LOCAL_API void LoadGroupUser(void) -{ -} diff --git a/services/param/manager/param_manager.c b/services/param/manager/param_manager.c index 0774a5996..96419f724 100644 --- a/services/param/manager/param_manager.c +++ b/services/param/manager/param_manager.c @@ -141,12 +141,20 @@ static int DumpTrieDataNodeTraversal(const WorkSpace *workSpace, const ParamTrie entry->commitId, entry->keyLength, entry->valueLength, entry->data); } } - if (current->labelIndex != 0 && verbose) { - ParamSecurityNode *label = (ParamSecurityNode *)GetTrieNode(workSpace, current->labelIndex); - if (label != NULL) { - PARAM_DUMP("\tparameter label dac %u %u %o selinuxIndex %u \n", - label->uid, label->gid, label->mode, label->selinuxIndex); - } + if (current->labelIndex == 0) { + return 0; + } + ParamSecurityNode *label = (ParamSecurityNode *)GetTrieNode(workSpace, current->labelIndex); + if (label == NULL) { + return 0; + } + PARAM_DUMP("\tparameter label dac %u %u 0%o \n", label->uid, label->gid, label->mode); + PARAM_DUMP("\tparameter label dac member [%u] ", label->memberNum); + for (uint32_t i = 0; i < label->memberNum; i++) { + PARAM_DUMP(" %u", label->members[i]); + } + if (label->memberNum > 0) { + PARAM_DUMP("\n"); } return 0; }