diff --git a/private/app_neverallows.te b/private/app_neverallows.te
index b8889f74e951a59bd708429df7a0324e04a5a380..ab080c29029f9de861dfe2969c47fc0f7f233188 100644
--- a/private/app_neverallows.te
+++ b/private/app_neverallows.te
@@ -48,6 +48,7 @@ neverallow {
   all_untrusted_apps
   -untrusted_app_25
   -untrusted_app_27
+  -runas_app
 } { app_data_file privapp_data_file }:file execute_no_trans;
 
 # Do not allow untrusted apps to be assigned mlstrustedsubject.
diff --git a/private/runas_app.te b/private/runas_app.te
new file mode 100644
index 0000000000000000000000000000000000000000..b976b91879ed85a34e98e032c07ce622e1f76537
--- /dev/null
+++ b/private/runas_app.te
@@ -0,0 +1,11 @@
+type runas_app, domain;
+typeattribute runas_app coredomain;
+
+app_domain(runas_app)
+untrusted_app_domain(runas_app)
+net_domain(runas_app)
+bluetooth_domain(runas_app)
+
+# The ability to call exec() on files in the apps home directories
+# when using run-as on a debuggable app. Needed by simpleperf.
+allow runas_app app_data_file:file execute_no_trans;
diff --git a/private/seapp_contexts b/private/seapp_contexts
index 821ef0c2b5f231a0389bd0b3f509553b77937205..55391ea36ba96d2e9a695e76825aabf8cfbab374 100644
--- a/private/seapp_contexts
+++ b/private/seapp_contexts
@@ -9,6 +9,7 @@
 #       path (string)
 #       isPrivApp (boolean)
 #       minTargetSdkVersion (unsigned integer)
+#       fromRunAs (boolean)
 # isSystemServer=true can only be used once.
 # An unspecified isSystemServer defaults to false.
 # isEphemeralApp=true will match apps marked by PackageManager as Ephemeral
@@ -25,6 +26,7 @@
 # minTargetSdkVersion will match applications with a targetSdkVersion
 #       greater than or equal to the specified value. If unspecified,
 #       it has a default value of 0.
+# fromRunAs=true means the setcontext request is from run-as. Default is false.
 # All specified input selectors in an entry must match (i.e. logical AND).
 # Matching is case-insensitive.
 #
@@ -43,6 +45,7 @@
 #       (11) Specified isPrivApp= before unspecified isPrivApp= boolean.
 #       (12) Higher value of minTargetSdkVersion= before lower value of minTargetSdkVersion=
 #              integer. Note that minTargetSdkVersion= defaults to 0 if unspecified.
+#       (13) fromRunAs=true before fromRunAs=false.
 #
 # Outputs:
 #       domain (string)
@@ -118,3 +121,4 @@ user=_app minTargetSdkVersion=29 domain=untrusted_app type=app_data_file levelFr
 user=_app minTargetSdkVersion=28 domain=untrusted_app_27 type=app_data_file levelFrom=all
 user=_app minTargetSdkVersion=26 domain=untrusted_app_27 type=app_data_file levelFrom=user
 user=_app domain=untrusted_app_25 type=app_data_file levelFrom=user
+user=_app fromRunAs=true domain=runas_app levelFrom=all
diff --git a/tools/check_seapp.c b/tools/check_seapp.c
index c23c1f6c6a58ad3a82fe296a7d25b7320a73102d..1022cbd485ce2353d024d8de9731d1afa372091d 100644
--- a/tools/check_seapp.c
+++ b/tools/check_seapp.c
@@ -212,6 +212,7 @@ key_map rules[] = {
                 { .name = "path",           .dir = dir_in,                              },
                 { .name = "isPrivApp",      .dir = dir_in, .fn_validate = validate_bool },
                 { .name = "minTargetSdkVersion", .dir = dir_in, .fn_validate = validate_uint },
+                { .name = "fromRunAs",       .dir = dir_in, .fn_validate = validate_bool },
                 /*Outputs*/
                 { .name = "domain",         .dir = dir_out, .fn_validate = validate_selinux_type  },
                 { .name = "type",           .dir = dir_out, .fn_validate = validate_selinux_type  },