From bc0e94a4a32dd6a7f342c8d8c44caae84da30443 Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Thu, 11 May 2017 11:27:25 -0700 Subject: [PATCH] Native test for qtaguid module Add a native test to check the qtaguid module nolonger hold the fd of a closed socket. The test does not work in java because android framework will force untag the socket before closing it. Bug: 36374484 Test: run this test as CTS test and all devices should pass Signed-off-by: Chenbo Feng Change-Id: I9e015d412d1aec10d843dfee4b480169d1f6ff8e --- tests/cts/net/native/Android.mk | 15 ++++ tests/cts/net/native/qtaguid/Android.mk | 43 ++++++++++ tests/cts/net/native/qtaguid/AndroidTest.xml | 27 ++++++ .../native/qtaguid/src/NativeSocketRefCnt.cpp | 84 +++++++++++++++++++ 4 files changed, 169 insertions(+) create mode 100644 tests/cts/net/native/Android.mk create mode 100644 tests/cts/net/native/qtaguid/Android.mk create mode 100644 tests/cts/net/native/qtaguid/AndroidTest.xml create mode 100644 tests/cts/net/native/qtaguid/src/NativeSocketRefCnt.cpp diff --git a/tests/cts/net/native/Android.mk b/tests/cts/net/native/Android.mk new file mode 100644 index 0000000000..b798d87878 --- /dev/null +++ b/tests/cts/net/native/Android.mk @@ -0,0 +1,15 @@ +# Copyright (C) 2017 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) diff --git a/tests/cts/net/native/qtaguid/Android.mk b/tests/cts/net/native/qtaguid/Android.mk new file mode 100644 index 0000000000..fed852045d --- /dev/null +++ b/tests/cts/net/native/qtaguid/Android.mk @@ -0,0 +1,43 @@ +# Copyright (C) 2017 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. + +# Build the unit tests. + +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := CtsNativeNetTestCases +LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativetest +LOCAL_MULTILIB := both +LOCAL_MODULE_STEM_32 := $(LOCAL_MODULE)32 +LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64 + +LOCAL_SRC_FILES := \ + src/NativeSocketRefCnt.cpp + +LOCAL_SHARED_LIBRARIES := \ + libutils \ + liblog \ + libcutils \ + +LOCAL_STATIC_LIBRARIES := \ + libgtest + +LOCAL_CTS_TEST_PACKAGE := android.net.native +# Tag this module as a cts test artifact +LOCAL_COMPATIBILITY_SUITE := cts + +LOCAL_CFLAGS := -Werror -Wall + +include $(BUILD_CTS_EXECUTABLE) diff --git a/tests/cts/net/native/qtaguid/AndroidTest.xml b/tests/cts/net/native/qtaguid/AndroidTest.xml new file mode 100644 index 0000000000..6f4e8f5452 --- /dev/null +++ b/tests/cts/net/native/qtaguid/AndroidTest.xml @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/tests/cts/net/native/qtaguid/src/NativeSocketRefCnt.cpp b/tests/cts/net/native/qtaguid/src/NativeSocketRefCnt.cpp new file mode 100644 index 0000000000..926a740f1b --- /dev/null +++ b/tests/cts/net/native/qtaguid/src/NativeSocketRefCnt.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2017 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 +#include +#include +#include +#include + +#include +#include + +int getCtrlRefCnt(int tag, uid_t uid) { + FILE *fp; + fp = fopen("/proc/net/xt_qtaguid/ctrl", "r"); + if (!fp) + return -ENOENT; + uint64_t full_tag = (uint64_t)tag << 32 | uid; + char pattern[40]; + snprintf(pattern, sizeof(pattern), " tag=0x%" PRIx64 " (uid=%" PRIu32 ")", full_tag, uid); + + size_t len; + char *line_buffer = NULL; + while(getline(&line_buffer, &len, fp) != -1) { + if (strstr(line_buffer, pattern) == NULL) + continue; + int res; + uint32_t ref_cnt; + pid_t dummy_pid; + uint64_t dummy_sk; + uint64_t k_tag; + uint32_t k_uid; + const int TOTAL_PARAM = 5; + res = sscanf(line_buffer, "sock=%" PRIx64 " tag=0x%" PRIx64 " (uid=%" PRIu32 ") " + "pid=%u f_count=%u", &dummy_sk, &k_tag, &k_uid, + &dummy_pid, &ref_cnt); + if (!(res == TOTAL_PARAM && k_tag == full_tag && k_uid == uid)) + res = -EINVAL; + res = ref_cnt; + free(line_buffer); + return res; + } + free(line_buffer); + return -ENOENT; +} + +TEST (NativeSocketRefCnt, close_socket_without_untag) { + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + uid_t uid = getuid(); + int tag = arc4random(); + EXPECT_EQ(0, qtaguid_tagSocket(sockfd, tag, uid)); + EXPECT_GE(2, getCtrlRefCnt(tag, uid)); + close(sockfd); + EXPECT_EQ(-ENOENT, getCtrlRefCnt(tag, uid)); +} + +TEST (NativeSocketRefCnt, close_socket_without_untag_ipv6) { + int sockfd = socket(AF_INET6, SOCK_STREAM, 0); + uid_t uid = getuid(); + int tag = arc4random(); + EXPECT_EQ(0, qtaguid_tagSocket(sockfd, tag, uid)); + EXPECT_GE(2, getCtrlRefCnt(tag, uid)); + close(sockfd); + EXPECT_EQ(-ENOENT, getCtrlRefCnt(tag, uid)); +} + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +}