Add task capability in capability.c Add corresponding settings during system startup from Zhuruohai

it is OK
This commit is contained in:
xuedongliang 2024-12-30 09:36:42 +08:00
commit ed934b5bae
10 changed files with 323 additions and 1 deletions

View File

@ -3,7 +3,7 @@ menu "File system"
menuconfig FS_VFS menuconfig FS_VFS
bool "Using device virtual file system" bool "Using device virtual file system"
select KERNEL_MUTEX select KERNEL_MUTEX
default n default y
help help
The device file system is a light weight virtual file system. The device file system is a light weight virtual file system.

View File

@ -78,6 +78,10 @@ menu "Kernel feature"
help help
Enable task isolation Enable task isolation
config KERNEL_CAPABILITY
bool "Enable task capability"
default n
menu "Inter-Task communication" menu "Inter-Task communication"
config KERNEL_SEMAPHORE config KERNEL_SEMAPHORE
bool "Enable semaphore" bool "Enable semaphore"

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file: xs_capability.h
* @brief: capability header file for XiZi-IIoT
* @version: 1.0
* @author: AIIT XUOS Lab
* @date: 2024/10/14
*
*/
#ifndef XS_CAPABILITY_H
#define XS_CAPABILITY_H
/* import board special configuration */
#include <xsconfig.h>
#include <xs_base.h>
#include <xs_memory.h>
#include <xs_assign.h>
// assume the number of capability types is limited to 8*MAX_NUM_TA
typedef enum {
XS_CAP = 0,
XS_CAP_ROOT,
XS_CAP_TASK,
XS_CAP_MEM,
XS_CAP_RESOURCES,
XS_CAP_MAX // the number of capability types
} xs_capability_type;
typedef struct {
uint8 flags[XS_CAP_MAX/8+1];
} xs_capability, *xs_capability_t;
typedef struct {
int32 pid;
xs_capability cap;
} xs_task_capability, *xs_task_capability_t;
typedef struct capability_node{
xs_task_capability inner;
struct capability_node* next;
} capability_node, *capability_node_t;
// functions to manipulate capability flags
int CheckCapability(xs_capability *cap, xs_capability_type type);
// set_capability and clear_capability are used to manipulate capability flags
void SetCapability(xs_capability *cap, xs_capability_type type);
// clear_capability is used to manipulate capability flags
void ClearCapability(xs_capability *cap, xs_capability_type type);
// functions to manipulate task capabilities
xs_capability* FindTaskCapability(int32 pid);
// add_task_capability and remove_task_capability are used to manipulate task capabilities
void AddTaskCapability(int32 pid, xs_capability *cap);
// remove_task_capability is used to manipulate task capabilities
void RemoveTaskCapability(int32 pid);
// add_root_task_capability is used to manipulate task capabilities
void AddRootTaskCapability(int32 pid);
// Capability_Copy is used to deep copy capabilitie
void CapabilityCopy(xs_capability *cap, xs_capability *cap_copy_from);
// check_task_capability is used to check if a task has a certain capability
x_bool CheckTaskCapability(int32 pid, xs_capability_type type);
// set_task_capability and clear_task_capability are used to manipulate task capabilities
void SetTaskCapability(int32 pid, xs_capability_type type);
// clear_task_capability is used to manipulate task capabilities
void ClearTaskCapability(int32 pid, xs_capability_type type);
// test
void PrintTaskCapability();
typedef struct CapsOps
{
int (*CheckCap) (xs_capability *cap, xs_capability_type type);
void (*SetCap) (xs_capability *cap, xs_capability_type type);
void (*ClearCap) (xs_capability *cap, xs_capability_type type);
xs_capability* (*GetTaskCaps) (int32 pid);
void (*AddTaskCaps) (int32 pid, xs_capability *cap);
void (*RemoveTaskCaps) (int32 pid);
void (*AddRootTaskCaps) (int32 pid);
void (*Copy)(xs_capability *cap, xs_capability *cap_copy_from);
x_bool (*CheckTaskCap)(int32 pid, xs_capability_type type);
void (*SetTaskCap) (int32 pid, xs_capability_type type);
void (*ClearTaskCap) (int32 pid, xs_capability_type type);
void (*Print) ();
} CapsOps;
#endif /* XS_CAPABILITY_H */

View File

@ -11,6 +11,10 @@ menuconfig KERNEL_TEST
bool "Config test Circular area" bool "Config test Circular area"
default n default n
select KERNEL_CIRCULAR_AREA select KERNEL_CIRCULAR_AREA
config KERNEL_TEST_CAPABILITY
bool "Config test capability"
default n
select KERNEL_AVL_TREE
config KERNEL_TEST_MEM config KERNEL_TEST_MEM
bool "Config test mem" bool "Config test mem"
default n default n

View File

@ -16,6 +16,11 @@ ifeq ($(CONFIG_KERNEL_TEST_MSG),y)
SRC_FILES += test_mq.c SRC_FILES += test_mq.c
endif endif
ifeq ($(CONFIG_KERNEL_TEST_CAPABILITY),y)
SRC_FILES += test_capability.c
endif
ifeq ($(CONFIG_KERNEL_TEST_AVLTREE),y) ifeq ($(CONFIG_KERNEL_TEST_AVLTREE),y)
SRC_FILES += test_avltree.c SRC_FILES += test_avltree.c
endif endif

View File

@ -75,4 +75,9 @@ ifeq ($(CONFIG_USER_APPLICATION),y)
SRC_FILES += appstartup.c SRC_FILES += appstartup.c
endif endif
ifeq ($(CONFIG_KERNEL_CAPABILITY),y)
SRC_FILES += capability.c
endif
include $(KERNEL_ROOT)/compiler.mk include $(KERNEL_ROOT)/compiler.mk

View File

@ -28,6 +28,11 @@
#ifdef APP_STARTUP_FROM_SDCARD #ifdef APP_STARTUP_FROM_SDCARD
#include <iot-vfs_posix.h> #include <iot-vfs_posix.h>
#endif #endif
#ifdef KERNEL_CAPABILITY
#include <xs_capability.h>
extern CapsOps CapsOperations;
#endif
extern int main(void); extern int main(void);
#ifdef USER_APPLICATION #ifdef USER_APPLICATION
@ -76,6 +81,10 @@ void CreateMainTask(void)
KPrintf("main create failed ...%s %d.\n",__FUNCTION__,__LINE__); KPrintf("main create failed ...%s %d.\n",__FUNCTION__,__LINE__);
return; return;
} }
#ifdef KERNEL_CAPABILITY
// MainTask has Root privileges
CapsOperations.SetTaskCap(main, XS_CAP_ROOT);
#endif
StartupKTask(main); StartupKTask(main);
} }

View File

@ -0,0 +1,160 @@
#include "xs_capability.h"
#ifdef __cplusplus
#define NULL 0L
#else
#define NULL ((void*)0)
#endif
// global task capability list, used to manage task capabilities
static capability_node task_capabilities={
.next = NULL
};
CapsOps CapsOperations = {
CheckCapability,
SetCapability,
ClearCapability,
FindTaskCapability,
AddTaskCapability,
RemoveTaskCapability,
AddRootTaskCapability,
CapabilityCopy,
CheckTaskCapability,
SetTaskCapability,
ClearTaskCapability,
PrintTaskCapability,
};
// functions to manipulate capability flags
int CheckCapability(xs_capability *cap, xs_capability_type type){
return cap->flags[type/8] & (1 << (type%8));
}
// set_capability and clear_capability are used to manipulate capability flags
void SetCapability(xs_capability *cap, xs_capability_type type){
cap->flags[type/8] |= (1 << (type%8));
}
// clear_capability is used to manipulate capability flags
void ClearCapability(xs_capability *cap, xs_capability_type type){
cap->flags[type/8] &= ~(1 << (type%8));
}
// functions to manipulate task capabilities
xs_capability* FindTaskCapability(int32 pid){
capability_node* node = task_capabilities.next;
while(node){
if(node->inner.pid == pid){
return &node->inner.cap;
}
node = node->next;
}
return NULL;
}
// test print
void PrintTaskCapability(){
x_base lock = CriticalAreaLock();
capability_node* node = task_capabilities.next;
KPrintf("All cap:\n");
while(node){
KPrintf("pid : %d, : %d \n", node->inner.pid, node->inner.cap.flags[0]);
node = node->next;
}
KPrintf("\n");
CriticalAreaUnLock(lock);
}
// add_task_capability and remove_task_capability are used to manipulate task capabilities
void AddTaskCapability(int32 pid, xs_capability *cap){
x_base lock = CriticalAreaLock();
capability_node* node = (capability_node*)x_malloc(sizeof(capability_node));
node->inner.pid = pid;
node->inner.cap = *cap;
node->next = task_capabilities.next;
task_capabilities.next = node;
CriticalAreaUnLock(lock);
}
// add_root_task_capability is used to manipulate task capabilities
void AddRootTaskCapability(int32 pid){
x_base lock = CriticalAreaLock();
capability_node* node = (capability_node*)x_malloc(sizeof(capability_node));
xs_capability *cap = (xs_capability*)x_malloc(sizeof(xs_capability));
for(int i = 0; i < XS_CAP_MAX/8+1; i++) cap->flags[i] = 0xFF;
node->inner.pid = pid;
node->inner.cap = *cap;
node->next = task_capabilities.next;
task_capabilities.next = node;
CriticalAreaUnLock(lock);
}
// Capability_Copy is used to deep copy capabilitie
void CapabilityCopy(xs_capability *cap, xs_capability *cap_copy_from){
for(int i = 0; i < XS_CAP_MAX/8+1; i++){
cap->flags[i] = cap_copy_from->flags[i];
}
}
// remove_task_capability is used to manipulate task capabilities
void RemoveTaskCapability(int32 pid){
x_base lock = CriticalAreaLock();
capability_node* node = &task_capabilities;
while(node->next){
if(node->next->inner.pid == pid){
capability_node* removing = node->next;
node->next = node->next->next;
x_free(removing);
CriticalAreaUnLock(lock);
return;
}
node = node->next;
}
CriticalAreaUnLock(lock);
}
// check_task_capability is used to check if a task has a certain capability
x_bool CheckTaskCapability(int32 pid, xs_capability_type type){
x_base lock = CriticalAreaLock();
xs_capability* cap = FindTaskCapability(pid);
x_bool result = cap && CheckCapability(cap, type);
CriticalAreaUnLock(lock);
return result;
}
// set_task_capability and clear_task_capability are used to manipulate task capabilities
void SetTaskCapability(int32 pid, xs_capability_type type){
int32 current = GetKTaskDescriptor()->id.id;
xs_capability* cap = FindTaskCapability(current);
if(CheckCapability(cap, XS_CAP_ROOT)){
x_base lock = CriticalAreaLock();
xs_capability* cap = FindTaskCapability(pid);
if(cap){
SetCapability(cap, type);
}
CriticalAreaUnLock(lock);
} else {
KPrintf("No permission to SetTaskCapability\n");
}
}
// clear_task_capability is used to manipulate task capabilities
void ClearTaskCapability(int32 pid, xs_capability_type type){
int32 current = GetKTaskDescriptor()->id.id;
xs_capability* cap = FindTaskCapability(current);
if(CheckCapability(cap, XS_CAP_ROOT) || current == pid){
x_base lock = CriticalAreaLock();
xs_capability* cap = FindTaskCapability(pid);
if(cap){
ClearCapability(cap, type);
}
CriticalAreaUnLock(lock);
} else {
KPrintf("No permission to ClearTaskCapability\n");
}
}

View File

@ -29,6 +29,10 @@
#include <xs_isolation.h> #include <xs_isolation.h>
#endif #endif
#ifdef KERNEL_CAPABILITY
#include <xs_capability.h>
extern CapsOps CapsOperations;
#endif
static volatile int __exstatus; static volatile int __exstatus;
extern DoubleLinklistType KTaskZombie; extern DoubleLinklistType KTaskZombie;
@ -51,6 +55,9 @@ DECLARE_ID_MANAGER(k_task_id_manager, ID_NUM_MAX);
void KTaskIdDelete(int32 id) void KTaskIdDelete(int32 id)
{ {
#ifdef KERNEL_CAPABILITY
CapsOperations.RemoveTaskCaps(id);
#endif
IdRemoveObj(&k_task_id_manager, id); IdRemoveObj(&k_task_id_manager, id);
} }
@ -861,6 +868,20 @@ int32 KTaskCreate(const char *name,
if( task->Done->init(task, name, entry, parameter, stack_depth, priority) == EOK ) { if( task->Done->init(task, name, entry, parameter, stack_depth, priority) == EOK ) {
HOOK(hook.task.hook_TaskCreate, (task)); HOOK(hook.task.hook_TaskCreate, (task));
#ifdef KERNEL_CAPABILITY
int32 current = GetKTaskDescriptor()->id.id;
KPrintf("current : %d, new : %d\n", current, id);
if(current >= 1000){
// The system has just started
CapsOperations.AddRootTaskCaps(id);
}else{
xs_capability *cap = (xs_capability*)x_malloc(sizeof(xs_capability));
xs_capability* current_cap = CapsOperations.GetTaskCaps(current);
CapsOperations.Copy(cap, current_cap);
CapsOperations.ClearCap(cap, XS_CAP_ROOT);
CapsOperations.AddTaskCaps(id, cap);
}
#endif
return id; return id;
} else { } else {
KPrintf("%s %d task init failed.\n",__func__,__LINE__); KPrintf("%s %d task init failed.\n",__func__,__LINE__);
@ -911,6 +932,9 @@ x_err_t KTaskDelete(int32 id)
task = GetTaskWithIdnodeInfo(id); task = GetTaskWithIdnodeInfo(id);
NULL_PARAM_CHECK(task); NULL_PARAM_CHECK(task);
#ifdef KERNEL_CAPABILITY
CapsOperations.RemoveTaskCaps(id);
#endif
return task->Done->Delete(task); return task->Done->Delete(task);
} }