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