maruos / vendor_maruos

Common files for Maru OS.
Apache License 2.0
5 stars 15 forks source link

Restrict perspectived sepolicy #4

Closed utzcoz closed 5 years ago

utzcoz commented 5 years ago

Hi @pdsouza , now MaruOS uses permissive perspectived to permissive perspectived operations. It is easy and works fine. But in Android 8.0, when we build user variant images, the system/sepolicy will ensure there doesn't exist permissive rule in .te, and it will cause building failed for MaruOS user variant building. So I try to remove permissive rule from perspectived.te and make MaruOS works fine again.

My modification are in vendor/maruos and system/sepolicy. And I use below command to get the rules that perspectived needs to work fine:

adb shell dmesg | grep "avc:" > avc_log.txt
audit2allow -i avc_log.txt

And finally, the perspectived.te is :

# perspectived daemon
type perspectived, domain;
typeattribute perspectived coredomain;
typeattribute perspectived socket_between_core_and_vendor_violators;
type perspectived_exec, exec_type, file_type;

# started by init
init_daemon_domain(perspectived)

# Binder IPC
binder_use(perspectived)
#binder_call(perspectived, binderservicedomain)
binder_call(perspectived, appdomain)
binder_service(perspectived)

# register Binder service
allow perspectived mperspective_service:service_manager add;

# allow system_server to find perspectived
allow system_server mperspective_service:service_manager find;

# socket communicate
allow perspectived mflinger:unix_stream_socket connectto;
allow perspectived port:tcp_socket { name_connect name_bind };
allow perspectived node:tcp_socket node_bind;
allow perspectived self:tcp_socket { connect create setopt bind };
allow perspectived self:udp_socket { connect create getattr ioctl write setopt };

# uevent socket access
allow perspectived self:netlink_audit_socket { bind create setopt getattr getopt nlmsg_relay read write };
allow perspectived self:netlink_kobject_uevent_socket { create setopt bind read getopt write getattr };
allow perspectived self:netlink_route_socket nlmsg_read;
allow perspectived self:netlink_route_socket { bind create getattr getopt nlmsg_write read setopt write };

# capability
allow perspectived self:capability { kill fowner net_admin dac_override ipc_owner sys_admin sys_boot chown fsetid net_raw setgid setuid audit_write setpcap sys_chroot sys_nice sys_ptrace sys_resource mknod };
allow perspectived self:capability2 { audit_read block_suspend };

# su
allow perspectived su:dir search;
allow perspectived su:file { getattr open read };
allow perspectived su:lnk_file read;

# fd share
allow perspectived hal_graphics_allocator:fd use;
allow perspectived self:shm *;

# lxc
allow perspectived input_device:chr_file { getattr ioctl open write read };
allow perspectived input_device:dir { getattr search };

allow perspectived proc_net:file { getattr open read };

allow perspectived labeledfs:filesystem unmount;

allow perspectived mnt_user_file:dir search;
allow perspectived mnt_user_file:lnk_file read;

allow perspectived sdcardfs:dir { mounton search };
allow perspectived sdcardfs:filesystem { remount unmount };

allow perspectived sysfs:file { getattr open read write };
allow perspectived sysfs:filesystem { mount unmount };
allow perspectived sysfs:dir { open read write mounton };

allow perspectived configfs:filesystem { unmount mount };
allow perspectived configfs:dir mounton;

allow perspectived debugfs:dir mounton;
allow perspectived debugfs:filesystem { mount unmount };
allow perspectived debugfs_tracing:dir mounton;

allow perspectived device:dir { mounton write add_name create };

allow perspectived devpts:chr_file { ioctl setattr };
allow perspectived devpts:filesystem { mount unmount };
allow perspectived devpts:dir mounton;

allow perspectived functionfs:dir mounton;
allow perspectived functionfs:filesystem unmount;

allow perspectived pstorefs:filesystem unmount;
allow perspectived pstorefs:dir mounton;

allow perspectived rootfs:dir mounton;

allow perspectived selinuxfs:dir mounton;
allow perspectived selinuxfs:filesystem { remount unmount };

allow perspectived storage_file:dir search;
allow perspectived storage_file:lnk_file read;

allow perspectived system_data_file:dir mounton;
allow perspectived system_file:dir mounton;

# shell data files
allow perspectived shell_data_file:dir { search write add_name remove_name };
allow perspectived shell_data_file:file { create open read unlink };

# proc, cgroups
allow perspectived init:file r_file_perms;
allow perspectived init:dir w_dir_perms;
allow perspectived cgroup:dir { add_name create mounton setattr open read remove_name rmdir };
allow perspectived cgroup:file { getattr read };
allow perspectived cgroup:filesystem { mount unmount remount };
allow perspectived proc:dir mounton;
allow perspectived proc:file { getattr open read };
allow perspectived proc:filesystem { mount unmount };

# execute scripts (TODO make this specific script file)
allow perspectived shell_exec:file rx_file_perms;

allow perspectived maru_file:dir { rmdir setattr create_dir_perms rw_dir_perms create mounton };
allow perspectived maru_file:file { link execute execute_no_trans create_file_perms };
allow perspectived maru_file:sock_file { create setattr write unlink getattr };
allow perspectived maru_file:lnk_file { create read rename unlink r_file_perms };

# TODO update cache label to maru_file
allow perspectived cache_file:file create_file_perms;
allow perspectived cache_file:dir { create_dir_perms mounton };
allow perspectived cache_file:lnk_file read;

allow perspectived tmpfs:blk_file { create getattr };
allow perspectived tmpfs:chr_file { ioctl open read write create getattr mounton };
allow perspectived tmpfs:dir { create_dir_perms mounton };
allow perspectived tmpfs:fifo_file { getattr open read write create unlink };
allow perspectived tmpfs:file create_file_perms;
allow perspectived tmpfs:filesystem { mount remount unmount };
allow perspectived tmpfs:lnk_file { read create getattr };
allow perspectived tmpfs:sock_file { create write getattr };

allow perspectived perspectived_tmpfs:file { append lock create mounton open rename setattr unlink };

allow perspectived storage_stub_file:dir search;
allow perspectived sysfs_zram:dir search;
allow perspectived sysfs_leds:dir { open read search };
allow perspectived sysfs_devices_system_cpu:file write;
allow perspectived sysfs_hwrandom:dir search;
allow perspectived sysfs_hwrandom:file { read open write getattr };
allow perspectived sysfs_lowmemorykiller:dir search;
allow perspectived sysfs_thermal:file write;
allow perspectived sysfs_zram_uevent:file { getattr read write open };
allow perspectived proc_sysrq:file getattr;
allow perspectived proc_timer:file getattr;
allow perspectived proc_irq:dir mounton;
allow perspectived sysfs_usb:file write;
allow perspectived sysfs_batteryinfo:file { read open };

Some rules can't assigned to coredomain, so I also modify the system/sepolicy to remove those neverallow rules for coredomain(perspectived is coredomain).

From c4cd60fcc012c02916e9c8fd013e8270af544030 Mon Sep 17 00:00:00 2001
From: utzcoz <utzcoz@outlook.com>
Date: Sat, 4 May 2019 22:51:59 +0800
Subject: [PATCH] Draft to restrictive perspectived sepolicy

Change-Id: I9ffe8459cc1bd6f71a38163227de04ef7a35ed6e
Signed-off-by: utzcoz <utzcoz@outlook.com>
---
 private/domain.te |  2 ++
 public/domain.te  | 27 +++++++++++++++++++++++----
 2 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/private/domain.te b/private/domain.te
index d37a0bd2..5c3fb7b6 100644
--- a/private/domain.te
+++ b/private/domain.te
@@ -7,6 +7,8 @@ allow domain crash_dump:process sigchld;
 # with other UIDs to these whitelisted domains.
 neverallow {
   domain
+  # maru
+  -coredomain
   -vold
   -dumpstate
   -storaged
diff --git a/public/domain.te b/public/domain.te
index 8d0b507b..16c493c7 100644
--- a/public/domain.te
+++ b/public/domain.te
@@ -242,6 +242,8 @@ neverallow {
   domain
   -kernel
   -init
+  # maru
+  -coredomain
   -ueventd
   -vold
 } self:capability mknod;
@@ -343,7 +345,9 @@ neverallow domain device:chr_file { open read write };
 # Limit what domains can mount filesystems or change their mount flags.
 # sdcard_type / vfat is exempt as a larger set of domains need
 # this capability, including device-specific domains.
-neverallow { domain -kernel -init -recovery -vold -zygote -update_engine -otapreopt_chroot } { fs_type -sdcard_type }:filesystem { mount remount relabelfrom relabelto };
+# maru
+# neverallow { domain -kernel -init -recovery -vold -zygote -update_engine -otapreopt_chroot } { fs_type -sdcard_type }:filesystem { mount remount relabelfrom relabelto };
+neverallow { domain -kernel -init -recovery -vold -zygote -update_engine -otapreopt_chroot -coredomain } { fs_type -sdcard_type }:filesystem { mount remount relabelfrom relabelto };

 #
 # Assert that, to the extent possible, we're not loading executable content from
@@ -352,6 +356,8 @@ neverallow { domain -kernel -init -recovery -vold -zygote -update_engine -otapre
 neverallow {
     domain
     -appdomain
+    # maru
+    -coredomain
     with_asan(`-asan_extract')
     -dumpstate
     -shell
@@ -378,6 +384,8 @@ neverallow domain { cache_file cache_backup_file cache_private_backup_file cache
 neverallow {
   domain
   -appdomain
+  # maru
+  -coredomain
 } {
   data_file_type
   -dalvikcache_data_file
@@ -410,7 +418,9 @@ neverallow { domain -recovery -kernel -update_engine with_asan(`-asan_extract')

 # Don't allow mounting on top of /system files or directories
 neverallow * exec_type:dir_file_class_set mounton;
-neverallow { domain -init userdebug_or_eng(`-recovery') } { system_file vendor_file_type }:dir_file_class_set mounton;
+# maru
+# neverallow { domain -init userdebug_or_eng(`-recovery') } { system_file vendor_file_type }:dir_file_class_set mounton;
+neverallow { domain -init -coredomain userdebug_or_eng(`-recovery') } { system_file vendor_file_type }:dir_file_class_set mounton;

 # Nothing should be writing to files in the rootfs.
 neverallow { domain userdebug_or_eng(`-recovery -update_engine') } rootfs:file { create write setattr relabelto append unlink link rename };
@@ -800,7 +810,8 @@ neverallow { domain -dumpstate -system_server } tombstoned_intercept_socket:unix
 # that, even assuming only non-buggy and non-malicious code, it is very likely
 # that over time, the kernel global tables used to implement SysV IPCs will fill
 # up.
-neverallow * *:{ shm sem msg msgq } *;
+# maru
+#neverallow * *:{ shm sem msg msgq } *;

 # Do not mount on top of symlinks, fifos, or sockets.
 # Feature parity with Chromium LSM.
@@ -846,7 +857,9 @@ ifelse(target_needs_platform_text_relocations, `true', ,
   `neverallow { domain -untrusted_app_all } file_type:file execmod;'
 )

-neverallow { domain -init } proc:{ file dir } mounton;
+# maru
+# neverallow { domain -init } proc:{ file dir } mounton;
+neverallow { domain -init -coredomain } proc:{ file dir } mounton;

 # Ensure that all types assigned to processes are included
 # in the domain attribute, so that all allow and neverallow rules
@@ -943,6 +956,8 @@ neverallow {
   -dumpstate
   -installd
   -init
+  # maru
+  -coredomain
   -shell
   -vold
 } shell_data_file:dir no_w_dir_perms;
@@ -950,6 +965,8 @@ neverallow {
 neverallow {
   domain
   -adbd
+  # maru
+  -coredomain
   -appdomain
   -dumpstate
   -init
@@ -964,6 +981,8 @@ neverallow {
   domain
   -adbd
   -appdomain
+  # maru
+  -coredomain
   -dumpstate
   -installd
   userdebug_or_eng(`-uncrypt')
-- 
2.17.1

After above modifications, the MaruOS can run and show Linux to Android secondary display. Also I can visit the network in tty created by lxc-start --name default.

This work is fussy, and changes the Android default sepolicy rules, what maybe cause security problem. For example, the Android doesn't support System V IPC, but MaruOS' Linux part needs System V IPC, what may cause global kernel resource leakage.

Android does not support System V IPCs. The reason for this is due to the fact that, by design, they lead to global kernel resource leakage.

For example, there is no way to automatically release a SysV semaphore allocated in the kernel when:

  • a buggy or malicious process exits
  • a non-buggy and non-malicious process crashes or is explicitly killed.

Killing processes automatically to make room for new ones is an important part of Android's application lifecycle implementation. This means that, even assuming only non-buggy and non-malicious code, it is very likely that over time, the kernel global tables used to implement SysV IPCs will fill up.

Maybe it's time to discuss the solution to restrict perspectived sepolicy rules, so I post it here to discuss.

Thanks.

utzcoz commented 5 years ago

I also test it with user build(pixel), and the MaruOS Linux can show in Android secondary simulate display. I will test it with network and other functions later with real WiFi display.

pdsouza commented 5 years ago

Thanks for looking into this! Yes, I just made it permissive when I was initially developing Maru to save time, and later on I discovered that we had to modify system/sepolicy so I just kept it permissive. I wish we didn't need to modify Android default sepolicy rules.

Also, since we are based on LineageOS now, we just publish userdebug builds rather than user builds like we did before, so this may not be an urgent problem right now.

Regarding SYSVIPC, Maru uses shared memory between mclient and xorg to reduce buffer copies. I think we are ok for now since we do not use semaphores or message queues. Hopefully when we transition to using hardware acceleration we can remove this entirely.

utzcoz commented 5 years ago

Okay, I got it. If publishing userdebug can be accepted, keeping permissive is a good solution to process it. SYSVIPC maybe be used by other processes inner Linux, regarding mclient and xorg, I guess. I don't check whether Linux can work fine without SYSVIPC sepolicy permissive.

Lastly, @pdsouza thanks for your response.