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/Kconfig b/Ubiquitous/XiZi_IIoT/kernel/Kconfig index 9d8756ef8..7df2e2c50 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/Kconfig +++ b/Ubiquitous/XiZi_IIoT/kernel/Kconfig @@ -78,6 +78,10 @@ menu "Kernel feature" help Enable task isolation + config KERNEL_CAPABILITY + bool "Enable task capability" + default n + menu "Inter-Task communication" config KERNEL_SEMAPHORE bool "Enable semaphore" diff --git a/Ubiquitous/XiZi_IIoT/kernel/include/xs_capability.h b/Ubiquitous/XiZi_IIoT/kernel/include/xs_capability.h new file mode 100644 index 000000000..48bda5625 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/kernel/include/xs_capability.h @@ -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 +#include +#include +#include + + +// 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 */ + + diff --git a/Ubiquitous/XiZi_IIoT/kernel/kernel_test/Kconfig b/Ubiquitous/XiZi_IIoT/kernel/kernel_test/Kconfig index 0de9621a0..6929939fe 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/kernel_test/Kconfig +++ b/Ubiquitous/XiZi_IIoT/kernel/kernel_test/Kconfig @@ -11,6 +11,10 @@ menuconfig KERNEL_TEST bool "Config test Circular area" default n select KERNEL_CIRCULAR_AREA + config KERNEL_TEST_CAPABILITY + bool "Config test capability" + default n + select KERNEL_AVL_TREE config KERNEL_TEST_MEM bool "Config test mem" default n diff --git a/Ubiquitous/XiZi_IIoT/kernel/kernel_test/Makefile b/Ubiquitous/XiZi_IIoT/kernel/kernel_test/Makefile index 1c4f0656a..4025274bd 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/kernel_test/Makefile +++ b/Ubiquitous/XiZi_IIoT/kernel/kernel_test/Makefile @@ -16,6 +16,11 @@ ifeq ($(CONFIG_KERNEL_TEST_MSG),y) SRC_FILES += test_mq.c endif +ifeq ($(CONFIG_KERNEL_TEST_CAPABILITY),y) + SRC_FILES += test_capability.c +endif + + ifeq ($(CONFIG_KERNEL_TEST_AVLTREE),y) SRC_FILES += test_avltree.c endif diff --git a/Ubiquitous/XiZi_IIoT/kernel/kernel_test/test_capability.c b/Ubiquitous/XiZi_IIoT/kernel/kernel_test/test_capability.c new file mode 100644 index 000000000..e69de29bb diff --git a/Ubiquitous/XiZi_IIoT/kernel/thread/Makefile b/Ubiquitous/XiZi_IIoT/kernel/thread/Makefile index 21cb5613f..bb8cd43ff 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/thread/Makefile +++ b/Ubiquitous/XiZi_IIoT/kernel/thread/Makefile @@ -75,4 +75,9 @@ ifeq ($(CONFIG_USER_APPLICATION),y) SRC_FILES += appstartup.c endif +ifeq ($(CONFIG_KERNEL_CAPABILITY),y) + SRC_FILES += capability.c +endif + + include $(KERNEL_ROOT)/compiler.mk 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 new file mode 100644 index 000000000..c87563b07 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/kernel/thread/capability.c @@ -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"); + } +} + + + 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); }