未验证 提交 57455849 编写于 作者: O openharmony_ci 提交者: Gitee

!1116 支持用户容器

Merge pull request !1116 from zhushengle/user_container
......@@ -250,6 +250,7 @@ config("container_config") {
"-DLOSCFG_CHROOT",
"-DLOSCFG_IPC_CONTAINER",
"-DLOSCFG_TIME_CONTAINER",
"-DLOSCFG_USER_CONTAINER",
"-DLOSCFG_PROC_PROCESS_DIR",
]
}
......
......@@ -46,6 +46,11 @@ typedef enum {
#ifdef LOSCFG_KERNEL_CPUP
PROC_PID_CPUP,
#endif
#ifdef LOSCFG_USER_CONTAINER
PROC_UID_MAP,
PROC_GID_MAP,
#endif
PROC_P_TYPE_MAX,
} ProcessDataType;
struct ProcProcess {
......@@ -84,6 +89,8 @@ static ssize_t ProcessContainerLink(unsigned int containerID, ContainerType type
count = snprintf_s(buffer, bufLen, bufLen - 1, "'ipc:[%u]'", containerID);
} else if ((type == TIME_CONTAINER) || (type == TIME_CHILD_CONTAINER)) {
count = snprintf_s(buffer, bufLen, bufLen - 1, "'time:[%u]'", containerID);
} else if (type == USER_CONTAINER) {
count = snprintf_s(buffer, bufLen, bufLen - 1, "'user:[%u]'", containerID);
}
if (count < 0) {
......@@ -105,7 +112,7 @@ static ssize_t ProcessContainerReadLink(struct ProcDirEntry *entry, char *buffer
}
LosProcessCB *processCB = ProcGetProcessCB(data);
SCHEDULER_LOCK(intSave);
UINT32 containerID = OsGetContainerID(processCB->container, (ContainerType)data->type);
UINT32 containerID = OsGetContainerID(processCB, (ContainerType)data->type);
SCHEDULER_UNLOCK(intSave);
if (containerID != OS_INVALID_VALUE) {
return ProcessContainerLink(containerID, (ContainerType)data->type, buffer, bufLen);
......@@ -320,6 +327,121 @@ static const struct ProcFileOperations TIME_CONTAINER_FOPS = {
};
#endif
#ifdef LOSCFG_USER_CONTAINER
static void *MemdupUserNul(const void *src, size_t len)
{
char *des = NULL;
if (len <= 0) {
return NULL;
}
des = LOS_MemAlloc(OS_SYS_MEM_ADDR, len + 1);
if (des == NULL) {
return NULL;
}
if (LOS_ArchCopyFromUser(des, src, len) != 0) {
(VOID)LOS_MemFree(OS_SYS_MEM_ADDR, des);
return NULL;
}
des[len] = '\0';
return des;
}
static LosProcessCB *ProcUidGidMapWriteCheck(struct ProcFile *pf, const char *buf, size_t size,
char **kbuf, ProcessDataType *type)
{
if ((pf == NULL) || (size <= 0) || (size >= PAGE_SIZE)) {
return NULL;
}
struct ProcDirEntry *entry = pf->pPDE;
if (entry == NULL) {
return NULL;
}
struct ProcessData *data = (struct ProcessData *)entry->data;
if (data == NULL) {
return NULL;
}
*kbuf = MemdupUserNul(buf, size);
if (*kbuf == NULL) {
return NULL;
}
*type = (ProcessDataType)data->type;
return ProcGetProcessCB(data);
}
static ssize_t ProcIDMapWrite(struct ProcFile *file, const char *buf, size_t size, loff_t *ppos)
{
(void)ppos;
char *kbuf = NULL;
int ret;
unsigned int intSave;
ProcessDataType type = PROC_P_TYPE_MAX;
LosProcessCB *processCB = ProcUidGidMapWriteCheck(file, buf, size, &kbuf, &type);
if (processCB == NULL) {
return -EINVAL;
}
SCHEDULER_LOCK(intSave);
if ((processCB->credentials == NULL) || (processCB->credentials->userContainer == NULL)) {
SCHEDULER_UNLOCK(intSave);
(void)LOS_MemFree(m_aucSysMem1, kbuf);
return -EINVAL;
}
UserContainer *userContainer = processCB->credentials->userContainer;
if (userContainer->parent == NULL) {
SCHEDULER_UNLOCK(intSave);
(void)LOS_MemFree(m_aucSysMem1, kbuf);
return -EPERM;
}
if (type == PROC_UID_MAP) {
ret = OsUserContainerMapWrite(file, kbuf, size, CAP_SETUID,
&userContainer->uidMap, &userContainer->parent->uidMap);
} else {
ret = OsUserContainerMapWrite(file, kbuf, size, CAP_SETGID,
&userContainer->gidMap, &userContainer->parent->gidMap);
}
SCHEDULER_UNLOCK(intSave);
(void)LOS_MemFree(m_aucSysMem1, kbuf);
return ret;
}
static int ProcIDMapRead(struct SeqBuf *seqBuf, void *v)
{
unsigned int intSave;
if ((seqBuf == NULL) || (v == NULL)) {
return -EINVAL;
}
struct ProcessData *data = (struct ProcessData *)v;
LosProcessCB *processCB = ProcGetProcessCB(data);
SCHEDULER_LOCK(intSave);
if ((processCB->credentials == NULL) || (processCB->credentials->userContainer == NULL)) {
SCHEDULER_UNLOCK(intSave);
return -EINVAL;
}
UserContainer *userContainer = processCB->credentials->userContainer;
if ((userContainer != NULL) && (userContainer->parent == NULL)) {
UidGidExtent uidGidExtent = userContainer->uidMap.extent[0];
SCHEDULER_UNLOCK(intSave);
(void)LosBufPrintf(seqBuf, "%d %d %u\n", uidGidExtent.first, uidGidExtent.lowerFirst,
uidGidExtent.count);
return 0;
}
SCHEDULER_LOCK(intSave);
return 0;
}
static const struct ProcFileOperations UID_GID_MAP_FOPS = {
.read = ProcIDMapRead,
.write = ProcIDMapWrite,
};
#endif
static int ProcProcessRead(struct SeqBuf *m, void *v)
{
if ((m == NULL) || (v == NULL)) {
......@@ -432,6 +554,26 @@ static struct ProcProcess g_procProcess[] = {
.fileOps = &TIME_CONTAINER_FOPS
},
#endif
#ifdef LOSCFG_IPC_CONTAINER
{
.name = "container/user",
.mode = S_IFLNK,
.type = USER_CONTAINER,
.fileOps = &PID_CONTAINER_FOPS
},
{
.name = "uid_map",
.mode = 0,
.type = PROC_UID_MAP,
.fileOps = &UID_GID_MAP_FOPS
},
{
.name = "gid_map",
.mode = 0,
.type = PROC_GID_MAP,
.fileOps = &UID_GID_MAP_FOPS
},
#endif
#endif
};
......
......@@ -103,6 +103,11 @@ config TIME_CONTAINER
default n
depends on KERNEL_CONTAINER
config USER_CONTAINER
bool "Enable user container"
default n
depends on KERNEL_CONTAINER
######################### config options of extended #####################
source "kernel/extended/Kconfig"
......
......@@ -33,10 +33,12 @@ module_name = get_path_info(rebase_path("."), "name")
kernel_module(module_name) {
sources = [
"container/los_container.c",
"container/los_credentials.c",
"container/los_ipc_container.c",
"container/los_mnt_container.c",
"container/los_pid_container.c",
"container/los_time_container.c",
"container/los_user_container.c",
"container/los_uts_container.c",
"core/los_bitmap.c",
"core/los_info.c",
......
......@@ -34,6 +34,9 @@
STATIC Container g_rootContainer;
STATIC Atomic g_containerCount = 0xF0000000U;
#ifdef LOSCFG_USER_CONTAINER
STATIC Credentials *g_rootCredentials = NULL;
#endif
UINT32 OsAllocContainerID(VOID)
{
......@@ -43,6 +46,9 @@ UINT32 OsAllocContainerID(VOID)
VOID OsContainerInitSystemProcess(LosProcessCB *processCB)
{
processCB->container = &g_rootContainer;
#ifdef LOSCFG_USER_CONTAINER
processCB->credentials = g_rootCredentials;
#endif
LOS_AtomicInc(&processCB->container->rc);
#ifdef LOSCFG_PID_CONTAINER
(VOID)OsAllocSpecifiedVpidUnsafe(processCB->processID, processCB->container->pidContainer, processCB, NULL);
......@@ -52,6 +58,9 @@ VOID OsContainerInitSystemProcess(LosProcessCB *processCB)
VOID OsInitRootContainer(VOID)
{
#ifdef LOSCFG_USER_CONTAINER
OsInitRootUserCredentials(&g_rootCredentials);
#endif
#ifdef LOSCFG_PID_CONTAINER
(VOID)OsInitRootPidContainer(&g_rootContainer.pidContainer);
g_rootContainer.pidForChildContainer = g_rootContainer.pidContainer;
......@@ -95,6 +104,12 @@ STATIC UINT32 CopyContainers(UINTPTR flags, LosProcessCB *child, LosProcessCB *p
return ret;
}
#endif
#ifdef LOSCFG_USER_CONTAINER
ret = OsCopyCredentials(flags, child, parent);
if (ret != LOS_OK) {
return ret;
}
#endif
#ifdef LOSCFG_UTS_CONTAINER
ret = OsCopyUtsContainer(flags, child, parent);
if (ret != LOS_OK) {
......@@ -182,6 +197,10 @@ VOID OsContainersDestroy(LosProcessCB *processCB)
}
#endif
#ifdef LOSCFG_USER_CONTAINER
OsUserContainerDestroy(processCB);
#endif
#ifdef LOSCFG_UTS_CONTAINER
OsUtsContainerDestroy(processCB->container);
#endif
......@@ -245,8 +264,9 @@ STATIC VOID DeInitContainers(UINT32 flags, Container *container, LosProcessCB *p
SCHEDULER_UNLOCK(intSave);
}
UINT32 OsGetContainerID(Container *container, ContainerType type)
UINT32 OsGetContainerID(LosProcessCB *processCB, ContainerType type)
{
Container *container = processCB->container;
if (container == NULL) {
return OS_INVALID_VALUE;
}
......@@ -258,6 +278,10 @@ UINT32 OsGetContainerID(Container *container, ContainerType type)
case PID_CHILD_CONTAINER:
return OsGetPidContainerID(container->pidForChildContainer);
#endif
#ifdef LOSCFG_USER_CONTAINER
case USER_CONTAINER:
return OsGetUserContainerID(processCB->credentials);
#endif
#ifdef LOSCFG_UTS_CONTAINER
case UTS_CONTAINER:
return OsGetUtsContainerID(container->utsContainer);
......@@ -324,12 +348,22 @@ INT32 OsUnshare(UINT32 flags)
UINT32 intSave;
LosProcessCB *curr = OsCurrProcessGet();
Container *oldContainer = curr->container;
UINT32 unshareFlags = CLONE_NEWPID | CLONE_NEWTIME | CLONE_NEWUTS | CLONE_NEWNS | CLONE_NEWIPC;
UINT32 unshareFlags = CLONE_NEWPID | CLONE_NEWTIME | CLONE_NEWUTS | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUSER;
if (!(flags & unshareFlags) || ((flags & (~unshareFlags)) != 0)) {
return -EINVAL;
}
#ifdef LOSCFG_USER_CONTAINER
ret = OsUnshareUserCredentials(flags, curr);
if (ret != LOS_OK) {
return ret;
}
if (flags == CLONE_NEWUSER) {
return LOS_OK;
}
#endif
Container *newContainer = CreateContainer();
if (newContainer == NULL) {
return -ENOMEM;
......@@ -363,6 +397,8 @@ STATIC UINT32 SetNsGetFlagByContainerType(UINT32 containerType)
case PID_CONTAINER:
case PID_CHILD_CONTAINER:
return CLONE_NEWPID;
case USER_CONTAINER:
return CLONE_NEWUSER;
case UTS_CONTAINER:
return CLONE_NEWUTS;
case MNT_CONTAINER:
......@@ -414,46 +450,75 @@ STATIC UINT32 SetNsCreateNewContainers(UINT32 flags, Container *newContainer, Co
return LOS_OK;
}
INT32 OsSetNs(INT32 fd, INT32 type)
STATIC UINT32 SetNsParamCheck(INT32 fd, INT32 type, UINT32 *flag, LosProcessCB **target)
{
UINT32 intSave;
UINT32 typeMask = CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWTIME;
UINT32 typeMask = CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWTIME | CLONE_NEWUSER;
*flag = (UINT32)(type & typeMask);
UINT32 containerType = 0;
UINT32 flag = (UINT32)(type & typeMask);
LosProcessCB *curr = OsCurrProcessGet();
if (((type & (~typeMask)) != 0)) {
return -EINVAL;
}
Container *newContainer = CreateContainer();
if (newContainer == NULL) {
return -ENOMEM;
return EINVAL;
}
LosProcessCB *processCB = (LosProcessCB *)ProcfsContainerGet(fd, &containerType);
if (processCB == NULL) {
(VOID)LOS_MemFree(m_aucSysMem1, newContainer);
return -EBADF;
return EBADF;
}
SCHEDULER_LOCK(intSave);
Container *targetContainer = processCB->container;
if (targetContainer == NULL) {
if (*flag == 0) {
*flag = SetNsGetFlagByContainerType(containerType);
}
if ((*flag == 0) || (*flag != SetNsGetFlagByContainerType(containerType))) {
return EINVAL;
}
if (processCB == OsCurrProcessGet()) {
return EINVAL;
}
*target = processCB;
return LOS_OK;
}
INT32 OsSetNs(INT32 fd, INT32 type)
{
UINT32 intSave, ret;
UINT32 flag = 0;
LosProcessCB *curr = OsCurrProcessGet();
LosProcessCB *processCB = NULL;
ret = SetNsParamCheck(fd, type, &flag, &processCB);
if (ret != LOS_OK) {
return -ret;
}
#ifdef LOSCFG_USER_CONTAINER
if (flag == CLONE_NEWUSER) {
SCHEDULER_LOCK(intSave);
if ((processCB->credentials == NULL) || (processCB->credentials->userContainer == NULL)) {
SCHEDULER_UNLOCK(intSave);
return -EBADF;
}
UserContainer *userContainer = processCB->credentials->userContainer;
ret = OsSetNsUserContainer(userContainer, curr);
SCHEDULER_UNLOCK(intSave);
return -EBADF;
return ret;
}
#endif
if (flag == 0) {
flag = SetNsGetFlagByContainerType(containerType);
Container *newContainer = CreateContainer();
if (newContainer == NULL) {
return -ENOMEM;
}
if ((flag == 0) || (flag != SetNsGetFlagByContainerType(containerType)) || (targetContainer == curr->container)) {
SCHEDULER_LOCK(intSave);
Container *targetContainer = processCB->container;
if (targetContainer == NULL) {
SCHEDULER_UNLOCK(intSave);
return -EBADF;
}
UINT32 ret = SetNsCreateNewContainers(flag, newContainer, targetContainer);
ret = SetNsCreateNewContainers(flag, newContainer, targetContainer);
if (ret != LOS_OK) {
SCHEDULER_UNLOCK(intSave);
goto EXIT;
......
/*
* Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <errno.h>
#include "los_credentials_pri.h"
#include "los_user_container_pri.h"
#include "los_config.h"
#include "los_memory.h"
#include "los_process_pri.h"
#ifdef LOSCFG_USER_CONTAINER
STATIC Credentials *CreateNewCredential(LosProcessCB *parent)
{
UINT32 size = sizeof(Credentials);
Credentials *newCredentials = LOS_MemAlloc(m_aucSysMem1, size);
if (newCredentials == NULL) {
return NULL;
}
if (parent != NULL) {
const Credentials *oldCredentials = parent->credentials;
(VOID)memcpy_s(newCredentials, sizeof(Credentials), oldCredentials, sizeof(Credentials));
LOS_AtomicSet(&newCredentials->rc, 1);
} else {
(VOID)memset_s(newCredentials, sizeof(Credentials), 0, sizeof(Credentials));
LOS_AtomicSet(&newCredentials->rc, 3); /* 3: Three system processes */
}
newCredentials->userContainer = NULL;
return newCredentials;
}
Credentials *PrepareCredential(LosProcessCB *runProcessCB)
{
Credentials *newCredentials = CreateNewCredential(runProcessCB);
if (newCredentials == NULL) {
return NULL;
}
newCredentials->userContainer = runProcessCB->credentials->userContainer;
LOS_AtomicInc(&newCredentials->userContainer->rc);
return newCredentials;
}
VOID FreeCredential(Credentials *credentials)
{
if (credentials == NULL) {
return;
}
if (credentials->userContainer != NULL) {
LOS_AtomicDec(&credentials->userContainer->rc);
if (LOS_AtomicRead(&credentials->userContainer->rc) <= 0) {
FreeUserContainer(credentials->userContainer);
credentials->userContainer = NULL;
}
}
LOS_AtomicDec(&credentials->rc);
if (LOS_AtomicRead(&credentials->rc) <= 0) {
(VOID)LOS_MemFree(m_aucSysMem1, credentials);
}
}
VOID OsUserContainerDestroy(LosProcessCB *curr)
{
UINT32 intSave;
SCHEDULER_LOCK(intSave);
FreeCredential(curr->credentials);
curr->credentials = NULL;
SCHEDULER_UNLOCK(intSave);
return;
}
STATIC Credentials *CreateCredentials(unsigned long flags, LosProcessCB *parent)
{
UINT32 ret;
Credentials *newCredentials = CreateNewCredential(parent);
if (newCredentials == NULL) {
return NULL;
}
if (!(flags & CLONE_NEWUSER)) {
newCredentials->userContainer = parent->credentials->userContainer;
LOS_AtomicInc(&newCredentials->userContainer->rc);
return newCredentials;
}
if (parent != NULL) {
ret = OsCreateUserContainer(newCredentials, parent->credentials->userContainer);
} else {
ret = OsCreateUserContainer(newCredentials, NULL);
}
if (ret != LOS_OK) {
FreeCredential(newCredentials);
return NULL;
}
return newCredentials;
}
UINT32 OsCopyCredentials(unsigned long flags, LosProcessCB *child, LosProcessCB *parent)
{
UINT32 intSave;
SCHEDULER_LOCK(intSave);
child->credentials = CreateCredentials(flags, parent);
SCHEDULER_UNLOCK(intSave);
if (child->credentials == NULL) {
return ENOMEM;
}
return LOS_OK;
}
UINT32 OsInitRootUserCredentials(Credentials **credentials)
{
*credentials = CreateCredentials(CLONE_NEWUSER, NULL);
if (*credentials == NULL) {
return ENOMEM;
}
return LOS_OK;
}
UINT32 OsUnshareUserCredentials(UINTPTR flags, LosProcessCB *curr)
{
UINT32 intSave;
if (!(flags & CLONE_NEWUSER)) {
return LOS_OK;
}
SCHEDULER_LOCK(intSave);
UINT32 ret = OsCreateUserContainer(curr->credentials, curr->credentials->userContainer);
SCHEDULER_UNLOCK(intSave);
return ret;
}
UINT32 OsSetNsUserContainer(struct UserContainer *targetContainer, LosProcessCB *runProcess)
{
Credentials *oldCredentials = runProcess->credentials;
Credentials *newCredentials = CreateNewCredential(runProcess);
if (newCredentials == NULL) {
return ENOMEM;
}
runProcess->credentials = newCredentials;
newCredentials->userContainer = targetContainer;
LOS_AtomicInc(&targetContainer->rc);
FreeCredential(oldCredentials);
return LOS_OK;
}
UINT32 OsGetUserContainerID(Credentials *credentials)
{
if ((credentials == NULL) || (credentials->userContainer == NULL)) {
return OS_INVALID_VALUE;
}
return credentials->userContainer->containerID;
}
INT32 CommitCredentials(Credentials *newCredentials)
{
Credentials *oldCredentials = OsCurrProcessGet()->credentials;
if (LOS_AtomicRead(&newCredentials->rc) < 1) {
return -EINVAL;
}
OsCurrProcessGet()->credentials = newCredentials;
FreeCredential(oldCredentials);
return 0;
}
Credentials *CurrentCredentials(VOID)
{
return OsCurrProcessGet()->credentials;
}
UserContainer *OsCurrentUserContainer(VOID)
{
UserContainer *userContainer = OsCurrProcessGet()->credentials->userContainer;
return userContainer;
}
#endif
/*
* Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "los_user_container_pri.h"
#include "errno.h"
#include "ctype.h"
#include "los_config.h"
#include "los_memory.h"
#include "proc_fs.h"
#include "user_copy.h"
#include "los_seq_buf.h"
#include "capability_type.h"
#include "capability_api.h"
#include "internal.h"
#define DEFAULT_OVERFLOWUID 65534
#define DEFAULT_OVERFLOWGID 65534
#define LEVEL_MAX 3
#define HEX 16
#define OCT 8
#define DEC 10
#ifdef LOSCFG_USER_CONTAINER
UINT32 g_currentUserContainerNum = 1;
UINT32 OsCreateUserContainer(Credentials *newCredentials, UserContainer *parentUserContainer)
{
if ((parentUserContainer != NULL) && (parentUserContainer->level >= LEVEL_MAX)) {
return EINVAL;
}
if ((newCredentials->euid < 0) || (newCredentials->egid < 0)) {
return EINVAL;
}
UserContainer *userContainer = LOS_MemAlloc(m_aucSysMem1, sizeof(UserContainer));
if (userContainer == NULL) {
return ENOMEM;
}
(VOID)memset_s(userContainer, sizeof(UserContainer), 0, sizeof(UserContainer));
g_currentUserContainerNum++;
userContainer->containerID = OsAllocContainerID();
userContainer->parent = parentUserContainer;
newCredentials->userContainer = userContainer;
if (parentUserContainer != NULL) {
LOS_AtomicInc(&parentUserContainer->rc);
LOS_AtomicSet(&userContainer->rc, 1);
userContainer->level = parentUserContainer->level + 1;
userContainer->owner = newCredentials->euid;
userContainer->group = newCredentials->egid;
} else {
LOS_AtomicSet(&userContainer->rc, 3); /* 3: Three system processes */
userContainer->uidMap.extentCount = 1;
userContainer->uidMap.extent[0].count = 4294967295U;
userContainer->gidMap.extentCount = 1;
userContainer->gidMap.extent[0].count = 4294967295U;
}
return LOS_OK;
}
VOID FreeUserContainer(UserContainer *userContainer)
{
UserContainer *parent = NULL;
do {
parent = userContainer->parent;
(VOID)LOS_MemFree(m_aucSysMem1, userContainer);
userContainer->parent = NULL;
userContainer = parent;
g_currentUserContainerNum--;
} while ((userContainer != NULL) && (LOS_AtomicRead(&userContainer->rc) <= 0));
}
STATIC UidGidExtent *MapIdUpBase(UINT32 extents, UidGidMap *map, UINT32 id)
{
UINT32 idx;
UINT32 first;
UINT32 last;
for (idx = 0; idx < extents; idx++) {
first = map->extent[idx].lowerFirst;
last = first + map->extent[idx].count - 1;
if ((id >= first) && (id <= last)) {
return &map->extent[idx];
}
}
return NULL;
}
STATIC UINT32 MapIdUp(UidGidMap *map, UINT32 id)
{
UINT32 extents = map->extentCount;
if (extents > UID_GID_MAP_MAX_EXTENTS) {
return (UINT32)-1;
}
UidGidExtent *extent = MapIdUpBase(extents, map, id);
if (extent != NULL) {
return ((id - extent->lowerFirst) + extent->first);
}
return (UINT32)-1;
}
UINT32 FromKuid(UserContainer *userContainer, UINT32 kuid)
{
return MapIdUp(&userContainer->uidMap, kuid);
}
UINT32 FromKgid(UserContainer *userContainer, UINT32 kgid)
{
return MapIdUp(&userContainer->gidMap, kgid);
}
UINT32 OsFromKuidMunged(UserContainer *userContainer, UINT32 kuid)
{
UINT32 uid = FromKuid(userContainer, kuid);
if (uid == (UINT32)-1) {
uid = DEFAULT_OVERFLOWUID;
}
return uid;
}
UINT32 OsFromKgidMunged(UserContainer *userContainer, UINT32 kgid)
{
UINT32 gid = FromKgid(userContainer, kgid);
if (gid == (UINT32)-1) {
gid = DEFAULT_OVERFLOWGID;
}
return gid;
}
STATIC UidGidExtent *MapIdRangeDownBase(UINT32 extents, UidGidMap *map, UINT32 id, UINT32 count)
{
UINT32 idx;
UINT32 first;
UINT32 last;
UINT32 id2;
id2 = id + count - 1;
for (idx = 0; idx < extents; idx++) {
first = map->extent[idx].first;
last = first + map->extent[idx].count - 1;
if ((id >= first && id <= last) && (id2 >= first && id2 <= last)) {
return &map->extent[idx];
}
}
return NULL;
}
STATIC UINT32 MapIdRangeDown(UidGidMap *map, UINT32 id, UINT32 count)
{
UINT32 extents = map->extentCount;
if (extents > UID_GID_MAP_MAX_EXTENTS) {
return (UINT32)-1;
}
UidGidExtent *extent = MapIdRangeDownBase(extents, map, id, count);
if (extent != NULL) {
return ((id - extent->first) + extent->lowerFirst);
}
return (UINT32)-1;
}
STATIC UINT32 MapIdDown(UidGidMap *map, UINT32 id)
{
return MapIdRangeDown(map, id, 1);
}
UINT32 OsMakeKuid(UserContainer *userContainer, UINT32 uid)
{
return MapIdDown(&userContainer->uidMap, uid);
}
UINT32 OsMakeKgid(UserContainer *userContainer, UINT32 gid)
{
return MapIdDown(&userContainer->gidMap, gid);
}
STATIC INT32 InsertExtent(UidGidMap *idMap, UidGidExtent *extent)
{
if (idMap->extentCount > UID_GID_MAP_MAX_EXTENTS) {
return -EINVAL;
}
UidGidExtent *dest = &idMap->extent[idMap->extentCount];
*dest = *extent;
idMap->extentCount++;
return 0;
}
STATIC BOOL MappingsOverlap(UidGidMap *idMap, UidGidExtent *extent)
{
UINT32 upperFirst = extent->first;
UINT32 lowerFirst = extent->lowerFirst;
UINT32 upperLast = upperFirst + extent->count - 1;
UINT32 lowerLast = lowerFirst + extent->count - 1;
INT32 idx;
for (idx = 0; idx < idMap->extentCount; idx++) {
if (idMap->extentCount > UID_GID_MAP_MAX_EXTENTS) {
return TRUE;
}
UidGidExtent *prev = &idMap->extent[idx];
UINT32 prevUpperFirst = prev->first;
UINT32 prevLowerFirst = prev->lowerFirst;
UINT32 prevUpperLast = prevUpperFirst + prev->count - 1;
UINT32 prevLowerLast = prevLowerFirst + prev->count - 1;
if ((prevUpperFirst <= upperLast) && (prevUpperLast >= upperFirst)) {
return TRUE;
}
if ((prevLowerFirst <= lowerLast) && (prevLowerLast >= lowerFirst)) {
return TRUE;
}
}
return FALSE;
}
STATIC CHAR *SkipSpaces(const CHAR *str)
{
while (isspace(*str)) {
++str;
}
return (CHAR *)str;
}
STATIC UINTPTR StrToUInt(const CHAR *str, CHAR **endp, UINT32 base)
{
unsigned long result = 0;
unsigned long value;
if (*str == '0') {
str++;
if ((*str == 'x') && isxdigit(str[1])) {
base = HEX;
str++;
}
if (!base) {
base = OCT;
}
}
if (!base) {
base = DEC;
}
while (isxdigit(*str) && (value = isdigit(*str) ? *str - '0' : (islower(*str) ?
toupper(*str) : *str) - 'A' + DEC) < base) {
result = result * base + value;
str++;
}
if (endp != NULL) {
*endp = (CHAR *)str;
}
return result;
}
STATIC INT32 ParsePosData(CHAR *pos, UidGidExtent *extent)
{
INT32 ret = -EINVAL;
pos = SkipSpaces(pos);
extent->first = StrToUInt(pos, &pos, DEC);
if (!isspace(*pos)) {
return ret;
}
pos = SkipSpaces(pos);
extent->lowerFirst = StrToUInt(pos, &pos, DEC);
if (!isspace(*pos)) {
return ret;
}
pos = SkipSpaces(pos);
extent->count = StrToUInt(pos, &pos, DEC);
if (*pos && !isspace(*pos)) {
return ret;
}
pos = SkipSpaces(pos);
if (*pos != '\0') {
return ret;
}
return LOS_OK;
}
STATIC INT32 ParseUserData(CHAR *kbuf, UidGidExtent *extent, UidGidMap *newMap)
{
INT32 ret = -EINVAL;
CHAR *pos = NULL;
CHAR *nextLine = NULL;
for (pos = kbuf; pos != NULL; pos = nextLine) {
nextLine = strchr(pos, '\n');
if (nextLine != NULL) {
*nextLine = '\0';
nextLine++;
if (*nextLine == '\0') {
nextLine = NULL;
}
}
if (ParsePosData(pos, extent) != LOS_OK) {
return ret;
}
if ((extent->first == (UINT32)-1) || (extent->lowerFirst == (UINT32)-1)) {
return ret;
}
if ((extent->first + extent->count) <= extent->first) {
return ret;
}
if ((extent->lowerFirst + extent->count) <= extent->lowerFirst) {
return ret;
}
if (MappingsOverlap(newMap, extent)) {
return ret;
}
if ((newMap->extentCount + 1) == UID_GID_MAP_MAX_EXTENTS && (nextLine != NULL)) {
return ret;
}
ret = InsertExtent(newMap, extent);
if (ret < 0) {
return ret;
}
ret = 0;
}
if (newMap->extentCount == 0) {
return -EINVAL;
}
return ret;
}
STATIC INT32 ParentMapIdRange(UidGidMap *newMap, UidGidMap *parentMap)
{
UINT32 idx;
INT32 ret = -EPERM;
for (idx = 0; idx < newMap->extentCount; idx++) {
if (newMap->extentCount > UID_GID_MAP_MAX_EXTENTS) {
return ret;
}
UidGidExtent *extent = &newMap->extent[idx];
UINT32 lowerFirst = MapIdRangeDown(parentMap, extent->lowerFirst, extent->count);
if (lowerFirst == (UINT32) -1) {
return ret;
}
extent->lowerFirst = lowerFirst;
}
return 0;
}
INT32 OsUserContainerMapWrite(struct ProcFile *fp, CHAR *kbuf, size_t count,
INT32 capSetid, UidGidMap *map, UidGidMap *parentMap)
{
UidGidMap newMap = {0};
UidGidExtent extent;
INT32 ret;
if (map->extentCount != 0) {
return -EPERM;
}
if (!IsCapPermit(capSetid)) {
return -EPERM;
}
ret = ParseUserData(kbuf, &extent, &newMap);
if (ret < 0) {
return -EPERM;
}
ret = ParentMapIdRange(&newMap, parentMap);
if (ret < 0) {
return -EPERM;
}
if (newMap.extentCount <= UID_GID_MAP_MAX_EXTENTS) {
size_t mapSize = newMap.extentCount * sizeof(newMap.extent[0]);
ret = memcpy_s(map->extent, sizeof(map->extent), newMap.extent, mapSize);
if (ret != EOK) {
return -EPERM;
}
}
map->extentCount = newMap.extentCount;
return count;
}
#endif
......@@ -822,7 +822,11 @@ LITE_OS_SEC_TEXT INT32 LOS_GetUserID(VOID)
INT32 uid;
SCHEDULER_LOCK(intSave);
#ifdef LOSCFG_USER_CONTAINER
uid = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->uid);
#else
uid = (INT32)OsCurrUserGet()->userID;
#endif
SCHEDULER_UNLOCK(intSave);
return uid;
#else
......@@ -837,7 +841,11 @@ LITE_OS_SEC_TEXT INT32 LOS_GetGroupID(VOID)
INT32 gid;
SCHEDULER_LOCK(intSave);
#ifdef LOSCFG_USER_CONTAINER
gid = OsFromKgidMunged(OsCurrentUserContainer(), CurrentCredentials()->gid);
#else
gid = (INT32)OsCurrUserGet()->gid;
#endif
SCHEDULER_UNLOCK(intSave);
return gid;
......@@ -2123,6 +2131,9 @@ LITE_OS_SEC_TEXT INT32 OsClone(UINT32 flags, UINTPTR sp, UINT32 size)
#ifdef LOSCFG_TIME_CONTAINER
cloneFlag |= CLONE_NEWTIME;
#endif
#ifdef LOSCFG_USER_CONTAINER
cloneFlag |= CLONE_NEWUSER;
#endif
#endif
if (flags & (~cloneFlag)) {
......
......@@ -45,6 +45,9 @@
#ifdef LOSCFG_IPC_CONTAINER
#include "los_ipc_container_pri.h"
#endif
#ifdef LOSCFG_USER_CONTAINER
#include "los_user_container_pri.h"
#endif
#ifdef LOSCFG_TIME_CONTAINER
#include "los_time_container_pri.h"
#endif
......@@ -56,6 +59,7 @@ typedef enum {
UTS_CONTAINER,
MNT_CONTAINER,
IPC_CONTAINER,
USER_CONTAINER,
TIME_CONTAINER,
TIME_CHILD_CONTAINER,
CONTAINER_MAX,
......@@ -94,7 +98,7 @@ VOID OsContainerFree(LosProcessCB *processCB);
UINT32 OsAllocContainerID(VOID);
UINT32 OsGetContainerID(Container *container, ContainerType type);
UINT32 OsGetContainerID(LosProcessCB *processCB, ContainerType type);
INT32 OsUnshare(UINT32 flags);
......
/*
* Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_CREDENTIALS_PRI_H
#define _LOS_CREDENTIALS_PRI_H
#include "los_atomic.h"
#include "los_list.h"
#ifdef LOSCFG_USER_CONTAINER
struct Container;
struct UserContainer;
typedef struct ProcessCB LosProcessCB;
typedef struct Credentials {
Atomic rc;
UINT32 uid;
UINT32 gid;
UINT32 euid;
UINT32 egid;
struct UserContainer *userContainer;
} Credentials;
UINT32 OsCopyCredentials(unsigned long flags, LosProcessCB *child, LosProcessCB *parent);
UINT32 OsInitRootUserCredentials(Credentials **credentials);
UINT32 OsUnshareUserCredentials(UINTPTR flags, LosProcessCB *curr);
UINT32 OsSetNsUserContainer(struct UserContainer *targetContainer, LosProcessCB *runProcess);
VOID FreeCredential(Credentials *credentials);
VOID OsUserContainerDestroy(LosProcessCB *curr);
UINT32 OsGetUserContainerID(Credentials *credentials);
Credentials *PrepareCredential(LosProcessCB *runProcessCB);
INT32 CommitCredentials(Credentials *newCredentials);
Credentials *CurrentCredentials(VOID);
struct UserContainer *OsCurrentUserContainer(VOID);
#endif
#endif /* _LOS_CREDENTIALS_PRI_H */
......@@ -132,6 +132,9 @@ typedef struct ProcessCB {
struct rlimit *resourceLimit;
#ifdef LOSCFG_KERNEL_CONTAINER
Container *container;
#ifdef LOSCFG_USER_CONTAINER
struct Credentials *credentials;
#endif
#endif
#ifdef LOSCFG_PROC_PROCESS_DIR
struct ProcDirEntry *procDir;
......
/*
* Copyright (c) 2022-2022 Huawei Device Co., Ltd. All rights reserved.
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOS_USER_CONTAINER_PRI_H
#define _LOS_USER_CONTAINER_PRI_H
#include "los_atomic.h"
#include "los_credentials_pri.h"
#define UID_GID_MAP_MAX_EXTENTS 5
#ifdef LOSCFG_USER_CONTAINER
struct ProcFile;
typedef struct UidGidExtent {
UINT32 first;
UINT32 lowerFirst;
UINT32 count;
} UidGidExtent;
typedef struct UidGidMap {
UINT32 extentCount;
union {
UidGidExtent extent[UID_GID_MAP_MAX_EXTENTS];
};
} UidGidMap;
typedef struct UserContainer {
Atomic rc;
INT32 level;
UINT32 owner;
UINT32 group;
struct UserContainer *parent;
UidGidMap uidMap;
UidGidMap gidMap;
UINT32 containerID;
} UserContainer;
UINT32 OsCreateUserContainer(Credentials *newCredentials, UserContainer *parentUserContainer);
VOID FreeUserContainer(UserContainer *userContainer);
UINT32 OsFromKuidMunged(UserContainer *userContainer, UINT32 kuid);
UINT32 OsFromKgidMunged(UserContainer *userContainer, UINT32 kgid);
UINT32 OsMakeKuid(UserContainer *userContainer, UINT32 uid);
UINT32 OsMakeKgid(UserContainer *userContainer, UINT32 gid);
INT32 OsUserContainerMapWrite(struct ProcFile *fp, CHAR *buf, size_t count,
INT32 capSetid, UidGidMap *map, UidGidMap *parentMap);
#endif
#endif
......@@ -448,7 +448,11 @@ int SysGetEffUserID(void)
int euid;
SCHEDULER_LOCK(intSave);
#ifdef LOSCFG_USER_CONTAINER
euid = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->euid);
#else
euid = (int)OsCurrUserGet()->effUserID;
#endif
SCHEDULER_UNLOCK(intSave);
return euid;
#else
......@@ -463,7 +467,11 @@ int SysGetEffGID(void)
int egid;
SCHEDULER_LOCK(intSave);
#ifdef LOSCFG_USER_CONTAINER
egid = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->egid);
#else
egid = (int)OsCurrUserGet()->effGid;
#endif
SCHEDULER_UNLOCK(intSave);
return egid;
#else
......@@ -479,9 +487,15 @@ int SysGetRealEffSaveUserID(int *ruid, int *euid, int *suid)
unsigned int intSave;
SCHEDULER_LOCK(intSave);
#ifdef LOSCFG_USER_CONTAINER
realUserID = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->uid);
effUserID = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->euid);
saveUserID = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->euid);
#else
realUserID = OsCurrUserGet()->userID;
effUserID = OsCurrUserGet()->effUserID;
saveUserID = OsCurrUserGet()->effUserID;
#endif
SCHEDULER_UNLOCK(intSave);
#else
realUserID = 0;
......@@ -507,6 +521,58 @@ int SysGetRealEffSaveUserID(int *ruid, int *euid, int *suid)
return 0;
}
#ifdef LOSCFG_USER_CONTAINER
long SysSetUserID(int uid)
{
#ifdef LOSCFG_SECURITY_CAPABILITY
UserContainer *userContainer = CurrentCredentials()->userContainer;
int retval = -EPERM;
unsigned int intSave;
UINT32 kuid = OsMakeKuid(userContainer, uid);
if (kuid == (UINT32)-1) {
return -EINVAL;
}
Credentials *newCredentials = PrepareCredential(OsCurrProcessGet());
if (newCredentials == NULL) {
return -ENOMEM;
}
Credentials *oldCredentials = CurrentCredentials();
SCHEDULER_LOCK(intSave);
User *user = OsCurrUserGet();
if (IsCapPermit(CAP_SETUID)) {
newCredentials->uid = kuid;
if (kuid != oldCredentials->uid) {
user->userID = kuid;
user->effUserID = kuid;
}
retval = LOS_OK;
} else if (kuid != oldCredentials->uid) {
goto ERROR;
}
newCredentials->euid = kuid;
retval = CommitCredentials(newCredentials);
SCHEDULER_UNLOCK(intSave);
return retval;
ERROR:
FreeCredential(newCredentials);
SCHEDULER_UNLOCK(intSave);
return retval;
#else
if (uid != 0) {
return -EPERM;
}
return 0;
#endif
}
#else
int SysSetUserID(int uid)
{
#ifdef LOSCFG_SECURITY_CAPABILITY
......@@ -540,6 +606,7 @@ EXIT:
return 0;
#endif
}
#endif
#ifdef LOSCFG_SECURITY_CAPABILITY
static int SetRealEffSaveUserIDCheck(int ruid, int euid, int suid)
......@@ -607,6 +674,62 @@ int SysSetRealEffUserID(int ruid, int euid)
#endif
}
#ifdef LOSCFG_USER_CONTAINER
int SysSetGroupID(int gid)
{
#ifdef LOSCFG_SECURITY_CAPABILITY
UserContainer *userContainer = CurrentCredentials()->userContainer;
int retval = -EPERM;
unsigned int oldGid;
unsigned int intSave;
int count;
unsigned int kgid = OsMakeKgid(userContainer, gid);
if (kgid == (UINT32)-1) {
return -EINVAL;
}
Credentials *newCredentials = PrepareCredential(OsCurrProcessGet());
if (newCredentials == NULL) {
return -ENOMEM;
}
SCHEDULER_LOCK(intSave);
User *user = OsCurrUserGet();
if (IsCapPermit(CAP_SETGID)) {
newCredentials->gid = kgid;
newCredentials->egid = kgid;
oldGid = user->gid;
user->gid = kgid;
user->effGid = kgid;
for (count = 0; count < user->groupNumber; count++) {
if (user->groups[count] == oldGid) {
user->groups[count] = kgid;
retval = LOS_OK;
break;
}
}
} else if (user->gid != kgid) {
goto ERROR;
}
retval = CommitCredentials(newCredentials);
SCHEDULER_UNLOCK(intSave);
return retval;
ERROR:
FreeCredential(newCredentials);
SCHEDULER_UNLOCK(intSave);
return retval;
#else
if (gid != 0) {
return -EPERM;
}
return 0;
#endif
}
#else
int SysSetGroupID(int gid)
{
#ifdef LOSCFG_SECURITY_CAPABILITY
......@@ -651,6 +774,7 @@ EXIT:
return 0;
#endif
}
#endif
int SysGetRealEffSaveGroupID(int *rgid, int *egid, int *sgid)
{
......@@ -660,9 +784,15 @@ int SysGetRealEffSaveGroupID(int *rgid, int *egid, int *sgid)
unsigned int intSave;
SCHEDULER_LOCK(intSave);
#ifdef LOSCFG_USER_CONTAINER
realGroupID = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->gid);
effGroupID = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->egid);
saveGroupID = OsFromKuidMunged(OsCurrentUserContainer(), CurrentCredentials()->egid);
#else
realGroupID = OsCurrUserGet()->gid;
effGroupID = OsCurrUserGet()->effGid;
saveGroupID = OsCurrUserGet()->effGid;
#endif
SCHEDULER_UNLOCK(intSave);
#else
realGroupID = 0;
......
......@@ -142,6 +142,7 @@ LOSCFG_USER_TEST_UTS_CONTAINER = false
LOSCFG_USER_TEST_MNT_CONTAINER = false
LOSCFG_USER_TEST_IPC_CONTAINER = false
LOSCFG_USER_TEST_TIME_CONTAINER = false
LOSCFG_USER_TEST_USER_CONTAINER = false
if (defined(LOSCFG_KERNEL_CONTAINER) || liteos_container_test_enable == true) {
LOSCFG_USER_TEST_CONTAINER = true
if (defined(LOSCFG_PID_CONTAINER) || liteos_container_test_enable == true) {
......@@ -159,6 +160,9 @@ if (defined(LOSCFG_KERNEL_CONTAINER) || liteos_container_test_enable == true) {
if (defined(LOSCFG_TIME_CONTAINER) || liteos_container_test_enable == true) {
LOSCFG_USER_TEST_TIME_CONTAINER = true
}
if (defined(LOSCFG_USER_CONTAINER) || liteos_container_test_enable == true) {
LOSCFG_USER_TEST_USER_CONTAINER = true
}
}
########## fuzz test ##########
......
......@@ -47,6 +47,9 @@ config("container_config") {
if (defined(LOSCFG_USER_TEST_TIME_CONTAINER)) {
cflags += [ "-DLOSCFG_USER_TEST_TIME_CONTAINER" ]
}
if (defined(LOSCFG_USER_TEST_USER_CONTAINER)) {
cflags += [ "-DLOSCFG_USER_TEST_USER_CONTAINER" ]
}
cflags_cc = cflags
}
......
......@@ -589,6 +589,55 @@ HWTEST_F(ContainerTest, ItTimeContainer010, TestSize.Level0)
ItTimeContainer010();
}
#endif
#if defined(LOSCFG_USER_TEST_USER_CONTAINER)
/**
* @tc.name: Container_UTS_Test_001
* @tc.desc: uts container function test case
* @tc.type: FUNC
* @tc.require: issueI6EC0A
* @tc.author:
*/
HWTEST_F(ContainerTest, ItUserContainer001, TestSize.Level0)
{
ItUserContainer001();
}
/**
* @tc.name: Container_UTS_Test_002
* @tc.desc: uts container function test case
* @tc.type: FUNC
* @tc.require: issueI6EC0A
* @tc.author:
*/
HWTEST_F(ContainerTest, ItUserContainer002, TestSize.Level0)
{
ItUserContainer002();
}
/**
* @tc.name: Container_UTS_Test_003
* @tc.desc: uts container function test case
* @tc.type: FUNC
* @tc.require: issueI6EC0A
* @tc.author:
*/
HWTEST_F(ContainerTest, ItUserContainer003, TestSize.Level0)
{
ItUserContainer003();
}
/**
* @tc.name: Container_UTS_Test_004
* @tc.desc: uts container function test case
* @tc.type: FUNC
* @tc.require: issueI6EC0A
* @tc.author:
*/
HWTEST_F(ContainerTest, ItUserContainer004, TestSize.Level0)
{
ItUserContainer004();
}
#endif
#endif /* LOSCFG_USER_TEST_SMOKE */
#if defined(LOSCFG_USER_TEST_FULL)
......@@ -884,6 +933,19 @@ HWTEST_F(ContainerTest, ItUtsContainer003, TestSize.Level0)
ItUtsContainer003();
}
#endif
#if defined(LOSCFG_USER_TEST_USER_CONTAINER)
/**
* @tc.name: Container_UTS_Test_005
* @tc.desc: uts container function test case
* @tc.type: FUNC
* @tc.require: issueI6EC0A
* @tc.author:
*/
HWTEST_F(ContainerTest, ItUserContainer005, TestSize.Level0)
{
ItUserContainer005();
}
#endif
#endif
} // namespace OHOS
......
......@@ -137,6 +137,11 @@ private:
int m_shmid;
};
void ItUserContainer001(void);
void ItUserContainer002(void);
void ItUserContainer003(void);
void ItUserContainer004(void);
void ItUserContainer005(void);
#if defined(LOSCFG_USER_TEST_SMOKE)
void ItContainer001(void);
void ItContainerChroot001(void);
......
......@@ -128,3 +128,14 @@ if (defined(LOSCFG_USER_TEST_TIME_CONTAINER)) {
"$TEST_UNITTEST_DIR/container/smoke/It_time_container_010.cpp",
]
}
if (defined(LOSCFG_USER_TEST_USER_CONTAINER)) {
sources_smoke += [
"$TEST_UNITTEST_DIR/container/smoke/It_user_container_001.cpp",
"$TEST_UNITTEST_DIR/container/smoke/It_user_container_002.cpp",
"$TEST_UNITTEST_DIR/container/smoke/It_user_container_003.cpp",
"$TEST_UNITTEST_DIR/container/smoke/It_user_container_004.cpp",
]
sources_full +=
[ "$TEST_UNITTEST_DIR/container/full/It_user_container_005.cpp" ]
}
/*
* Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "It_container_test.h"
#include "sys/resource.h"
#include "sys/wait.h"
#include "pthread.h"
#include "sched.h"
const int EXIT_TRUE_CODE = 255;
const int MAX_PID_RANGE = 100000;
const int SLEEP_TIME_US = 1000;
const int LOOP_NUM = 1000;
static int childFunc(void *arg)
{
(void)arg;
usleep(SLEEP_TIME_US);
exit(EXIT_TRUE_CODE);
}
static int GroupProcess(void *arg)
{
(void)arg;
int ret;
int status = 0;
for (int i = 0; i < LOOP_NUM; i++) {
int arg_child = CHILD_FUNC_ARG;
auto pid = CloneWrapper(childFunc, CLONE_NEWUSER, &arg_child);
if (pid == -1) {
return EXIT_CODE_ERRNO_1;
}
ret = waitpid(pid, &status, 0);
if (ret != pid) {
return EXIT_CODE_ERRNO_2;
}
status = WEXITSTATUS(status);
if (status != EXIT_TRUE_CODE) {
return EXIT_CODE_ERRNO_3;
}
}
exit(EXIT_TRUE_CODE);
}
void ItUserContainer005(void)
{
int ret;
int status = 0;
int arg = CHILD_FUNC_ARG;
auto pid = CloneWrapper(GroupProcess, CLONE_NEWUSER, &arg);
ASSERT_NE(pid, -1);
ret = waitpid(pid, &status, 0);
ASSERT_EQ(ret, pid);
status = WEXITSTATUS(status);
ASSERT_EQ(status, EXIT_TRUE_CODE);
}
/*
* Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "It_container_test.h"
using namespace std;
const int RETURN_CODE = 2;
static int childFunc(void *arg)
{
int value = *((int*)arg);
if (value != CHILD_FUNC_ARG) {
return EXIT_CODE_ERRNO_1;
}
sleep(1);
return RETURN_CODE;
}
void ItUserContainer001(void)
{
int ret;
int arg = CHILD_FUNC_ARG;
auto pid = CloneWrapper(childFunc, CLONE_NEWUSER, &arg);
ASSERT_NE(pid, -1);
int status;
ret = waitpid(pid, &status, 0);
ASSERT_EQ(ret, pid);
ret = WIFEXITED(status);
ASSERT_NE(ret, 0);
int exitCode = WEXITSTATUS(status);
ASSERT_EQ(exitCode, RETURN_CODE);
}
/*
* Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "It_container_test.h"
#include "sys/utsname.h"
const int EXIT_TRUE_CODE = 255;
const int TEST_SET_OLD_ID = 1001;
const int TEST_SET_NEW_ID = 4;
static const int SLEEP_TIME = 3;
std::string GetIdMapPath(int pid, const std::string& mapType)
{
std::ostringstream buf;
buf << "/proc/" << pid << "/" << mapType;
return buf.str();
}
int WriteIdMap(int pid)
{
std::string uidMapPath = GetIdMapPath(pid, "uid_map");
std::string gidMapPath = GetIdMapPath(pid, "gid_map");
const char* idMapStr = "0 1000 1\n1 1001 1\n2 1002 1\n3 1003 1\n4 1004 1\n";
int strLen = strlen(idMapStr);
int uidMap = open(uidMapPath.c_str(), O_WRONLY);
if (uidMap == -1) {
return EXIT_CODE_ERRNO_1;
}
int ret = write(uidMap, idMapStr, strLen);
if (ret != strLen) {
close(uidMap);
return EXIT_CODE_ERRNO_2;
}
close(uidMap);
int gidMap = open(gidMapPath.c_str(), O_WRONLY);
if (gidMap == -1) {
close(gidMap);
return EXIT_CODE_ERRNO_3;
}
ret = write(gidMap, idMapStr, strLen);
if (ret != strLen) {
close(gidMap);
return EXIT_CODE_ERRNO_4;
}
close(gidMap);
return 0;
}
static int childFunc(void *arg)
{
(void)arg;
sleep(SLEEP_TIME);
int newUid = getuid();
if (newUid != 1) {
return EXIT_CODE_ERRNO_1;
}
int newGid = getgid();
if (newGid != 1) {
return EXIT_CODE_ERRNO_2;
}
int ret = setuid(TEST_SET_NEW_ID);
if (ret != 0) {
return EXIT_CODE_ERRNO_3;
}
ret = setgid(TEST_SET_NEW_ID);
if (ret != 0) {
return EXIT_CODE_ERRNO_4;
}
newUid = getuid();
if (newUid != TEST_SET_NEW_ID) {
return EXIT_CODE_ERRNO_5;
}
newGid = getgid();
if (newGid != TEST_SET_NEW_ID) {
return EXIT_CODE_ERRNO_6;
}
exit(EXIT_TRUE_CODE);
}
void ItUserContainer002(void)
{
int ret = setuid(TEST_SET_OLD_ID);
ASSERT_EQ(ret, 0);
int oldUid = getuid();
ASSERT_EQ(oldUid, TEST_SET_OLD_ID);
ret = setgid(TEST_SET_OLD_ID);
ASSERT_EQ(ret, 0);
int oldGid = getgid();
ASSERT_EQ(oldGid, TEST_SET_OLD_ID);
int arg = CHILD_FUNC_ARG;
auto pid = CloneWrapper(childFunc, CLONE_NEWUSER, &arg);
ASSERT_NE(pid, -1);
ret = WriteIdMap(pid);
ASSERT_EQ(ret, 0);
int status;
ret = waitpid(pid, &status, 0);
ASSERT_EQ(ret, pid);
status = WEXITSTATUS(status);
ASSERT_EQ(status, EXIT_TRUE_CODE);
int oldUid1 = getuid();
ASSERT_EQ(oldUid1, TEST_SET_OLD_ID);
int oldGid1 = getgid();
ASSERT_EQ(oldGid1, TEST_SET_OLD_ID);
ASSERT_EQ(oldUid, oldUid1);
ASSERT_EQ(oldGid, oldGid1);
}
/*
* Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "It_container_test.h"
#include "sys/utsname.h"
const int EXIT_TRUE_CODE = 255;
const int MAX_PID_RANGE = 100000;
const int TEST_SET_OLD_ID = 1001;
const int TEST_SET_NEW_ID = 4;
std::string GetIdMapPath(int pid, const std::string& mapType);
int WriteIdMap(int pid);
static int TestMap(int oldUid, int oldGid)
{
pid_t pid = getpid();
int ret = WriteIdMap(pid);
if (ret != 0) {
return EXIT_CODE_ERRNO_6;
}
int newUid = getuid();
if (newUid != 1) {
return EXIT_CODE_ERRNO_7;
}
int newGid = getgid();
if (newGid != 1) {
return EXIT_CODE_ERRNO_8;
}
ret = setuid(TEST_SET_NEW_ID);
if (ret != 0) {
return EXIT_CODE_ERRNO_9;
}
ret = setgid(TEST_SET_NEW_ID);
if (ret != 0) {
return EXIT_CODE_ERRNO_10;
}
newUid = getuid();
if (newUid != TEST_SET_NEW_ID) {
return EXIT_CODE_ERRNO_11;
}
newGid = getgid();
if (newGid != TEST_SET_NEW_ID) {
exit(1);
}
if (oldUid == newUid) {
return EXIT_CODE_ERRNO_12;
}
if (oldGid == newGid) {
return EXIT_CODE_ERRNO_13;
}
return 0;
}
static int childFunc(void *arg)
{
(void)arg;
int ret;
int oldUid;
int oldGid;
ret = setuid(TEST_SET_OLD_ID);
if (ret != 0) {
return EXIT_CODE_ERRNO_1;
}
oldUid = getuid();
if (oldUid != TEST_SET_OLD_ID) {
return EXIT_CODE_ERRNO_2;
}
ret = setgid(TEST_SET_OLD_ID);
if (ret != 0) {
return EXIT_CODE_ERRNO_3;
}
oldGid = getgid();
if (oldGid != TEST_SET_OLD_ID) {
return EXIT_CODE_ERRNO_4;
}
ret = unshare(CLONE_NEWUSER);
if (ret == -1) {
return EXIT_CODE_ERRNO_5;
}
ret = TestMap(oldUid, oldGid);
if (ret != 0) {
return ret;
}
exit(EXIT_TRUE_CODE);
}
void ItUserContainer003(void)
{
int ret;
int status = 0;
int arg = CHILD_FUNC_ARG;
auto pid = CloneWrapper(childFunc, SIGCHLD, &arg);
ASSERT_NE(pid, -1);
ret = waitpid(pid, &status, 0);
ASSERT_EQ(ret, pid);
status = WEXITSTATUS(status);
ASSERT_EQ(status, EXIT_TRUE_CODE);
}
/*
* Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sched.h>
#include <unistd.h>
#include <string>
#include <iostream>
#include "It_container_test.h"
const int EXIT_TRUE_CODE = 255;
const int MAX_PID_RANGE = 100000;
static int childFunc(void *arg)
{
(void)arg;
std::string containerType = "user";
std::string childlink;
std::string filePath;
std::string parentlink1;
int fd;
int ret;
int status;
int parentPid = getpid();
auto parentlink = ReadlinkContainer(parentPid, containerType);
int childsPid = CloneWrapper(ChildFunction, CLONE_NEWUSER, NULL);
if (childsPid == -1) {
return EXIT_CODE_ERRNO_1;
}
childlink = ReadlinkContainer(childsPid, containerType);
filePath = GenContainerLinkPath(childsPid, containerType);
fd = open(filePath.c_str(), O_RDONLY);
if (fd == -1) {
return EXIT_CODE_ERRNO_2;
}
ret = setns(fd, CLONE_NEWUSER);
if (ret == -1) {
close(fd);
return EXIT_CODE_ERRNO_3;
}
parentlink1 = ReadlinkContainer(parentPid, containerType);
close(fd);
ret = waitpid(childsPid, &status, 0);
if (ret != childsPid) {
return EXIT_CODE_ERRNO_4;
}
ret = parentlink.compare(parentlink1);
if (ret == 0) {
return EXIT_CODE_ERRNO_5;
}
ret = parentlink1.compare(childlink);
if (ret != 0) {
return EXIT_CODE_ERRNO_6;
}
exit(EXIT_TRUE_CODE);
}
void ItUserContainer004(void)
{
int ret;
int status = 0;
int arg = CHILD_FUNC_ARG;
auto pid = CloneWrapper(childFunc, SIGCHLD, &arg);
ASSERT_NE(pid, -1);
ret = waitpid(pid, &status, 0);
ASSERT_EQ(ret, pid);
status = WEXITSTATUS(status);
ASSERT_EQ(status, EXIT_TRUE_CODE);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册