From de438ed9a5f5e947590d5df66ad9c012c47d7567 Mon Sep 17 00:00:00 2001 From: zhuruohai Date: Mon, 28 Oct 2024 11:19:43 +0800 Subject: [PATCH] support task capability and fix a kconfig bug --- Ubiquitous/XiZi_IIoT/fs/Kconfig | 2 +- .../XiZi_IIoT/kernel/include/xs_capability.h | 26 ++++++ .../XiZi_IIoT/kernel/thread/appstartup.c | 9 ++ .../XiZi_IIoT/kernel/thread/capability.c | 87 ++++++++++++++++--- Ubiquitous/XiZi_IIoT/kernel/thread/ktask.c | 24 +++++ 5 files changed, 137 insertions(+), 11 deletions(-) diff --git a/Ubiquitous/XiZi_IIoT/fs/Kconfig b/Ubiquitous/XiZi_IIoT/fs/Kconfig index 37fc0e8fc..3fe35a067 100644 --- a/Ubiquitous/XiZi_IIoT/fs/Kconfig +++ b/Ubiquitous/XiZi_IIoT/fs/Kconfig @@ -3,7 +3,7 @@ menu "File system" menuconfig FS_VFS bool "Using device virtual file system" select KERNEL_MUTEX - default n + default y help The device file system is a light weight virtual file system. diff --git a/Ubiquitous/XiZi_IIoT/kernel/include/xs_capability.h b/Ubiquitous/XiZi_IIoT/kernel/include/xs_capability.h index f04fc6c17..48bda5625 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/include/xs_capability.h +++ b/Ubiquitous/XiZi_IIoT/kernel/include/xs_capability.h @@ -32,6 +32,7 @@ // 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, @@ -71,6 +72,12 @@ 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); @@ -80,6 +87,25 @@ 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 */ diff --git a/Ubiquitous/XiZi_IIoT/kernel/thread/appstartup.c b/Ubiquitous/XiZi_IIoT/kernel/thread/appstartup.c index 30ee11ac4..7eb02d493 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/thread/appstartup.c +++ b/Ubiquitous/XiZi_IIoT/kernel/thread/appstartup.c @@ -28,6 +28,11 @@ #ifdef APP_STARTUP_FROM_SDCARD #include #endif +#ifdef KERNEL_CAPABILITY +#include +extern CapsOps CapsOperations; +#endif + extern int main(void); #ifdef USER_APPLICATION @@ -76,6 +81,10 @@ void CreateMainTask(void) KPrintf("main create failed ...%s %d.\n",__FUNCTION__,__LINE__); return; } + #ifdef KERNEL_CAPABILITY + // MainTask has Root privileges + CapsOperations.SetTaskCap(main, XS_CAP_ROOT); + #endif StartupKTask(main); } diff --git a/Ubiquitous/XiZi_IIoT/kernel/thread/capability.c b/Ubiquitous/XiZi_IIoT/kernel/thread/capability.c index bc6c5bee3..c87563b07 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/thread/capability.c +++ b/Ubiquitous/XiZi_IIoT/kernel/thread/capability.c @@ -11,6 +11,21 @@ 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)); @@ -37,27 +52,66 @@ xs_capability* FindTaskCapability(int32 pid){ 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 @@ -71,22 +125,35 @@ 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){ - x_base lock = CriticalAreaLock(); - xs_capability* cap = FindTaskCapability(pid); - if(cap){ - SetCapability(cap, 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"); } - CriticalAreaUnLock(lock); + } // clear_task_capability is used to manipulate task capabilities void ClearTaskCapability(int32 pid, xs_capability_type type){ - x_base lock = CriticalAreaLock(); - xs_capability* cap = FindTaskCapability(pid); - if(cap){ - ClearCapability(cap, 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"); } - CriticalAreaUnLock(lock); } diff --git a/Ubiquitous/XiZi_IIoT/kernel/thread/ktask.c b/Ubiquitous/XiZi_IIoT/kernel/thread/ktask.c index b3b7b5381..4ffa7410a 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/thread/ktask.c +++ b/Ubiquitous/XiZi_IIoT/kernel/thread/ktask.c @@ -29,6 +29,10 @@ #include #endif +#ifdef KERNEL_CAPABILITY +#include +extern CapsOps CapsOperations; +#endif static volatile int __exstatus; extern DoubleLinklistType KTaskZombie; @@ -51,6 +55,9 @@ DECLARE_ID_MANAGER(k_task_id_manager, ID_NUM_MAX); void KTaskIdDelete(int32 id) { + #ifdef KERNEL_CAPABILITY + CapsOperations.RemoveTaskCaps(id); + #endif 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 ) { 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; } else { KPrintf("%s %d task init failed.\n",__func__,__LINE__); @@ -911,6 +932,9 @@ x_err_t KTaskDelete(int32 id) task = GetTaskWithIdnodeInfo(id); NULL_PARAM_CHECK(task); + #ifdef KERNEL_CAPABILITY + CapsOperations.RemoveTaskCaps(id); + #endif return task->Done->Delete(task); }