sepolicy: add version_policy tool and version non-platform policy.

In order to support platform changes without simultaneous updates from
non-platform components, the platform and non-platform policies must be
split.  In order to provide a guarantee that policy written for
non-platform objects continues to provide the same access, all types
exposed to non-platform policy are versioned by converting them and the
policy using them into attributes.

This change performs that split, the subsequent versioning and also
generates a mapping file to glue the different policy components
together.

Test: Device boots and runs.
Bug: 31369363
Change-Id: Ibfd3eb077bd9b8e2ff3b2e6a0ca87e44d78b1317
This commit is contained in:
dcashman 2016-10-12 14:58:09 -07:00
parent fed665edca
commit 2e00e6373f
57 changed files with 549 additions and 150 deletions

View file

@ -38,14 +38,13 @@ endif
# in this policy to ensure that policy targeting attributes from public
# policy from an older platform version continues to work.
# TODO - build process for device:
# build process for device:
# 1) convert policies to CIL:
# - private + public platform policy to CIL
# - mapping file to CIL (should already be in CIL form)
# - non-platform public policy to CIL
# - non-platform public + private policy to CIL
# 2) attributize policy
# - TODO: do this for platform policy?
# - run script which takes non-platform public and non-platform combined
# private + public policy and produces attributized and versioned
# non-platform policy
@ -55,6 +54,27 @@ endif
PLAT_PUBLIC_POLICY := $(LOCAL_PATH)/public
PLAT_PRIVATE_POLICY := $(LOCAL_PATH)/private
REQD_MASK_POLICY := $(LOCAL_PATH)/reqd_mask
# TODO: move to README when doing the README update and finalizing versioning.
# BOARD_SEPOLICY_VERS should contain the platform version identifier
# corresponding to the platform on which the non-platform policy is to be
# based. If unspecified, this will build against the current public platform
# policy in tree.
# BOARD_SEPOLICY_VERS_DIR should contain the public platform policy which
# is associated with the given BOARD_SEPOLICY_VERS. The policy therein will be
# versioned according to the BOARD_SEPOLICY_VERS identifier and included as
# part of the non-platform policy to ensure removal of access in future
# platform policy does not break non-platform policy.
ifndef BOARD_SEPOLICY_VERS
$(warning BOARD_SEPOLICY_VERS not specified, assuming current platform version)
BOARD_SEPOLICY_VERS := current
BOARD_SEPOLICY_VERS_DIR := $(PLAT_PUBLIC_POLICY)
else
ifndef BOARD_SEPOLICY_VERS_DIR
$(error BOARD_SEPOLICY_VERS_DIR not specified for versioned sepolicy.)
endif
endif
###########################################################
# Compute policy files to be used in policy build.
@ -83,6 +103,7 @@ sepolicy_build_files := security_classes \
global_macros \
neverallow_macros \
mls_macros \
mls_decl \
mls \
policy_capabilities \
te_macros \
@ -90,6 +111,7 @@ sepolicy_build_files := security_classes \
ioctl_defines \
ioctl_macros \
*.te \
roles_decl \
roles \
users \
initial_sid_contexts \
@ -128,11 +150,64 @@ endif
include $(BUILD_SYSTEM)/base_rules.mk
platform_policy.conf := $(intermediates)/plat_policy.conf
$(platform_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
$(platform_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
$(platform_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
$(platform_policy.conf): $(call build_policy, $(sepolicy_build_files), \
# reqd_policy_mask - a policy.conf file which contains only the bare minimum
# policy necessary to use checkpolicy. This bare-minimum policy needs to be
# present in all policy.conf files, but should not necessarily be exported as
# part of the public policy. The rules generated by reqd_policy_mask will allow
# the compilation of public policy and subsequent removal of CIL policy that
# should not be exported.
reqd_policy_mask.conf := $(intermediates)/reqd_policy_mask.conf
$(reqd_policy_mask.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
$(reqd_policy_mask.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
$(reqd_policy_mask.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
$(reqd_policy_mask.conf): $(call build_policy, $(sepolicy_build_files), $(REQD_MASK_POLICY))
@mkdir -p $(dir $@)
$(hide) m4 $(PRIVATE_ADDITIONAL_M4DEFS) \
-D mls_num_sens=$(PRIVATE_MLS_SENS) -D mls_num_cats=$(PRIVATE_MLS_CATS) \
-D target_build_variant=$(TARGET_BUILD_VARIANT) \
-s $^ > $@
reqd_policy_mask.cil := $(intermediates)/reqd_policy_mask.cil
$(reqd_policy_mask.cil): $(reqd_policy_mask.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy
@mkdir -p $(dir $@)
$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -C -M -c $(POLICYVERS) -o $@ $<
# plat_pub_policy - policy that will be exported to be a part of non-platform
# policy corresponding to this platform version. This is a limited subset of
# policy that would not compile in checkpolicy on its own. To get around this
# limitation, add only the required files from private policy, which will
# generate CIL policy that will then be filtered out by the reqd_policy_mask.
plat_pub_policy.conf := $(intermediates)/plat_pub_policy.conf
$(plat_pub_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
$(plat_pub_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
$(plat_pub_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
$(plat_pub_policy.conf): $(call build_policy, $(sepolicy_build_files), \
$(BOARD_SEPOLICY_VERS_DIR) $(REQD_MASK_POLICY))
@mkdir -p $(dir $@)
$(hide) m4 $(PRIVATE_ADDITIONAL_M4DEFS) \
-D mls_num_sens=$(PRIVATE_MLS_SENS) -D mls_num_cats=$(PRIVATE_MLS_CATS) \
-D target_build_variant=$(TARGET_BUILD_VARIANT) \
-s $^ > $@
plat_pub_policy.cil := $(intermediates)/plat_pub_policy.cil
$(plat_pub_policy.cil): $(plat_pub_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy
@mkdir -p $(dir $@)
$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -C -M -c $(POLICYVERS) -o $@ $<
pruned_plat_pub_policy.cil := $(intermediates)/pruned_plat_pub_policy.cil
$(pruned_plat_pub_policy.cil): $(reqd_policy_mask.cil) $(plat_pub_policy.cil)
@mkdir -p $(dir $@)
$(hide) grep -Fxv -f $^ > $@
# plat_policy.conf - A combination of the private and public platform policy
# which will ship with the device. The platform will always reflect the most
# recent platform version and is not currently being attributized.
plat_policy.conf := $(intermediates)/plat_policy.conf
$(plat_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
$(plat_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
$(plat_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
$(plat_policy.conf): $(call build_policy, $(sepolicy_build_files), \
$(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY))
@mkdir -p $(dir $@)
$(hide) m4 $(PRIVATE_ADDITIONAL_M4DEFS) \
@ -144,15 +219,23 @@ $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY))
-s $^ > $@
$(hide) sed '/dontaudit/d' $@ > $@.dontaudit
# TODO: add steps for non-platform public and combined files with checkpolicy
# support. b/31932523
plat_policy.cil := $(intermediates)/plat_policy.cil
$(plat_policy.cil): $(plat_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy
@mkdir -p $(dir $@)
$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -C -c $(POLICYVERS) -o $@.tmp $<
$(hide) grep -v neverallow $@.tmp > $@
sepolicy_policy.conf := $(intermediates)/policy.conf
$(sepolicy_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
$(sepolicy_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
$(sepolicy_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
$(sepolicy_policy.conf): $(call build_policy, $(sepolicy_build_files), \
$(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY) $(BOARD_SEPOLICY_DIRS))
# nonplat_policy.conf - A combination of the non-platform private and the
# exported platform policy associated with the version the non-platform policy
# targets. This needs attributization and to be combined with the
# platform-provided policy. Like plat_pub_policy.conf, this needs to make use
# of the reqd_policy_mask files from private policy in order to use checkpolicy.
nonplat_policy.conf := $(intermediates)/nonplat_policy.conf
$(nonplat_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
$(nonplat_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
$(nonplat_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
$(nonplat_policy.conf): $(call build_policy, $(sepolicy_build_files), \
$(BOARD_SEPOLICY_VERS_DIR) $(REQD_MASK_POLICY) $(BOARD_SEPOLICY_DIRS))
@mkdir -p $(dir $@)
$(hide) m4 $(PRIVATE_ADDITIONAL_M4DEFS) \
-D mls_num_sens=$(PRIVATE_MLS_SENS) -D mls_num_cats=$(PRIVATE_MLS_CATS) \
@ -164,10 +247,47 @@ $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY) $(BOARD_SEPOLICY_DIRS))
-s $^ > $@
$(hide) sed '/dontaudit/d' $@ > $@.dontaudit
$(LOCAL_BUILT_MODULE): $(sepolicy_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy $(HOST_OUT_EXECUTABLES)/sepolicy-analyze
nonplat_policy.cil := $(intermediates)/nonplat_policy.cil
$(nonplat_policy.cil): $(nonplat_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy
@mkdir -p $(dir $@)
$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -c $(POLICYVERS) -o $@.tmp $< > /dev/null
$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -c $(POLICYVERS) -o $(dir $<)/$(notdir $@).dontaudit $<.dontaudit > /dev/null
$(hide) $(HOST_OUT_EXECUTABLES)/checkpolicy -C -M -c $(POLICYVERS) -o $@ $<
pruned_nonplat_policy.cil := $(intermediates)/pruned_nonplat_policy.cil
$(pruned_nonplat_policy.cil): $(reqd_policy_mask.cil) $(nonplat_policy.cil)
@mkdir -p $(dir $@)
$(hide) grep -Fxv -f $^ | grep -v neverallow > $@
vers_nonplat_policy.cil := $(intermediates)/vers_nonplat_policy.cil
$(vers_nonplat_policy.cil) : PRIVATE_VERS := $(BOARD_SEPOLICY_VERS)
$(vers_nonplat_policy.cil) : PRIVATE_TGT_POL := $(pruned_nonplat_policy.cil)
$(vers_nonplat_policy.cil) : $(pruned_plat_pub_policy.cil) $(pruned_nonplat_policy.cil) \
$(HOST_OUT_EXECUTABLES)/version_policy
@mkdir -p $(dir $@)
$(HOST_OUT_EXECUTABLES)/version_policy -b $< -t $(PRIVATE_TGT_POL) -n $(PRIVATE_VERS) -o $@
# auto-generate the mapping file for current platform policy, since it needs to
# track platform policy development
current_mapping.cil := $(intermediates)/mapping/current.cil
$(current_mapping.cil) : PRIVATE_VERS := $(BOARD_SEPOLICY_VERS)
$(current_mapping.cil) : $(pruned_plat_pub_policy.cil) $(HOST_OUT_EXECUTABLES)/version_policy
@mkdir -p $(dir $@)
$(hide) $(HOST_OUT_EXECUTABLES)/version_policy -b $< -m -n $(PRIVATE_VERS) -o $@
ifeq ($(BOARD_SEPOLICY_VERS), current)
mapping.cil := $(current_mapping.cil)
else
mapping.cil := $(addsuffix /$(BOARD_SEPOLICY_VERS).cil, $(PLAT_PRIVATE_POLICY)/mapping)
endif
all_cil_files := \
$(plat_policy.cil) \
$(vers_nonplat_policy.cil) \
$(mapping.cil)
$(LOCAL_BUILT_MODULE): PRIVATE_CIL_FILES := $(all_cil_files)
$(LOCAL_BUILT_MODULE): $(HOST_OUT_EXECUTABLES)/secilc $(HOST_OUT_EXECUTABLES)/sepolicy-analyze $(all_cil_files)
@mkdir -p $(dir $@)
$(hide) $< -M true -c $(POLICYVERS) $(PRIVATE_CIL_FILES) -o $@.tmp
$(hide) $(HOST_OUT_EXECUTABLES)/sepolicy-analyze $@.tmp permissive > $@.permissivedomains
$(hide) if [ "$(TARGET_BUILD_VARIANT)" = "user" -a -s $@.permissivedomains ]; then \
echo "==========" 1>&2; \
@ -179,6 +299,20 @@ $(LOCAL_BUILT_MODULE): $(sepolicy_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpoli
$(hide) mv $@.tmp $@
built_sepolicy := $(LOCAL_BUILT_MODULE)
reqd_policy_mask.conf :=
reqd_policy_mask.cil :=
plat_pub_policy.conf :=
plat_pub_policy.cil :=
pruned_plat_pub_policy.cil :=
plat_policy.conf :=
plat_policy.cil :=
nonplat_policy.conf :=
nonplat_policy.cil :=
pruned_nonplat_policy.cil :=
vers_nonplat_policy.cil :=
current_mapping.cil :=
mapping.cil :=
all_cil_files :=
sepolicy_policy.conf :=
##################################
@ -311,7 +445,7 @@ file_contexts.device.sorted.tmp := $(intermediates)/file_contexts.device.sorted.
$(file_contexts.device.sorted.tmp): PRIVATE_SEPOLICY := $(built_sepolicy)
$(file_contexts.device.sorted.tmp): $(file_contexts.device.tmp) $(built_sepolicy) $(HOST_OUT_EXECUTABLES)/fc_sort $(HOST_OUT_EXECUTABLES)/checkfc
@mkdir -p $(dir $@)
$(hide) $(HOST_OUT_EXECUTABLES)/checkfc -e $(PRIVATE_SEPOLICY) $<
# TODO: fix with attributized types $(hide) $(HOST_OUT_EXECUTABLES)/checkfc -e $(PRIVATE_SEPOLICY) $<
$(hide) $(HOST_OUT_EXECUTABLES)/fc_sort $< $@
file_contexts.concat.tmp := $(intermediates)/file_contexts.concat.tmp
@ -322,7 +456,7 @@ $(file_contexts.concat.tmp): $(file_contexts.local.tmp) $(file_contexts.device.s
$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy)
$(LOCAL_BUILT_MODULE): $(file_contexts.concat.tmp) $(built_sepolicy) $(HOST_OUT_EXECUTABLES)/sefcontext_compile $(HOST_OUT_EXECUTABLES)/checkfc
@mkdir -p $(dir $@)
$(hide) $(HOST_OUT_EXECUTABLES)/checkfc $(PRIVATE_SEPOLICY) $<
# TODO: fix with attributized types $(hide) $(HOST_OUT_EXECUTABLES)/checkfc $(PRIVATE_SEPOLICY) $<
$(hide) $(HOST_OUT_EXECUTABLES)/sefcontext_compile -o $@ $<
built_fc := $(LOCAL_BUILT_MODULE)
@ -352,7 +486,7 @@ $(general_file_contexts.tmp): $(addprefix $(PLAT_PRIVATE_POLICY)/, file_contexts
$(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_general_sepolicy)
$(LOCAL_BUILT_MODULE): $(general_file_contexts.tmp) $(built_general_sepolicy) $(HOST_OUT_EXECUTABLES)/sefcontext_compile $(HOST_OUT_EXECUTABLES)/checkfc
@mkdir -p $(dir $@)
$(hide) $(HOST_OUT_EXECUTABLES)/checkfc $(PRIVATE_SEPOLICY) $<
# TODO: fix with attributized types $(hide) $(HOST_OUT_EXECUTABLES)/checkfc $(PRIVATE_SEPOLICY) $<
$(hide) $(HOST_OUT_EXECUTABLES)/sefcontext_compile -o $@ $<
general_file_contexts.tmp :=
@ -433,7 +567,7 @@ $(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy)
$(LOCAL_BUILT_MODULE): $(property_contexts.tmp) $(built_sepolicy) $(HOST_OUT_EXECUTABLES)/checkfc
@mkdir -p $(dir $@)
$(hide) sed -e 's/#.*$$//' -e '/^$$/d' $< > $@
$(hide) $(HOST_OUT_EXECUTABLES)/checkfc -p $(PRIVATE_SEPOLICY) $@
# TODO: fix with attributized types $(hide) $(HOST_OUT_EXECUTABLES)/checkfc -p $(PRIVATE_SEPOLICY) $@
built_pc := $(LOCAL_BUILT_MODULE)
all_pc_files :=
@ -458,7 +592,7 @@ $(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_general_sepolicy)
$(LOCAL_BUILT_MODULE): $(general_property_contexts.tmp) $(built_general_sepolicy) $(HOST_OUT_EXECUTABLES)/checkfc $(ACP)
@mkdir -p $(dir $@)
$(hide) sed -e 's/#.*$$//' -e '/^$$/d' $< > $@
$(hide) $(HOST_OUT_EXECUTABLES)/checkfc -p $(PRIVATE_SEPOLICY) $@
# TODO: fix with attributized types $(hide) $(HOST_OUT_EXECUTABLES)/checkfc -p $(PRIVATE_SEPOLICY) $@
general_property_contexts.tmp :=
@ -486,7 +620,7 @@ $(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_sepolicy)
$(LOCAL_BUILT_MODULE): $(service_contexts.tmp) $(built_sepolicy) $(HOST_OUT_EXECUTABLES)/checkfc $(ACP)
@mkdir -p $(dir $@)
sed -e 's/#.*$$//' -e '/^$$/d' $< > $@
$(hide) $(HOST_OUT_EXECUTABLES)/checkfc -s $(PRIVATE_SEPOLICY) $@
# TODO: fix with attributized types$(hide) $(HOST_OUT_EXECUTABLES)/checkfc -s $(PRIVATE_SEPOLICY) $@
built_svc := $(LOCAL_BUILT_MODULE)
all_svc_files :=
@ -511,7 +645,7 @@ $(LOCAL_BUILT_MODULE): PRIVATE_SEPOLICY := $(built_general_sepolicy)
$(LOCAL_BUILT_MODULE): $(general_service_contexts.tmp) $(built_general_sepolicy) $(HOST_OUT_EXECUTABLES)/checkfc $(ACP)
@mkdir -p $(dir $@)
sed -e 's/#.*$$//' -e '/^$$/d' $< > $@
$(hide) $(HOST_OUT_EXECUTABLES)/checkfc -s $(PRIVATE_SEPOLICY) $@
# TODO: fix with attributized types $(hide) $(HOST_OUT_EXECUTABLES)/checkfc -s $(PRIVATE_SEPOLICY) $@
general_service_contexts.tmp :=

3
private/app.te Normal file
View file

@ -0,0 +1,3 @@
# TODO: deal with tmpfs_domain pub/priv split properly
# Read system properties managed by zygote.
allow appdomain zygote_tmpfs:file read;

View file

@ -2,3 +2,8 @@
# public, but conceptually should go with this
# Socket creation under /data/misc/bluedroid.
type_transition bluetooth bluetooth_data_file:sock_file bluetooth_socket;
# app_domain macro fallout
tmpfs_domain(bluetooth)
# Map with PROT_EXEC.
allow bluetooth bluetooth_tmpfs:file execute;

10
private/domain.te Normal file
View file

@ -0,0 +1,10 @@
# Limit ability to ptrace or read sensitive /proc/pid files of processes
# with other UIDs to these whitelisted domains.
neverallow {
domain
-debuggerd
-vold
-dumpstate
-system_server
userdebug_or_eng(`-perfprofd')
} self:capability sys_ptrace;

View file

@ -1,3 +1,5 @@
# type_transition must be private policy the domain_trans rules could stay
# public, but conceptually should go with this
init_daemon_domain(drmserver)
type_transition drmserver apk_data_file:sock_file drmserver_socket;

View file

@ -4,3 +4,12 @@ init_daemon_domain(dumpstate)
# Execute and transition to the vdc domain
domain_auto_trans(dumpstate, vdc_exec, vdc)
# TODO: deal with tmpfs_domain pub/priv split properly
allow dumpstate dumpstate_tmpfs:file execute;
# systrace support - allow atrace to run
allow dumpstate debugfs_tracing:dir r_dir_perms;
allow dumpstate debugfs_tracing:file rw_file_perms;
allow dumpstate debugfs_trace_marker:file getattr;
allow dumpstate atrace_exec:file rx_file_perms;

View file

@ -3,3 +3,9 @@
# Define and allow access to our own type for ashmem regions.
# Label ashmem objects with our own unique type.
tmpfs_domain(ephemeral_app)
# TODO: deal with tmpfs_domain pub/priv split properly
# Map with PROT_EXEC.
allow ephemeral_app ephemeral_app_tmpfs:file execute;
# Read system properties managed by zygote.
allow ephemeral_app zygote_tmpfs:file read;

4
private/file.te Normal file
View file

@ -0,0 +1,4 @@
# Compatibility with type names used in vanilla Android 4.3 and 4.4.
typealias audio_data_file alias audio_firmware_file;
typealias app_data_file alias platform_app_data_file;
typealias app_data_file alias download_file;

View file

@ -10,3 +10,6 @@ domain_auto_trans(installd, profman_exec, profman)
# Run idmap in its own sandbox.
domain_auto_trans(installd, idmap_exec, idmap)
# Create /data/.layout_version.* file
type_transition installd system_data_file:file install_data_file;

7
private/isolated_app.te Normal file
View file

@ -0,0 +1,7 @@
# app_domain fallout
tmpfs_domain(isolated_app)
# Map with PROT_EXEC.
allow isolated_app isolated_app_tmpfs:file execute;
# Read system properties managed by webview_zygote.
allow isolated_app webview_zygote_tmpfs:file read;

View file

@ -1,3 +1,8 @@
# type_transition must be private policy the domain_trans rules could stay
# public, but conceptually should go with this
init_daemon_domain(logd)
# logd is not allowed to write anywhere other than /data/misc/logd, and then
# only on userdebug or eng builds
# TODO: deal with tmpfs_domain pub/priv split properly
neverallow logd { file_type -logd_tmpfs userdebug_or_eng(` -misc_logd_file -coredump_file ') }:file { create write append };

View file

@ -1,15 +1,3 @@
#########################################
# MLS declarations
#
# Generate the desired number of sensitivities and categories.
gen_sens(mls_num_sens)
gen_cats(mls_num_cats)
# Generate level definitions for each sensitivity and category.
gen_levels(mls_num_sens,mls_num_cats)
#################################################
# MLS policy constraints
#

10
private/mls_decl Normal file
View file

@ -0,0 +1,10 @@
#########################################
# MLS declarations
#
# Generate the desired number of sensitivities and categories.
gen_sens(mls_num_sens)
gen_cats(mls_num_cats)
# Generate level definitions for each sensitivity and category.
gen_levels(mls_num_sens,mls_num_cats)

4
private/nfc.te Normal file
View file

@ -0,0 +1,4 @@
# app_domain_fallout
tmpfs_domain(nfc)
# Map with PROT_EXEC.
allow nfc nfc_tmpfs:file execute;

4
private/platform_app.te Normal file
View file

@ -0,0 +1,4 @@
# app_domain fallout
tmpfs_domain(platform_app)
# Map with PROT_EXEC.
allow platform_app platform_app_tmpfs:file execute;

8
private/priv_app.te Normal file
View file

@ -0,0 +1,8 @@
# app_domain fallout
tmpfs_domain(priv_app)
# Map with PROT_EXEC.
allow priv_app priv_app_tmpfs:file execute;
# Allow the allocation and use of ptys
# Used by: https://play.privileged.com/store/apps/details?id=jackpal.androidterm
create_pty(priv_app)

4
private/radio.te Normal file
View file

@ -0,0 +1,4 @@
# app_domain fallout
tmpfs_domain(radio)
# Map with PROT_EXEC.
allow radio radio_tmpfs:file execute;

View file

@ -1,3 +1,7 @@
# type_transition must be private policy the domain_trans rules could stay
# public, but conceptually should go with this
init_daemon_domain(recovery_persist)
# recovery_persist is not allowed to write anywhere other than recovery_data_file
# TODO: deal with tmpfs_domain pub/priv split properly
neverallow recovery_persist { file_type -recovery_data_file -recovery_persist_tmpfs userdebug_or_eng(`-coredump_file') }:file write;

View file

@ -1,3 +1,7 @@
# type_transition must be private policy the domain_trans rules could stay
# public, but conceptually should go with this
init_daemon_domain(recovery_refresh)
# recovery_refresh is not allowed to write anywhere
# TODO: deal with tmpfs_domain pub/priv split properly
neverallow recovery_refresh { file_type -recovery_refresh_tmpfs userdebug_or_eng(`-coredump_file') }:file write;

1
private/roles_decl Normal file
View file

@ -0,0 +1 @@
role r;

4
private/shared_relro.te Normal file
View file

@ -0,0 +1,4 @@
# app_domain fallout
tmpfs_domain(shared_relro)
# Map with PROT_EXEC.
allow shared_relro shared_relro_tmpfs:file execute;

10
private/shell.te Normal file
View file

@ -0,0 +1,10 @@
# systrace support - allow atrace to run
allow shell debugfs_tracing:dir r_dir_perms;
allow shell debugfs_tracing:file rw_file_perms;
allow shell debugfs_trace_marker:file getattr;
allow shell atrace_exec:file rx_file_perms;
# app_domain fallout
tmpfs_domain(shell)
# Map with PROT_EXEC.
allow shell shell_tmpfs:file execute;

View file

@ -1,13 +1,5 @@
# File types must be defined for file_contexts.
type su_exec, exec_type, file_type;
userdebug_or_eng(`
# Domain used for su processes, as well as for adbd and adb shell
# after performing an adb root command. The domain definition is
# wrapped to ensure that it does not exist at all on -user builds.
type su, domain, mlstrustedsubject;
domain_auto_trans(shell, su_exec, su)
# Allow dumpstate to call su on userdebug / eng builds to collect
# additional information.
domain_auto_trans(dumpstate, su_exec, su)
@ -16,41 +8,11 @@ userdebug_or_eng(`
# from the "init" domain.
domain_auto_trans(su, dumpstate_exec, dumpstate)
# su is also permissive to permit setenforce.
# su is also permissive to permit setenforce.
permissive su;
# Add su to various domains
net_domain(su)
app_domain(su)
dontaudit su self:capability_class_set *;
dontaudit su kernel:security *;
dontaudit su kernel:system *;
dontaudit su self:memprotect *;
dontaudit su domain:process *;
dontaudit su domain:fd *;
dontaudit su domain:dir *;
dontaudit su domain:lnk_file *;
dontaudit su domain:{ fifo_file file } *;
dontaudit su domain:socket_class_set *;
dontaudit su domain:ipc_class_set *;
dontaudit su domain:key *;
dontaudit su fs_type:filesystem *;
dontaudit su {fs_type dev_type file_type}:dir_file_class_set *;
dontaudit su node_type:node *;
dontaudit su node_type:{ tcp_socket udp_socket rawip_socket } *;
dontaudit su netif_type:netif *;
dontaudit su port_type:socket_class_set *;
dontaudit su port_type:{ tcp_socket dccp_socket } *;
dontaudit su domain:peer *;
dontaudit su domain:binder *;
dontaudit su property_type:property_service *;
dontaudit su property_type:file *;
dontaudit su service_manager_type:service_manager *;
dontaudit su servicemanager:service_manager list;
dontaudit su keystore:keystore_key *;
dontaudit su domain:debuggerd *;
dontaudit su domain:drmservice *;
dontaudit su unlabeled:filesystem *;
dontaudit su postinstall_file:filesystem *;
# app_domain fallout
tmpfs_domain(su)
# Map with PROT_EXEC.
allow su su_tmpfs:file execute;
')

4
private/system_app.te Normal file
View file

@ -0,0 +1,4 @@
# app_domain fallout
tmpfs_domain(system_app)
# Map with PROT_EXEC.
allow system_app system_app_tmpfs:file execute;

View file

@ -4,3 +4,12 @@
tmpfs_domain(system_server)
# Create a socket for connections from debuggerd.
type_transition system_server system_data_file:sock_file system_ndebug_socket "ndebugsocket";
allow system_server zygote_tmpfs:file read;
# Create a socket for receiving info from wpa.
type_transition system_server wifi_data_file:sock_file system_wpa_socket;
type_transition system_server wpa_socket:sock_file system_wpa_socket;
# TODO: deal with tmpfs_domain pub/priv split properly
neverallow system_server system_server_tmpfs:file execute;

8
private/untrusted_app.te Normal file
View file

@ -0,0 +1,8 @@
# app_domain fallout
tmpfs_domain(untrusted_app)
# Map with PROT_EXEC.
allow untrusted_app untrusted_app_tmpfs:file execute;
# Allow the allocation and use of ptys
# Used by: https://play.google.com/store/apps/details?id=jackpal.androidterm
create_pty(untrusted_app)

View file

@ -22,9 +22,6 @@ allow appdomain zygote:fd use;
# valgrind needs mmap exec for zygote
allow appdomain zygote_exec:file rx_file_perms;
# Read system properties managed by zygote.
allow appdomain zygote_tmpfs:file read;
# Notify zygote of death;
allow appdomain zygote:process sigchld;

View file

@ -192,17 +192,6 @@ neverallowxperm * devpts:chr_file ioctl TIOCSTI;
# 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.
neverallow {
domain
-debuggerd
-vold
-dumpstate
-system_server
userdebug_or_eng(`-perfprofd')
} self:capability sys_ptrace;
# Limit device node creation to these whitelisted domains.
neverallow {
domain
@ -506,7 +495,7 @@ neverallow { domain -init } proc:{ file dir } mounton;
# written on domain are applied to all processes.
# This is achieved by ensuring that it is impossible to transition
# from a domain to a non-domain type and vice versa.
neverallow domain ~domain:process { transition dyntransition };
# TODO - rework this: neverallow domain ~domain:process { transition dyntransition };
neverallow ~domain domain:process { transition dyntransition };
#
@ -617,10 +606,10 @@ neverallow {
neverallow * ~servicemanager:service_manager list;
# only service_manager_types can be added to service_manager
neverallow * ~service_manager_type:service_manager { add find };
# TODO - rework this: neverallow * ~service_manager_type:service_manager { add find };
# Prevent assigning non property types to properties
neverallow * ~property_type:property_service set;
# TODO - rework this: neverallow * ~property_type:property_service set;
# Domain types should never be assigned to any files other
# than the /proc/pid files associated with a process. The

View file

@ -30,7 +30,6 @@ type drmserver_socket, file_type;
# /data/app/tlcd_sock socket file.
# Clearly, /data/app is the most logical place to create a socket. Not.
allow drmserver apk_data_file:dir rw_dir_perms;
type_transition drmserver apk_data_file:sock_file drmserver_socket;
allow drmserver drmserver_socket:sock_file create_file_perms;
allow drmserver tee:unix_stream_socket connectto;
# Delete old socket file if present.

View file

@ -120,7 +120,6 @@ allow dumpstate shell_exec:file rx_file_perms;
allow dumpstate zygote_exec:file rx_file_perms;
# Dalvik Compiler JIT.
allow dumpstate ashmem_device:chr_file execute;
allow dumpstate dumpstate_tmpfs:file execute;
allow dumpstate self:process execmem;
# For art.
allow dumpstate libart_file:file { r_file_perms execute };
@ -187,12 +186,6 @@ set_prop(dumpstate, dumpstate_prop)
# dumpstate_options_prop is used to pass extra command-line args.
set_prop(dumpstate, dumpstate_options_prop)
# systrace support - allow atrace to run
allow dumpstate debugfs_tracing:dir r_dir_perms;
allow dumpstate debugfs_tracing:file rw_file_perms;
allow dumpstate debugfs_trace_marker:file getattr;
allow dumpstate atrace_exec:file rx_file_perms;
# Access to /data/media.
# This should be removed if sdcardfs is modified to alter the secontext for its
# accesses to the underlying FS.

View file

@ -16,12 +16,6 @@ net_domain(ephemeral_app)
allow ephemeral_app self:process execmem;
allow ephemeral_app ashmem_device:chr_file execute;
# Map with PROT_EXEC.
allow ephemeral_app ephemeral_app_tmpfs:file execute;
# Read system properties managed by zygote.
allow ephemeral_app zygote_tmpfs:file read;
# Send logcat messages to logd.
write_logd(ephemeral_app)

View file

@ -172,16 +172,12 @@ type perfprofd_data_file, file_type, data_file_type, mlstrustedobject;
# /data/misc/trace for method traces on userdebug / eng builds
type method_trace_data_file, file_type, data_file_type, mlstrustedobject;
# Compatibility with type names used in vanilla Android 4.3 and 4.4.
typealias audio_data_file alias audio_firmware_file;
# /data/data subdirectories - app sandboxes
type app_data_file, file_type, data_file_type;
type ephemeral_data_file, file_type, data_file_type;
# /data/data subdirectory for system UID apps.
type system_app_data_file, file_type, data_file_type, mlstrustedobject;
# Compatibility with type name used in Android 4.3 and 4.4.
typealias app_data_file alias platform_app_data_file;
typealias app_data_file alias download_file;
# Default type for anything under /cache
type cache_file, file_type, mlstrustedobject;
# Type for /cache/backup_stage/* (fd interchange with apps)

View file

@ -53,7 +53,6 @@ allow installd keychain_data_file:dir create_dir_perms;
allow installd keychain_data_file:file {r_file_perms unlink};
# Create /data/.layout_version.* file
type_transition installd system_data_file:file install_data_file;
allow installd install_data_file:file create_file_perms;
# Create files under /data/dalvik-cache.

View file

@ -39,8 +39,6 @@ auditallow isolated_app sdcard_type:file { write append };
# webview_zygote process. These rules are specialized copies of the ones in app.te.
# Inherit FDs from the webview_zygote.
allow isolated_app webview_zygote:fd use;
# Read system properties managed by webview_zygote.
allow isolated_app webview_zygote_tmpfs:file read;
# Notify webview_zygote of child death.
allow isolated_app webview_zygote:process sigchld;
# Inherit logd write socket.

View file

@ -57,10 +57,6 @@ neverallow logd system_file:dir_file_class_set write;
# Write to files in /data/data or system files on /data
neverallow logd { app_data_file system_data_file }:dir_file_class_set write;
# logd is not allowed to write anywhere other than /data/misc/logd, and then
# only on userdebug or eng builds
neverallow logd { file_type -logd_tmpfs userdebug_or_eng(` -misc_logd_file -coredump_file ') }:file { create write append };
# logpersist is only allowed on userdebug/eng builds
neverallow { domain userdebug_or_eng(`-logd -shell -dumpstate') } misc_logd_file:file no_rw_file_perms;
neverallow { domain userdebug_or_eng(`-logd') } misc_logd_file:dir { add_name link relabelfrom remove_name rename reparent rmdir write };

View file

@ -19,10 +19,6 @@ auditallow priv_app app_data_file:file { execute execute_no_trans };
# android.process.media uses /dev/mtp_usb
allow priv_app mtp_device:chr_file rw_file_perms;
# Allow the allocation and use of ptys
# Used by: https://play.privileged.com/store/apps/details?id=jackpal.androidterm
create_pty(priv_app)
allow priv_app audioserver_service:service_manager find;
allow priv_app cameraserver_service:service_manager find;
allow priv_app drmserver_service:service_manager find;

View file

@ -25,5 +25,3 @@ neverallow recovery_persist system_file:dir_file_class_set write;
# Write to files in /data/data
neverallow recovery_persist { app_data_file system_data_file }:dir_file_class_set write;
# recovery_persist is not allowed to write anywhere other than recovery_data_file
neverallow recovery_persist { file_type -recovery_data_file -recovery_persist_tmpfs userdebug_or_eng(`-coredump_file') }:file write;

View file

@ -22,6 +22,3 @@ neverallow recovery_refresh system_file:dir_file_class_set write;
# Write to files in /data/data or system files on /data
neverallow recovery_refresh { app_data_file system_data_file }:dir_file_class_set write;
# recovery_refresh is not allowed to write anywhere
neverallow recovery_refresh { file_type -recovery_refresh_tmpfs userdebug_or_eng(`-coredump_file') }:file write;

View file

@ -1,2 +1 @@
role r;
role r types domain;

View file

@ -72,12 +72,6 @@ set_prop(shell, wifi_log_prop)
userdebug_or_eng(`set_prop(shell, log_prop)')
userdebug_or_eng(`set_prop(shell, logpersistd_logging_prop)')
# systrace support - allow atrace to run
allow shell debugfs_tracing:dir r_dir_perms;
allow shell debugfs_tracing:file rw_file_perms;
allow shell debugfs_trace_marker:file getattr;
allow shell atrace_exec:file rx_file_perms;
userdebug_or_eng(`
# "systrace --boot" support - allow boottrace service to run
allow shell boottrace_data_file:dir rw_dir_perms;

44
public/su.te Normal file
View file

@ -0,0 +1,44 @@
# File types must be defined for file_contexts.
type su_exec, exec_type, file_type;
userdebug_or_eng(`
# Domain used for su processes, as well as for adbd and adb shell
# after performing an adb root command. The domain definition is
# wrapped to ensure that it does not exist at all on -user builds.
type su, domain, mlstrustedsubject;
# Add su to various domains
net_domain(su)
app_domain(su)
dontaudit su self:capability_class_set *;
dontaudit su kernel:security *;
dontaudit su kernel:system *;
dontaudit su self:memprotect *;
dontaudit su domain:process *;
dontaudit su domain:fd *;
dontaudit su domain:dir *;
dontaudit su domain:lnk_file *;
dontaudit su domain:{ fifo_file file } *;
dontaudit su domain:socket_class_set *;
dontaudit su domain:ipc_class_set *;
dontaudit su domain:key *;
dontaudit su fs_type:filesystem *;
dontaudit su {fs_type dev_type file_type}:dir_file_class_set *;
dontaudit su node_type:node *;
dontaudit su node_type:{ tcp_socket udp_socket rawip_socket } *;
dontaudit su netif_type:netif *;
dontaudit su port_type:socket_class_set *;
dontaudit su port_type:{ tcp_socket dccp_socket } *;
dontaudit su domain:peer *;
dontaudit su domain:binder *;
dontaudit su property_type:property_service *;
dontaudit su property_type:file *;
dontaudit su service_manager_type:service_manager *;
dontaudit su servicemanager:service_manager list;
dontaudit su keystore:keystore_key *;
dontaudit su domain:debuggerd *;
dontaudit su domain:drmservice *;
dontaudit su unlabeled:filesystem *;
dontaudit su postinstall_file:filesystem *;
')

View file

@ -25,7 +25,6 @@ allow system_server self:process ptrace;
# Child of the zygote.
allow system_server zygote:fd use;
allow system_server zygote:process sigchld;
allow system_server zygote_tmpfs:file read;
# May kill zygote on crashes.
allow system_server zygote:process sigkill;
@ -381,8 +380,6 @@ set_prop(system_server, ctl_bugreport_prop)
set_prop(system_server, cppreopt_prop)
# Create a socket for receiving info from wpa.
type_transition system_server wifi_data_file:sock_file system_wpa_socket;
type_transition system_server wpa_socket:sock_file system_wpa_socket;
allow system_server wpa_socket:dir rw_dir_perms;
allow system_server system_wpa_socket:sock_file create_file_perms;
@ -626,4 +623,3 @@ neverallow system_server { dev_type -frp_block_device }:blk_file no_rw_file_perm
# system_server should never use JIT functionality
neverallow system_server self:process execmem;
neverallow system_server ashmem_device:chr_file execute;
neverallow system_server system_server_tmpfs:file execute;

View file

@ -95,10 +95,6 @@ tmpfs_domain($1)
# Allow a base set of permissions required for all apps.
define(`app_domain', `
typeattribute $1 appdomain;
# Label ashmem objects with our own unique type.
tmpfs_domain($1)
# Map with PROT_EXEC.
allow $1 $1_tmpfs:file execute;
')
#####################################

View file

@ -38,10 +38,6 @@ allow untrusted_app asec_apk_file:dir r_dir_perms;
# Execute libs in asec containers.
allow untrusted_app asec_public_file:file { execute execmod };
# Allow the allocation and use of ptys
# Used by: https://play.google.com/store/apps/details?id=jackpal.androidterm
create_pty(untrusted_app)
# Used by Finsky / Android "Verify Apps" functionality when
# running "adb install foo.apk".
# TODO: Long term, we don't want apps probing into shell data files.

1
reqd_mask/access_vectors Symbolic link
View file

@ -0,0 +1 @@
../private/access_vectors

View file

@ -0,0 +1 @@
sid reqd_mask u:r:reqd_mask_type:s0

3
reqd_mask/initial_sids Normal file
View file

@ -0,0 +1,3 @@
sid reqd_mask
# FLASK

1
reqd_mask/mls Normal file
View file

@ -0,0 +1 @@
mlsconstrain binder { set_context_mgr } (l1 eq l2);

1
reqd_mask/mls_decl Symbolic link
View file

@ -0,0 +1 @@
../private/mls_decl

1
reqd_mask/mls_macros Symbolic link
View file

@ -0,0 +1 @@
../private/mls_macros

1
reqd_mask/reqd_mask.te Normal file
View file

@ -0,0 +1 @@
type reqd_mask_type;

1
reqd_mask/roles Normal file
View file

@ -0,0 +1 @@
role r types reqd_mask_type;

1
reqd_mask/roles_decl Normal file
View file

@ -0,0 +1 @@
role r;

1
reqd_mask/security_classes Symbolic link
View file

@ -0,0 +1 @@
../private/security_classes

1
reqd_mask/users Normal file
View file

@ -0,0 +1 @@
user u roles { r } level s0 range s0 - mls_systemhigh;

View file

@ -46,4 +46,17 @@ LOCAL_CXX_STL := none
include $(BUILD_HOST_EXECUTABLE)
###################################
include $(CLEAR_VARS)
LOCAL_MODULE := version_policy
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS := -Wall -Werror
LOCAL_SRC_FILES := version_policy.c
LOCAL_SHARED_LIBRARIES := libsepol
LOCAL_CXX_STL := none
include $(BUILD_HOST_EXECUTABLE)
include $(call all-makefiles-under,$(LOCAL_PATH))

184
tools/version_policy.c Normal file
View file

@ -0,0 +1,184 @@
/*
* version_policy.c - Takes the given public platform policy, a private policy
* and a version number to produced a combined "versioned" policy file.
*/
#include <errno.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <sys/stat.h>
#include <cil/android.h>
#include <cil/cil.h>
#include <cil/cil_write_ast.h>
void __attribute__ ((noreturn)) static usage(char *prog) {
printf("Usage: %s [OPTION]...\n", prog);
printf("\n");
printf("Options:\n");
printf(" -b, --base=<file> (req'd) base policy for versioning.\n");
printf(" -m, --mapping generate cil version mapping from base policy\n");
printf(" -n, --number (req'd) version number to use.\n");
printf(" -o, --output=<file> write cil policy to <file>\n");
printf(" -t, --tgt_policy policy to be versioned according to base policy\n");
printf(" -h, --help display usage information\n");
exit(1);
}
/*
* read_cil_file - Initialize db and parse CIL input file.
*/
static int read_cil_file(struct cil_db **db, char *path) {
int rc = SEPOL_ERR;
FILE *file;
struct stat filedata;
uint32_t file_size;
char *buff = NULL;
cil_db_init(db);
file = fopen(path, "re");
if (!file) {
fprintf(stderr, "Could not open file: %s\n", path);
goto file_err;
}
rc = stat(path, &filedata);
if (rc == -1) {
fprintf(stderr, "Could not stat file: %s - %s\n", path, strerror(errno));
goto err;
}
file_size = filedata.st_size;
buff = malloc(file_size);
if (buff == NULL) {
fprintf(stderr, "OOM!\n");
rc = SEPOL_ERR;
goto err;
}
rc = fread(buff, file_size, 1, file);
if (rc != 1) {
fprintf(stderr, "Failure reading file: %s\n", path);
rc = SEPOL_ERR;
goto err;
}
fclose(file);
file = NULL;
/* creates parse_tree */
rc = cil_add_file(*db, path, buff, file_size);
if (rc != SEPOL_OK) {
fprintf(stderr, "Failure adding %s to parse tree\n", path);
goto err;
}
free(buff);
return SEPOL_OK;
err:
free(buff);
fclose(file);
file_err:
cil_db_destroy(db);
return rc;
}
int main(int argc, char *argv[])
{
int opt_char;
int opt_index = 0;
int rc = SEPOL_ERR;
bool mapping = false;
char *base = NULL;
char *tgt_policy = NULL;
char *num = NULL;
char *output = NULL;
struct cil_db *base_db = NULL;
struct cil_db *out_db = NULL;
static struct option long_opts[] = {
{"help", no_argument, 0, 'h'},
{"base", required_argument, 0, 'b'},
{"mapping", no_argument, 0, 'm'},
{"number", required_argument, 0, 'n'},
{"output", required_argument, 0, 'o'},
{"tgt_policy", required_argument, 0, 't'},
{0, 0, 0, 0}
};
while (1) {
opt_char = getopt_long(argc, argv, "b:mn:o:t:h", long_opts, &opt_index);
if (opt_char == -1) {
break;
}
switch (opt_char) {
case 'b':
base = strdup(optarg);
break;
case 'm':
mapping = true;
break;
case 'n':
num = strdup(optarg);
break;
case 'o':
output = strdup(optarg);
break;
case 't':
tgt_policy = strdup(optarg);
break;
case 'h':
usage(argv[0]);
default:
fprintf(stderr, "Unsupported option: %s\n", optarg);
usage(argv[0]);
}
}
if (optind < argc) {
fprintf(stderr, "Unknown arguments supplied\n");
usage(argv[0]);
}
if (num == NULL || base == NULL || (mapping == false && tgt_policy == NULL)) {
fprintf(stderr, "Please specify required arguments\n");
usage(argv[0]);
}
if (mapping && tgt_policy) {
fprintf(stderr, "Please select only one mode between --mapping and --tgt_policy\n");
usage(argv[0]);
}
/* gimme all the details */
cil_set_log_level(CIL_INFO);
/* read platform policy */
rc = read_cil_file(&base_db, base);
if (rc != SEPOL_OK) {
goto exit;
}
if (mapping) {
rc = cil_android_attrib_mapping(&out_db, base_db, num);
if (rc != SEPOL_OK)
goto exit;
} else {
/* read target policy, ready for manipulation */
rc = read_cil_file(&out_db, tgt_policy);
if (rc != SEPOL_OK) {
goto exit;
}
/* attributize the target policy */
rc = cil_android_attributize(out_db, base_db, num);
if (rc != SEPOL_OK) {
goto exit;
}
}
rc = cil_write_ast(out_db, output);
if (rc != SEPOL_OK) {
goto exit;
}
exit:
free(base);
free(tgt_policy);
free(num);
free(output);
cil_db_destroy(&base_db);
cil_db_destroy(&out_db);
return rc;
}