• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <gtest/gtest.h>
2 
3 #include <android-base/file.h>
4 #include <android-base/macros.h>
5 #include <android-base/stringprintf.h>
6 
7 #include "android_internal.h"
8 #include "label_internal.h"
9 
10 using android::base::StringPrintf;
11 using android::base::WriteStringToFile;
12 using std::string;
13 
14 class AndroidSELinuxTest : public ::testing::Test {
15     protected:
16 	const char* kUnknownDomain = "u:r:unknown";
17 	TemporaryDir tdir_;
18 
LoadSeAppContexts(string content)19 	int LoadSeAppContexts(string content)
20 	{
21 		string seapp_contexts = StringPrintf("%s/seapp_contexts", tdir_.path);
22 		WriteStringToFile(content, seapp_contexts);
23 		path_alts_t seapp_paths = {
24 			.paths = {
25 				{ seapp_contexts.c_str() }
26 			},
27 			.partitions = {
28 				"system"
29 			}
30 		};
31 		return seapp_context_reload_internal(&seapp_paths);
32 	}
33 
34         /* Resolve the context for a specific `seinfo` and ensures that it matches
35          * `expected`. If `expected` is NULL, ensures that the context is not modified
36          */
ExpectContextForSeInfo(const char * seinfo,const char * expected)37         void ExpectContextForSeInfo(const char* seinfo, const char* expected)
38 	{
39 		context_t ctx = context_new(kUnknownDomain);
40 		int ret = seapp_context_lookup_internal(SEAPP_DOMAIN, 10001, false, seinfo, "com.android.test", ctx);
41 		EXPECT_EQ(ret, 0);
42 		if (!expected) {
43 			expected = kUnknownDomain;
44 		}
45 		EXPECT_STREQ(context_str(ctx), expected);
46 		context_free(ctx);
47 	}
48 };
49 
TEST_F(AndroidSELinuxTest,LoadAndLookupServiceContext)50 TEST_F(AndroidSELinuxTest, LoadAndLookupServiceContext)
51 {
52 	string service_contexts =
53 		StringPrintf("%s/service_contexts", tdir_.path);
54 	string unused_service_contexts =
55 		StringPrintf("%s/unused_contexts", tdir_.path);
56 	string vendor_contexts =
57 		StringPrintf("%s/vendor_service_contexts", tdir_.path);
58 
59 	WriteStringToFile("account  u:object_r:account_service:s0\n",
60 			  service_contexts);
61 	WriteStringToFile("ignored  u:object_r:ignored_service:s0\n",
62 			  unused_service_contexts);
63 	WriteStringToFile(
64 		"android.hardware.power.IPower/default  u:object_r:hal_power_service:s0\n",
65 		vendor_contexts);
66 
67 	const path_alts_t service_paths = { .paths = {
68 		{ service_contexts.c_str(), unused_service_contexts.c_str() },
69 		{ vendor_contexts.c_str() }
70 	}};
71 
72 	struct selabel_handle *handle = context_handle(
73 		SELABEL_CTX_ANDROID_SERVICE, &service_paths, "test_service");
74 	EXPECT_NE(handle, nullptr);
75 
76 	char *tcontext;
77 	EXPECT_EQ(selabel_lookup_raw(handle, &tcontext, "foobar",
78 				     SELABEL_CTX_ANDROID_SERVICE),
79 		  -1);
80 
81 	EXPECT_EQ(selabel_lookup_raw(handle, &tcontext, "account",
82 				     SELABEL_CTX_ANDROID_SERVICE),
83 		  0);
84 	EXPECT_STREQ(tcontext, "u:object_r:account_service:s0");
85 	free(tcontext);
86 
87 	EXPECT_EQ(selabel_lookup_raw(handle, &tcontext, "ignored",
88 				     SELABEL_CTX_ANDROID_SERVICE),
89 		  -1);
90 
91 	EXPECT_EQ(selabel_lookup_raw(handle, &tcontext,
92 				     "android.hardware.power.IPower/default",
93 				     SELABEL_CTX_ANDROID_SERVICE),
94 		  0);
95 	EXPECT_STREQ(tcontext, "u:object_r:hal_power_service:s0");
96 	free(tcontext);
97 
98 	selabel_close(handle);
99 }
100 
TEST_F(AndroidSELinuxTest,FailLoadingServiceContext)101 TEST_F(AndroidSELinuxTest, FailLoadingServiceContext)
102 {
103 	string service_contexts =
104 		StringPrintf("%s/service_contexts", tdir_.path);
105 
106 	WriteStringToFile("garbage\n", service_contexts);
107 
108 	const path_alts_t service_paths = { .paths = {
109 		{ service_contexts.c_str() }
110 	}};
111 
112 	struct selabel_handle *handle = context_handle(
113 		SELABEL_CTX_ANDROID_SERVICE, &service_paths, "test_service");
114 	EXPECT_EQ(handle, nullptr);
115 }
116 
TEST_F(AndroidSELinuxTest,LoadAndLookupSeAppContext)117 TEST_F(AndroidSELinuxTest, LoadAndLookupSeAppContext)
118 {
119 	int ret = LoadSeAppContexts(
120 		"# some comment\n"
121 		"user=_app seinfo=platform domain=platform_app type=app_data_file levelFrom=user\n"
122 	);
123 
124 	EXPECT_EQ(ret, 0);
125 
126 	context_t ctx = context_new("u:r:unknown");
127 	ret = seapp_context_lookup_internal(SEAPP_DOMAIN, 10001, false, "platform", "com.android.test1", ctx);
128 	EXPECT_EQ(ret, 0);
129 	EXPECT_STREQ(context_str(ctx), "u:r:platform_app:s0:c512,c768");
130 	context_free(ctx);
131 
132 	ctx = context_new("u:r:unknown_data_file");
133 	ret = seapp_context_lookup_internal(SEAPP_TYPE, 10001, false, "platform", "com.android.test1", ctx);
134 	EXPECT_EQ(ret, 0);
135 	EXPECT_STREQ(context_str(ctx), "u:r:app_data_file:s0:c512,c768");
136 	context_free(ctx);
137 }
138 
TEST_F(AndroidSELinuxTest,LoadAndLookupSeAppContextBooleanDefault)139 TEST_F(AndroidSELinuxTest, LoadAndLookupSeAppContextBooleanDefault)
140 {
141 	int ret = LoadSeAppContexts(
142 		"user=_app domain=catchall_app type=x levelFrom=user\n"
143 	);
144 
145 	EXPECT_EQ(ret, 0);
146 
147 	ExpectContextForSeInfo("default:privapp:partition=system:complete", "u:r:catchall_app:s0:c512,c768");
148 	ExpectContextForSeInfo("default:ephemeralapp:partition=system:complete", "u:r:catchall_app:s0:c512,c768");
149 
150 	ExpectContextForSeInfo("default:isolatedComputeApp:partition=system:complete", nullptr);
151 	ExpectContextForSeInfo("default:isSdkSandboxAudit:partition=system:complete", nullptr);
152 	ExpectContextForSeInfo("default:isSdkSandboxNext:partition=system:complete", nullptr);
153 	ExpectContextForSeInfo("default:fromRunAs:partition=system:complete", nullptr);
154 }
155 
TEST_F(AndroidSELinuxTest,LoadAndLookupSeAppContextBooleanFalse)156 TEST_F(AndroidSELinuxTest, LoadAndLookupSeAppContextBooleanFalse)
157 {
158 	int ret = LoadSeAppContexts(
159 		"user=_app isPrivApp=false domain=noprivapp type=x levelFrom=user\n"
160 		"user=_app isEphemeralApp=false domain=noephemeralapp type=x levelFrom=user\n"
161 		"user=_app domain=catchall_app type=x levelFrom=user\n"
162 	);
163 
164 	EXPECT_EQ(ret, 0);
165 
166 	ExpectContextForSeInfo("default:privapp:partition=system:complete", "u:r:noephemeralapp:s0:c512,c768");
167 	ExpectContextForSeInfo("default:ephemeralapp:partition=system:complete", "u:r:noprivapp:s0:c512,c768");
168 	// isEphemeralApp has precedence over isPrivApp.
169 	ExpectContextForSeInfo("default:partition=system:complete", "u:r:noephemeralapp:s0:c512,c768");
170 
171         // For the boolean selectors with a default value, check that the
172         // loading fail (as this is a duplicate of the catchall).
173         string defaultFalseBooleans[] = { "isIsolatedComputeApp", "isSdkSandboxAudit", "isSdkSandboxNext", "fromRunAs" };
174 	for (int i=0; i < arraysize(defaultFalseBooleans); i++) {
175 		string seapp_contexts =
176 			"user=_app " + defaultFalseBooleans[i] + "=false domain=y type=x levelFrom=user\n"
177 			"user=_app domain=catchall_app type=x levelFrom=user\n";
178 		ret = LoadSeAppContexts(seapp_contexts);
179 		EXPECT_EQ(ret, -1); // we expect a failure because of the duplicate.
180 	}
181 }
182 
TEST_F(AndroidSELinuxTest,LoadAndLookupSeAppContextBooleanTrue)183 TEST_F(AndroidSELinuxTest, LoadAndLookupSeAppContextBooleanTrue)
184 {
185 	int ret = LoadSeAppContexts(
186 		"user=_app isPrivApp=true domain=privapp type=x levelFrom=user\n"
187 		"user=_app isEphemeralApp=true domain=ephemeralapp type=x levelFrom=user\n"
188 		"user=_app isIsolatedComputeApp=true domain=isolatedapp type=x levelFrom=user\n"
189 		"user=_app isSdkSandboxAudit=true domain=sdk_audit type=x levelFrom=user\n"
190 		"user=_app isSdkSandboxNext=true domain=sdk_next type=x levelFrom=user\n"
191 		"user=_app fromRunAs=true domain=runas type=x levelFrom=user\n"
192 		"user=_app domain=catchall_app type=x levelFrom=user\n"
193 	);
194 
195 	EXPECT_EQ(ret, 0);
196 
197 	ExpectContextForSeInfo("default:privapp:partition=system:complete", "u:r:privapp:s0:c512,c768");
198 	ExpectContextForSeInfo("default:ephemeralapp:partition=system:complete", "u:r:ephemeralapp:s0:c512,c768");
199 	ExpectContextForSeInfo("default:isolatedComputeApp:partition=system:complete", "u:r:isolatedapp:s0:c512,c768");
200 	ExpectContextForSeInfo("default:isSdkSandboxAudit:partition=system:complete", "u:r:sdk_audit:s0:c512,c768");
201 	ExpectContextForSeInfo("default:isSdkSandboxNext:partition=system:complete", "u:r:sdk_next:s0:c512,c768");
202 	ExpectContextForSeInfo("default:fromRunAs:partition=system:complete", "u:r:runas:s0:c512,c768");
203 
204 	ExpectContextForSeInfo("default:partition=system:complete", "u:r:catchall_app:s0:c512,c768");
205 }
206 
TEST(AndroidSeAppTest,ParseValidSeInfo)207 TEST(AndroidSeAppTest, ParseValidSeInfo)
208 {
209 	struct parsed_seinfo info;
210 	memset(&info, 0, sizeof(info));
211 
212 	string seinfo = "default:privapp:targetSdkVersion=10000:partition=system:complete";
213 	int ret = parse_seinfo(seinfo.c_str(), &info);
214 
215 	EXPECT_EQ(ret, 0);
216 	EXPECT_STREQ(info.base, "default");
217 	EXPECT_EQ(info.targetSdkVersion, 10000);
218 	EXPECT_EQ(info.is, IS_PRIV_APP);
219 	EXPECT_EQ(info.isPreinstalledApp, true);
220 	EXPECT_STREQ(info.partition, "system");
221 
222 	seinfo = "platform:ephemeralapp:partition=system:complete";
223 	ret = parse_seinfo(seinfo.c_str(), &info);
224 
225 	EXPECT_EQ(ret, 0);
226 	EXPECT_STREQ(info.base, "platform");
227 	EXPECT_EQ(info.targetSdkVersion, 0);
228 	EXPECT_EQ(info.is, IS_EPHEMERAL_APP);
229 	EXPECT_EQ(info.isPreinstalledApp, true);
230 	EXPECT_STREQ(info.partition, "system");
231 
232 	seinfo = "bluetooth";
233 	ret = parse_seinfo(seinfo.c_str(), &info);
234 
235 	EXPECT_EQ(ret, 0);
236 	EXPECT_STREQ(info.base, "bluetooth");
237 	EXPECT_EQ(info.targetSdkVersion, 0);
238 	EXPECT_EQ(info.isPreinstalledApp, false);
239 	EXPECT_EQ(info.is, 0);
240 }
241 
TEST(AndroidSeAppTest,ParseInvalidSeInfo)242 TEST(AndroidSeAppTest, ParseInvalidSeInfo)
243 {
244 	struct parsed_seinfo info;
245 
246 	string seinfo = "default:targetSdkVersion:complete";
247 	int ret = parse_seinfo(seinfo.c_str(), &info);
248 	EXPECT_EQ(ret, -1);
249 
250 	seinfo = "default:targetSdkVersion=:complete";
251 	ret = parse_seinfo(seinfo.c_str(), &info);
252 	EXPECT_EQ(ret, -1);
253 }
254 
TEST(AndroidSeAppTest,ParseOverflow)255 TEST(AndroidSeAppTest, ParseOverflow)
256 {
257 	struct parsed_seinfo info;
258 
259 	string seinfo = std::string(255, 'x');
260 	int ret = parse_seinfo(seinfo.c_str(), &info);
261 	EXPECT_EQ(ret, 0);
262 	EXPECT_STREQ(info.base, seinfo.c_str());
263 
264 	seinfo = std::string(256, 'x');
265 	ret = parse_seinfo(seinfo.c_str(), &info);
266 	EXPECT_EQ(ret, -1);
267 }
268 
TEST(AndroidSELinuxPathTest,IsAppDataPath)269 TEST(AndroidSELinuxPathTest, IsAppDataPath)
270 {
271 	EXPECT_TRUE(is_app_data_path("/data/data"));
272 	EXPECT_TRUE(is_app_data_path("/data/user/0"));
273 
274 	EXPECT_FALSE(is_app_data_path("/data"));
275 }
276 
TEST(AndroidSELinuxPathTest,IsCredentialEncryptedPath)277 TEST(AndroidSELinuxPathTest, IsCredentialEncryptedPath)
278 {
279 	EXPECT_TRUE(is_credential_encrypted_path("/data/system_ce/0"));
280 	EXPECT_TRUE(is_credential_encrypted_path("/data/system_ce/0/backup"));
281 	EXPECT_TRUE(is_credential_encrypted_path("/data/misc_ce/0"));
282 	EXPECT_TRUE(is_credential_encrypted_path("/data/misc_ce/0/apexdata"));
283 	EXPECT_TRUE(is_credential_encrypted_path("/data/vendor_ce/0"));
284 	EXPECT_TRUE(is_credential_encrypted_path("/data/vendor_ce/0/data"));
285 
286 	EXPECT_FALSE(is_credential_encrypted_path("/data"));
287 	EXPECT_FALSE(is_credential_encrypted_path("/data/data"));
288 	EXPECT_FALSE(is_credential_encrypted_path("/data/user/0"));
289 }
290 
TEST(AndroidSELinuxPathTest,ExtractPkgnameAndUserid)291 TEST(AndroidSELinuxPathTest, ExtractPkgnameAndUserid)
292 {
293 	char *pkgname = NULL;
294 	unsigned int userid;
295 
296 	EXPECT_EQ(extract_pkgname_and_userid("/data/", &pkgname, &userid), -1);
297 
298 	char const* path = "/data/user/0/com.android.myapp";
299 	EXPECT_EQ(extract_pkgname_and_userid(path, &pkgname, &userid), 0);
300 	EXPECT_STREQ("com.android.myapp", pkgname);
301 	EXPECT_EQ(userid, 0);
302 	free(pkgname);
303 	pkgname = NULL;
304 
305 	path = "/data/user/0/com.android.myapp/som/subdir";
306 	EXPECT_EQ(extract_pkgname_and_userid(path, &pkgname, &userid), 0);
307 	EXPECT_STREQ("com.android.myapp", pkgname);
308 	EXPECT_EQ(userid, 0);
309 	free(pkgname);
310 	pkgname = NULL;
311 
312 	path = "/data/data/com.android.myapp2";
313 	EXPECT_EQ(extract_pkgname_and_userid(path, &pkgname, &userid), 0);
314 	EXPECT_STREQ("com.android.myapp2", pkgname);
315 	EXPECT_EQ(userid, 0);
316 	free(pkgname);
317 	pkgname = NULL;
318 
319 	path = "/data/misc_de/10/sdksandbox/com.android.myapp3";
320 	EXPECT_EQ(extract_pkgname_and_userid(path, &pkgname, &userid), 0);
321 	EXPECT_STREQ("com.android.myapp3", pkgname);
322 	EXPECT_EQ(userid, 10);
323 	free(pkgname);
324 	pkgname = NULL;
325 }
326