1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17 
18 /*
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.
22  */
23 
24 #define LOG_TAG "socketTagTest"
25 
26 #include <assert.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <inttypes.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string>
33 #include <sys/socket.h>
34 #include <sys/types.h>
35 
36 #include <fstream>
37 
38 #include <android-base/stringprintf.h>
39 #include <gtest/gtest.h>
40 #include <utils/Log.h>
41 
42 #include <testUtil.h>
43 
44 namespace android {
45 
46 class SockInfo {
47 public:
SockInfo()48     SockInfo() : fd(-1), addr(NULL) {};
49     int setup(uint64_t tag);
50     bool checkTag(uint64_t tag, uid_t uid);
51     int fd;
52     void *addr;
53 };
54 
55 
openCtrl()56 int openCtrl() {
57     int ctrl;
58     ctrl = open("/proc/net/xt_qtaguid/ctrl", O_RDWR);
59     if (!ctrl) {
60        testPrintE("qtaguid ctrl open failed: %s", strerror(errno));
61     }
62     return ctrl;
63 }
64 
65 int doCtrlCommand(const char *fmt, ...)
66     __attribute__((__format__(__printf__, 1, 2)));
67 
doCtrlCommand(const char * fmt,...)68 int doCtrlCommand(const char *fmt, ...) {
69     char *buff;
70     int ctrl;
71     int res;
72     va_list argp;
73 
74     va_start(argp, fmt);
75     ctrl = openCtrl();
76     vasprintf(&buff, fmt, argp);
77     errno = 0;
78     res = write(ctrl, buff, strlen(buff));
79     testPrintI("cmd: '%s' res=%d %d/%s", buff, res, errno, strerror(errno));
80     close(ctrl);
81     free(buff);
82     va_end(argp);
83     return res;
84 }
85 
86 
writeModuleParam(const char * param,const char * data)87 int writeModuleParam(const char *param, const char *data) {
88     int param_fd;
89     int res;
90     std::string filename("/sys/module/xt_qtaguid/parameters/");
91 
92     filename += param;
93     param_fd = open(filename.c_str(), O_WRONLY);
94     if (param_fd < 0) {
95         testPrintE("qtaguid param open failed: %s", strerror(errno));
96         return -1;
97     }
98     res = write(param_fd, data, strlen(data));
99     if (res < 0) {
100         testPrintE("qtaguid param write failed: %s", strerror(errno));
101     }
102     close(param_fd);
103     return res;
104 }
105 
106 /*----------------------------------------------------------------*/
setup(uint64_t tag)107 int SockInfo::setup(uint64_t tag) {
108     fd = socket(AF_INET, SOCK_STREAM, 0);
109     if (fd < 0) {
110         testPrintE("socket creation failed: %s", strerror(errno));
111         return -1;
112     }
113     if (doCtrlCommand("t %d %" PRIu64, fd, tag) < 0) {
114         testPrintE("socket setup: failed to tag");
115         close(fd);
116         return -1;
117     }
118     if (!checkTag(tag, getuid())) {
119         testPrintE("socket setup: Unexpected results: tag not found");
120         close(fd);
121         return -1;
122     }
123     if (doCtrlCommand("u %d", fd) < 0) {
124         testPrintE("socket setup: Unexpected results");
125         close(fd);
126         return -1;
127     }
128     return 0;
129 }
130 
131 /* checkTag() also tries to lookup the socket address in the kernel and
132  * return it when *addr  == NULL.
133  * This allows for better look ups when another process is also setting the same
134  * tag + uid. But it is not fool proof.
135  * Without the kernel reporting more info on who setup the socket tag, it is
136  * not easily verifiable from user-space.
137  * Returns: true if tag found.
138  */
checkTag(uint64_t acct_tag,uid_t uid)139 bool SockInfo::checkTag(uint64_t acct_tag, uid_t uid) {
140     int res;
141     uint64_t k_tag;
142     uint32_t k_uid;
143     long dummy_count;
144     pid_t dummy_pid;
145 
146     std::ifstream fctrl("/proc/net/xt_qtaguid/ctrl", std::fstream::in);
147     if(!fctrl.is_open()) {
148         testPrintI("qtaguid ctrl open failed!");
149     }
150 
151     uint64_t full_tag = acct_tag | uid;
152     std::string buff = android::base::StringPrintf(" tag=0x%" PRIx64 " (uid=%u)", full_tag, uid);
153     if (addr) {
154           buff = android::base::StringPrintf("sock=%" PRIxPTR, (uintptr_t)addr) + buff;
155     }
156 
157     testPrintI("looking for '%s'", buff.c_str());
158     std::string ctrl_data;
159     std::size_t pos = std::string::npos;
160     while(std::getline(fctrl, ctrl_data)) {
161         testPrintI("<ctrl_raw_data> : %s", ctrl_data.c_str());
162         pos = ctrl_data.find(buff);
163         if (pos != std::string::npos) {
164             if(!addr) {
165                 testPrintI("matched data : %s", ctrl_data.c_str());
166                 assert(sizeof(void*) == sizeof(long int));
167                 res = sscanf(ctrl_data.c_str(),
168                             "sock=%" SCNxPTR " tag=0x%" SCNx64 " (uid=%" SCNu32 ") pid=%u f_count=%lu",
169                             (uintptr_t *)&addr, &k_tag, &k_uid, &dummy_pid, &dummy_count );
170                 if (!(res == 5 && k_tag == full_tag && k_uid == uid)) {
171                     testPrintE("Unable to read sock addr res=%d", res);
172                     addr = 0;
173                 } else {
174                     testPrintI("Got sock_addr %lx", addr);
175                 }
176             }
177             break;
178         }
179     }
180     return pos != std::string::npos;
181 }
182 
183 
184 class SocketTaggingTest : public ::testing::Test {
185 protected:
SetUp()186     virtual void SetUp() {
187         ctrl_fd = -1;
188         dev_fd = -1;
189         my_uid = getuid();
190         my_pid = getpid();
191         srand48(my_pid * my_uid);
192         // Adjust fake UIDs and tags so that multiple instances can run in parallel.
193         fake_uid = testRand();
194         fake_uid2 = testRand();
195         valid_tag1 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
196         valid_tag2 = ((uint64_t)my_pid << 48) | ((uint64_t)testRand() << 32);
197         valid_tag2 &= 0xffffff00ffffffffllu;  // Leave some room to make counts visible.
198         testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
199                    " tag1=0x%" PRIx64 "/%" PRIu64 " tag2=0x%" PRIx64 "/% " PRIu64,
200                    (unsigned long)my_pid, (unsigned long)my_uid,
201                    (unsigned long)fake_uid, (unsigned long)fake_uid,
202                    (unsigned long)fake_uid2, (unsigned long)fake_uid2,
203                    valid_tag1, valid_tag1, valid_tag2, valid_tag2);
204         max_uint_tag = 0xffffffff00000000llu;
205         max_uint_tag = 1llu << 63 | (((uint64_t)my_pid << 48) ^ max_uint_tag);
206 
207         testPrintI("kernel has qtaguid");
208         ctrl_fd = openCtrl();
209         ASSERT_GE(ctrl_fd, 0) << "qtaguid ctrl open failed";
210         close(ctrl_fd);
211         dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
212         EXPECT_GE(dev_fd, 0) << "qtaguid dev open failed";
213 
214         // We want to clean up any previous faulty test runs.
215         testPrintI("delete command does not fail");
216         EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid), 0) << "Failed to delete fake_uid";
217         EXPECT_GE(doCtrlCommand("d 0 %u", fake_uid2), 0) << "Failed to delete fake_uid2";
218         EXPECT_GE(doCtrlCommand("d 0 %u", my_uid), 0) << "Failed to delete my_uid";
219 
220         testPrintI("setup sock0 and addr via tag");
221         ASSERT_FALSE(sock0.setup(valid_tag1))  << "socket0 setup failed";
222         testPrintI("setup sock1 and addr via tag");
223         ASSERT_FALSE(sock1.setup(valid_tag1))  << "socket1 setup failed";
224     }
225 
TearDown()226    virtual void TearDown() {
227        if (dev_fd >= 0) {
228            close(dev_fd);
229        }
230        if (ctrl_fd >= 0) {
231            close(ctrl_fd);
232        }
233    }
234 
235    SockInfo sock0;
236    SockInfo sock1;
237    int ctrl_fd;
238    int dev_fd;
239    uid_t fake_uid;
240    uid_t fake_uid2;
241    uid_t my_uid;
242    pid_t my_pid;
243    uint64_t valid_tag1;
244    uint64_t valid_tag2;
245    uint64_t max_uint_tag;
246    static const uint64_t invalid_tag1 = 0x0000000100000001llu;
247    static const int max_tags = 5;
248 };
249 
TEST_F(SocketTaggingTest,TagData)250 TEST_F(SocketTaggingTest, TagData) {
251     max_uint_tag = 0xffffffff00000000llu;
252     char *max_tags_str;
253 
254     testPrintI("setup tag limit");
255     asprintf(&max_tags_str, "%d", max_tags);
256     ASSERT_GE(writeModuleParam("max_sock_tags", max_tags_str), 0) << "Failed to setup tag limit";
257 
258     testPrintI("tag quota reach limit");
259     for (int cnt = 0; cnt < max_tags; cnt++ ) {
260         uint64_t tag = valid_tag2 + ((uint64_t)cnt << 32);
261         EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, tag , fake_uid2), 0)
262             << "Tagging within limit failed";
263         EXPECT_TRUE(sock0.checkTag(tag, fake_uid2))<<  "Unexpected results: tag not found";
264     }
265 
266     testPrintI("tag quota go over limit");
267     uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
268     EXPECT_LT(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag, fake_uid2), 0);
269     EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32),
270                                fake_uid2)) << "Unexpected results: tag not found";
271 
272     testPrintI("valid untag");
273     EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
274     EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2))
275         << "Untagged tag should not be there";
276 
277     testPrintI("tag after untag should not free up max tags");
278     uint64_t new_tag2 = valid_tag2 + ((uint64_t)max_tags << 32);
279     EXPECT_LT(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag2 , fake_uid2), 0);
280     EXPECT_FALSE(sock0.checkTag(valid_tag2 + ((uint64_t)max_tags << 32), fake_uid2))
281         << "Tag should not be there";
282 
283     testPrintI("delete one tag");
284     uint64_t new_tag3 = valid_tag2 + (((uint64_t)max_tags / 2) << 32);
285     EXPECT_GE(doCtrlCommand("d %" PRIu64 " %u", new_tag3, fake_uid2), 0);
286 
287     testPrintI("2 tags after 1 delete pass/fail");
288     uint64_t new_tag4;
289     new_tag4 = valid_tag2 + (((uint64_t)max_tags + 1 ) << 32);
290     EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag4 , fake_uid2), 0);
291     EXPECT_TRUE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 1) << 32), fake_uid2))
292         << "Tag not found";
293     new_tag4 = valid_tag2 + (((uint64_t)max_tags + 2 ) << 32);
294     EXPECT_LT(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, new_tag4 , fake_uid2), 0);
295     EXPECT_FALSE(sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 2) << 32), fake_uid2))
296         << "Tag should not be there";
297 
298     /* TODO(jpa): test tagging two different sockets with same tags and
299      * check refcounts  the tag_node should be +2
300      */
301 }
302 
TEST_F(SocketTaggingTest,InsufficientArgsFails)303 TEST_F(SocketTaggingTest, InsufficientArgsFails) {
304     // Insufficient args. Expected failure
305     EXPECT_LE(doCtrlCommand("t"), 0) << "Insufficient args, should fail.";
306 }
307 
TEST_F(SocketTaggingTest,BadCommandFails)308 TEST_F(SocketTaggingTest, BadCommandFails) {
309     // Bad command. Expected failure";
310     EXPECT_LE(doCtrlCommand("?"), 0) << "Bad command, should fail";
311 }
312 
TEST_F(SocketTaggingTest,NoTagNoUid)313 TEST_F(SocketTaggingTest, NoTagNoUid) {
314     // no tag, no uid
315     EXPECT_GE(doCtrlCommand("t %d", sock0.fd), 0);
316     ASSERT_TRUE(sock0.checkTag(0, my_uid))  << "Tag not found";
317 }
318 
TEST_F(SocketTaggingTest,InvalidTagFail)319 TEST_F(SocketTaggingTest, InvalidTagFail) {
320     // Invalid tag. Expected failure
321     EXPECT_LE(doCtrlCommand("t %d %" PRIu64, sock0.fd, invalid_tag1), 0);
322     ASSERT_FALSE(sock0.checkTag(invalid_tag1, my_uid)) << "Tag should not be there";
323 }
324 
TEST_F(SocketTaggingTest,ValidTagWithNoUid)325 TEST_F(SocketTaggingTest, ValidTagWithNoUid) {
326     // Valid tag with no uid
327     EXPECT_GE(doCtrlCommand("t %d %" PRIu64, sock0.fd, valid_tag1), 0);
328     EXPECT_TRUE(sock0.checkTag(valid_tag1, my_uid)) << "Tag not found";
329 }
330 
TEST_F(SocketTaggingTest,ValidUntag)331 TEST_F(SocketTaggingTest, ValidUntag) {
332     // Valid untag
333     EXPECT_GE(doCtrlCommand("t %d %" PRIu64, sock0.fd, valid_tag1), 0);
334     EXPECT_TRUE(sock0.checkTag(valid_tag1, my_uid)) << "Tag not found";
335     EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
336     EXPECT_FALSE(sock0.checkTag(valid_tag1, my_uid)) << "Tag should be removed";
337 }
338 
TEST_F(SocketTaggingTest,ValidFirsttag)339 TEST_F(SocketTaggingTest, ValidFirsttag) {
340     // Valid 1st tag
341     EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag2, fake_uid), 0);
342     EXPECT_TRUE(sock0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
343 }
344 
TEST_F(SocketTaggingTest,ValidReTag)345 TEST_F(SocketTaggingTest, ValidReTag) {
346     // Valid re-tag
347     EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag2, fake_uid), 0);
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.";
350 }
351 
TEST_F(SocketTaggingTest,ValidReTagWithAcctTagChange)352 TEST_F(SocketTaggingTest, ValidReTagWithAcctTagChange) {
353     // Valid re-tag with acct_tag change
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_tag1, fake_uid), 0);
356     EXPECT_TRUE(sock0.checkTag(valid_tag1, fake_uid)) << "Tag not found.";
357 }
358 
TEST_F(SocketTaggingTest,ReTagWithUidChange)359 TEST_F(SocketTaggingTest, ReTagWithUidChange) {
360     // Re-tag with uid change
361     EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag1, fake_uid), 0);
362     EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag2, fake_uid2), 0);
363 }
364 
TEST_F(SocketTaggingTest,Valid64BitAcctTag)365 TEST_F(SocketTaggingTest, Valid64BitAcctTag) {
366     // Valid 64bit acct tag
367     EXPECT_GE(doCtrlCommand("t %d %" PRIu64, sock0.fd, max_uint_tag), 0);
368     EXPECT_TRUE(sock0.checkTag(max_uint_tag, my_uid)) << "Tag not found.";
369 }
370 
TEST_F(SocketTaggingTest,TagAnotherSocket)371 TEST_F(SocketTaggingTest, TagAnotherSocket) {
372     testPrintI("Tag two sockets");
373     EXPECT_GE(doCtrlCommand("t %d %" PRIu64, sock0.fd, max_uint_tag), 0);
374     EXPECT_GE(doCtrlCommand("t %d %" PRIu64 " %u", sock1.fd, valid_tag1, fake_uid2), 0);
375     EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found.";
376     testPrintI("Untag socket0 of them only.");
377     EXPECT_GE(doCtrlCommand("u %d", sock0.fd), 0);
378     EXPECT_FALSE(sock0.checkTag(max_uint_tag, fake_uid)) << "Tag should not be there";
379     EXPECT_TRUE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag not found";
380     testPrintI("Now untag socket1 as well.");
381     EXPECT_GE(doCtrlCommand("u %d", sock1.fd), 0);
382     EXPECT_FALSE(sock1.checkTag(valid_tag1, fake_uid2)) << "Tag should not be there";
383 }
384 
TEST_F(SocketTaggingTest,TagInvalidSocketFail)385 TEST_F(SocketTaggingTest, TagInvalidSocketFail) {
386     // Invalid tag. Expected failure
387     close(sock0.fd);
388     EXPECT_LE(doCtrlCommand("t %d %" PRIu64 " %u", sock0.fd, valid_tag1, my_uid), 0);
389     EXPECT_FALSE(sock0.checkTag(valid_tag1, my_uid)) << "Tag should not be there";
390 }
391 
TEST_F(SocketTaggingTest,UntagInvalidSocketFail)392 TEST_F(SocketTaggingTest, UntagInvalidSocketFail) {
393     // Invalid untag. Expected failure";
394     close(sock1.fd);
395     EXPECT_LE(doCtrlCommand("u %d", sock1.fd), 0);
396 }
397 
398 }  // namespace android
399