Merge "zygote/dex2oat: Grant additional symlink permissions"
diff --git a/adbd.te b/adbd.te
index 9d3d30d..c21e703 100644
--- a/adbd.te
+++ b/adbd.te
@@ -60,6 +60,14 @@
allow adbd adb_keys_file:dir search;
allow adbd adb_keys_file:file r_file_perms;
+userdebug_or_eng(`
+ # Write debugging information to /data/adb
+ # when persist.adb.trace_mask is set
+ # https://code.google.com/p/android/issues/detail?id=72895
+ allow adbd adb_data_file:dir rw_dir_perms;
+ allow adbd adb_data_file:file create_file_perms;
+')
+
# ndk-gdb invokes adb forward to forward the gdbserver socket.
allow adbd app_data_file:dir search;
allow adbd app_data_file:sock_file write;
diff --git a/app.te b/app.te
index be3ead8..ea74cb0 100644
--- a/app.te
+++ b/app.te
@@ -19,7 +19,7 @@
allow appdomain zygote_exec:file rx_file_perms;
# gdbserver for ndk-gdb ptrace attaches to app process.
-allow appdomain self:process ptrace;
+allow { appdomain -isolated_app } self:process ptrace;
# Read system properties managed by zygote.
allow appdomain zygote_tmpfs:file read;
@@ -46,8 +46,8 @@
allow appdomain surfaceflinger:unix_stream_socket { read write setopt getattr getopt shutdown };
# App sandbox file accesses.
-allow { appdomain -isolated_app } app_data_file:dir create_dir_perms;
-allow { appdomain -isolated_app } app_data_file:notdevfile_class_set create_file_perms;
+allow appdomain app_data_file:dir create_dir_perms;
+allow appdomain app_data_file:notdevfile_class_set create_file_perms;
# lib subdirectory of /data/data dir is system-owned.
allow appdomain system_data_file:dir r_dir_perms;
@@ -284,7 +284,8 @@
# Write to various other parts of /data.
neverallow appdomain drm_data_file:dir_file_class_set
{ create write setattr relabelfrom relabelto append unlink link rename };
-neverallow appdomain gps_data_file:dir_file_class_set
+neverallow { appdomain -system_app }
+ gps_data_file:dir_file_class_set
{ create write setattr relabelfrom relabelto append unlink link rename };
neverallow { appdomain -platform_app }
apk_data_file:dir_file_class_set
diff --git a/device.te b/device.te
index c1f3d28..20e95a5 100644
--- a/device.te
+++ b/device.te
@@ -11,6 +11,7 @@
type loop_device, dev_type;
type radio_device, dev_type;
type ram_device, dev_type;
+type vold_device, dev_type;
type console_device, dev_type;
type cpuctl_device, dev_type;
type fscklogs, dev_type;
@@ -82,3 +83,8 @@
# Block device for any swap partition.
type swap_block_device, dev_type;
+
+# Metadata block device used for encryption metadata.
+# Assign this type to the partition specified by the encryptable=
+# mount option in your fstab file in the entry for userdata.
+type metadata_block_device, dev_type;
diff --git a/domain.te b/domain.te
index 86aeb07..3851506 100644
--- a/domain.te
+++ b/domain.te
@@ -170,8 +170,8 @@
### neverallow rules
###
-# Do not allow any confined domain to create new unlabeled files.
-neverallow { domain -unconfineddomain -recovery } unlabeled:dir_file_class_set create;
+# Do not allow any domain other than init or recovery to create unlabeled files.
+neverallow { domain -init -recovery } unlabeled:dir_file_class_set create;
# Limit ability to ptrace or read sensitive /proc/pid files of processes
# with other UIDs to these whitelisted domains.
@@ -231,7 +231,7 @@
neverallow { domain -init } kernel:security setsecparam;
# Only init, ueventd and system_server should be able to access HW RNG
-neverallow { domain -init -system_server -ueventd -unconfineddomain } hw_random_device:chr_file *;
+neverallow { domain -init -system_server -ueventd } hw_random_device:chr_file *;
# Ensure that all entrypoint executables are in exec_type.
neverallow domain { file_type -exec_type }:file entrypoint;
@@ -254,12 +254,13 @@
# Don't allow raw read/write/open access to block_device
# Rather force a relabel to a more specific type
-neverallow { domain -kernel -init -recovery -vold -uncrypt -install_recovery -fsck } block_device:blk_file { open read write };
+neverallow { domain -kernel -init -recovery -vold -uncrypt -install_recovery } block_device:blk_file { open read write };
# Don't allow raw read/write/open access to generic devices.
# Rather force a relabel to a more specific type.
-# ueventd is exempt from this, as its managing these devices.
-neverallow { domain -unconfineddomain -ueventd } device:chr_file { open read write };
+# init is exempt from this as there are character devices that only it uses.
+# ueventd is exempt from this, as it is managing these devices.
+neverallow { domain -init -ueventd } 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
diff --git a/file.te b/file.te
index cc11677..5c91cf0 100644
--- a/file.te
+++ b/file.te
@@ -52,6 +52,8 @@
type install_data_file, file_type, data_file_type;
# /data/drm - DRM plugin data
type drm_data_file, file_type, data_file_type;
+# /data/adb - adb debugging files
+type adb_data_file, file_type, data_file_type;
# /data/anr - ANR traces
type anr_data_file, file_type, data_file_type, mlstrustedobject;
# /data/tombstones - core dumps
diff --git a/file_contexts b/file_contexts
index 2efd7e9..1d81cbf 100644
--- a/file_contexts
+++ b/file_contexts
@@ -40,7 +40,9 @@
/dev/audio.* u:object_r:audio_device:s0
/dev/binder u:object_r:binder_device:s0
/dev/block(/.*)? u:object_r:block_device:s0
+/dev/block/dm-[0-9]+ u:object_r:dm_device:s0
/dev/block/loop[0-9]* u:object_r:loop_device:s0
+/dev/block/vold/[0-9]+:[0-9]+ u:object_r:vold_device:s0
/dev/block/ram[0-9]* u:object_r:ram_device:s0
/dev/bus/usb(.*)? u:object_r:usb_device:s0
/dev/cam u:object_r:camera_device:s0
@@ -124,6 +126,7 @@
#
/system(/.*)? u:object_r:system_file:s0
/system/bin/e2fsck -- u:object_r:fsck_exec:s0
+/system/bin/fsck\.f2fs -- u:object_r:fsck_exec:s0
/system/bin/toolbox -- u:object_r:toolbox_exec:s0
/system/bin/logcat -- u:object_r:logcat_exec:s0
/system/bin/sh -- u:object_r:shell_exec:s0
@@ -186,6 +189,7 @@
/data/resource-cache(/.*)? u:object_r:resourcecache_data_file:s0
/data/dalvik-cache(/.*)? u:object_r:dalvikcache_data_file:s0
/data/dalvik-cache/profiles(/.*)? u:object_r:dalvikcache_profiles_data_file:s0
+/data/adb(/.*)? u:object_r:adb_data_file:s0
/data/anr(/.*)? u:object_r:anr_data_file:s0
/data/app(/.*)? u:object_r:apk_data_file:s0
/data/app/vmdl.*\.tmp(/.*)? u:object_r:apk_tmp_file:s0
diff --git a/fsck.te b/fsck.te
index d255175..b4eb698 100644
--- a/fsck.te
+++ b/fsck.te
@@ -10,13 +10,9 @@
allow fsck tmpfs:chr_file { read write ioctl };
# Inherit and use pty created by android_fork_execvp_ext().
-allow fsck devpts:chr_file { read write ioctl };
+allow fsck devpts:chr_file { read write ioctl getattr };
# Run e2fsck on block devices.
-# TODO: Assign userdata and cache block device types to the corresponding
-# block devices in all device policies, and then remove access to
-# block_device:blk_file from here.
-allow fsck block_device:blk_file rw_file_perms;
allow fsck userdata_block_device:blk_file rw_file_perms;
allow fsck cache_block_device:blk_file rw_file_perms;
diff --git a/init.te b/init.te
index a6fadbd..cce2e41 100644
--- a/init.te
+++ b/init.te
@@ -102,6 +102,28 @@
# set scheduling parameters for a kernel domain task.
allow init kernel:process setsched;
+# swapon() needs write access to swap device
+# system/core/fs_mgr/fs_mgr.c - fs_mgr_swapon_all
+allow init swap_block_device:blk_file rw_file_perms;
+
+# Read from /dev/hw_random if present.
+# system/core/init/init.c - mix_hwrng_into_linux_rng_action
+allow init hw_random_device:chr_file r_file_perms;
+
+# Create and access /dev files without a specific type,
+# e.g. /dev/.coldboot_done.
+# TODO: Move these files into their own type unless they are
+# only ever accessed by init.
+allow init device:file create_file_perms;
+auditallow init device:file create_file_perms;
+
+# Access character devices without a specific type,
+# e.g. /dev/keychord.
+# TODO: Move these devices into their own type unless they
+# are only ever accessed by init.
+allow init device:chr_file { rw_file_perms setattr };
+auditallow init device:chr_file { rw_file_perms setattr };
+
###
### neverallow rules
###
diff --git a/init_shell.te b/init_shell.te
deleted file mode 100644
index 51dbd07..0000000
--- a/init_shell.te
+++ /dev/null
@@ -1,10 +0,0 @@
-# Restricted domain for shell processes spawned by init.
-# Normally these are shell commands or scripts invoked via sh
-# from an init*.rc file. No service should ever run in this domain.
-type init_shell, domain;
-domain_auto_trans(init, shell_exec, init_shell)
-permissive_or_unconfined(init_shell)
-
-# Run helpers from / or /system without changing domain.
-allow init_shell rootfs:file execute_no_trans;
-allow init_shell system_file:file execute_no_trans;
diff --git a/isolated_app.te b/isolated_app.te
index 6fc7a99..f17372a 100644
--- a/isolated_app.te
+++ b/isolated_app.te
@@ -12,12 +12,6 @@
type isolated_app, domain;
app_domain(isolated_app)
-# Access already open app data files received over Binder or local socket IPC.
-allow isolated_app app_data_file:file { read write getattr };
-
-# Isolated apps should not directly open app data files themselves.
-neverallow isolated_app app_data_file:file open;
-
# Isolated apps shouldn't be able to access the driver directly.
neverallow isolated_app gpu_device:file { rw_file_perms execute };
diff --git a/keystore.te b/keystore.te
index f2c5039..700b99b 100644
--- a/keystore.te
+++ b/keystore.te
@@ -21,8 +21,8 @@
neverallow { domain -keystore } keystore_data_file:dir ~{ open create read getattr setattr search relabelto };
neverallow { domain -keystore } keystore_data_file:notdevfile_class_set ~{ relabelto getattr };
-neverallow { domain -keystore -init -kernel -recovery } keystore_data_file:dir *;
-neverallow { domain -keystore -init -kernel -recovery } keystore_data_file:notdevfile_class_set *;
+neverallow { domain -keystore -init } keystore_data_file:dir *;
+neverallow { domain -keystore -init } keystore_data_file:notdevfile_class_set *;
neverallow domain keystore:process ptrace;
diff --git a/logd.te b/logd.te
index ca6719a..70a894c 100644
--- a/logd.te
+++ b/logd.te
@@ -19,6 +19,8 @@
allow logd logd_debug:file create_file_perms;
')
+allow logd kernel:system syslog_mod;
+
###
### Neverallow rules
###
diff --git a/recovery.te b/recovery.te
index 75a024c..204c096 100644
--- a/recovery.te
+++ b/recovery.te
@@ -29,7 +29,7 @@
# We may be asked to set an SELinux label for a type not known to the
# currently loaded policy. Allow it.
- allow recovery unlabeled:file { create_file_perms relabelfrom relabelto };
+ allow recovery unlabeled:{ file lnk_file } { create_file_perms relabelfrom relabelto };
allow recovery unlabeled:dir { create_dir_perms relabelfrom relabelto };
# 0eb17d944704b3eb140bb9dded299d3be3aed77e in build/ added SELinux
diff --git a/system_server.te b/system_server.te
index 020f2ab..e1528f9 100644
--- a/system_server.te
+++ b/system_server.te
@@ -405,3 +405,10 @@
# Do not allow accessing SDcard files as unsafe ejection could
# cause the kernel to kill the system_server.
neverallow system_server sdcard_type:file rw_file_perms;
+
+# system server should never be opening zygote spawned app data
+# files directly. Rather, they should always be passed via a
+# file descriptor.
+# Types extracted from seapp_contexts type= fields, excluding
+# those types that system_server needs to open directly.
+neverallow system_server { bluetooth_data_file nfc_data_file shell_data_file app_data_file }:file open;
diff --git a/tools/README b/tools/README
index 8a8dce1..2aa520a 100644
--- a/tools/README
+++ b/tools/README
@@ -94,3 +94,37 @@
-foo -bar is expanded to individual allow rules by the policy
compiler). Domains with unconfineddomain will typically have such
duplicate rules as a natural side effect and can be ignored.
+
+ PERMISSIVE DOMAINS
+ sepolicy-analyze -p -P out/target/product/<board>/root/sepolicy
+
+ Displays domains in the policy that are permissive, i.e. avc
+ denials are logged but not enforced for these domains. While
+ permissive domains can be helpful during development, they
+ should not be present in a final -user build.
+
+ NEVERALLOW CHECKING
+ sepolicy-analyze [-w] [-z] -n neverallows.conf -P out/target/product/<board>/root/sepolicy
+
+ Check whether the sepolicy file violates any of the neverallow rules
+ from neverallows.conf. neverallows.conf is a file containing neverallow
+ statements in the same format as the SELinux policy.conf file, i.e. after
+ m4 macro expansion of the rules from a .te file. You can use an entire
+ policy.conf file as the neverallows.conf file and sepolicy-analyze will
+ ignore everything except for the neverallows within it. If there are
+ no violations, sepolicy-analyze will exit successfully with no output.
+ Otherwise, sepolicy-analyze will report all violations and exit
+ with a non-zero exit status.
+
+ The -w or --warn option may be used to warn on any types, attributes,
+ classes, or permissions from a neverallow rule that could not be resolved
+ within the sepolicy file. This can be normal due to differences between
+ the policy from which the neverallow rules were taken and the policy
+ being checked. Such values are ignored for the purposes of neverallow
+ checking.
+
+ The -z (-d was already taken!) or --debug option may be used to cause
+ sepolicy-analyze to emit the neverallow rules as it parses them from
+ the neverallows.conf file. This is principally a debugging facility
+ for the parser but could also be used to extract neverallow rules from
+ a full policy.conf file and output them in a more easily parsed format.
diff --git a/tools/sepolicy-analyze.c b/tools/sepolicy-analyze.c
index c9dab81..afebd69 100644
--- a/tools/sepolicy-analyze.c
+++ b/tools/sepolicy-analyze.c
@@ -12,10 +12,14 @@
#include <sepol/policydb/expand.h>
#include <sepol/policydb/util.h>
#include <stdbool.h>
+#include <ctype.h>
+
+static int debug;
+static int warn;
void usage(char *arg0)
{
- fprintf(stderr, "%s [-e|--equiv] [-d|--diff] [-D|--dups] [-p|--permissive] -P <policy file>\n", arg0);
+ fprintf(stderr, "%s [-w|--warn] [-z|--debug] [-e|--equiv] [-d|--diff] [-D|--dups] [-p|--permissive] [-n|--neverallow <neverallow file>] -P <policy file>\n", arg0);
exit(1);
}
@@ -425,24 +429,466 @@
return 0;
}
+static int read_typeset(policydb_t *policydb, char **ptr, char *end,
+ type_set_t *typeset, uint32_t *flags)
+{
+ const char *keyword = "self";
+ size_t keyword_size = strlen(keyword), len;
+ char *p = *ptr;
+ unsigned openparens = 0;
+ char *start, *id;
+ type_datum_t *type;
+ struct ebitmap_node *n;
+ unsigned int bit;
+ bool negate = false;
+ int rc;
+
+ do {
+ while (p < end && isspace(*p))
+ p++;
+
+ if (p == end)
+ goto err;
+
+ if (*p == '~') {
+ if (debug)
+ printf(" ~");
+ typeset->flags = TYPE_COMP;
+ p++;
+ while (p < end && isspace(*p))
+ p++;
+ if (p == end)
+ goto err;
+ }
+
+ if (*p == '{') {
+ if (debug && !openparens)
+ printf(" {");
+ openparens++;
+ p++;
+ continue;
+ }
+
+ if (*p == '}') {
+ if (debug && openparens == 1)
+ printf(" }");
+ if (openparens == 0)
+ goto err;
+ openparens--;
+ p++;
+ continue;
+ }
+
+ if (*p == '*') {
+ if (debug)
+ printf(" *");
+ typeset->flags = TYPE_STAR;
+ p++;
+ continue;
+ }
+
+ if (*p == '-') {
+ if (debug)
+ printf(" -");
+ negate = true;
+ p++;
+ continue;
+ }
+
+ if (*p == '#') {
+ while (p < end && *p != '\n')
+ p++;
+ continue;
+ }
+
+ start = p;
+ while (p < end && !isspace(*p) && *p != ':' && *p != ';' && *p != '{' && *p != '}' && *p != '#')
+ p++;
+
+ if (p == start)
+ goto err;
+
+ len = p - start;
+ if (len == keyword_size && !strncmp(start, keyword, keyword_size)) {
+ if (debug)
+ printf(" self");
+ *flags |= RULE_SELF;
+ continue;
+ }
+
+ id = calloc(1, len + 1);
+ if (!id)
+ goto err;
+ memcpy(id, start, len);
+ if (debug)
+ printf(" %s", id);
+ type = hashtab_search(policydb->p_types.table, id);
+ if (!type) {
+ if (warn)
+ fprintf(stderr, "Warning! Type or attribute %s used in neverallow undefined in policy being checked.\n", id);
+ negate = false;
+ continue;
+ }
+ free(id);
+
+ if (type->flavor == TYPE_ATTRIB) {
+ if (negate)
+ rc = ebitmap_union(&typeset->negset, &policydb->attr_type_map[type->s.value - 1]);
+ else
+ rc = ebitmap_union(&typeset->types, &policydb->attr_type_map[type->s.value - 1]);
+ } else if (negate) {
+ rc = ebitmap_set_bit(&typeset->negset, type->s.value - 1, 1);
+ } else {
+ rc = ebitmap_set_bit(&typeset->types, type->s.value - 1, 1);
+ }
+
+ negate = false;
+
+ if (rc)
+ goto err;
+
+ } while (p < end && openparens);
+
+ if (p == end)
+ goto err;
+
+ if (typeset->flags & TYPE_STAR) {
+ for (bit = 0; bit < policydb->p_types.nprim; bit++) {
+ if (ebitmap_get_bit(&typeset->negset, bit))
+ continue;
+ if (policydb->type_val_to_struct[bit] &&
+ policydb->type_val_to_struct[bit]->flavor == TYPE_ATTRIB)
+ continue;
+ if (ebitmap_set_bit(&typeset->types, bit, 1))
+ goto err;
+ }
+ }
+
+ ebitmap_for_each_bit(&typeset->negset, n, bit) {
+ if (!ebitmap_node_get_bit(n, bit))
+ continue;
+ if (ebitmap_set_bit(&typeset->types, bit, 0))
+ goto err;
+ }
+
+ if (typeset->flags & TYPE_COMP) {
+ for (bit = 0; bit < policydb->p_types.nprim; bit++) {
+ if (policydb->type_val_to_struct[bit] &&
+ policydb->type_val_to_struct[bit]->flavor == TYPE_ATTRIB)
+ continue;
+ if (ebitmap_get_bit(&typeset->types, bit))
+ ebitmap_set_bit(&typeset->types, bit, 0);
+ else {
+ if (ebitmap_set_bit(&typeset->types, bit, 1))
+ goto err;
+ }
+ }
+ }
+
+ if (warn && ebitmap_length(&typeset->types) == 0 && !(*flags))
+ fprintf(stderr, "Warning! Empty type set\n");
+
+ *ptr = p;
+ return 0;
+err:
+ return -1;
+}
+
+static int read_classperms(policydb_t *policydb, char **ptr, char *end,
+ class_perm_node_t **perms)
+{
+ char *p = *ptr;
+ unsigned openparens = 0;
+ char *id, *start;
+ class_datum_t *cls = NULL;
+ perm_datum_t *perm = NULL;
+ class_perm_node_t *classperms = NULL, *node = NULL;
+ bool complement = false;
+
+ while (p < end && isspace(*p))
+ p++;
+
+ if (p == end || *p != ':')
+ goto err;
+ p++;
+
+ if (debug)
+ printf(" :");
+
+ do {
+ while (p < end && isspace(*p))
+ p++;
+
+ if (p == end)
+ goto err;
+
+ if (*p == '{') {
+ if (debug && !openparens)
+ printf(" {");
+ openparens++;
+ p++;
+ continue;
+ }
+
+ if (*p == '}') {
+ if (debug && openparens == 1)
+ printf(" }");
+ if (openparens == 0)
+ goto err;
+ openparens--;
+ p++;
+ continue;
+ }
+
+ if (*p == '#') {
+ while (p < end && *p != '\n')
+ p++;
+ continue;
+ }
+
+ start = p;
+ while (p < end && !isspace(*p) && *p != '{' && *p != '}' && *p != ';' && *p != '#')
+ p++;
+
+ if (p == start)
+ goto err;
+
+ id = calloc(1, p - start + 1);
+ if (!id)
+ goto err;
+ memcpy(id, start, p - start);
+ if (debug)
+ printf(" %s", id);
+ cls = hashtab_search(policydb->p_classes.table, id);
+ if (!cls) {
+ if (warn)
+ fprintf(stderr, "Warning! Class %s used in neverallow undefined in policy being checked.\n", id);
+ continue;
+ }
+
+ node = calloc(1, sizeof *node);
+ if (!node)
+ goto err;
+ node->class = cls->s.value;
+ node->next = classperms;
+ classperms = node;
+ free(id);
+ } while (p < end && openparens);
+
+ if (p == end)
+ goto err;
+
+ if (warn && !classperms)
+ fprintf(stderr, "Warning! Empty class set\n");
+
+ do {
+ while (p < end && isspace(*p))
+ p++;
+
+ if (p == end)
+ goto err;
+
+ if (*p == '~') {
+ if (debug)
+ printf(" ~");
+ complement = true;
+ p++;
+ while (p < end && isspace(*p))
+ p++;
+ if (p == end)
+ goto err;
+ }
+
+ if (*p == '{') {
+ if (debug && !openparens)
+ printf(" {");
+ openparens++;
+ p++;
+ continue;
+ }
+
+ if (*p == '}') {
+ if (debug && openparens == 1)
+ printf(" }");
+ if (openparens == 0)
+ goto err;
+ openparens--;
+ p++;
+ continue;
+ }
+
+ if (*p == '#') {
+ while (p < end && *p != '\n')
+ p++;
+ continue;
+ }
+
+ start = p;
+ while (p < end && !isspace(*p) && *p != '{' && *p != '}' && *p != ';' && *p != '#')
+ p++;
+
+ if (p == start)
+ goto err;
+
+ id = calloc(1, p - start + 1);
+ if (!id)
+ goto err;
+ memcpy(id, start, p - start);
+ if (debug)
+ printf(" %s", id);
+
+ if (!strcmp(id, "*")) {
+ for (node = classperms; node; node = node->next)
+ node->data = ~0;
+ continue;
+ }
+
+ for (node = classperms; node; node = node->next) {
+ cls = policydb->class_val_to_struct[node->class-1];
+ perm = hashtab_search(cls->permissions.table, id);
+ if (cls->comdatum && !perm)
+ perm = hashtab_search(cls->comdatum->permissions.table, id);
+ if (!perm) {
+ if (warn)
+ fprintf(stderr, "Warning! Permission %s used in neverallow undefined in class %s in policy being checked.\n", id, policydb->p_class_val_to_name[node->class-1]);
+ continue;
+ }
+ node->data |= 1U << (perm->s.value - 1);
+ }
+ free(id);
+ } while (p < end && openparens);
+
+ if (p == end)
+ goto err;
+
+ if (complement) {
+ for (node = classperms; node; node = node->next)
+ node->data = ~node->data;
+ }
+
+ if (warn) {
+ for (node = classperms; node; node = node->next)
+ if (!node->data)
+ fprintf(stderr, "Warning! Empty permission set\n");
+ }
+
+ *perms = classperms;
+ *ptr = p;
+ return 0;
+err:
+ return -1;
+}
+
+static int check_neverallows(policydb_t *policydb, const char *filename)
+{
+ const char *keyword = "neverallow";
+ size_t keyword_size = strlen(keyword), len;
+ struct avrule *neverallows = NULL, *avrule;
+ int fd;
+ struct stat sb;
+ char *text, *end, *start;
+ char *p;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
+ return -1;
+ }
+ if (fstat(fd, &sb) < 0) {
+ fprintf(stderr, "Can't stat '%s': %s\n", filename, strerror(errno));
+ close(fd);
+ return -1;
+ }
+ text = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ end = text + sb.st_size;
+ if (text == MAP_FAILED) {
+ fprintf(stderr, "Can't mmap '%s': %s\n", filename, strerror(errno));
+ close(fd);
+ return -1;
+ }
+ close(fd);
+
+ p = text;
+ while (p < end) {
+ while (p < end && isspace(*p))
+ p++;
+
+ if (*p == '#') {
+ while (p < end && *p != '\n')
+ p++;
+ continue;
+ }
+
+ start = p;
+ while (p < end && !isspace(*p))
+ p++;
+
+ len = p - start;
+ if (len != keyword_size || strncmp(start, keyword, keyword_size))
+ continue;
+
+ if (debug)
+ printf("neverallow");
+
+ avrule = calloc(1, sizeof *avrule);
+ if (!avrule)
+ goto err;
+
+ avrule->specified = AVRULE_NEVERALLOW;
+
+ if (read_typeset(policydb, &p, end, &avrule->stypes, &avrule->flags))
+ goto err;
+
+ if (read_typeset(policydb, &p, end, &avrule->ttypes, &avrule->flags))
+ goto err;
+
+ if (read_classperms(policydb, &p, end, &avrule->perms))
+ goto err;
+
+ while (p < end && *p != ';')
+ p++;
+
+ if (p == end || *p != ';')
+ goto err;
+
+ if (debug)
+ printf(";\n");
+
+ avrule->next = neverallows;
+ neverallows = avrule;
+ }
+
+ return check_assertions(NULL, policydb, neverallows);
+err:
+ if (errno == ENOMEM) {
+ fprintf(stderr, "Out of memory while parsing %s\n", filename);
+ } else
+ fprintf(stderr, "Error while parsing %s\n", filename);
+ return -1;
+}
+
int main(int argc, char **argv)
{
- char *policy = NULL;
+ char *policy = NULL, *neverallows = NULL;
struct policy_file pf;
policydb_t policydb;
char ch;
char equiv = 0, diff = 0, dups = 0, permissive = 0;
+ int rc = 0;
struct option long_options[] = {
{"equiv", no_argument, NULL, 'e'},
+ {"debug", no_argument, NULL, 'z'},
{"diff", no_argument, NULL, 'd'},
{"dups", no_argument, NULL, 'D'},
+ {"neverallow", required_argument, NULL, 'n'},
{"permissive", no_argument, NULL, 'p'},
{"policy", required_argument, NULL, 'P'},
+ {"warn", no_argument, NULL, 'w'},
{NULL, 0, NULL, 0}
};
- while ((ch = getopt_long(argc, argv, "edDpP:", long_options, NULL)) != -1) {
+ while ((ch = getopt_long(argc, argv, "edDpn:P:wz", long_options, NULL)) != -1) {
switch (ch) {
case 'e':
equiv = 1;
@@ -453,18 +899,27 @@
case 'D':
dups = 1;
break;
+ case 'n':
+ neverallows = optarg;
+ break;
case 'p':
permissive = 1;
break;
case 'P':
policy = optarg;
break;
+ case 'w':
+ warn = 1;
+ break;
+ case 'z':
+ debug = 1;
+ break;
default:
usage(argv[0]);
}
}
- if (!policy || (!equiv && !diff && !dups && !permissive))
+ if (!policy || (!equiv && !diff && !dups && !permissive && !neverallows))
usage(argv[0]);
if (load_policy(policy, &policydb, &pf))
@@ -479,7 +934,10 @@
if (permissive)
list_permissive(&policydb);
+ if (neverallows)
+ rc |= check_neverallows(&policydb, neverallows);
+
policydb_destroy(&policydb);
- return 0;
+ return rc;
}
diff --git a/unconfined.te b/unconfined.te
index a76c3d8..1a51942 100644
--- a/unconfined.te
+++ b/unconfined.te
@@ -55,6 +55,7 @@
-security_file
-shell_data_file
-app_data_file
+ -unlabeled
}:{ dir lnk_file sock_file fifo_file } ~relabelto;
allow unconfineddomain exec_type:dir r_dir_perms;
allow unconfineddomain exec_type:file { r_file_perms execute };
@@ -69,8 +70,9 @@
-contextmount_type
-rootfs
-sdcard_type
+ -device
}:{ chr_file file } ~{entrypoint execute_no_trans execmod execute relabelto};
-allow unconfineddomain {dev_type -kmem_device}:{ chr_file file } ~{entrypoint execute_no_trans execmod execute relabelto};
+allow unconfineddomain {dev_type -device -kmem_device -hw_random_device}:{ chr_file file } ~{entrypoint execute_no_trans execmod execute relabelto};
allow unconfineddomain {
file_type
-keystore_data_file
@@ -80,6 +82,7 @@
-security_file
-shell_data_file
-app_data_file
+ -unlabeled
}:{ chr_file file } ~{entrypoint execute_no_trans execmod execute relabelto};
allow unconfineddomain rootfs:file execute;
allow unconfineddomain contextmount_type:dir r_dir_perms;
diff --git a/untrusted_app.te b/untrusted_app.te
index 7e67ea8..2b2a2e7 100644
--- a/untrusted_app.te
+++ b/untrusted_app.te
@@ -101,4 +101,4 @@
# Allow verifier to access staged apks.
allow untrusted_app { apk_tmp_file apk_private_tmp_file }:dir r_dir_perms;
-allow untrusted_app { apk_tmp_file apk_private_tmp_file }:file r_file_perms;
\ No newline at end of file
+allow untrusted_app { apk_tmp_file apk_private_tmp_file }:file r_file_perms;
diff --git a/vold.te b/vold.te
index ef3924b..f605f8a 100644
--- a/vold.te
+++ b/vold.te
@@ -5,9 +5,11 @@
init_daemon_domain(vold)
typeattribute vold mlstrustedsubject;
+allow vold self:process setfscreate;
allow vold system_file:file x_file_perms;
allow vold block_device:dir create_dir_perms;
allow vold block_device:blk_file create_file_perms;
+auditallow vold block_device:blk_file create_file_perms;
allow vold device:dir write;
allow vold devpts:chr_file rw_file_perms;
allow vold rootfs:dir mounton;
@@ -22,8 +24,10 @@
allow vold self:netlink_kobject_uevent_socket create_socket_perms;
allow vold app_data_file:dir search;
allow vold app_data_file:file rw_file_perms;
-allow vold loop_device:blk_file rw_file_perms;
+allow vold loop_device:blk_file create_file_perms;
+allow vold vold_device:blk_file create_file_perms;
allow vold dm_device:chr_file rw_file_perms;
+allow vold dm_device:blk_file rw_file_perms;
# For vold Process::killProcessesWithOpenFiles function.
allow vold domain:dir r_dir_perms;
allow vold domain:{ file lnk_file } r_file_perms;
@@ -94,4 +98,6 @@
# Access userdata block device.
allow vold userdata_block_device:blk_file rw_file_perms;
-auditallow vold userdata_block_device:blk_file rw_file_perms;
+
+# Access metadata block device used for encryption meta-data.
+allow vold metadata_block_device:blk_file rw_file_perms;