2013年6月4日 星期二

Flask & SELinux


Flask was developed to work through some of the inherent problems with a MAC architecture. Traditional MAC is closely integrated with the multi-level security (MLS) model. Access decisions in MLS are based on clearances for subjects and classifications for objects, with the objective of no read-up, no write-down . This provides a very static lattice that allows the system to decide by a subject's security clearance level which objects can be read and written to. The focus of the MLS architecture is entirely on maintaining confidentiality.

The inflexible aspect of this kind of MAC is the focus on confidentiality. The MLS system does not care about integrity of data, least privilege, or separating processes and objects by their duty, and has no mechanisms for controlling these security needs. MLS is a mechanism for maintaining confidentiality of files on the system, by making sure that unauthorized users cannot read from or write to them.

Flask solves the inflexibility of MLS-based MAC by separating the policy enforcement from the policy logic, which is also known as the security server. In traditional Flask, the security server holds the security policy logic, handling the interpretation of security contexts. Security contexts or labels are the set of security attributes associated with a process or an object. Such security labels have the format of <user>:<role>:<type>, for example, system_u:object_r:httpd_exec_t. The SELinux user system_u is a standard identity used for daemons. The role object_r is the role for system objects such as files and devices. The type httpd_exec_t is the type applied to the httpd executable /usr/sbin/httpd.



Above picture shows the Flask architecture. In this operation, standard DAC has occurred, which means the subject already has gained access to the object via regular Linux file permissions based on the UID[1]. The operation can be anything: reading from or writing to a file/device, transitioning a process from one type to another type, opening a socket for an operation, delivering a signal call, and so forth.
  1. A subject, which is a process, attempts to perform an operation on an object, such as a file, device, process, or socket.
  2. The policy enforcement server gathers the security context from the subject and object, and sends the pair of labels to the security server, which is responsible for policy decision making.
  3. The policy server first checks the AVC, and returns a decision to the enforcement server.
  4. If the AVC does not have a policy decision cached, it turns to the security server, which uses the binary policy that is loaded into the kernel during initialization. The AVC caches the decision, and returns the decision to the enforcement server, that is, the kernel.
  5. If the policy permits the subject to perform the desired operation on the object, the operation is allowed to proceed.
If the policy does not permit the subject to perform the desired operation, the action is denied, and one or more avc: denied messages are logged to$AUDIT_LOG, which is typically /var/log/messages in Red Hat Enterprise Linux.With the security server handling the policy decision making, the enforcement server handles the rest of the tasks. In this role, you can think of the enforcement code as being an object manager. Object management includes labeling objects with a security context, managing object labels in memory, and managing client and server labeling.


Reference:



2013年6月2日 星期日

Android SELinux: binder & socket

Introduction of binder


Inter Process Communication (IPC) has been a part of Android since 1.0, and yet most of us take it for granted.




















While processes cannot directly invoke operations (or read/write data) on other processes, the kernel can, so they make use of the Binder driver. Binder driver is exposed via /dev/binder and offers a relatively simple API based on open, release, poll,mmap, flush, and ioctl operations.


Security Mechanism of binder

Malicious applications can make use of binder mechanism to get unauthorized data, SEforAndroid implements security control to check the permissions. The details are as following:

1. Declare a class for kernel policy in external/sepolicy/access_vectors
class binder
{
    impersonate
    call
    set_context_mgr
    transfer
    receive
}


Impersonate:該 process 是否可以代表另一process使用binder.  kernel (selinux/hooks.c) checks permission in selinux_binder_transaction call.
Call:Perform a binder IPC to a given target process (can A call B?).
Set_context_mgr:是否可以将自己註册成Context Manager. Can A set the context manager to B, where normally A == B.See policy module servicemanager.te.
Transfer:是否可以傳遞某類型的binder引用到其他process. Transfer a binder reference to another process (can A transfer a binder reference to B?).
Receive:是否可以接收某類型binder引用.

2. TE中使用 macro 進行配置 binder_use、binder_call、binder_transfer、binder_service
Ex:
# 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;')
例如servicemanager
allow servicemanager self:binder set_context_mgr;
allow servicemanager domain:binder { receive transfer };
配置表示了servicemanager可以将自己设置为context manager,并且它可以对所有domain执行receivetransfer的操作。


3. 於 source code中增加相關的操作函數
Ex. kernel/goldfish/security/selinux/hooks.c defines four functions

.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);
}

socket

SEAndroidservice sockets的權限同樣受到管理。Init process 在創建service附属socket的同時,根據 file_contexts 查詢當前socket權限,並將信息加入到socketsecurity 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使用权限的配置可以简单的使用两个 macro 定義 unix_socket_connectunix_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 domainsubject可以通过vold_socket类型的socket访问volddomain
unix_socket_connect(adbd, vold, vold)




reference: