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
     */
}
Example #2
0
int testTagData(void) {
    SockInfo sock0;
    SockInfo sock1;
    int res;
    int total_errors = 0;
    int ctrl_fd = -1;
    int dev_fd = -1;
    const uint64_t invalid_tag1 = 0x0000000100000001llu;
    uint64_t valid_tag1;
    uint64_t valid_tag2;
    uint64_t max_uint_tag = 0xffffffff00000000llu;
    uid_t fake_uid;
    uid_t fake_uid2;
    const char *test_name;
    uid_t my_uid = getuid();
    pid_t my_pid = getpid();
    const int max_tags = 5;

    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.
    testSetLogCatTag(LOG_TAG);

    testPrintI("** %s ** ============================", __FUNCTION__);
    testPrintI("* start: pid=%lu uid=%lu uid1=0x%lx/%lu uid2=0x%lx/%lu"
               " tag1=0x%llx/%llu tag2=0x%llx/%llu",
               my_pid, my_uid, fake_uid, fake_uid, fake_uid2, fake_uid2,
               valid_tag1, valid_tag1, valid_tag2, valid_tag2);

    // ---------------
    test_name = "kernel has qtaguid";
    testPrintI("* test: %s ", test_name);
    ctrl_fd = openCtrl();
    if (ctrl_fd < 0) {
        testPrintE("qtaguid ctrl open failed: %s", strerror(errno));
        return 1;
    }
    close(ctrl_fd);
    dev_fd = open("/dev/xt_qtaguid", O_RDONLY);
    if (dev_fd < 0) {
        testPrintE("! %s: qtaguid dev open failed: %s", test_name, strerror(errno));
        total_errors++;
    }
    // ---------------
    test_name = "delete command doesn't fail";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("d 0 %u", fake_uid);
    if (res < 0) {
            testPrintE("! %s: Unexpected results", test_name);
            total_errors++;
    }

    res = doCtrlCommand("d 0 %u", fake_uid2);
    if (res < 0) {
            testPrintE("! %s: Unexpected results", test_name);
            total_errors++;
    }

    res = doCtrlCommand("d 0 %u", my_uid);
    if (res < 0) {
            testPrintE("! %s: Unexpected results", test_name);
            total_errors++;
    }

    // ---------------
    test_name = "setup sock0 and addr via tag";
    testPrintI("* test: %s", test_name);
    if (sock0.setup(valid_tag1)) {
        testPrintE("socket setup failed: %s", strerror(errno));
        return 1;
    }
    // ---------------
    test_name = "setup sock1 and addr via tag";
    testPrintI("* test: %s", test_name);
    if (sock1.setup(valid_tag1)) {
        testPrintE("socket setup failed: %s", strerror(errno));
        return 1;
    }
    // ---------------
    test_name = "setup tag limit";
    testPrintI("* test: %s ", test_name);
    char *max_tags_str;
    asprintf(&max_tags_str, "%d", max_tags);
    res = writeModuleParam("max_sock_tags", max_tags_str);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        free(max_tags_str);
        return 1;
    }

    // ---------------
    test_name = "tag quota reach limit";
    testPrintI("* test: %s", test_name);
    for (int cnt = 0; cnt < max_tags; cnt++ ) {
        uint64_t new_tag = valid_tag2 + ((uint64_t)cnt << 32);
        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
        if (res < 0) {
                testPrintE("! %s: Unexpected results", test_name);
                total_errors++;
        }
        if (!sock0.checkTag(new_tag, fake_uid2)) {
                testPrintE("! %s: Unexpected results: tag not found", test_name);
                total_errors++;
        }
    }
    test_name = "tag quota go over limit";
    testPrintI("* test: %s", test_name);
    {
        uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
        if (res > 0) {
                testPrintE("! %s: Unexpected results", test_name);
                total_errors++;
        }
        if (!sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2)) {
                testPrintE("! %s: Unexpected results: tag not found", test_name);
                total_errors++;
        }
    }

    // ---------------
    test_name = "valid untag";
    testPrintI("* test: %s", test_name);
    res = doCtrlCommand("u %d", sock0.fd);
    if (res < 0) {
        testPrintE("! %s: Unexpected results", test_name);
        total_errors++;
    }
    if (sock0.checkTag(valid_tag2 + (((uint64_t)max_tags - 1) << 32), fake_uid2)) {
        testPrintE("! %s: Unexpected results: tag should not be there", test_name);
        total_errors++;
    }

    // ---------------
    test_name = "tag after untag shouldn't free up max tags";
    testPrintI("* test: %s", test_name);
    {
        uint64_t new_tag = valid_tag2 + ((uint64_t)max_tags << 32);
        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
        if (res > 0) {
                testPrintE("! %s: Unexpected results", test_name);
                total_errors++;
        }
        if (sock0.checkTag(valid_tag2 + ((uint64_t)max_tags << 32), fake_uid2)) {
            testPrintE("! %s: Unexpected results: tag should not be there", test_name);
            total_errors++;
        }
    }

    // ---------------
    test_name = "delete one tag";
    testPrintI("* test: %s", test_name);
    {
            uint64_t new_tag = valid_tag2 + (((uint64_t)max_tags / 2) << 32);
            res = doCtrlCommand("d %llu %u", new_tag, fake_uid2);
            if (res < 0) {
                    testPrintE("! %s: Unexpected results", test_name);
                    total_errors++;
            }
    }

    // ---------------
    test_name = "2 tags after 1 delete pass/fail";
    testPrintI("* test: %s", test_name);
    {
        uint64_t new_tag;
        new_tag = valid_tag2 + (((uint64_t)max_tags + 1 ) << 32);
        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
        if (res < 0) {
                testPrintE("! %s: Unexpected results", test_name);
                total_errors++;
        }
        if (!sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 1) << 32), fake_uid2)) {
            testPrintE("! %s: Unexpected results: tag not found", test_name);
            total_errors++;
        }

        new_tag = valid_tag2 + (((uint64_t)max_tags + 2 ) << 32);
        res = doCtrlCommand("t %d %llu %u", sock0.fd, new_tag , fake_uid2);
        if (res > 0) {
                testPrintE("! %s: Unexpected results", test_name);
                total_errors++;
        }
        if (sock0.checkTag(valid_tag2 + (((uint64_t)max_tags + 2) << 32), fake_uid2)) {
            testPrintE("! %s: Unexpected results: tag should not be there", test_name);
            total_errors++;
        }
    }

    /* TODO(jpa): test tagging two different sockets with same tags and
     * check refcounts  the tag_node should be +2
     */

    // ---------------
    if (total_errors) {
        testPrintE("! Errors found");
    } else {
        testPrintI("No Errors found");
    }

done:
    if (dev_fd >= 0) {
        close(dev_fd);
    }
    if (ctrl_fd >= 0) {
        close(ctrl_fd);
    }
    return total_errors;
}