upload android base code part6
This commit is contained in:
parent
421e214c7d
commit
4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions
17
android/system/extras/tests/iptables/Android.mk
Normal file
17
android/system/extras/tests/iptables/Android.mk
Normal file
|
@ -0,0 +1,17 @@
|
|||
#
|
||||
# Copyright (C) 2011 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
include $(call all-subdir-makefiles)
|
28
android/system/extras/tests/iptables/qtaguid/Android.mk
Normal file
28
android/system/extras/tests/iptables/qtaguid/Android.mk
Normal file
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
# Copyright (C) 2011 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
LOCAL_MODULE := socketTag
|
||||
LOCAL_SRC_FILES := socketTag.cpp
|
||||
LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libbase
|
||||
LOCAL_STATIC_LIBRARIES += libtestUtil
|
||||
LOCAL_C_INCLUDES += system/extras/tests/include
|
||||
LOCAL_CFLAGS += -fno-strict-aliasing
|
||||
|
||||
include $(BUILD_NATIVE_TEST)
|
398
android/system/extras/tests/iptables/qtaguid/socketTag.cpp
Normal file
398
android/system/extras/tests/iptables/qtaguid/socketTag.cpp
Normal file
|
@ -0,0 +1,398 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless requied by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This socket tagging test is to ensure that the
|
||||
* netfilter/xt_qtaguid kernel module somewhat behaves as expected
|
||||
* with respect to tagging sockets.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "socketTagTest"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <testUtil.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class SockInfo {
|
||||
public:
|
||||
SockInfo() : fd(-1), addr(NULL) {};
|
||||
int setup(uint64_t tag);
|
||||
bool checkTag(uint64_t tag, uid_t uid);
|
||||
int fd;
|
||||
void *addr;
|
||||
};
|
||||
|
||||
|
||||
int openCtrl() {
|
||||
int ctrl;
|
||||
ctrl = open("/proc/net/xt_qtaguid/ctrl", O_RDWR);
|
||||
if (!ctrl) {
|
||||
testPrintE("qtaguid ctrl open failed: %s", strerror(errno));
|
||||
}
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
int doCtrlCommand(const char *fmt, ...)
|
||||
__attribute__((__format__(__printf__, 1, 2)));
|
||||
|
||||
int doCtrlCommand(const char *fmt, ...) {
|
||||
char *buff;
|
||||
int ctrl;
|
||||
int res;
|
||||
va_list argp;
|
||||
|
||||
va_start(argp, fmt);
|
||||
ctrl = openCtrl();
|
||||
vasprintf(&buff, fmt, argp);
|
||||
errno = 0;
|
||||
res = write(ctrl, buff, strlen(buff));
|
||||
testPrintI("cmd: '%s' res=%d %d/%s", buff, res, errno, strerror(errno));
|
||||
close(ctrl);
|
||||
free(buff);
|
||||
va_end(argp);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int writeModuleParam(const char *param, const char *data) {
|
||||
int param_fd;
|
||||
int res;
|
||||
std::string filename("/sys/module/xt_qtaguid/parameters/");
|
||||
|
||||
filename += param;
|
||||
param_fd = open(filename.c_str(), O_WRONLY);
|
||||
if (param_fd < 0) {
|
||||
testPrintE("qtaguid param open failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
res = write(param_fd, data, strlen(data));
|
||||
if (res < 0) {
|
||||
testPrintE("qtaguid param write failed: %s", strerror(errno));
|
||||
}
|
||||
close(param_fd);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
int SockInfo::setup(uint64_t tag) {
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (fd < 0) {
|
||||
testPrintE("socket creation failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (doCtrlCommand("t %d %" PRIu64, fd, tag) < 0) {
|
||||
testPrintE("socket setup: failed to tag");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
if (!checkTag(tag, getuid())) {
|
||||
testPrintE("socket setup: Unexpected results: tag not found");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
if (doCtrlCommand("u %d", fd) < 0) {
|
||||
testPrintE("socket setup: Unexpected results");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* checkTag() also tries to lookup the socket address in the kernel and
|
||||
* return it when *addr == NULL.
|
||||
* This allows for better look ups when another process is also setting the same
|
||||
* tag + uid. But it is not fool proof.
|
||||
* Without the kernel reporting more info on who setup the socket tag, it is
|
||||
* not easily verifiable from user-space.
|
||||
* Returns: true if tag found.
|
||||
*/
|
||||
bool SockInfo::checkTag(uint64_t acct_tag, uid_t uid) {
|
||||
int res;
|
||||
uint64_t k_tag;
|
||||
uint32_t k_uid;
|
||||
long dummy_count;
|
||||
pid_t dummy_pid;
|
||||
|
||||
std::ifstream fctrl("/proc/net/xt_qtaguid/ctrl", std::fstream::in);
|
||||
if(!fctrl.is_open()) {
|
||||
testPrintI("qtaguid ctrl open failed!");
|
||||
}
|
||||
|
||||
uint64_t full_tag = acct_tag | uid;
|
||||
std::string buff = android::base::StringPrintf(" tag=0x%" PRIx64 " (uid=%u)", full_tag, uid);
|
||||
if (addr) {
|
||||
buff = android::base::StringPrintf("sock=%" PRIxPTR, (uintptr_t)addr) + buff;
|
||||
}
|
||||
|
||||
testPrintI("looking for '%s'", buff.c_str());
|
||||
std::string ctrl_data;
|
||||
std::size_t pos = std::string::npos;
|
||||
while(std::getline(fctrl, ctrl_data)) {
|
||||
testPrintI("<ctrl_raw_data> : %s", ctrl_data.c_str());
|
||||
pos = ctrl_data.find(buff);
|
||||
if (pos != std::string::npos) {
|
||||
if(!addr) {
|
||||
testPrintI("matched data : %s", ctrl_data.c_str());
|
||||
assert(sizeof(void*) == sizeof(long int));
|
||||
res = sscanf(ctrl_data.c_str(),
|
||||
"sock=%" SCNxPTR " tag=0x%" SCNx64 " (uid=%" SCNu32 ") pid=%u f_count=%lu",
|
||||
(uintptr_t *)&addr, &k_tag, &k_uid, &dummy_pid, &dummy_count );
|
||||
if (!(res == 5 && k_tag == full_tag && k_uid == uid)) {
|
||||
testPrintE("Unable to read sock addr res=%d", res);
|
||||
addr = 0;
|
||||
} else {
|
||||
testPrintI("Got sock_addr %lx", addr);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pos != std::string::npos;
|
||||
}
|
||||
|
||||
|
||||
class SocketTaggingTest : public ::testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
ctrl_fd = -1;
|
||||
dev_fd = -1;
|
||||
my_uid = getuid();
|
||||
my_pid = getpid();
|
||||
srand48(my_pid * my_uid);
|
||||
// Adjust fake UIDs and tags so that multiple instances can run in parallel.
|
||||
fake_uid = testRand();
|
||||
fake_uid2 = testRand();
|
||||
valid_tag1 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
|
||||
valid_tag2 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
|
||||
valid_tag2 &= 0xffffff00ffffffffllu; // Leave some room to make counts visible.
|
||||
testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
|
||||
" tag1=0x%" PRIx64 "/%" PRIu64 " tag2=0x%" PRIx64 "/% " PRIu64,
|
||||
(unsigned long)my_pid, (unsigned long)my_uid,
|
||||
(unsigned long)fake_uid, (unsigned long)fake_uid,
|
||||
(unsigned long)fake_uid2, (unsigned long)fake_uid2,
|
||||
valid_tag1, valid_tag1, valid_tag2, valid_tag2);
|
||||
max_uint_tag = 0xffffffff00000000llu;
|
||||
max_uint_tag = 1llu << 63 | (((uint64_t)my_pid << 48) ^ max_uint_tag);
|
||||
|
||||
testPrintI("kernel has qtaguid");
|
||||
ctrl_fd = openCtrl();
|
||||
ASSERT_GE(ctrl_fd, 0) << "qtaguid ctrl open failed";
|
||||
close(ctrl_fd);
|
||||
dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
|
||||
EXPECT_GE(dev_fd, 0) << "qtaguid dev open failed";
|
||||
|
||||
// We want to clean up any previous faulty test runs.
|
||||
testPrintI("delete command does not fail");
|
||||
EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid), 0) << "Failed to delete fake_uid";
|
||||
EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid2), 0) << "Failed to delete fake_uid2";
|
||||
EXPECT_GE(doCtrlCommand("d 0 %u", my_uid), 0) << "Failed to delete my_uid";
|
||||
|
||||
testPrintI("setup sock0 and addr via tag");
|
||||
ASSERT_FALSE(sock0.setup(valid_tag1)) << "socket0 setup failed";
|
||||
testPrintI("setup sock1 and addr via tag");
|
||||
ASSERT_FALSE(sock1.setup(valid_tag1)) << "socket1 setup failed";
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
if (dev_fd >= 0) {
|
||||
close(dev_fd);
|
||||
}
|
||||
if (ctrl_fd >= 0) {
|
||||
close(ctrl_fd);
|
||||
}
|
||||
}
|
||||
|
||||
SockInfo sock0;
|
||||
SockInfo sock1;
|
||||
int ctrl_fd;
|
||||
int dev_fd;
|
||||
uid_t fake_uid;
|
||||
uid_t fake_uid2;
|
||||
uid_t my_uid;
|
||||
pid_t my_pid;
|
||||
uint64_t valid_tag1;
|
||||
uint64_t valid_tag2;
|
||||
uint64_t max_uint_tag;
|
||||
static const uint64_t invalid_tag1 = 0x0000000100000001llu;
|
||||
static const int max_tags = 5;
|
||||
};
|
||||
|
||||
TEST_F(SocketTaggingTest, TagData) {
|
||||
max_uint_tag = 0xffffffff00000000llu;
|
||||
char *max_tags_str;
|
||||
|
||||
testPrintI("setup tag limit");
|
||||
asprintf(&max_tags_str, "%d", max_tags);
|
||||
ASSERT_GE(writeModuleParam("max_sock_tags", max_tags_str), 0) << "Failed to setup tag limit";
|
||||
|
||||
testPrintI("tag quota reach limit");
|
||||
for (int cnt = 0; cnt < max_tags; cnt++ ) {
|
||||
uint64_t tag = valid_tag2 + ((uint64_t)cnt << 32);
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, tag , fake_uid2), 0)
|
||||
<< "Tagging within limit failed";
|
||||
EXPECT_TRUE(sock0.checkTag(tag, fake_uid2))<< "Unexpected results: tag not found";
|
||||
}
|
||||
|
||||
testPrintI("tag quota go over limit");
|
||||
uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
|
||||
EXPECT_LT(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag, fake_uid2), 0);
|
||||
EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32),
|
||||
fake_uid2)) << "Unexpected results: tag not found";
|
||||
|
||||
testPrintI("valid untag");
|
||||
EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
|
||||
EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2))
|
||||
<< "Untagged tag should not be there";
|
||||
|
||||
testPrintI("tag after untag should not free up max tags");
|
||||
uint64_t new_tag2 = valid_tag2 + ((uint64_t)max_tags << 32);
|
||||
EXPECT_LT(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag2 , fake_uid2), 0);
|
||||
EXPECT_FALSE(sock0.checkTag(valid_tag2 + ((uint64_t)max_tags << 32), fake_uid2))
|
||||
<< "Tag should not be there";
|
||||
|
||||
testPrintI("delete one tag");
|
||||
uint64_t new_tag3 = valid_tag2 + (((uint64_t)max_tags / 2) << 32);
|
||||
EXPECT_GE(doCtrlCommand("d %" PRIu64 " %u", new_tag3, fake_uid2), 0);
|
||||
|
||||
testPrintI("2 tags after 1 delete pass/fail");
|
||||
uint64_t new_tag4;
|
||||
new_tag4 = valid_tag2 + (((uint64_t)max_tags + 1 ) << 32);
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag4 , fake_uid2), 0);
|
||||
EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 1) << 32), fake_uid2))
|
||||
<< "Tag not found";
|
||||
new_tag4 = valid_tag2 + (((uint64_t)max_tags + 2 ) << 32);
|
||||
EXPECT_LT(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag4 , fake_uid2), 0);
|
||||
EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 2) << 32), fake_uid2))
|
||||
<< "Tag should not be there";
|
||||
|
||||
/* TODO(jpa): test tagging two different sockets with same tags and
|
||||
* check refcounts the tag_node should be +2
|
||||
*/
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, InsufficientArgsFails) {
|
||||
// Insufficient args. Expected failure
|
||||
EXPECT_LE(doCtrlCommand("t"), 0) << "Insufficient args, should fail.";
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, BadCommandFails) {
|
||||
// Bad command. Expected failure";
|
||||
EXPECT_LE(doCtrlCommand("?"), 0) << "Bad command, should fail";
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, NoTagNoUid) {
|
||||
// no tag, no uid
|
||||
EXPECT_GE(doCtrlCommand("t %d", sock0.fd), 0);
|
||||
ASSERT_TRUE(sock0.checkTag(0, my_uid)) << "Tag not found";
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, InvalidTagFail) {
|
||||
// Invalid tag. Expected failure
|
||||
EXPECT_LE(doCtrlCommand("t %d %" PRIu64, sock0.fd, invalid_tag1), 0);
|
||||
ASSERT_FALSE(sock0.checkTag(invalid_tag1, my_uid)) << "Tag should not be there";
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, ValidTagWithNoUid) {
|
||||
// Valid tag with no uid
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64, sock0.fd, valid_tag1), 0);
|
||||
EXPECT_TRUE(sock0.checkTag(valid_tag1, my_uid)) << "Tag not found";
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, ValidUntag) {
|
||||
// Valid untag
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64, sock0.fd, valid_tag1), 0);
|
||||
EXPECT_TRUE(sock0.checkTag(valid_tag1, my_uid)) << "Tag not found";
|
||||
EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
|
||||
EXPECT_FALSE(sock0.checkTag(valid_tag1, my_uid)) << "Tag should be removed";
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, ValidFirsttag) {
|
||||
// Valid 1st tag
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag2, fake_uid), 0);
|
||||
EXPECT_TRUE(sock0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, ValidReTag) {
|
||||
// Valid re-tag
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag2, fake_uid), 0);
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag2, fake_uid), 0);
|
||||
EXPECT_TRUE(sock0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, ValidReTagWithAcctTagChange) {
|
||||
// Valid re-tag with acct_tag change
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag2, fake_uid), 0);
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag1, fake_uid), 0);
|
||||
EXPECT_TRUE(sock0.checkTag(valid_tag1, fake_uid)) << "Tag not found.";
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, ReTagWithUidChange) {
|
||||
// Re-tag with uid change
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag1, fake_uid), 0);
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag2, fake_uid2), 0);
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, Valid64BitAcctTag) {
|
||||
// Valid 64bit acct tag
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64, sock0.fd, max_uint_tag), 0);
|
||||
EXPECT_TRUE(sock0.checkTag(max_uint_tag, my_uid)) << "Tag not found.";
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, TagAnotherSocket) {
|
||||
testPrintI("Tag two sockets");
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64, sock0.fd, max_uint_tag), 0);
|
||||
EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock1.fd, valid_tag1, fake_uid2), 0);
|
||||
EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found.";
|
||||
testPrintI("Untag socket0 of them only.");
|
||||
EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
|
||||
EXPECT_FALSE(sock0.checkTag(max_uint_tag, fake_uid)) << "Tag should not be there";
|
||||
EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found";
|
||||
testPrintI("Now untag socket1 as well.");
|
||||
EXPECT_GE(doCtrlCommand("u %d", sock1.fd), 0);
|
||||
EXPECT_FALSE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag should not be there";
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, TagInvalidSocketFail) {
|
||||
// Invalid tag. Expected failure
|
||||
close(sock0.fd);
|
||||
EXPECT_LE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag1, my_uid), 0);
|
||||
EXPECT_FALSE(sock0.checkTag(valid_tag1, my_uid)) << "Tag should not be there";
|
||||
}
|
||||
|
||||
TEST_F(SocketTaggingTest, UntagInvalidSocketFail) {
|
||||
// Invalid untag. Expected failure";
|
||||
close(sock1.fd);
|
||||
EXPECT_LE(doCtrlCommand("u %d", sock1.fd), 0);
|
||||
}
|
||||
|
||||
} // namespace android
|
Loading…
Add table
Add a link
Reference in a new issue