# FineGrainedSyscall **Repository Path**: distributed-access-control/fine-grained-syscall ## Basic Information - **Project Name**: FineGrainedSyscall - **Description**: Fine-grained syscall enforcement for C/S apps. - **Primary Language**: C - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-02-22 - **Last Updated**: 2021-08-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 项目结构 本项目包含: 1. 系统调用额外参数性能开销评估 2. 系统调用Sandbox实现(TODO) 本项目依赖Kernel项目,并且需要使用qemu运行我们修改过的Kernel,并在用户态运行评估程序。 ``` fine-grained-syscall ├── README.md ├── bin # 放qemu镜像等运行需要的文件 ├── docs # 文档 ├── kernel-5.11.2 # kernel代码(需要自己Clone) ├── init.sh # 安装qemu和kernel编译依赖 ├── run.sh # 运行qemu ├── setup_img.sh # 初始化qemu镜像 └── userspace # 用户态评测程序 ``` 项目初始化: - 获取kernel项目 ``` git clone https://gitee.com/distributed-access-control/kernel-5.11.2.git ``` - 初始化qemu镜像 ``` ./init.sh ./setup_img.sh ./run.sh ``` 参考: [1. 基于Qemu的开发环境部署](docs/2.dev.md) ## 系统调用额外参数检查设计 ### 1. 设计目标 客体Service在响应多个Client时,强制访问控制根据客体(service)的ID来进行权限判断。 为了能精确映射主体(Client)的ID,需要Service在调用系统调用时将Client ID也传递到 系统调用中,这样就能根据Client ID去确定Client是否有权限。 我们只需要对少量的系统调用进行额外判断,例如:检查File相关的系统调用来实现对访问 目录的控制,以及检查ioctl参数实现对Binder通信对象的限制。 ### 2. 实例说明 为了评估额外的检查带来的性能开销,我们选取read系统调用,添加一个参数来表示client_id, 并进行额外的权限检查: ``` // 原版 SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) { return ksys_read(fd, buf, count); } // 我们的版本 SYSCALL_DEFINE4(myread, int, client_id, unsigned int, fd, char __user *, buf, size_t, count) { // printk("This is myread syscall: %d\n", client_id); if (!check_valid_client(client_id)) { // printk("check_valid_client") return -1; } return ksys_read(fd, buf, count);; } ``` ### 3. 框架层封装 最终这个额外的参数client_id可以由框架层自动填充,例如:Binder对象中自动传入BinderId。 ## Demo实现说明 1. 代码说明 用户态评估代码: https://gitee.com/distributed-access-control/fine-grained-syscall/blob/master/userspace/src/main.c kernel层修改: https://gitee.com/distributed-access-control/kernel-5.11.2/blob/master/hello/hello.c 我们使用hashmap来记录client权限(主体标识映射),这里使用的RCU map。每一次调用都去查询是否有权限。单次调用会查询hashmap来确定是否有权限: ``` hash_for_each_possible_rcu(acl_tbl, cur, node, key) { struct client_info *client = cur->client; // 遍历当前chain if (client_id == client->client_id) { // pr_info("myhashtable: element named %d found!\n", client_id); return client->op == 1; } return 0; } ``` 2. 系统调用client_id映射评估 修改Linux-5.11.2 kernel实现了对SYS_read的简单封装,进行client_id映射。 评估方法: 分别读取4M和400M的文件,约13w~1300w次系统调用累计时间的延时。取200次测量的平均值。 i. hashtable中hash没出现冲突(100元素,桶数量256),不需要去遍历链表: 无权限的情况下直接返回,单次查询时间: ``` Origin Syscall-----------------------Start Microbenchmark: read once Time: 0.000606s Marcobenchmark: read size 4194304 Time: 0.273496s Origin Syscall-----------------------End New Syscall-----------------------Start Microbenchmark: read once Time: 0.000195s Marcobenchmark: read size -1 Time: 0.000016s New Syscall-----------------------End ``` 有权限,进行检查之后继续调用原始系统调用: ``` # 4M Origin Syscall-----------------------Start Microbenchmark: read once Time: 0.000097s Marcobenchmark: read size 4194304 Time: 0.275600s Origin Syscall-----------------------End New Syscall-----------------------Start Microbenchmark: read once Time: 0.000047s Marcobenchmark: read size 4194304 Time: 0.288025s New Syscall-----------------------End # 400M Origin Syscall-----------------------Start Microbenchmark: read once Time: 0.000251s Marcobenchmark: read size 41943040 Time: 2.717510s Origin Syscall-----------------------End New Syscall-----------------------Start Microbenchmark: read once Time: 0.000056s Marcobenchmark: read size 41943040 Time: 2.674195s New Syscall-----------------------End ``` 平均overhead为: 13w -> 0.70%, 1300w -> 0.82% ii. 用不同的hashmap参数比较一下时间。100元素,桶数量32,存在hash冲突, chain的长度约为4。 平均:13w -> 3.78% 1300w -> 5.9% 开销分析: 我们只需要对open、ioctl这些设置fd的系统调用进行检查,read/write这些频繁操作fd的系统调用不需要每次都检查。 因此对整体系统开销的相当于有限次数的调用,单次调用时的权限检查的性能消耗几乎可以忽略不计。因此可以用于非热点Syscall。 ## 系统调用沙盒(TODO)