diff --git a/Android.mk b/Android.mk
index 254acd0fcf7f4406a500fd4f0eb43dcbd14ef364..e2883560fc544b0785b49deae0c5d4d5e9396056 100644
--- a/Android.mk
+++ b/Android.mk
@@ -131,6 +131,11 @@ endif
 
 intermediates := $(TARGET_OUT_INTERMEDIATES)/ETC/sepolicy_intermediates
 
+with_asan := false
+ifneq (,$(filter address,$(SANITIZE_TARGET)))
+  with_asan := true
+endif
+
 ##################################
 # 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
@@ -143,6 +148,7 @@ 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_TGT_ARCH := $(my_target_arch)
+$(reqd_policy_mask.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
 $(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 $@)
@@ -151,6 +157,7 @@ $(reqd_policy_mask.conf): $(call build_policy, $(sepolicy_build_files), $(REQD_M
 		-D target_build_variant=$(TARGET_BUILD_VARIANT) \
 		-D target_with_dexpreopt=$(WITH_DEXPREOPT) \
 		-D target_arch=$(PRIVATE_TGT_ARCH) \
+		-D target_with_asan=$(PRIVATE_TGT_WITH_ASAN) \
 		-s $^ > $@
 
 reqd_policy_mask.cil := $(intermediates)/reqd_policy_mask.cil
@@ -170,6 +177,7 @@ 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_TGT_ARCH := $(my_target_arch)
+$(plat_pub_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
 $(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))
@@ -179,6 +187,7 @@ $(BOARD_SEPOLICY_VERS_DIR) $(REQD_MASK_POLICY))
 		-D target_build_variant=$(TARGET_BUILD_VARIANT) \
 		-D target_with_dexpreopt=$(WITH_DEXPREOPT) \
 		-D target_arch=$(PRIVATE_TGT_ARCH) \
+		-D target_with_asan=$(PRIVATE_TGT_WITH_ASAN) \
 		-s $^ > $@
 
 plat_pub_policy.cil := $(intermediates)/plat_pub_policy.cil
@@ -223,6 +232,7 @@ 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_TGT_ARCH := $(my_target_arch)
+$(plat_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
 $(plat_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
 $(plat_policy.conf): $(call build_policy, $(sepolicy_build_files), \
 $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY))
@@ -232,6 +242,7 @@ $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY))
 		-D target_build_variant=$(TARGET_BUILD_VARIANT) \
 		-D target_with_dexpreopt=$(WITH_DEXPREOPT) \
 		-D target_arch=$(PRIVATE_TGT_ARCH) \
+		-D target_with_asan=$(PRIVATE_TGT_WITH_ASAN) \
 		-s $^ > $@
 	$(hide) sed '/dontaudit/d' $@ > $@.dontaudit
 
@@ -320,6 +331,7 @@ 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_TGT_ARCH := $(my_target_arch)
+$(nonplat_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
 $(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) $(PLAT_VENDOR_POLICY) $(BOARD_SEPOLICY_DIRS))
@@ -329,6 +341,7 @@ $(BOARD_SEPOLICY_VERS_DIR) $(REQD_MASK_POLICY) $(PLAT_VENDOR_POLICY) $(BOARD_SEP
 		-D target_build_variant=$(TARGET_BUILD_VARIANT) \
 		-D target_with_dexpreopt=$(WITH_DEXPREOPT) \
 		-D target_arch=$(PRIVATE_TGT_ARCH) \
+		-D target_with_asan=$(PRIVATE_TGT_WITH_ASAN) \
 		-s $^ > $@
 	$(hide) sed '/dontaudit/d' $@ > $@.dontaudit
 
@@ -452,6 +465,7 @@ plat_pub_policy.recovery.conf := $(intermediates)/plat_pub_policy.recovery.conf
 $(plat_pub_policy.recovery.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
 $(plat_pub_policy.recovery.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
 $(plat_pub_policy.recovery.conf): PRIVATE_TGT_ARCH := $(my_target_arch)
+$(plat_pub_policy.recovery.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
 $(plat_pub_policy.recovery.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
 $(plat_pub_policy.recovery.conf): $(call build_policy, $(sepolicy_build_files), \
 $(BOARD_SEPOLICY_VERS_DIR) $(REQD_MASK_POLICY))
@@ -461,6 +475,7 @@ $(BOARD_SEPOLICY_VERS_DIR) $(REQD_MASK_POLICY))
 		-D target_build_variant=$(TARGET_BUILD_VARIANT) \
 		-D target_with_dexpreopt=$(WITH_DEXPREOPT) \
 		-D target_arch=$(PRIVATE_TGT_ARCH) \
+		-D target_with_asan=$(PRIVATE_TGT_WITH_ASAN) \
 		-D target_recovery=true \
 		-s $^ > $@
 
@@ -479,6 +494,7 @@ plat_policy.recovery.conf := $(intermediates)/plat_policy.recovery.conf
 $(plat_policy.recovery.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
 $(plat_policy.recovery.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
 $(plat_policy.recovery.conf): PRIVATE_TGT_ARCH := $(my_target_arch)
+$(plat_policy.recovery.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
 $(plat_policy.recovery.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
 $(plat_policy.recovery.conf): $(call build_policy, $(sepolicy_build_files), \
 $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY))
@@ -488,6 +504,7 @@ $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY))
 		-D target_build_variant=$(TARGET_BUILD_VARIANT) \
 		-D target_with_dexpreopt=$(WITH_DEXPREOPT) \
 		-D target_arch=$(PRIVATE_TGT_ARCH) \
+		-D target_with_asan=$(PRIVATE_TGT_WITH_ASAN) \
 		-D target_recovery=true \
 		-s $^ > $@
 	$(hide) sed '/dontaudit/d' $@ > $@.dontaudit
@@ -526,6 +543,7 @@ nonplat_policy.recovery.conf := $(intermediates)/nonplat_policy.recovery.conf
 $(nonplat_policy.recovery.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
 $(nonplat_policy.recovery.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
 $(nonplat_policy.recovery.conf): PRIVATE_TGT_ARCH := $(my_target_arch)
+$(nonplat_policy.recovery.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
 $(nonplat_policy.recovery.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
 $(nonplat_policy.recovery.conf): $(call build_policy, $(sepolicy_build_files), \
 $(BOARD_SEPOLICY_VERS_DIR) $(REQD_MASK_POLICY) $(PLAT_VENDOR_POLICY) $(BOARD_SEPOLICY_DIRS))
@@ -535,6 +553,7 @@ $(BOARD_SEPOLICY_VERS_DIR) $(REQD_MASK_POLICY) $(PLAT_VENDOR_POLICY) $(BOARD_SEP
 		-D target_build_variant=$(TARGET_BUILD_VARIANT) \
 		-D target_with_dexpreopt=$(WITH_DEXPREOPT) \
 		-D target_arch=$(PRIVATE_TGT_ARCH) \
+		-D target_with_asan=$(PRIVATE_TGT_WITH_ASAN) \
 		-D target_recovery=true \
 		-s $^ > $@
 	$(hide) sed '/dontaudit/d' $@ > $@.dontaudit
@@ -603,6 +622,7 @@ $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY))
 		-D target_build_variant=user \
 		-D target_with_dexpreopt=$(WITH_DEXPREOPT) \
 		-D target_arch=$(PRIVATE_TGT_ARCH) \
+		-D target_with_asan=false \
 		-s $^ > $@
 	$(hide) sed '/dontaudit/d' $@ > $@.dontaudit
 
@@ -1090,5 +1110,6 @@ plat_policy_nvr :=
 plat_pub_policy.cil :=
 reqd_policy_mask.cil :=
 sepolicy_build_files :=
+with_asan :=
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/private/system_server.te b/private/system_server.te
index 73613077a58605f7b0dd0e3015c58d66d2e8870a..d1f9bc322bc884a4b65fdd12e83e0b474b03a925 100644
--- a/private/system_server.te
+++ b/private/system_server.te
@@ -623,6 +623,12 @@ allow system_server sysfs_leds:dir r_dir_perms;
 allow system_server debugfs_tracing_instances:dir search;
 allow system_server debugfs_wifi_tracing:file rw_file_perms;
 
+# allow system_server to exec shell on ASAN builds. Needed to run
+# asanwrapper.
+with_asan(`
+  allow system_server shell_exec:file rx_file_perms;
+')
+
 ###
 ### Neverallow rules
 ###
@@ -644,7 +650,12 @@ neverallow system_server { bluetooth_data_file nfc_data_file shell_data_file app
 # example, https://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them
 # Prevent the addition of new file execs to stop the problem from
 # getting worse. b/28035297
-neverallow system_server { file_type -toolbox_exec -logcat_exec }:file execute_no_trans;
+neverallow system_server {
+  file_type
+  -toolbox_exec
+  -logcat_exec
+  with_asan(`-shell_exec')
+}:file execute_no_trans;
 
 # Ensure that system_server doesn't perform any domain transitions other than
 # transitioning to the crash_dump domain when a crash occurs.
diff --git a/public/te_macros b/public/te_macros
index 0e1bffb8f0848238042bae36ef52621c1eb6150f..d31bb1dcedc96be6fe2ca3f1777ef3f6ad1e2138 100644
--- a/public/te_macros
+++ b/public/te_macros
@@ -386,6 +386,12 @@ define(`recovery_only', ifelse(target_recovery, `true', $1, ))
 #
 define(`userdebug_or_eng', ifelse(target_build_variant, `eng', $1, ifelse(target_build_variant, `userdebug', $1)))
 
+#####################################
+# asan builds
+# SELinux rules which apply only to asan builds
+#
+define(`with_asan', ifelse(target_with_asan, `true', userdebug_or_eng(`$1'), ))
+
 ####################################
 # Fallback crash handling for processes that can't exec crash_dump (e.g. because of seccomp).
 #