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
diff --git a/tools/check_seapp.c b/tools/check_seapp.c
index d8fa636..96b9ebf 100644
--- a/tools/check_seapp.c
+++ b/tools/check_seapp.c
@@ -194,6 +194,7 @@
 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 @@
                 { .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 @@
 	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