天天看點

SEAndroid在IPC中安全功能進行分析

SELinux在系統級增加了強制通路控制,每個VFS node均在Security Server的控制之中。IPC是系統的重要功能,未經授權的使用均會給系統帶來安全隐患,是以本文重點對SEAndroid在IPC中安全功能進行分析,作為Android的主要通信工具socket和binder,在SEAndroid均增加了權限的控制,下面分别對兩個進行簡要的分析。由于Android行業化應用越來愈多,對SE的研究越來越多了,例如trustdroid。

SE目前實作太複雜了,另外僅提供kernel的MAC,架構層的也需要啊。類似的機制已經有廠商實作了,如三星S4 Knox! 

一、  binder

為了增加binder的權限控制,首先在kernel的policy中增加一個class,并且增加了幾個方法,

代碼:

{ "binder", { "impersonate", "call", "set_context_mgr", "transfer", "receive"} },
      

Impersonate:該程序是否可以代表另一個程序使用binder

Call:該程序是否可以調用另一個程序

Set_context_mgr:是否可以将自己注冊成Context Manager

Transfer:是否可以傳遞某類型的binder引用到其他程序

Receive:是否可以接收某類型binder引用

對binder調用規則的配置有些繁瑣,是以在TE中使用宏進行配置binder_use、binder_call、binder_transfer、binder_service。相應的功能介紹在代碼裡已經注釋的比較清晰,如:

代碼:

# binder_call(clientdomain, serverdomain)
# Allow clientdomain to perform binder IPC to serverdomain.
define(`binder_call', `
# First we receive a Binder ref to the server, then we call it.
allow $1 $2:binder { receive call };
# Receive and use open files from the server.
allow $1 $2:fd use;')
      

對于TE檔案隻需簡單配置即可,例如servicemanager:

allow servicemanager self:binder set_context_mgr;

allow servicemanager domain:binder { receive transfer };

配置表示了servicemanager可以将自己設定為context manager,并且它可以對所有domain執行receive和transfer的操作。

下面看一下驅動的實作流程。首先在security_ops中增加了4個操作函數

代碼:

.binder_set_context_mgr =  selinux_binder_set_context_mgr,
.binder_transaction =    selinux_binder_transaction,
.binder_transfer_binder =  selinux_binder_transfer_binder,
.binder_transfer_file =    selinux_binder_transfer_file,
      

首先看一下第一個函數,其的實作原理就是去AVC中查詢目前的sid是否設定了context_mgr的權限,如果未經授權,則禁止此次操作。

代碼:

static int selinux_binder_set_context_mgr(struct task_struct *mgr)
{
  u32 mysid = current_sid();
  u32 mgrsid = task_sid(mgr);
  return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER, BINDER__SET_CONTEXT_MGR, NULL);
}
      

對于transaction的控制也是類似,在binder_transaction中增加hook,用來檢查本次調用的權限,其中也是同樣在AVC中查詢權限。

代碼:

static void binder_transaction(struct binder_proc *proc,
             struct binder_thread *thread,
             struct binder_transaction_data *tr, int reply)
……
    if (security_binder_transaction(proc->tsk, target_proc->tsk) < 0) {
      return_error = BR_FAILED_REPLY;
      goto err_invalid_target_handle;
    }
……
      

代碼:

static int selinux_binder_transaction(struct task_struct *from, struct task_struct *to)
{
  u32 mysid = current_sid();
  u32 fromsid = task_sid(from);
  u32 tosid = task_sid(to);
  int rc;

  if (mysid != fromsid) {
    rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER, BINDER__IMPERSONATE, NULL);
    if (rc)
      return rc;
  }

  return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL, NULL);
}
      

調用AVC進行權限查詢和其他hook是一緻的,基本原理如下圖所示,如果cache中未能查到,就會去security server中查詢policy,并且cache起來。

SEAndroid在IPC中安全功能進行分析

二、  socket

在SEAndroid中service sockets的權限同樣受到管理。Init程序在建立service附屬socket的同時,根據file_contexts查詢目前socket的權限,并将資訊加入到socket的security context中,啟動後的權限如下所示:

代碼:

srw------- system   system            u:object_r:installd_socket:s0 installd
srw-rw-rw- root     root              u:object_r:keystore_socket:s0 keystore
srw-rw---- root     system            u:object_r:netd_socket:s0 netd
srw-rw-rw- root     root              u:object_r:property_socket:s0 property_service
srw-rw---- root     radio             u:object_r:rild_socket:s0 rild
      

……

關于socket使用權限的配置可以簡單的使用兩個宏定義unix_socket_connect、unix_socket_send,他們分别對應着TCP和UDP類型的socket通路。

代碼:

# unix_socket_connect(clientdomain, socket, serverdomain)
# Allow a local socket connection from clientdomain via
# socket to serverdomain.
define(`unix_socket_connect', `
allow $1 $2_socket:sock_file write;
allow $1 $3:unix_stream_socket connectto;
')
      

對于規則的配置隻需如下,他表示了adbd domain的subject可以通過vold_socket類型的socket通路vold的domain。

代碼:

unix_socket_connect(adbd, vold, vold)
      

繼續閱讀