MTK Android12 串口设备读写权限问题的详细指南

本文将详细介绍在 Android 12+ 开发过程中,涉及对串口设备(如 /dev/ttyS1)的读写操作时,可能会遇到 SELinux 权限不足的问题,包括涉及的 SELinux 策略修改和其他相关问题的解决方案。

问题描述

在尝试对串口设备进行读写操作时,遇到了如下权限拒绝问题:

07-26 15:46:23.048  5964  5964 W com.sysout.app: type=1400 audit(0.0:854): avc: denied { write } for name="ttyS1" dev="tmpfs" ino=57 scontext=u:r:untrusted_app:s0:c68,c256,c512,c768 tcontext=u:object_r:ttyS_device:s0 tclass=chr_file permissive=0 app=com.xxx.featuretest

初步解决方案

为了允许 untrusted_appttyS_device 进行读写操作,需要修改 SELinux 策略,添加相应的权限。修改以下文件:

  1. device/mediatek/sepolicy/basic/non_plat/untrusted_app.te
  2. device/mediatek/sepolicy/basic/non_plat/untrusted_app_25.te
  3. device/mediatek/sepolicy/basic/non_plat/shell.te
  4. device/mediatek/sepolicy/basic/non_plat/system.te

在这些文件中添加如下权限:

allow untrusted_app ttyS_device:chr_file { getattr read write open ioctl };
allow untrusted_app proc_tty_drivers:file { getattr read write open };

权限解释

allow untrusted_app ttyS_device:chr_file { getattr read write open ioctl };
# or
allow untrusted_app ttyS_device:chr_file rw_file_perms;

这条规则允许 untrusted_appttyS_device 类型的字符设备文件执行 getattrreadwriteopenioctl 操作。

allow untrusted_app proc_tty_drivers:file { getattr read write open };

这条规则允许 untrusted_appproc_tty_drivers 类型的文件执行 getattrreadwriteopen 操作。

rw_file_perms 详细说明

在 SELinux 中,rw_file_perms 是一个预定义的权限集,通常包括对文件执行读写操作的所有必要权限。具体来说,它包括以下权限:

define(`x_file_perms', `{ getattr execute execute_no_trans map }')
define(`r_file_perms', `{ getattr open read ioctl lock map watch watch_reads }')
define(`w_file_perms', `{ open append write lock map }')
define(`rx_file_perms', `{ r_file_perms x_file_perms }')
define(`ra_file_perms', `{ r_file_perms append }')
define(`rw_file_perms', `{ r_file_perms w_file_perms }')
define(`rwx_file_perms', `{ rw_file_perms x_file_perms }')
define(`create_file_perms', `{ create rename setattr unlink rw_file_perms }')

这些权限定义在 system/sepolicy/public/global_macros 文件中,用于方便地组合常用的权限集。例如,rw_file_perms 包含读取、写入和获取属性的权限。

调试过程

检查和确认设备文件的权限

  1. 检查设备文件的权限

使用以下命令查看设备文件的权限和 SELinux 上下文:

ls -l /dev/ttyS*
ls -lZ /dev/ttyS*

示例输出:

ls -l /dev/ttyS*
crwxrwxrwx 1 root root 4, 64 2024-07-30 16:04 /dev/ttyS0
crwxrwxrwx 1 root root 4, 65 2024-07-30 16:04 /dev/ttyS1
crwxrwxrwx 1 root root 4, 66 2024-07-30 16:04 /dev/ttyS2

ls -lZ /dev/ttyS*
crwxrwxrwx 1 root root u:object_r:ttyS_device:s0 4, 64 2024-07-30 16:04 /dev/ttyS0
crwxrwxrwx 1 root root u:object_r:ttyS_device:s0 4, 65 2024-07-30 16:04 /dev/ttyS1
crwxrwxrwx 1 root root u:object_r:ttyS_device:s0 4, 66 2024-07-30 16:04 /dev/ttyS2
  1. 确认当前系统的应用类型

根据 AVC 日志确认当前应用类型,例如:

scontext=u:r:untrusted_app:s0:c68,c256,c512,c768

这表明当前应用类型为 untrusted_app

确认权限问题

通过 AVC 日志,可以确定当前应用类型及报什么权限问题:

  • 设备节点权限问题:确认设备文件的权限是否正确。
  • SELinux 权限问题:确认 SELinux 策略是否正确。

解决 write 不生效问题

.te 文件中添加权限规则后,串口写操作仍不生效,且没有报 avc 错误时,可以尝试以下方法:

使用 mlstrustedobject 解决问题

如果上述修改仍然无法解决问题,可以尝试将 untrusted_app 类型设置为 mlstrustedobject。修改 device/mediatek/sepolicy/basic/non_plat/untrusted_app.te 文件,添加以下内容:

typeattribute untrusted_app mlstrustedobject;

这将使 untrusted_app 类型具有更多权限,能够跨越一些安全级别限制。

解决 untrusted_app 访问 ttyS_device 权限问题

基于之前的分析,主要问题可能是 MLS(多级安全性)约束。为了确保 untrusted_app 能够正确访问 ttyS_device,需要确认和修改以下几个方面:

1. 确保 untrusted_app 类型具有必要的权限

确保在 untrusted_app.te 文件中添加以下规则:

allow untrusted_app ttyS_device:chr_file { getattr read write open };
2. 确认和设置 MLS 相关属性

需要确认并设置 untrusted_appttyS_device 的 MLS 属性。

设置 untrusted_appmlstrustedsubject

untrusted_app.te 文件中添加以下行:

typeattribute untrusted_app mlstrustedsubject;
确保 ttyS_devicemlstrustedobject

在相应的策略文件中添加以下行:

typeattribute ttyS_device mlstrustedobject;

解决 read 不生效问题

如果串口读操作不生效,可以检查并添加以下权限:

# 目前读还是有问题,增加了权限无用,也没报错, 有空查一下,后续解决后补充到本篇
allow untrusted_app ttyS_device:chr_file { getattr read open };

不同应用的权限差异

不同类型的应用(普通应用、系统应用、签名应用)具有不同的 SELinux 策略。这些策略定义了应用可以执行的操作和访问的资源。具体来说:

  • 普通应用:通常受到严格限制,只能访问特定的资源。
  • 系统应用:具有更多权限,可以访问系统资源。
  • 签名应用:由系统签名,通常具有更高的权限。

这些策略在不同的 .te 文件中定义,以确保每种类型的应用都遵循相应的安全策略。

为什么 typeattribute ttyS_device mlstrustedobject 有效

ttyS_device 类型设置为 mlstrustedobject 后,该设备文件的访问权限将不再受限于 MLS(多级安全性)约束。mlstrustedobject 类型允许跨越不同安全级别的访问,从而使串口写操作生效。

验证与调试

  1. 检查 stty 设置:确保 stty 设置正确。使用 stty -F /dev/ttyS1stty -a -F /dev/ttyS1 查看详细设置,确认没有冲突。
stty -F /dev/ttyS1
speed 9600 baud; line = 0;
hupcl clocal
-brkint ixon -imaxbel
  1. 使用调试工具:使用其他串口调试工具(如 stty)来进一步检查通信:
stty -F /dev/ttyS1 115200
  1. 手动测试:通过手动发送和接收来验证数据传输。

    • 读取数据:打开一个终端,运行以下命令读取数据:

      cat /dev/ttyS1
      
    • 发送数据:打开另一个终端,运行以下命令发送数据:

      echo "1" > /dev/ttyS1
      
    • 验证数据接收:检查另外的设备或终端是否显示 “1”。

在 Android 系统上的调试方法

由于 Android 系统环境的特殊性,可以使用以下方法进行调试:

  1. 通过 ADB shell 访问设备

    进入 shell 环境:

    adb shell
    
  2. 检查串口设备

    确认串口设备是否存在并查看其权限:

    ls -l /dev/ttyS1
    crwxrwxrwx 1 root root 4,  65 2024-08-02 08:57 /dev/ttyS1
    
  3. 设置串口参数

    使用 stty 设置串口参数:

    xxx:/ $ stty -F /dev/ttyS1 115200
    xxx:/ $ stty -F /dev/ttyS1
    speed 115200 baud; line = 0;
    hupcl clocal
    -brkint ixon -imaxbel
    
  4. 读取串口数据

    使用 cat 命令读取串口数据:

    cat /dev/ttyS1
    
  5. 发送串口数据

    使用 echo 命令发送数据到串口:

    echo "1" > /dev/ttyS1
    
  6. 应用层调试

    在应用层面,可以编写测试应用,通过标准的Google Android API 进行串口读写操作,并通过日志输出进行调试。


结论

通过以上步骤和修改,可以解决 Android 12+ 开发过程中遇到的串口权限问题。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一歲抬頭

点赞1元,收藏免费,打赏随意。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值