2017년 4월 5일 수요일

SE for Android

SE for Android



Security Enhancements for Android™ (SE for Android) 는 안드로이드 보안을 강화하기 위한 구글 프로젝트다.
Android 4.3이전에는 sandbox를 이용했지만 Android 4.3 이후로 SELinux를 적용했고, Android 5.0 부터 완전하게 적용되었다.


  • 보안정책 해제


enforcing : 보안정책에 위반되는 접근은 모두 거부되고, EPERM 에러를 반환한다.
permissive: 보안정잭이 적용되지 않고,  로깅만 된다.


Android 5.0 이후 버젼은 아래 명령으로 AVC 거부 로그를 확인할 수 있다.
adb logcat | grep avc:


enforcing 상태 확인:
adb shell getenforce


enforcing 로 전환
adb shell su 0 setenforce 1


permissive로 전환
adb shell su 0 setenforce 0


영구적으로 해제하려면, bootargs에 androidboot.selinux=permissive를 추가하면 된다.


  • 정책설정
아래명령으로 거부로그를 캡춰한 후 audit2allow를 이용해서 보안정책을 적용할 수 있다.
adb shell su 0 cat /proc/kmsg > dmesg.txt &
audit2allow -p out/target/product/device/root/sepolicy < dmesg.txt


우분투에서 audit2allow를 사용하려면 아래 패키지를 인스톨해야한다.
sudo apt-get install policycoreutils


  • 정책파일 로딩
정책파일은 안드로이드 빌드시 컴파일되고, 램디스크 이미지에 추가된다. 그래서 시스템파티션이 마운트되기전 부팅초기에 로딩된다. 부팅 후에는 정책파일을 /data/security/current에 위치시키고, selinux.reload_policy property를 1로 설정하면 업데이트된다.


  • 정책소스파일 구성
정책설정파일은 external/sepolicy/* 에 위치한다. 이 정책은 안드로이드 플래폼 공통 정책이고 이 파일들은 수정할 필요가 없을 것이다.  각 보드별 정책은 device/vendor/device/BoardConfig.mk 에 BOARD_SEPOLICY* 변수로 설정하고, 정책파일은 device/vendor/device/sepolicy/*에 위치 한다. 여기에 필요한 정책을 추가하면 된다.


정책을 구성하기 위해서는 여러 소스파일이 이용된다.  아래는 주요 안드로이드 정책소스파일이다.
file_contexts : device node, socket, /data directory등 파일 label을 설정
property_contexts: Android properties  위한 label 설정
seapp_contests: 앱 프로세스나 앱 패키지 디렉토리를 위한 label 설정
mac_permissions.xml:  middleware MAC(Mandatory Access Control) 정책 설정, SELinux에 없는 SE for Android 전용파일.
정책규칙은 아래 형식으로 구성된다.


allow  Domains  Types:Classes  Permissions;


Domain : 프로세스 설정을 위한 레이블
Type       : file, socket 같은 오브젝트 설정을 위한 레이블.
Class : 접근한는 오브젝트의 종류
Permission:  적용되는 오퍼레이션


예) allow appdomain app_data_file:file rw_file_perms;
appdomain은  file종류인 app_data_file오브젝트에 rw_fil_perms를 적용한다.


실행 중인 프로세스의 레이블 확인:


# adb shell ps -Z
LABEL                          USER     PID   PPID  NAME
u:r:init:s0                    root      1     0     /init
u:r:kernel:s0                  root      2     0     kthreadd
u:r:kernel:s0                  root      3     2     ksoftirqd/0
u:r:kernel:s0                  root      4     2     kworker/0:0
….
u:r:system_app:s0              system    3582  2471  com.android.settings
u:r:untrusted_app:s0           u0_a16    3605  2471  com.android.voicedialer
u:r:untrusted_app:s0           u0_a22    3627  2471  com.android.calendar
u:r:untrusted_app:s0           u0_a25    3655  2471  com.android.deskclock
u:r:untrusted_app:s0           u0_a28    3684  2471  com.android.email
u:r:untrusted_app:s0           u0_a29    3707  2471  com.android.exchange


  • SPI 장치를 접근하는 JNI를 통해 데이터를 읽어오는 앱을 위한 정책의 경우 아래와 같이 수정한다.
  1. 일단 앱을 실행시켜 AVC denial 로그를 확인한다.


~$ adb shell su -c dmesg | grep denied
<38>[  322.415652]  [6:    logd.auditd: 2406] [c6] type=1400 audit(1491383781.160:3): avc: denied { read write } for pid=4529 comm="Thread-158" name="spidev1.0" dev="tmpfs" ino=7687 scontext=u:r:untrusted_app:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
<38>[  322.438108]  [6:    logd.auditd: 2406] [c6] type=1400 audit(1491383781.160:4): avc: denied { open } for pid=4529 comm="Thread-158" path="/dev/spidev1.0" dev="tmpfs" ino=7687 scontext=u:r:untrusted_app:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
<38>[  322.460911]  [6:    logd.auditd: 2406] [c6] type=1400 audit(1491383781.160:5): avc: denied { ioctl } for pid=4529 comm="Thread-158" path="/dev/spidev1.0" dev="tmpfs" ino=7687 scontext=u:r:untrusted_app:s0 tcontext=u:object_r:device:s0 tclass=chr_file permissive=1
로그를 보면 Thread-158 에서 /dev/spidev1.0 장치에 read, write, open, ioctl을 수행하다 실패했다.  아래 정보를 확인하고 정책소스를 수정시 참고한다.
source context: untrusted_app  (프로세스 레이블)
target context: device                 (타겟 오브젝트 레이블)
target class: chr_file        (오브젝트 클래스)


2. file_contex에 spidev레이블을 myspi_dev로 설정한다.
/dev/spidev1.0             u:object_r:myspi_device:s0
  • external/sepolicy/domain.te를 보면 device:chr_file을 막았으므로, device말고 새로운 레이블이 필요하다.
    everallow { domain -unconfineddomain -ueventd -recovery } device:chr_file { open read write };


3.  아래 경로에 타겟보드의  myspi_device를 위한 정책소스를 추가한다.
device/vendor//board/sepolicy/myspidevice.te
type myspi_device, dev_type;

allow untrusted_app myspi_device:chr_file rw_file_perms;
  • external/sepolicy/global_macros 에서 rw_file_perms에  read/write/ioctl 이 포함되도록 정의 되어 있다.
    define(`r_file_perms', `{ getattr open read ioctl lock }')
    define(`w_file_perms', `{ open append write }')
    define(`rx_file_perms', `{ r_file_perms x_file_perms }')

4.myspidevice.te가 빌드시 포함되도록 device/vendor/board/BoardConfig.mk를 수정한다.
BOARD_SEPOLICY_UNION +=
myspidevice.te


5. adb shell su -c dmesg | grep denied  명령으로 정책이 잘 적용되었는 지 확인한다. 잘 적용이 되었다면 아무 메시지가 나오지 않는다.