aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiƩbaud Weksteen <tweek@google.com>2023-11-21 20:36:32 +1100
committerThiƩbaud Weksteen <tweek@google.com>2023-12-01 10:42:50 +1100
commit3d85f1e1163ea3d5e8a1d7a1dfdadc97ee761fcc (patch)
tree4f80190f2c928f89cdc1f65f50d43ee1c0e27474
parent7fd89c00f70d9c5d16550ef7e3c49b1e707be0af (diff)
downloadselinux-3d85f1e1163ea3d5e8a1d7a1dfdadc97ee761fcc.tar.gz
Use generic isSelector
seapp_contexts supports multiple boolean attributes: isPrivApp, isEphemeralApp, isIsolatedComputeApp, isSdkSandboxAudit, isSdkSandboxNext, fromRunAs. Each of these exists to support a specific labelling scenario from the framework. When a new predicate is required, an update to libselinux is also required. This change generically handles any attribute starting with "is" and maps it directly (case-insensitive) to the same seinfo field. It is assumed that only one of these is required at a time. An error is raised if seapp_contexts contains multiple is-selector within one rule. An error is raised if seinfo contains multiple is-selector. The order for comparison between seapp_contexts is altered: an entry with an is-selector will be prioritized over one with an unspecifed is-selector. This is not quite the previous order (e.g., isPrivApp < targetSdkVersion < fromRunAs), but it is understood that the previous order was not intentional and emerged from the incremental contributions to this library. The boolean info.isPreinstalledApp is replaced by checking the first byte of info.partition. Test: atest --host libselinux_test Bug: 307635909 Change-Id: Ice3b84870e3255f6d9357d9750acbe9691b45aad
-rw-r--r--libselinux/src/android/android_internal.h9
-rw-r--r--libselinux/src/android/android_seapp.c203
-rw-r--r--libselinux/src/android/android_unittest.cpp83
3 files changed, 143 insertions, 152 deletions
diff --git a/libselinux/src/android/android_internal.h b/libselinux/src/android/android_internal.h
index e5d69402..e9405645 100644
--- a/libselinux/src/android/android_internal.h
+++ b/libselinux/src/android/android_internal.h
@@ -105,14 +105,7 @@ int seapp_context_reload_internal(const path_alts_t *context_paths);
/* A parsed seinfo */
struct parsed_seinfo {
char base[SEINFO_BUFSIZ];
-#define IS_PRIV_APP (1 << 0)
-#define IS_FROM_RUN_AS (1 << 1)
-#define IS_EPHEMERAL_APP (1 << 2)
-#define IS_ISOLATED_COMPUTE_APP (1 << 3)
-#define IS_SDK_SANDBOX_AUDIT (1 << 4)
-#define IS_SDK_SANDBOX_NEXT (1 << 5)
- int32_t is;
- bool isPreinstalledApp;
+ char isSelector[SEINFO_BUFSIZ];
char partition[SEINFO_BUFSIZ];
int32_t targetSdkVersion;
};
diff --git a/libselinux/src/android/android_seapp.c b/libselinux/src/android/android_seapp.c
index d1f50292..5df5b338 100644
--- a/libselinux/src/android/android_seapp.c
+++ b/libselinux/src/android/android_seapp.c
@@ -128,18 +128,14 @@ static void free_prefix_str(struct prefix_str *p)
struct seapp_context {
/* input selectors */
bool isSystemServer;
- bool isEphemeralAppSet;
- bool isEphemeralApp;
struct prefix_str user;
char *seinfo;
struct prefix_str name;
- bool isPrivAppSet;
- bool isPrivApp;
int32_t minTargetSdkVersion;
- bool fromRunAs;
- bool isIsolatedComputeApp;
- bool isSdkSandboxAudit;
- bool isSdkSandboxNext;
+ /* name of a boolean selector such as isPrivApp, fromRunAs,
+ * isIsolatedComputeApp, etc. */
+ char *isSelector;
+ bool isSelectorValue;
/* outputs */
char *domain;
char *type;
@@ -153,6 +149,7 @@ static void free_seapp_context(struct seapp_context *s)
if (!s)
return;
+ free(s->isSelector);
free_prefix_str(&s->user);
free(s->seinfo);
free_prefix_str(&s->name);
@@ -181,11 +178,6 @@ static int seapp_context_cmp(const void *A, const void *B)
if (s1->isSystemServer != s2->isSystemServer)
return (s1->isSystemServer ? -1 : 1);
- /* Give precedence to a specified isEphemeral= over an
- * unspecified isEphemeral=. */
- if (s1->isEphemeralAppSet != s2->isEphemeralAppSet)
- return (s1->isEphemeralAppSet ? -1 : 1);
-
/* Give precedence to a specified user= over an unspecified user=. */
if (s1->user.str && !s2->user.str)
return -1;
@@ -224,9 +216,12 @@ static int seapp_context_cmp(const void *A, const void *B)
return (s1->name.len > s2->name.len) ? -1 : 1;
}
- /* Give precedence to a specified isPrivApp= over an unspecified isPrivApp=. */
- if (s1->isPrivAppSet != s2->isPrivAppSet)
- return (s1->isPrivAppSet ? -1 : 1);
+ /* Give precedence to a specified isSelector (e.g., isPrivApp)
+ * over an unspecified isSelector. */
+ if(s1->isSelector && !s2->isSelector)
+ return -1;
+ if(!s1->isSelector && s2->isSelector)
+ return 1;
/* Give precedence to a higher minTargetSdkVersion= over a lower minTargetSdkVersion=.
* If unspecified, minTargetSdkVersion has a default value of 0.
@@ -236,10 +231,6 @@ static int seapp_context_cmp(const void *A, const void *B)
else if (s1->minTargetSdkVersion < s2->minTargetSdkVersion)
return 1;
- /* Give precedence to fromRunAs=true. */
- if (s1->fromRunAs != s2->fromRunAs)
- return (s1->fromRunAs ? -1 : 1);
-
/* Give precedence to platform side contexts */
bool isS1Platform = is_platform(s1->partition);
bool isS2Platform = is_platform(s2->partition);
@@ -375,16 +366,6 @@ int seapp_context_reload_internal(const path_alts_t *context_paths)
free_seapp_context(cur);
goto err;
}
- } else if (!strcasecmp(name, "isEphemeralApp")) {
- cur->isEphemeralAppSet = true;
- if (!strcasecmp(value, "true"))
- cur->isEphemeralApp = true;
- else if (!strcasecmp(value, "false"))
- cur->isEphemeralApp = false;
- else {
- free_seapp_context(cur);
- goto err;
- }
} else if (!strcasecmp(name, "user")) {
if (cur->user.str) {
free_seapp_context(cur);
@@ -485,55 +466,30 @@ int seapp_context_reload_internal(const path_alts_t *context_paths)
free_seapp_context(cur);
goto oom;
}
- } else if (!strcasecmp(name, "isPrivApp")) {
- cur->isPrivAppSet = true;
- if (!strcasecmp(value, "true"))
- cur->isPrivApp = true;
- else if (!strcasecmp(value, "false"))
- cur->isPrivApp = false;
- else {
- free_seapp_context(cur);
- goto err;
- }
} else if (!strcasecmp(name, "minTargetSdkVersion")) {
cur->minTargetSdkVersion = get_minTargetSdkVersion(value);
if (cur->minTargetSdkVersion < 0) {
free_seapp_context(cur);
goto err;
}
- } else if (!strcasecmp(name, "fromRunAs")) {
- if (!strcasecmp(value, "true"))
- cur->fromRunAs = true;
- else if (!strcasecmp(value, "false"))
- cur->fromRunAs = false;
- else {
- free_seapp_context(cur);
- goto err;
- }
- } else if (!strcasecmp(name, "isIsolatedComputeApp")) {
- if (!strcasecmp(value, "true"))
- cur->isIsolatedComputeApp = true;
- else if (!strcasecmp(value, "false"))
- cur->isIsolatedComputeApp = false;
- else {
+ } else if ((!strncasecmp(name, "is", 2) && strlen(name) > 3) ||
+ !strcasecmp(name, "fromRunAs")) {
+ if (cur->isSelector) {
+ selinux_log(SELINUX_ERROR, "%s: isSelector set twice %s",
+ __FUNCTION__, name);
free_seapp_context(cur);
goto err;
}
- } else if (!strcasecmp(name, "isSdkSandboxAudit")) {
- if (!strcasecmp(value, "true"))
- cur->isSdkSandboxAudit = true;
- else if (!strcasecmp(value, "false"))
- cur->isSdkSandboxAudit = false;
- else {
+ cur->isSelector = strdup(name);
+ if (!cur->isSelector) {
free_seapp_context(cur);
goto err;
}
- } else if (!strcasecmp(name, "isSdkSandboxNext")) {
- if (!strcasecmp(value, "true"))
- cur->isSdkSandboxNext = true;
- else if (!strcasecmp(value, "false"))
- cur->isSdkSandboxNext = false;
- else {
+ if (!strcasecmp(value, "true")) {
+ cur->isSelectorValue = true;
+ } else if (!strcasecmp(value, "false")) {
+ cur->isSelectorValue = false;
+ } else {
free_seapp_context(cur);
goto err;
}
@@ -547,8 +503,9 @@ int seapp_context_reload_internal(const path_alts_t *context_paths)
break;
}
- if (!cur->isPrivApp && cur->name.str &&
- (!cur->seinfo || !strcmp(cur->seinfo, "default"))) {
+ if ((!cur->isSelector || strcasecmp(cur->isSelector, "isPrivApp") || !cur->isSelectorValue) &&
+ cur->name.str &&
+ (!cur->seinfo || !strcmp(cur->seinfo, "default"))) {
selinux_log(SELINUX_ERROR, "%s: No specific seinfo value specified with name=\"%s\", on line %u: insecure configuration!\n",
seapp_contexts_files[i], cur->name.str, lineno);
free_seapp_context(cur);
@@ -582,11 +539,8 @@ int seapp_context_reload_internal(const path_alts_t *context_paths)
bool dup = (!s1->user.str || !strcmp(s1->user.str, s2->user.str)) &&
(!s1->seinfo || !strcmp(s1->seinfo, s2->seinfo)) &&
(!s1->name.str || !strcmp(s1->name.str, s2->name.str)) &&
- (!s1->isPrivAppSet || s1->isPrivApp == s2->isPrivApp) &&
- (!s1->isEphemeralAppSet || s1->isEphemeralApp == s2->isEphemeralApp) &&
- (s1->isIsolatedComputeApp == s2->isIsolatedComputeApp) &&
- (s1->isSdkSandboxAudit == s2->isSdkSandboxAudit) &&
- (s1->isSdkSandboxNext == s2->isSdkSandboxNext);
+ (!s1->isSelector || !strcmp(s1->isSelector, s2->isSelector)) &&
+ (s1->isSelectorValue == s2->isSelectorValue);
if (dup) {
selinux_log(SELINUX_ERROR, "seapp_contexts: Duplicated entry\n");
@@ -608,27 +562,21 @@ int seapp_context_reload_internal(const path_alts_t *context_paths)
int i;
for (i = 0; i < nspec; i++) {
cur = seapp_contexts[i];
- selinux_log(SELINUX_INFO, "%s: isSystemServer=%s isEphemeralApp=%s "
- "isIsolatedComputeApp=%s isSdkSandboxAudit=%s isSdkSandboxNext=%s "
- "user=%s seinfo=%s name=%s isPrivApp=%s minTargetSdkVersion=%d "
- "fromRunAs=%s -> domain=%s type=%s level=%s levelFrom=%s",
+ selinux_log(SELINUX_INFO, "%s: isSystemServer=%s %s=%s "
+ "user=%s seinfo=%s name=%s minTargetSdkVersion=%d "
+ " -> domain=%s type=%s level=%s levelFrom=%s",
__FUNCTION__,
cur->isSystemServer ? "true" : "false",
- cur->isEphemeralAppSet ? (cur->isEphemeralApp ? "true" : "false") : "null",
+ cur->isSelector ? cur->isSelector : "isX",
+ cur->isSelector ? (cur->isSelectorValue ? "true" : "false") : "null",
cur->user.str,
cur->seinfo, cur->name.str,
- cur->isPrivAppSet ? (cur->isPrivApp ? "true" : "false") : "null",
cur->minTargetSdkVersion,
- cur->fromRunAs ? "true" : "false",
- cur->isIsolatedComputeApp ? "true" : "false",
- cur->isSdkSandboxAudit ? "true" : "false",
- cur->isSdkSandboxNext ? "true" : "false",
cur->domain, cur->type, cur->level,
levelFromName[cur->levelFrom]);
}
}
#endif
-
ret = 0;
out:
@@ -675,16 +623,21 @@ void selinux_android_seapp_context_init(void) {
*/
#define CAT_MAPPING_MAX_ID (0x1<<16)
-#define PRIVILEGED_APP_STR "privapp"
-#define ISOLATED_COMPUTE_APP_STR "isolatedComputeApp"
-#define APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS_STR "isSdkSandboxAudit"
-#define APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS_STR "isSdkSandboxNext"
-#define EPHEMERAL_APP_STR "ephemeralapp"
#define TARGETSDKVERSION_STR "targetSdkVersion"
#define PARTITION_STR "partition"
-#define FROM_RUNAS_STR "fromRunAs"
#define COMPLETE_STR "complete"
+/* Any selector from seapp_contexts starting with "is" is automatically mapped
+ * to an attribute of seinfo. For historical reasons, there are mappings that do
+ * not follow this convention. */
+static char* selector_mappings[][2] = {
+ /* seinfo field, seapp_contexts selector */
+ {"privapp", "isPrivApp"},
+ {"isolatedComputeApp", "isIsolatedComputeApp"},
+ {"ephemeralapp", "isEphemeralApp"},
+ {"fromRunAs", "fromRunAs"}
+};
+
static bool is_preinstalled_app_partition_valid(const char *app_policy, const char *app_partition) {
// We forbid system/system_ext/product installed apps from being labeled with vendor sepolicy.
// So, either the app shouldn't be platform, or the spec should be platform.
@@ -725,6 +678,8 @@ int set_range_from_level(context_t ctx, enum levelFrom levelFrom, uid_t userid,
return 0;
}
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
int parse_seinfo(const char* seinfo, struct parsed_seinfo* info) {
char local_seinfo[SEINFO_BUFSIZ];
@@ -747,28 +702,29 @@ int parse_seinfo(const char* seinfo, struct parsed_seinfo* info) {
first = false;
continue;
}
- if (!strcmp(token, PRIVILEGED_APP_STR)) {
- info->is |= IS_PRIV_APP;
- continue;
- }
- if (!strcmp(token, EPHEMERAL_APP_STR)) {
- info->is |= IS_EPHEMERAL_APP;
- continue;
- }
- if (!strcmp(token, ISOLATED_COMPUTE_APP_STR)) {
- info->is |= IS_ISOLATED_COMPUTE_APP;
- continue;
- }
- if (!strcmp(token, APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS_STR)) {
- info->is |= IS_SDK_SANDBOX_AUDIT;
- continue;
+ bool matched = false;
+ for (int i=0; i < ARRAY_SIZE(selector_mappings); i++) {
+ if (!strcmp(token, selector_mappings[i][0])) {
+ if(info->isSelector[0]) {
+ selinux_log(SELINUX_ERROR, "%s: isSelector already populated: %s in %s\n",
+ __FUNCTION__, token, seinfo);
+ return -1;
+ }
+ strcpy(info->isSelector, selector_mappings[i][1]);
+ matched = true;
+ break;
+ }
}
- if (!strcmp(token, APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS_STR)) {
- info->is |= IS_SDK_SANDBOX_NEXT;
+ if (matched) {
continue;
}
- if (!strcmp(token, FROM_RUNAS_STR)) {
- info->is |= IS_FROM_RUN_AS;
+ if (!strncmp(token, "is", 2)) {
+ if(info->isSelector[0]) {
+ selinux_log(SELINUX_ERROR, "%s: isSelector already populated: %s in %s\n",
+ __FUNCTION__, token, seinfo);
+ return -1;
+ }
+ strncpy(info->isSelector, token, strlen(token));
continue;
}
if (!strncmp(token, TARGETSDKVERSION_STR, strlen(TARGETSDKVERSION_STR))) {
@@ -792,7 +748,6 @@ int parse_seinfo(const char* seinfo, struct parsed_seinfo* info) {
__FUNCTION__, token, seinfo);
return -1;
}
- info->isPreinstalledApp = true;
strncpy(info->partition, subtoken, strlen(subtoken));
continue;
}
@@ -868,9 +823,6 @@ int seapp_context_lookup_internal(enum seapp_kind kind,
if (cur->isSystemServer != isSystemServer)
continue;
- if (cur->isEphemeralAppSet && cur->isEphemeralApp != ((info.is & IS_EPHEMERAL_APP) != 0))
- continue;
-
if (cur->user.str) {
if (cur->user.is_prefix) {
if (strncasecmp(username, cur->user.str, cur->user.len-1))
@@ -899,23 +851,16 @@ int seapp_context_lookup_internal(enum seapp_kind kind,
}
}
- if (cur->isPrivAppSet && cur->isPrivApp != ((info.is & IS_PRIV_APP) != 0))
- continue;
-
if (cur->minTargetSdkVersion > info.targetSdkVersion)
continue;
- if (cur->fromRunAs != ((info.is & IS_FROM_RUN_AS) != 0))
- continue;
-
- if (cur->isIsolatedComputeApp != ((info.is & IS_ISOLATED_COMPUTE_APP) != 0))
- continue;
-
- if (cur->isSdkSandboxAudit != ((info.is & IS_SDK_SANDBOX_AUDIT) != 0))
- continue;
-
- if (cur->isSdkSandboxNext != ((info.is & IS_SDK_SANDBOX_NEXT) != 0))
- continue;
+ if (cur->isSelector && cur->isSelectorValue) {
+ if (!info.isSelector[0])
+ continue;
+ if (strcasecmp(info.isSelector, cur->isSelector)) {
+ continue;
+ }
+ }
if (kind == SEAPP_TYPE && !cur->type)
continue;
@@ -940,7 +885,7 @@ int seapp_context_lookup_internal(enum seapp_kind kind,
goto oom;
}
- if (info.isPreinstalledApp
+ if (info.partition[0]
&& !is_preinstalled_app_partition_valid(cur->partition, info.partition)) {
// TODO(b/280547417): make this an error after fixing violations
selinux_log(SELINUX_WARNING,
diff --git a/libselinux/src/android/android_unittest.cpp b/libselinux/src/android/android_unittest.cpp
index 1eb9056e..72c67a5e 100644
--- a/libselinux/src/android/android_unittest.cpp
+++ b/libselinux/src/android/android_unittest.cpp
@@ -11,8 +11,17 @@ using android::base::WriteStringToFile;
using std::string;
class AndroidSELinuxTest : public ::testing::Test {
- protected:
+ protected:
+ void SetUp() override {
+ default_seapp_context_ = StringPrintf("%s/seapp_contexts", tdir_.path);
+ default_seapp_path_alts_ = { .paths = {
+ { default_seapp_context_.c_str() }
+ }};
+ }
+
TemporaryDir tdir_;
+ string default_seapp_context_;
+ path_alts_t default_seapp_path_alts_;
};
TEST_F(AndroidSELinuxTest, LoadAndLookupServiceContext)
@@ -84,19 +93,13 @@ TEST_F(AndroidSELinuxTest, FailLoadingServiceContext)
TEST_F(AndroidSELinuxTest, LoadAndLookupSeAppContext)
{
- string seapp_contexts =
- StringPrintf("%s/seapp_contexts", tdir_.path);
WriteStringToFile(
"# some comment\n"
"user=_app seinfo=platform domain=platform_app type=app_data_file levelFrom=user\n",
- seapp_contexts);
-
- const path_alts_t seapp_paths = { .paths = {
- { seapp_contexts.c_str() }
- }};
+ default_seapp_context_);
- EXPECT_EQ(seapp_context_reload_internal(&seapp_paths), 0);
+ EXPECT_EQ(seapp_context_reload_internal(&default_seapp_path_alts_), 0);
context_t ctx = context_new("u:r:unknown");
int ret = seapp_context_lookup_internal(SEAPP_DOMAIN, 10001, false, "platform", "com.android.test1", ctx);
@@ -111,6 +114,42 @@ TEST_F(AndroidSELinuxTest, LoadAndLookupSeAppContext)
context_free(ctx);
}
+TEST_F(AndroidSELinuxTest, LoadSeAppContextInsecure)
+{
+ WriteStringToFile(
+ "user=_app name=com.android.test domain=platform_app type=app_data_file\n",
+ default_seapp_context_);
+
+ EXPECT_EQ(seapp_context_reload_internal(&default_seapp_path_alts_), -1);
+
+ WriteStringToFile(
+ "user=_app name=com.android.test isSdkSandbox=true domain=platform_app type=app_data_file\n",
+ default_seapp_context_);
+
+ EXPECT_EQ(seapp_context_reload_internal(&default_seapp_path_alts_), -1);
+
+ WriteStringToFile(
+ "user=_app isPrivApp=false name=com.android.test domain=platform_app type=app_data_file\n",
+ default_seapp_context_);
+
+ EXPECT_EQ(seapp_context_reload_internal(&default_seapp_path_alts_), -1);
+}
+
+TEST_F(AndroidSELinuxTest, LoadSeAppContextInsecureWithSeInfoOrPrivApp)
+{
+ WriteStringToFile(
+ "user=_app isPrivApp=true name=com.android.test domain=platform_app type=app_data_file\n",
+ default_seapp_context_);
+
+ EXPECT_EQ(seapp_context_reload_internal(&default_seapp_path_alts_), 0);
+
+ WriteStringToFile(
+ "user=_app seinfo=platform name=com.android.test domain=platform_app type=app_data_file\n",
+ default_seapp_context_);
+
+ EXPECT_EQ(seapp_context_reload_internal(&default_seapp_path_alts_), 0);
+}
+
TEST(AndroidSeAppTest, ParseValidSeInfo)
{
struct parsed_seinfo info;
@@ -122,8 +161,7 @@ TEST(AndroidSeAppTest, ParseValidSeInfo)
EXPECT_EQ(ret, 0);
EXPECT_STREQ(info.base, "default");
EXPECT_EQ(info.targetSdkVersion, 10000);
- EXPECT_EQ(info.is, IS_PRIV_APP);
- EXPECT_EQ(info.isPreinstalledApp, true);
+ EXPECT_STREQ(info.isSelector, "isPrivApp");
EXPECT_STREQ(info.partition, "system");
seinfo = "platform:ephemeralapp:partition=system:complete";
@@ -132,8 +170,7 @@ TEST(AndroidSeAppTest, ParseValidSeInfo)
EXPECT_EQ(ret, 0);
EXPECT_STREQ(info.base, "platform");
EXPECT_EQ(info.targetSdkVersion, 0);
- EXPECT_EQ(info.is, IS_EPHEMERAL_APP);
- EXPECT_EQ(info.isPreinstalledApp, true);
+ EXPECT_STREQ(info.isSelector, "isEphemeralApp");
EXPECT_STREQ(info.partition, "system");
seinfo = "bluetooth";
@@ -142,8 +179,16 @@ TEST(AndroidSeAppTest, ParseValidSeInfo)
EXPECT_EQ(ret, 0);
EXPECT_STREQ(info.base, "bluetooth");
EXPECT_EQ(info.targetSdkVersion, 0);
- EXPECT_EQ(info.isPreinstalledApp, false);
- EXPECT_EQ(info.is, 0);
+ EXPECT_STREQ(info.isSelector, "");
+
+ seinfo = "default:isSdkSandboxNext:partition=system:complete";
+ ret = parse_seinfo(seinfo.c_str(), &info);
+
+ EXPECT_EQ(ret, 0);
+ EXPECT_STREQ(info.base, "default");
+ EXPECT_EQ(info.targetSdkVersion, 0);
+ EXPECT_STREQ(info.isSelector, "isSdkSandboxNext");
+ EXPECT_STREQ(info.partition, "system");
}
TEST(AndroidSeAppTest, ParseInvalidSeInfo)
@@ -157,6 +202,14 @@ TEST(AndroidSeAppTest, ParseInvalidSeInfo)
seinfo = "default:targetSdkVersion=:complete";
ret = parse_seinfo(seinfo.c_str(), &info);
EXPECT_EQ(ret, -1);
+
+ seinfo = "default:privapp:ephemeralapp:complete";
+ ret = parse_seinfo(seinfo.c_str(), &info);
+ EXPECT_EQ(ret, -1);
+
+ seinfo = "default:isANewSelector:isAnotherOne:complete";
+ ret = parse_seinfo(seinfo.c_str(), &info);
+ EXPECT_EQ(ret, -1);
}
TEST(AndroidSeAppTest, ParseOverflow)