From f54b3622c70d9c0fbdd6cdf2eff89ec5dd5d7f16 Mon Sep 17 00:00:00 2001
From: Michael Peck <mpeck@mitre.org>
Date: Tue, 14 Feb 2017 09:48:57 -0800
Subject: [PATCH] Add minTargetSdkVersion input selector to seapp_contexts

This new input selector allows phasing in new security policies by
giving app developers an opportunity to make any needed compatibility
changes before updating each app's targetSdkVersion.

When all else is equal, matching entries with higher
minTargetSdkVersion= values are preferred over entries with lower
minTargetSdkVersion= values.

Test: Marlin builds and boots. Apps targeting targetSdkVersion<=25
run in untrusted_app_25 domain. Apps targeting the current development
build >=26 run in the untrusted_app domain with fewer permissions. No
new denials observed during testing.
Bug: 34115651
Change-Id: I14bf4f51dbe26cb9bd3f62ad0b281085441d9806
---
 private/seapp_contexts | 52 +++++++++++++++++++++++-------------------
 tools/check_seapp.c    | 15 ++++++++++++
 2 files changed, 44 insertions(+), 23 deletions(-)

diff --git a/private/seapp_contexts b/private/seapp_contexts
index 0a30829bd..098ee6645 100644
--- a/private/seapp_contexts
+++ b/private/seapp_contexts
@@ -1,12 +1,13 @@
 # Input selectors:
-#	isSystemServer (boolean)
-#	isEphemeralApp (boolean)
-#	isOwner (boolean)
-#	user (string)
-#	seinfo (string)
-#	name (string)
-#	path (string)
-#	isPrivApp (boolean)
+#       isSystemServer (boolean)
+#       isEphemeralApp (boolean)
+#       isOwner (boolean)
+#       user (string)
+#       seinfo (string)
+#       name (string)
+#       path (string)
+#       isPrivApp (boolean)
+#       minTargetSdkVersion (unsigned integer)
 # isSystemServer=true can only be used once.
 # An unspecified isSystemServer defaults to false.
 # isEphemeralApp=true will match apps marked by PackageManager as Ephemeral
@@ -19,27 +20,32 @@
 # user=_isolated will match any isolated service UID.
 # isPrivApp=true will only match for applications preinstalled in
 #       /system/priv-app.
+# minTargetSdkVersion will match applications with a targetSdkVersion
+#       greater than or equal to the specified value. If unspecified,
+#       it has a default value of 0.
 # All specified input selectors in an entry must match (i.e. logical AND).
 # Matching is case-insensitive.
 #
 # Precedence rules (see external/selinux/libselinux/src/android/android.c seapp_context_cmp()):
-# 	  (1) isSystemServer=true before isSystemServer=false.
-# 	  (2) Specified isEphemeralApp= before unspecified isEphemeralApp= boolean.
-# 	  (3) Specified isOwner= before unspecified isOwner= boolean.
-#	  (4) Specified user= string before unspecified user= string.
-#	  (5) Fixed user= string before user= prefix (i.e. ending in *).
-#	  (6) Longer user= prefix before shorter user= prefix.
-#	  (7) Specified seinfo= string before unspecified seinfo= string.
-#	      ':' character is reserved and may not be used.
-#	  (8) Specified name= string before unspecified name= string.
-#	  (9) Specified path= string before unspecified path= string.
-# 	  (10) Specified isPrivApp= before unspecified isPrivApp= boolean.
+#       (1) isSystemServer=true before isSystemServer=false.
+#       (2) Specified isEphemeralApp= before unspecified isEphemeralApp= boolean.
+#       (3) Specified isOwner= before unspecified isOwner= boolean.
+#       (4) Specified user= string before unspecified user= string.
+#       (5) Fixed user= string before user= prefix (i.e. ending in *).
+#       (6) Longer user= prefix before shorter user= prefix.
+#       (7) Specified seinfo= string before unspecified seinfo= string.
+#           ':' character is reserved and may not be used.
+#       (8) Specified name= string before unspecified name= string.
+#       (9) Specified path= string before unspecified path= string.
+#       (10) Specified isPrivApp= before unspecified isPrivApp= boolean.
+#       (11) Higher value of minTargetSdkVersion= before lower value of minTargetSdkVersion=
+#              integer. Note that minTargetSdkVersion= defaults to 0 if unspecified.
 #
 # Outputs:
-#	domain (string)
-#	type (string)
-#	levelFrom (string; one of none, all, app, or user)
-#	level (string)
+#       domain (string)
+#       type (string)
+#       levelFrom (string; one of none, all, app, or user)
+#       level (string)
 # Only entries that specify domain= will be used for app process labeling.
 # Only entries that specify type= will be used for app directory labeling.
 # levelFrom=user is only supported for _app or _isolated UIDs.
diff --git a/tools/check_seapp.c b/tools/check_seapp.c
index d8fa63647..96b9ebf89 100644
--- a/tools/check_seapp.c
+++ b/tools/check_seapp.c
@@ -194,6 +194,7 @@ static bool validate_bool(char *value, char **errmsg);
 static bool validate_levelFrom(char *value, char **errmsg);
 static bool validate_selinux_type(char *value, char **errmsg);
 static bool validate_selinux_level(char *value, char **errmsg);
+static bool validate_uint(char *value, char **errmsg);
 
 /**
  * The heart of the mapping process, this must be updated if a new key value pair is added
@@ -209,6 +210,7 @@ key_map rules[] = {
                 { .name = "name",           .dir = dir_in,                              },
                 { .name = "path",           .dir = dir_in,                              },
                 { .name = "isPrivApp",      .dir = dir_in, .fn_validate = validate_bool },
+                { .name = "minTargetSdkVersion", .dir = dir_in, .fn_validate = validate_uint },
                 /*Outputs*/
                 { .name = "domain",         .dir = dir_out, .fn_validate = validate_selinux_type  },
                 { .name = "type",           .dir = dir_out, .fn_validate = validate_selinux_type  },
@@ -417,6 +419,19 @@ static bool validate_selinux_level(char *value, char **errmsg) {
 	return true;
 }
 
+static bool validate_uint(char *value, char **errmsg) {
+
+	char *endptr;
+	long longvalue;
+	longvalue = strtol(value, &endptr, 10);
+	if (('\0' != *endptr) || (longvalue < 0) || (longvalue > INT32_MAX)) {
+		*errmsg = "Expecting a valid unsigned integer";
+		return false;
+	}
+
+	return true;
+}
+
 /**
  * Validates a key_map against a set of enforcement rules, this
  * function exits the application on a type that cannot be properly
-- 
GitLab