2 * Copyright (C) 2011 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless requied by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 * This socket tagging test is to ensure that the
20 * netfilter/xt_qtaguid kernel module somewhat behaves as expected
21 * with respect to tagging sockets.
29 #include <gtest/gtest.h>
30 #include <sys/socket.h>
31 #include <sys/types.h>
34 #define LOG_TAG "socketTagTest"
35 #include <utils/Log.h>
42 SockInfo() : fd(-1), addr(NULL) {};
43 int setup(uint64_t tag);
44 bool checkTag(uint64_t tag, uid_t uid);
52 ctrl = open("/proc/net/xt_qtaguid/ctrl", O_RDWR);
54 testPrintE("qtaguid ctrl open failed: %s", strerror(errno));
59 int doCtrlCommand(const char *fmt, ...)
60 __attribute__((__format__(__printf__, 1, 2)));
62 int doCtrlCommand(const char *fmt, ...) {
70 vasprintf(&buff, fmt, argp);
72 res = write(ctrl, buff, strlen(buff));
73 testPrintI("cmd: '%s' res=%d %d/%s", buff, res, errno, strerror(errno));
81 int writeModuleParam(const char *param, const char *data) {
84 std::string filename("/sys/module/xt_qtaguid/parameters/");
87 param_fd = open(filename.c_str(), O_WRONLY);
89 testPrintE("qtaguid param open failed: %s", strerror(errno));
92 res = write(param_fd, data, strlen(data));
94 testPrintE("qtaguid param write failed: %s", strerror(errno));
100 /*----------------------------------------------------------------*/
101 int SockInfo::setup(uint64_t tag) {
102 fd = socket(AF_INET, SOCK_STREAM, 0);
104 testPrintE("socket creation failed: %s", strerror(errno));
107 if (doCtrlCommand("t %d %" PRIu64, fd, tag) < 0) {
108 testPrintE("socket setup: failed to tag");
112 if (!checkTag(tag, getuid())) {
113 testPrintE("socket setup: Unexpected results: tag not found");
117 if (doCtrlCommand("u %d", fd) < 0) {
118 testPrintE("socket setup: Unexpected results");
125 /* checkTag() also tries to lookup the socket address in the kernel and
126 * return it when *addr == NULL.
127 * This allows for better look ups when another process is also setting the same
128 * tag + uid. But it is not fool proof.
129 * Without the kernel reporting more info on who setup the socket tag, it is
130 * not easily verifiable from user-space.
131 * Returns: true if tag found.
133 bool SockInfo::checkTag(uint64_t acct_tag, uid_t uid) {
135 ctrl_fd = openCtrl();
136 char ctrl_data[1024];
141 char *match_template;
148 read_size = read(ctrl_fd, ctrl_data, sizeof(ctrl_data));
150 testPrintE("Unable to read active tags from ctrl %d/%s",
151 errno, strerror(errno));
153 ctrl_data[read_size] = '\0';
154 testPrintI("<ctrl_raw_data>\n%s</ctrl_raw_data>", ctrl_data);
157 assert(sizeof(void*) == sizeof(long int)); // Why does %p use 0x? grrr. %lx.
158 asprintf(&match_template, "sock=%" PRIxPTR " %s", (uintptr_t)addr, "tag=0x%" PRIx64" (uid=%u)");
161 /* Allocate for symmetry */
162 asprintf(&match_template, "%s", " tag=0x%" PRIx64 " (uid=%u)");
165 full_tag = acct_tag | uid;
167 asprintf(&buff, match_template, full_tag | uid, uid);
168 testPrintI("looking for '%s'", buff);
169 pos = strstr(ctrl_data, buff);
172 assert(sizeof(void*) == sizeof(long int)); // Why does %p use 0x? grrr. %lx.
173 res = sscanf(pos - strlen("sock=1234abcd"),
174 "sock=%" SCNxPTR " tag=0x%" SCNx64 " (uid=%" SCNu32 ") pid=%u f_count=%lu",
175 (uintptr_t *)&addr, &k_tag, &k_uid, &dummy_pid, &dummy_count );
176 if (!(res == 5 && k_tag == full_tag && k_uid == uid)) {
177 testPrintE("Unable to read sock addr res=%d", res);
181 testPrintI("Got sock_addr %lx", addr);
185 free(match_template);
191 class SocketTaggingTest : public ::testing::Test {
193 virtual void SetUp() {
198 srand48(my_pid * my_uid);
199 // Adjust fake UIDs and tags so that multiple instances can run in parallel.
200 fake_uid = testRand();
201 fake_uid2 = testRand();
202 valid_tag1 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
203 valid_tag2 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
204 valid_tag2 &= 0xffffff00ffffffffllu; // Leave some room to make counts visible.
205 testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
206 " tag1=0x%" PRIx64 "/%" PRIu64 " tag2=0x%" PRIx64 "/% "PRIu64,
207 (unsigned long)my_pid, (unsigned long)my_uid,
208 (unsigned long)fake_uid, (unsigned long)fake_uid,
209 (unsigned long)fake_uid2, (unsigned long)fake_uid2,
210 valid_tag1, valid_tag1, valid_tag2, valid_tag2);
211 max_uint_tag = 0xffffffff00000000llu;
212 max_uint_tag = 1llu << 63 | (((uint64_t)my_pid << 48) ^ max_uint_tag);
214 testPrintI("kernel has qtaguid");
215 ctrl_fd = openCtrl();
216 ASSERT_GE(ctrl_fd, 0) << "qtaguid ctrl open failed";
218 dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
219 EXPECT_GE(dev_fd, 0) << "qtaguid dev open failed";
221 // We want to clean up any previous faulty test runs.
222 testPrintI("delete command does not fail");
223 EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid), 0) << "Failed to delete fake_uid";
224 EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid2), 0) << "Failed to delete fake_uid2";
225 EXPECT_GE(doCtrlCommand("d 0 %u", my_uid), 0) << "Failed to delete my_uid";
227 testPrintI("setup sock0 and addr via tag");
228 ASSERT_FALSE(sock0.setup(valid_tag1)) << "socket0 setup failed";
229 testPrintI("setup sock1 and addr via tag");
230 ASSERT_FALSE(sock1.setup(valid_tag1)) << "socket1 setup failed";
233 virtual void TearDown() {
252 uint64_t max_uint_tag;
253 static const uint64_t invalid_tag1 = 0x0000000100000001llu;
254 static const int max_tags = 5;
257 TEST_F(SocketTaggingTest, TagData) {
258 max_uint_tag = 0xffffffff00000000llu;
261 testPrintI("setup tag limit");
262 asprintf(&max_tags_str, "%d", max_tags);
263 ASSERT_GE(writeModuleParam("max_sock_tags", max_tags_str), 0) << "Failed to setup tag limit";
265 testPrintI("tag quota reach limit");
266 for (int cnt = 0; cnt < max_tags; cnt++ ) {
267 uint64_t tag = valid_tag2 + ((uint64_t)cnt << 32);
268 EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, tag , fake_uid2), 0)
269 << "Tagging within limit failed";
270 EXPECT_TRUE(sock0.checkTag(tag, fake_uid2))<< "Unexpected results: tag not found";
273 testPrintI("tag quota go over limit");
274 uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
275 EXPECT_LT(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag, fake_uid2), 0);
276 EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32),
277 fake_uid2)) << "Unexpected results: tag not found";
279 testPrintI("valid untag");
280 EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
281 EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2))
282 << "Untagged tag should not be there";
284 testPrintI("tag after untag should not free up max tags");
285 uint64_t new_tag2 = valid_tag2 + ((uint64_t)max_tags << 32);
286 EXPECT_LT(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag2 , fake_uid2), 0);
287 EXPECT_FALSE(sock0.checkTag(valid_tag2 + ((uint64_t)max_tags << 32), fake_uid2))
288 << "Tag should not be there";
290 testPrintI("delete one tag");
291 uint64_t new_tag3 = valid_tag2 + (((uint64_t)max_tags / 2) << 32);
292 EXPECT_GE(doCtrlCommand("d %" PRIu64 " %u", new_tag3, fake_uid2), 0);
294 testPrintI("2 tags after 1 delete pass/fail");
296 new_tag4 = valid_tag2 + (((uint64_t)max_tags + 1 ) << 32);
297 EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag4 , fake_uid2), 0);
298 EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 1) << 32), fake_uid2))
300 new_tag4 = valid_tag2 + (((uint64_t)max_tags + 2 ) << 32);
301 EXPECT_LT(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag4 , fake_uid2), 0);
302 EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 2) << 32), fake_uid2))
303 << "Tag should not be there";
305 /* TODO(jpa): test tagging two different sockets with same tags and
306 * check refcounts the tag_node should be +2
310 TEST_F(SocketTaggingTest, InsufficientArgsFails) {
311 // Insufficient args. Expected failure
312 EXPECT_LE(doCtrlCommand("t"), 0) << "Insufficient args, should fail.";
315 TEST_F(SocketTaggingTest, BadCommandFails) {
316 // Bad command. Expected failure";
317 EXPECT_LE(doCtrlCommand("?"), 0) << "Bad command, should fail";
320 TEST_F(SocketTaggingTest, NoTagNoUid) {
322 EXPECT_GE(doCtrlCommand("t %d", sock0.fd), 0);
323 ASSERT_TRUE(sock0.checkTag(0, my_uid)) << "Tag not found";
326 TEST_F(SocketTaggingTest, InvalidTagFail) {
327 // Invalid tag. Expected failure
328 EXPECT_LE(doCtrlCommand("t %d %" PRIu64, sock0.fd, invalid_tag1), 0);
329 ASSERT_FALSE(sock0.checkTag(invalid_tag1, my_uid)) << "Tag should not be there";
332 TEST_F(SocketTaggingTest, ValidTagWithNoUid) {
333 // Valid tag with no uid
334 EXPECT_GE(doCtrlCommand("t %d %" PRIu64, sock0.fd, valid_tag1), 0);
335 EXPECT_TRUE(sock0.checkTag(valid_tag1, my_uid)) << "Tag not found";
338 TEST_F(SocketTaggingTest, ValidUntag) {
340 EXPECT_GE(doCtrlCommand("t %d %" PRIu64, sock0.fd, valid_tag1), 0);
341 EXPECT_TRUE(sock0.checkTag(valid_tag1, my_uid)) << "Tag not found";
342 EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
343 EXPECT_FALSE(sock0.checkTag(valid_tag1, my_uid)) << "Tag should be removed";
346 TEST_F(SocketTaggingTest, ValidFirsttag) {
348 EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag2, fake_uid), 0);
349 EXPECT_TRUE(sock0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
352 TEST_F(SocketTaggingTest, ValidReTag) {
354 EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag2, fake_uid), 0);
355 EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag2, fake_uid), 0);
356 EXPECT_TRUE(sock0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
359 TEST_F(SocketTaggingTest, ValidReTagWithAcctTagChange) {
360 // Valid re-tag with acct_tag change
361 EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag2, fake_uid), 0);
362 EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag1, fake_uid), 0);
363 EXPECT_TRUE(sock0.checkTag(valid_tag1, fake_uid)) << "Tag not found.";
366 TEST_F(SocketTaggingTest, ReTagWithUidChange) {
367 // Re-tag with uid change
368 EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag1, fake_uid), 0);
369 EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag2, fake_uid2), 0);
372 TEST_F(SocketTaggingTest, Valid64BitAcctTag) {
373 // Valid 64bit acct tag
374 EXPECT_GE(doCtrlCommand("t %d %" PRIu64, sock0.fd, max_uint_tag), 0);
375 EXPECT_TRUE(sock0.checkTag(max_uint_tag, my_uid)) << "Tag not found.";
378 TEST_F(SocketTaggingTest, TagAnotherSocket) {
379 testPrintI("Tag two sockets");
380 EXPECT_GE(doCtrlCommand("t %d %" PRIu64, sock0.fd, max_uint_tag), 0);
381 EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock1.fd, valid_tag1, fake_uid2), 0);
382 EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found.";
383 testPrintI("Untag socket0 of them only.");
384 EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
385 EXPECT_FALSE(sock0.checkTag(max_uint_tag, fake_uid)) << "Tag should not be there";
386 EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found";
387 testPrintI("Now untag socket1 as well.");
388 EXPECT_GE(doCtrlCommand("u %d", sock1.fd), 0);
389 EXPECT_FALSE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag should not be there";
392 TEST_F(SocketTaggingTest, TagInvalidSocketFail) {
393 // Invalid tag. Expected failure
395 EXPECT_LE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag1, my_uid), 0);
396 EXPECT_FALSE(sock0.checkTag(valid_tag1, my_uid)) << "Tag should not be there";
399 TEST_F(SocketTaggingTest, UntagInvalidSocketFail) {
400 // Invalid untag. Expected failure";
402 EXPECT_LE(doCtrlCommand("u %d", sock1.fd), 0);
405 } // namespace android