linux: my_cat实现

这篇博客介绍了两个实用的Linux命令行工具的实现:my_cat和my_ls。my_cat功能是读取文件并按指定选项显示内容,支持-b(不显示行号)和-n(显示行号)选项。my_ls则涉及目录操作和窗口尺寸获取,同时能够进行复杂的分列输出。文章深入探讨了getopt函数用于参数解析,以及dirent、opendir、readdir和access等文件操作函数的使用。

my_cat实现

功能:

-b 空行不标行号
-n 空行标行号

现在版本不支持读入多个文件,可以类似 ./a.out -b test -n test,因为optind每次while后都不移动,所以不知道如何实现类似./a.out -b test1 test2,多个文件读入。

Code:

知识点:getopd, fopen, fgets函数特性

/*************************************************************************
    > File Name: my_cat.c
    > Author: evadai
    > Mail: ***@126.com 
    > Created Time: Tue 27 Oct 2020 04:11:13 PM CST
 **************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_SIZE 1024
int b_flag = 0;
int n_flag = 0;

void my_cat(const char *name){
    FILE *fp;
    //文件无法打开
    if ((fp = fopen(name, "r")) == NULL){
        perror("name");//文件名 + 上一个错误原因
        exit(1);
    }
    //正常
    int count = 0;
    char buff[MAX_SIZE] = {0};
    while((fgets(buff, MAX_SIZE, fp)) != NULL){
        if (n_flag || (b_flag && buff[0] != '\n')){
            printf("%d\t%s", ++count, buff);
        }else if(b_flag && buff[0] == '\n'){
            printf("\n");
        }else{
            //不需要行号
            printf("%s", buff);
        }
        //printf("%s", buff);//不用加\n
    }
    return;
}


int main(int argc,char **argv){
    char ch;
    //getopt取参规则?返回-1? 
    while ((ch = getopt(argc, argv, "bn")) != -1){
        //printf("%c\n", ch);//循环取出所有参数,只输出b or n
        //状态分类
        switch (ch){
            case 'b': b_flag = 1; break;
            case 'n': n_flag = 1; break;
            default://接收到b,n以外参数,输出正确的文件名+参数提示
                fprintf(stderr, "Usage : %s [-b|-n] file\n ", argv[0]);
                exit(1);//return -1
        }
        my_cat(argv[optind]);
        b_flag = 0;
        n_flag = 0;
    }
    //printf("%d %d", argc, optind);
    //my_cat(argv[optind]);
    return 0;
}

my_ls实现

功能

Code

知识点:
linux目录操作(dirent, opendir, readdir, access)
窗口尺寸取出(iostl, winsize)
分列输出【复杂!】

SELinux : avc: denied { find } for interface=vendor.xiaomi.hw.touchfeature::ITouchFeature sid=u:r:system_server:s0 pid=1578 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.xiaomi.hardware.cld::ICld sid=u:r:system_server:s0 pid=1578 scontext=u:r:system_server:s0 tcontext=u:object_r:hal_health_storage_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.qti.sla.service::ISlaService sid=u:r:system_server:s0 pid=1578 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.xiaomi.hidl.miwill::IMiwillService sid=u:r:system_server:s0 pid=1578 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.qti.sla.service::ISlaService sid=u:r:system_server:s0 pid=1578 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.xiaomi.hidl.minet::IMiNetService sid=u:r:system_server:s0 pid=1578 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.xiaomi.hidl.minet::IMiNetService sid=u:r:system_server:s0 pid=1578 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.xiaomi.hw.touchfeature::ITouchFeature sid=u:r:system_app:s0 pid=3872 scontext=u:r:system_app:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.xiaomi.hardware.fbo::IFbo sid=u:r:system_server:s0 pid=1578 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.xiaomi.hardware.fbo::IFbo sid=u:r:system_server:s0 pid=1578 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.xiaomi.hardware.campostproc::IMiPostProcService sid=u:r:platform_app:s0:c512,c768 pid=9054 scontext=u:r:platform_app:s0:c512,c768 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.xiaomi.hw.touchfeature::ITouchFeature sid=u:r:system_app:s0 pid=10143 scontext=u:r:system_app:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.xiaomi.hw.touchfeature::ITouchFeature sid=u:r:system_app:s0 pid=10143 scontext=u:r:system_app:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.xiaomi.hw.touchfeature::ITouchFeature sid=u:r:system_app:s0 pid=11940 scontext=u:r:system_app:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.xiaomi.hardware.wireless::IWirelessSwitch sid=u:r:system_app:s0 pid=12014 scontext=u:r:system_app:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0 SELinux : avc: denied { find } for interface=vendor.xiaomi.hardware.fbo::IFbo sid=u:r:system_server:s0 pid=1578 scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_hwservice:s0 tclass=hwservice_manager permissive=0
07-24
<think>我们正在处理一个SELinux的avc denied错误,具体是在访问硬件服务时被拒绝。根据引用[2]中的错误示例,我们需要分析avc denied日志并添加相应的SELinux规则。 用户的问题中提到了“find interface vendor.xiaomi hwservice_manager”,这表明问题可能发生在尝试通过hwservice_manager查找或访问vendor.xiaomi.hardware命名空间下的某个硬件服务接口时。 解决SELinux avc denied问题的通用步骤如下: 1. 获取avc denied日志(通常通过`dmesg`或`logcat`) 2. 分析日志,提取关键信息:scontext(源上下文)、tcontext(目标上下文)、tclass(目标类别)和权限(denied权限) 3. 根据分析结果,在相应的SELinux策略文件(通常是.te文件)中添加允许规则 根据用户提供的信息,我们有一个avc denied日志片段(来自引用[2]): audit(1441759284.810:5): avc: denied { read } for pid=1494 comm="sdcard" name="0" dev="nandk" ino=245281 scontext=u:r:sdcardd:s0 tcontext=u:object_r:system_data_file:s0 tclass=dir 但用户现在的问题是关于“find interface vendor.xiaomi hwservice_manager”的,因此我们需要一个针对hwservice_manager访问的avc denied日志。 假设我们得到的avc denied日志类似于: avc: denied { find } for pid=xxx comm="xxx" scontext=u:r:my_domain:s0 tcontext=u:object_r:vendor_xiaomi_hwservice_service:s0 tclass=hwservice_manager 注意:实际日志可能有所不同,但关键点在于: - 权限:{ find } - tclass: hwservice_manager - tcontext: 通常是定义该硬件服务的安全上下文,如`vendor_xiaomi_hwservice_service` 解决步骤: 1. **确认avc denied日志** 首先,我们需要从设备中获取完整的avc denied日志。可以使用以下命令: ```bash adb shell dmesg | grep avc ``` 或者 ```bash adb logcat -b all -d | grep avc ``` 2. **分析日志** 假设我们得到如下日志: ``` avc: denied { find } for pid=1234 comm="my_process" scontext=u:r:my_domain:s0 tcontext=u:object_r:vendor_xiaomi_hardware_myservice_hwservice:s0 tclass=hwservice_manager ``` 关键信息: - 源上下文(scontext): `my_domain` - 目标上下文(tcontext): `vendor_xiaomi_hardware_myservice_hwservice` - 目标类(tclass): `hwservice_manager` - 被拒绝的权限: `find` 3. **添加SELinux规则** 我们需要在`my_domain.te`策略文件中添加允许规则,格式为: ``` allow my_domain vendor_xiaomi_hardware_myservice_hwservice: hwservice_manager find; ``` 但是,为了确保规则的正确性,我们还需要确认目标类型(`vendor_xiaomi_hardware_myservice_hwservice`)是否已经在hwservice_manager的类中定义。通常,这些类型会在厂商自定义的SELinux策略中定义。 4. **如果目标类型未定义** 如果目标类型未定义,我们需要在适当的文件中定义它。通常,硬件服务的上下文定义在`hwservice_contexts`文件中。例如,在设备厂商的SELinux策略中,可能有如下定义: ``` vendor.xiaomi.hardware.myservice::IMyService u:object_r:vendor_xiaomi_hardware_myservice_hwservice:s0 ``` 这个定义确保当服务名为`vendor.xiaomi.hardware.myservice::IMyService`在hwservice_manager中注册时,它会被赋予`vendor_xiaomi_hardware_myservice_hwservice`的安全上下文。 5. **编写策略规则** 在确认目标类型存在后,我们在源域(如`my_domain`)的策略文件中添加允许规则。 6. **编译和加载策略** 修改策略文件后,需要重新编译策略并加载到设备中。具体步骤取决于系统版本和构建环境。如果是AOSP开发,通常需要重新编译sepolicy并刷机,或者使用动态加载的方式(例如,在eng/userdebug版本中可以使用`adb push`和`adb shell load_policy`)。 7. **验证** 应用新策略后,重新运行测试,确认avc denied日志不再出现。 注意:在添加规则时,应遵循最小权限原则,只授予必要的权限。 示例策略规则: 假设我们的源域是`my_domain`,目标类型是`vendor_xiaomi_hardware_myservice_hwservice`,则添加: ``` # 在 my_domain.te 文件中 allow my_domain vendor_xiaomi_hardware_myservice_hwservice: hwservice_manager find; ``` 如果遇到多个权限被拒绝,需要为每个权限添加规则,或者如果多个权限同时需要,可以使用`{ find list }`的方式。 另外,如果这个规则是用于系统服务(例如作为系统服务的一部分),可能需要考虑域转换或其它更安全的策略,但通常对于find操作,允许即可。 如果问题仍然存在,请检查是否有其他相关的avc denied日志,因为有时一个操作可能涉及多个权限。 根据引用[3],如果访问的接口需要特权权限,我们还需要确保进程具有相应的Linux权限(尽管SELinux是独立的,但有时需要结合看)。但SELinux主要解决的是访问控制,而权限检查是应用层的。 因此,总结步骤: 1. 获取avc denied日志,确认被拒绝的权限、源上下文、目标上下文和目标类。 2. 在源域的策略文件中添加允许规则。 3. 确保目标上下文已经在hwservice_contexts中定义。 4. 重新编译并加载sepolicy。 5. 验证问题是否解决。 注意:在实际操作中,需要替换示例中的域名(my_domain)和目标类型(vendor_xiaomi_hardware_myservice_hwservice)为实际日志中的值。 如果用户没有提供具体的avc denied日志,建议先获取日志再进行分析。 下面,我们根据用户的问题,给出一个通用的解决模板:</think>要解决 Android SELinux 中 `avc: denied { find }` 错误(涉及 `vendor.xiaomi.hwservice_manager`),请按照以下步骤操作: --- ### 🔧 解决步骤(基于 avc denied 日志分析) #### 1️⃣ **提取完整 avc denied 日志** ```bash adb logcat -d | grep "avc:.*{ find }.*hwservice_manager" ``` 示例输出(关键字段): ``` avc: denied { find } for pid=1234 comm="vendor.process" scontext=u:r:vendor_xiaomi_hal:s0 tcontext=u:object_r:vendor_xiaomi_hwservice_service:s0 tclass=hwservice_manager ``` * **scontext**: 发起访问的进程域(如 `vendor_xiaomi_hal`) * **tcontext**: 目标服务上下文(如 `vendor_xiaomi_hwservice_service`) * **tclass**: 目标类 (`hwservice_manager`) --- #### 2️⃣ **添加 SELinux 策略规则** 在设备源码的 SELinux 策略文件(如 `vendor/xiaomi/sepolicy/vendor_xiaomi_hal.te`)中添加: ```diff # 允许 HAL 进程查找小米硬件服务 + allow vendor_xiaomi_hal vendor_xiaomi_hwservice_service:hwservice_manager { find }; ``` #### 3️⃣ **扩展规则(如需接口调用)** 若后续出现 `call` 权限拒绝,添加: ```diff # 允许调用接口方法 + allow vendor_xiaomi_hal vendor_xiaomi_hwservice_service:hwservice_manager { find call }; ``` #### 4️⃣ **验证并编译策略** ```bash # 编译策略 mmp -B sepolicy # 推送新策略到设备 adb push out/target/product/<device>/vendor/etc/selinux/vendor_sepolicy.cil /vendor/etc/selinux/ adb reboot ``` --- ### ⚙️ 根本原因分析 1. **权限不足** 硬件服务访问需要显式声明 `find` 权限(部分厂商服务需 `call`)[^3] 2. **策略缺失** 小米硬件服务 (`vendor.xiaomi.*`) 未在默认策略中开放访问 3. **上下文匹配** `hwservice_manager` 的 `tcontext` 需与服务注册的上下文一致 --- ### 📝 完整策略示例 ```te # vendor/xiaomi/sepolicy/vendor_xiaomi_hal.te # 允许访问小米硬件服务 allow vendor_xiaomi_hal vendor_xiaomi_hwservice_service:hwservice_manager { find call }; # 关联类型(如果服务使用独立类型) typeattribute vendor_xiaomi_hal coredomain; ``` --- ### ✅ 验证修复 ```bash # 检查新日志 adb logcat | grep "avc" # 测试硬件服务调用 adb shell lshal list | grep "vendor.xiaomi" ``` 成功时无 `avc: denied` 日志,且服务列表正常显示。 --- ### 📊 SELinux 调试技巧 | **命令** | **作用** | 示例 | |----------|----------|------| | `adb logcat -b all` | 获取完整内核日志 | `grep "avc\|xiaomi"` | | `adb shell seinfo` | 查看策略摘要 | `--type=hwservice_manager` | | `adb shell sesearch` | 搜索策略规则 | `-A -s vendor_xiaomi_hal -t hwservice_manager` | > 提示:使用 `audit2allow` 工具自动生成规则 > ```bash > adb pull /sys/fs/selinux/policy > cat avc_log.txt | audit2allow -p policy > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值