- 积分
- 300
贡献1443
飞刀569 FD
注册时间2015-12-21
在线时间50 小时

扫一扫,手机访问本帖 
|
硬件平台:飞凌嵌入式 OKT507-C开发板9 E, ?5 K9 p3 P) P- h
操作系统:Android10.0
: H" z; F7 e: J* N2 L" a! C
& h9 _! A* d# D+ S 飞凌嵌入式 T507 开发板 Android系统版本为Android10.0,默认开启了SELinux。基于MAC访问控制模型的SElinux,可以更好地保护我们的Android系统, 比如限制系统服务的访问权限、控制应用对数据和系统日志的访问等措施,这样就降低了恶意软件的影响,并且可以防止因代码存在的缺陷而产生的对系统安全的影响。
3 {+ ^$ g: i. R 从系统安全方面考虑,SELinux是保护神,但是从软件开发方面,SELinux就是一道牵绊,这是一把双刃剑。
2 F* _" H/ k6 y0 k
) D1 m, c% L: J x& f6 k; D. y 比如我们开发应用或者增加系统服务的某些权限的时候,我们必须遵循SELinux的规则,给我们的应用设置对应的安全策略,否则我们的应用就不具备访问数据或者设备的权限。下面我们MAC访问控制模型开始,简单的梳理一下飞凌嵌入式 T507 开发板 Android的安全策略,以及自定义飞凌嵌入式 T507 开发板 Android安全策略的方法。( J- o. S) l1 S5 l
访问控制模型DAC,MAC 访问控制是指控制对计算机或者网络中某个资源的访问。没有它,所有人都可以访问任何资源。有了访问控制,用户在获取实际访问资源或进行操作之前,必须通过识别、验证、授权。* b' s& U6 o+ w* |# ^( [* ?+ s' A
自主访问控制(DAC: Discretionary Access Control)系统识别用户,根据被操作对象的权限的设置,来决定该用户对其拥有的操作权限,read、write、exec。拥有这个对象权限的用户,又可以将该权限分配给其他用户,此谓之“Discretionary”。缺陷就是对权限控制比较分散,不便于管理,比如无法简单地将一组文件设置统一的权限开放给指定的一群用户。
, m! q2 H5 c* z* _ 强制访问控制(MAC: Mandatory Access Control)MAC是为了弥补DAC权限控制过于分散的问题而诞生的。在MAC这种模型里,管理员管理访问控制。管理员制定策略,用户不能改变它。策略定义了哪个主体能访问哪个对象。这种访问控制模型可以增加安全级别,因为它基于策略,任何没有被显式授权的操作都不能执行。MAC被开发和实现在最重视保密的系统中,如军事系统。主体获得清楚的标记,对象得到分类标记,或称安全级别。* n5 d% I0 k6 I" D$ v) }
基于MAC的SElinux 参考链接:https://source.android.google.cn/security/selinux
) [) X* b' Y5 C$ ?) V" | 软件通常情况下必须以 Root 用户帐号的身份运行,才能向原始块设备写入数据。在基于 DAC 的传统 Linux 环境中,如果 Root 用户遭到入侵,攻击者便可以利用该用户身份向每个原始块设备写入数据。从 Android 4.3 起,SELinux 开始为传统的自主访问控制 (DAC) 环境提供强制访问控制 (MAC) 保护功能。作为 Android 安全模型的一部分,Android 使用安全增强型 Linux (SELinux) 对所有进程强制执行强制访问控制 (MAC),甚至包括以 Root/超级用户权限运行的进程(Linux 功能)。例如,可以使用 SELinux 为这些设备添加标签,以便被分配了 Root 权限的进程只能向相关政策中指定的设备写入数据。这样一来,该进程便无法重写特定原始块设备之外的数据和系统设置。借助 SELinux,Android 可以更好地保护和限制系统服务、控制对应用数据和系统日志的访问、降低恶意软件的影响,并保护用户免遭移动设备上的代码可能存在的缺陷的影响。8 X4 Z6 n9 t' }
& ]3 K+ c1 F) X; ?3 c7 x* U
) l Y5 w' U( h1 Y9 M 飞凌嵌入式 T507 开发板 Android系统版本为Android10,SELinux默认开启,即使获得了该系统的root权限,也只能向相关策略中指定的设备写入数据,从而更好地保护和限制系统服务,保障系统和数据的安全。; `6 U/ F: C6 [
标签、规则和域 SELinux 依靠标签来匹配操作和策略。标签用于决定允许的事项。套接字、文件和进程在 SELinux 中都有标签。SELinux 在做决定时需参照两点:一是为这些对象分配的标签,二是定义这些对象如何交互的策略。5 O! v0 _+ C' Y% H
在 SELinux 中,标签采用以下形式:user:role:type:mls_level,其中 type 是访问决定的主要组成部分,可通过构成标签的其他组成部分进行修改。对象会映射到类,对每个类的不同访问类型由权限表示。
& M! g; I4 D1 x: ? 策略规则采用以下形式:allow domains types:classes permissions;,其中:& v* y+ w/ d: Y
6 v% {" {) W# a, O# b: G
Domain - 一个进程或一组进程的标签。也称为域类型,因为它只是指进程的类型。1 e5 J1 I- w& j. M3 D2 l' \
Type - 一个对象(例如,文件、套接字)或一组对象的标签。
: Y4 V% L& t" V' R% y% t3 u/ Q Class - 要访问的对象(例如,文件、套接字)的类型。Permission - 要执行的操作(例如,读取、写入)。
- O4 B* E$ v* A# f8 y/ ^7 q 策略配置源文件 1、external/sepolicy
0 T% ?( H, x; S q3 H3 X& { 这是独立于设备的配置,一般不能针对设备进行修改
5 A. y9 `2 z3 s& B9 x$ D, ]6 |3 ]& u6 a
2、device/<vendor>/<product>/sepolicy% p7 C- O8 X P) l; |: t
这是特定于设备的配置,基于 BOARD_SEPOLICY_* 变量来选择对应平台的策略配置。 A7 a w0 P+ }& C: T. @6 S
# s- h* y$ X7 c' p8 U 以飞凌嵌入式 T507 开发板 为例,T507策略文件的路径如下:( h$ u4 U \5 W& m* b
OKT507-android-source/android$ ls device/softwinner/common/sepolicy/private vendor
9 a) n8 L0 E4 ]/ N1 M2 `& o7 Q$ P Type Enforcement (TE) 配置文件 .te 文件中保存了对应对象的域和类型定义、规则。通常每个域一个 .te 文件,例如installd.te。在 device.te、file.te 中声明了设备和文件类型。在某些文件(例如domain.te、app.te)中则存储着共享规则。# G2 y) r2 \% C6 x
8 g' ]# l4 ~3 U, b6 ~
以飞凌嵌入式 T507 开发板 为例,T507 system_app的TE文件的路径如下:+ h) X: T4 J. X" J* d2 f
device/softwinner/common/sepolicy/vendor/system_app.te
* y9 S; r" x! S! E 标签配置文件 1、file_contexts:文件安全上下文# E* J& x1 ?% \$ k) X& j$ k
2、property_contexts:属性安全上下文. \4 y, E7 C1 `8 y. q
& t. c* H; O8 V& F; M/ \* ? 以飞凌嵌入式 T507 开发板 为例,T507 安全上下文文件路径如下:& s9 @( t" \7 u" v# I8 a/ E
device/softwinner/common/sepolicy/vendor/property_contexts4 I0 H/ s3 H; w G
device/softwinner/common/sepolicy/vendor/file_contexts
+ |7 i/ Q7 }1 W. Y3 ?# ?5 G* x" c SEAndroid app分类 SELinux(或SEAndroid)将app划分为主要三种类型(根据user不同,也有其他的domain类型):
7 q0 n' q+ z+ R6 ]7 d5 X) x 1)untrusted_app 第三方app,没有Android平台签名,没有system权限1 d0 k' i; M& W
2)platform_app 有android平台签名,没有system权限
b6 c1 o: N1 }. @& {: i+ o 3)system_app 有android平台签名和system权限" A+ t1 B: }0 w9 F$ t1 [) \
从上面划分,权限等级,理论上:untrusted_app < platform_app < system_app* s. R" N" a$ m0 {3 {
APP的domain和type 查看seapp_contexts文件,APP的domain和type由user和seinfo两个参数决定7 e# E3 d% J# E% Z" U* j
system/sepolicy/private/seapp_contexts# D3 \- B) M1 J% w% |; M6 t( o$ n
isSystemServer=true domain=system_server_startup
3 A* {. D% f; d! F; g user=_app seinfo=platform name=com.android.traceur domain=traceur_app type=app_data_file levelFrom=all; i& j$ x; t, ~; Y3 Y( @- Z
user=system seinfo=platform domain=system_app type=system_app_data_file
' w' `0 L" x0 U; J9 M) I' o user=bluetooth seinfo=platform domain=bluetooth type=bluetooth_data_file* y( t# p* l- f; h2 P6 x. O; E
user=network_stack seinfo=network_stack domain=network_stack levelFrom=all
. H8 ]% B) {1 X8 [, E& c9 } type=radio_data_file
7 }0 d1 j$ o: O& g9 u user=nfc seinfo=platform domain=nfc type=nfc_data_file8 |0 k7 w! [- p5 o6 k
user=secure_element seinfo=platform domain=secure_element levelFrom=all( Z5 E! r% W3 k3 r3 ~8 `8 q
user=radio seinfo=platform domain=radio type=radio_data_file# U6 a7 ~7 r! P% {4 @+ U& u) e
user=shared_relro domain=shared_relro2 K" m6 i# h }
user=shell seinfo=platform domain=shell name=com.android.shell type=shell_data_file+ S4 G! y3 b2 s) I
user=webview_zygote seinfo=webview_zygote domain=webview_zygote
' k/ ^, G; {! b/ L) I user=_isolated domain=isolated_app levelFrom=al( p; M1 \1 W. h m
luser=_app seinfo=app_zygote domain=app_zygote levelFrom=all
/ Z! [8 K, M8 ?* m user=_app seinfo=media domain=mediaprovider name=android.process.media type=app_data_file 6 I J3 ?! F8 h) f; u
levelFrom=user
% L2 p6 ~3 [; w6 h: g: J user=_app seinfo=platform domain=platform_app type=app_data_file levelFrom=user
, O0 J8 N2 o8 r% m6 r user=_app isEphemeralApp=true domain=ephemeral_app type=app_data_file levelFrom=all3 ~ c: r9 S- u, e
user=_app isPrivApp=true domain=priv_app type=privapp_data_file levelFrom=user( F% q! ?* ?; p- v
user=_app minTargetSdkVersion=29 domain=untrusted_app type=app_data_file levelFrom=all
, |$ H/ M3 r8 u' @" N; O user=_app minTargetSdkVersion=28 domain=untrusted_app_27 type=app_data_file levelFrom=all7 e1 b; S' e2 {" h
user=_app minTargetSdkVersion=26 domain=untrusted_app_27 type=app_data_file
0 M1 ~! N! n6 `- U levelFrom=user
( ^5 l X5 F8 c" ]* H% a& u user=_app domain=untrusted_app_25 type=app_data_file levelFrom=user
! o4 n g. a# l: R5 \& ^ user=_app minTargetSdkVersion=28 fromRunAs=true domain=runas_app levelFrom=all& M+ k- Y2 b" X x) W S% r
user=_app fromRunAs=true domain=runas_app levelFrom=user" y' D, p9 p4 {. ?: W4 R
user 参考链接:https://blog.csdn.net/huilin9960/article/details/81530568
, x4 i T0 T$ [ user可以理解为UID。android的UID和linux的UID根本是两回事,Linux的UID是用于针对多用户操作系统中用于区分用户的,而Android中的UID是用于系统进行权限管理的。参考链接中的文章对于uid的产生讲的很清楚。
" l2 V5 `% p3 b seinfo 不同签名会创建对应的selinux上下文。7 | O) R' M6 R! @" d* ?
Android.mk
- i' K' h4 ^5 q ^ LOCAL_CERTIFICATE := platform
: H" B" ?0 K8 c) \- P- f, { 有platform签名,所以seinfo是platform。
: ]( W4 @% [5 X0 d LOCAL_CERTIFICATE作用 参考文档https://blog.csdn.net/hnlgzb/article/details/107823874
0 I" a6 D+ b+ H* Q0 w5 v 可以查看Android源码build/target/product/security/ 目录下提供的默认签名文件,不同平台可能会有差异:飞凌嵌入式 T507 开发板 提供了media、networkstack、platform、shared、testkey、verity六种不同权限的签名文件。
2 j9 d1 K& K) v5 v8 w5 ~ . I6 X/ m6 H) i
以飞凌嵌入式 T507 开发板 为例,查看当前运行的应用信息:
& f6 P1 O" i3 z* q6 K7 y4 v( n: J console:/ # ps -Z
c, d/ I0 m; D u:r:system_app:s0 system 15712 1861 1050628 110868 SyS_epoll_wait # h+ p2 s5 L! k9 B: }
0 S forlinx.example.app* {8 W; f( s# z+ h
u:r:untrusted_app_27:s0:c512,c768 u0_a62 30259 1861 1052120 114132 SyS_epoll_wait . g/ j& ]1 |# G% Q" I
0 S com.forlinx.changelogo
) ]+ ~0 B- m8 ?4 y) _/ }: J0 |" X 当前运行的两个APP,forlinx.example.app的UID(user)是system,拥有platform签名,它的domain和type就是system_app。
v# f% D' |* ]1 Z $ I7 y5 I1 s8 I1 {6 w/ \* Q
# W5 U" \2 x: e
/ k; { |. O" c8 p0 Y o+ w com.forlinx.changelogo没有设置UID使用的默认设置,其UID为u0_a62,并且没有设置签名文件,它的domain和type就是untrusted_app。
. O( ~) s( o3 N$ R T507自定义安全策略 以上面两个运行的app来说,我们为这两个APP添加额外的权限,对应的TE配置文件分别就是system_app.te、untrusted_app.te,对应路径为:; ~4 G# G1 V0 I3 ~0 j" f" |
device/softwinner/common/sepolicy/vendor/system_app.te
* v8 ]/ n1 r$ u$ s! E6 Z |) E! T device/softwinner/common/sepolicy/vendor/untrusted_app.te
& g2 ^% ~4 Y( k, R+ c
& e7 Q4 w1 Z5 p, j7 \% | 以forlinx.example.app为例,我们为其添加can设备的执行权限:8 K# x) J2 x4 R8 U8 T
8 J8 t8 K) _' z& {: L& M+ _& P OKT507-android-source/android$ vi device/softwinner/common/sepolicy/vendor/system_app.te# y. y; _- r$ C* @
...
9 c! v* D @4 K9 H6 |7 ~ allow system_app vendor_shell_exec:file { getattr open read execute execute_no_trans };4 f4 w3 \2 k( L9 v4 Z% q+ x6 ?
allow system_app shell_exec:file { getattr open read execute execute_no_trans };' I2 o4 v. s( E b$ j) a4 P
allow system_app shell:file { getattr open read execute execute_no_trans };' M6 }' L# U. b
...) s, N% w5 d6 q5 A
以策略规则配置形式(allow domains types:classes permissions)
f# {5 [+ Y# Q0 q4 M/ C) k 分析:domains:system_app; O0 M( K6 O3 V& @5 K% y5 a
types:vendor_shell_exec
/ Z% D% L+ w! I classes:file
/ ?' \& z' a, ], [; t6 i: _ permissions:getattr open read execute execute_no_trans" o5 T4 x2 ] E3 r d6 ]$ W
neverallow failures 有时我们增加的权限,系统默认的配置是不允许的,比如我们上面给forlinx.example.app增加的执行脚本的权限,报错如下:
6 x6 b8 J: Q1 O- i" d
: O: @: B# m# c: S: F7 r$ S0 M- p libsepol.report_failure: neverallow on line 9 of system/sepolicy/private/system_app.te . m9 w+ @6 M7 a7 Y2 o. p$ i! }
(or line 41463 of policy.conf) violated by allow system_app shell:file { read open };
5 j- w+ c- M$ o! @ libsepol.report_failure: neverallow on line 22 of system/sepolicy/private/shell.te
! G9 k- z0 j' q (or line 40025 of policy.conf) violated by allow system_app shell:file { read open };
/ U: I, V! ?$ u$ z, t$ r libsepol.check_assertions: 2 neverallow failures occurred% F C) V! r* L) N
+ s% x! q- o# |. r" {/ E' s g s
系统默认的安全策略的路径为system/sepolicy/,根据报错的提示,我们可以修改默认的配置,修改system/sepolicy/private/system_app.te和system/sepolicy/private/shell.te,从而完成权限的赋予。$ L7 c5 h% m! h9 ~% a5 C& z
, A7 I/ z1 n8 J8 \$ I/ a3 B
以上就是Android 安全策略的脉络,以及飞凌嵌入式 T507 开发板 Android系统下自定义安全策略的方法了。* q5 n2 W$ n* {
4 ?' S- a3 F) ?: O4 G$ e$ y. A. M
|
|