/* 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 ctrl_fd; ctrl_fd = openCtrl(); char ctrl_data[1024]; ssize_t read_size; char *buff; char *pos; int res; char *match_template; uint64_t k_tag; uint32_t k_uid; uint64_t full_tag; long dummy_count; pid_t dummy_pid; read_size = read(ctrl_fd, ctrl_data, sizeof(ctrl_data)); if (read_size < 0) { testPrintE("Unable to read active tags from ctrl %d/%s", errno, strerror(errno)); } ctrl_data[read_size] = '\0'; testPrintI("<ctrl_raw_data>\n%s</ctrl_raw_data>", ctrl_data); if (addr) { assert(sizeof(void*) == sizeof(long int)); // Why does %p use 0x? grrr. %lx. asprintf(&match_template, "sock=%" PRIxPTR " %s", (uintptr_t)addr, "tag=0x%" PRIx64" (uid=%u)"); } else { /* Allocate for symmetry */ asprintf(&match_template, "%s", " tag=0x%" PRIx64 " (uid=%u)"); } full_tag = acct_tag | uid; asprintf(&buff, match_template, full_tag | uid, uid); testPrintI("looking for '%s'", buff); pos = strstr(ctrl_data, buff); if (pos && !addr) { assert(sizeof(void*) == sizeof(long int)); // Why does %p use 0x? grrr. %lx. res = sscanf(pos - strlen("sock=1234abcd"), "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); } } free(buff); free(match_template); close(ctrl_fd); return pos != NULL; }
/* * Initialize * * Perform testcase initialization, which includes: * * 1. Determine which CPUs are available for use * * 2. Determine total number of available CPUs * * 3. Stop framework * * 4. Determine whether WiFi driver is loaded and if so * stop wpa_supplicant and unload WiFi driver. */ void init(void) { int rv; unsigned int n1; char cmd[MAXCMD]; // Use whichever CPUs are available at start of test rv = sched_getaffinity(0, sizeof(availCPU), &availCPU); if (rv != 0) { testPrintE("init sched_getaffinity failed, rv: %i errno: %i", rv, errno); exit(40); } // How many CPUs are available numAvailCPU = 0; for (n1 = 0; n1 < CPU_SETSIZE; n1++) { if (CPU_ISSET(n1, &availCPU)) { numAvailCPU++; } } testPrintI("numAvailCPU: %u", numAvailCPU); // Stop framework rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK); if (rv >= (signed) sizeof(cmd) - 1) { testPrintE("Command too long for: %s\n", CMD_STOP_FRAMEWORK); exit(41); } testExecCmd(cmd); // Is WiFi driver loaded? // If so stop the wpa_supplicant and unload the driver. driverLoadedAtStart = is_wifi_driver_loaded(); testPrintI("driverLoadedAtStart: %u", driverLoadedAtStart); if (driverLoadedAtStart) { // Stop wpa_supplicant // Might already be stopped, in which case request should // return immediately with success. if ((rv = wifi_stop_supplicant(false)) != 0) { testPrintE("init stop supplicant failed, rv: %i", rv); exit(42); } testPrintI("Stopped wpa_supplicant"); if ((rv = wifi_unload_driver()) != 0) { testPrintE("init unload driver failed, rv: %i", rv); exit(43); } testPrintI("WiFi driver unloaded"); } }
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(pcmtest, CheckTimer) { int ver = 0; int fd = open("/dev/snd/timer", O_RDWR | O_NONBLOCK); ASSERT_GE(fd, 0); int ret = ioctl(fd, SNDRV_TIMER_IOCTL_PVERSION, &ver); EXPECT_EQ(0, ret); testPrintI(" Timer Version = 0x%x", ver); close(fd); }
/* 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; }
int getSndDev(unsigned int pcmdevs) { DIR *d; struct dirent *de; unsigned int prevcard = -1; d = opendir(kSoundDir); if (d == 0) return -ENXIO; pcmnodes = (pcm_node_t *)malloc(pcmdevs * sizeof(pcm_node_t)); if (!pcmnodes) return -ENOMEM; pcms = 0; while ((de = readdir(d)) != NULL) { if (de->d_name[0] == '.') continue; /* printf("%s\n", de->d_name); */ if (strstr(de->d_name, PCM_PREFIX)) { char flags; EXPECT_LE(pcms, pcmdevs) << "Too many PCMs"; if (pcms >= pcmdevs) continue; sscanf(de->d_name, PCM_PREFIX "C%uD%u", &(pcmnodes[pcms].card), &(pcmnodes[pcms].device)); flags = de->d_name[strlen(de->d_name)-1]; if (flags == 'c') { pcmnodes[pcms].flags = PCM_IN; } else if(flags == 'p') { pcmnodes[pcms].flags = PCM_OUT; } else { pcmnodes[pcms].flags = -1; testPrintI("Unknown PCM type = %c", flags); } if (prevcard != pcmnodes[pcms].card) cards++; prevcard = pcmnodes[pcms].card; pcms++; continue; } if (strstr(de->d_name, MIXER_PREFIX)) { unsigned int mixer = -1; sscanf(de->d_name, MIXER_PREFIX "C%u", &mixer); mixers++; continue; } if (strstr(de->d_name, TIMER_PREFIX)) { timers++; continue; } } closedir(d); return 0; }
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"; }
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 */ }
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; }
/* * Random Delay * * Delays for a random amount of time within the range given * by the file scope variables delayMin and delayMax. The * selected amount of delay can come from any part of the * range, with a bias towards values closer to delayMin. * The amount of bias is determined by the setting of DELAY_EXP. * The setting of DELAY_EXP should always be > 1.0, with higher * values causing a more significant bias toward the value * of delayMin. */ void randDelay(void) { const unsigned long nanosecspersec = 1000000000; float fract, biasedFract, amt; struct timeval startTime, endTime; // Obtain start time gettimeofday(&startTime, NULL); // Determine random amount to sleep. // Values closer to delayMin are prefered by an amount // determined by the value of DELAY_EXP. fract = testRandFract(); biasedFract = pow(DELAY_EXP, fract) / pow(DELAY_EXP, 1.0); amt = delayMin + ((delayMax - delayMin) * biasedFract); // Delay testDelay(amt); // Obtain end time and display delta gettimeofday(&endTime, NULL); testPrintI("delay: %.2f", (float) (tv2double(&endTime) - tv2double(&startTime))); }
/* * Main * * Performs the following high-level sequence of operations: * * 1. Command-line parsing * * 2. Initialization * * 3. Execute passes that repeatedly perform the WiFi load, scan, * associate, unload sequence. * * 4. Restore state of WiFi driver to state it was at the * start of the test. * * 5. Restart framework */ int main(int argc, char *argv[]) { FILE *fp; int rv, opt; int cpu; char *chptr; unsigned int pass; char cmd[MAXCMD]; float duration = DEFAULT_DURATION; unsigned int startPass = DEFAULT_START_PASS, endPass = DEFAULT_END_PASS; struct timeval startTime, currentTime, delta; testSetLogCatTag(LOG_TAG); // Parse command line arguments while ((opt = getopt(argc, argv, "d:D:s:e:p:t:?")) != -1) { switch (opt) { case 'd': // Minimum Delay delayMin = strtod(optarg, &chptr); if ((*chptr != '\0') || (delayMin < 0.0)) { testPrintE("Invalid command-line specified minimum delay " "of: %s", optarg); exit(1); } break; case 'D': // Maximum Delay delayMax = strtod(optarg, &chptr); if ((*chptr != '\0') || (delayMax < 0.0)) { testPrintE("Invalid command-line specified maximum delay " "of: %s", optarg); exit(2); } break; case 't': // Duration duration = strtod(optarg, &chptr); if ((*chptr != '\0') || (duration < 0.0)) { testPrintE("Invalid command-line specified duration of: %s", optarg); exit(3); } break; case 's': // Starting Pass if (sFlag || pFlag) { testPrintE("Invalid combination of command-line options,"); if (sFlag) { testPrintE(" -s flag specified multiple times."); } else { testPrintE(" -s and -p flags are mutually exclusive."); } exit(10); } sFlag = true; startPass = strtoul(optarg, &chptr, 10); if (*chptr != '\0') { testPrintE("Invalid command-line specified starting pass " "of: %s", optarg); exit(4); } break; case 'e': // Ending Pass if (eFlag || pFlag) { testPrintE("Invalid combination of command-line options,"); if (sFlag) { testPrintE(" -e flag specified multiple times."); } else { testPrintE(" -e and -p flags are mutually exclusive."); } exit(11); } eFlag = true; endPass = strtoul(optarg, &chptr, 10); if (*chptr != '\0') { testPrintE("Invalid command-line specified ending pass " "of: %s", optarg); exit(5); } break; case 'p': // Single Specific Pass if (pFlag || sFlag || eFlag) { testPrintE("Invalid combination of command-line options,"); if (pFlag) { testPrintE(" -p flag specified multiple times."); } else { testPrintE(" -p and -%c flags are mutually exclusive.", (sFlag) ? 's' : 'e'); } exit(12); } pFlag = true; endPass = startPass = strtoul(optarg, &chptr, 10); if (*chptr != '\0') { testPrintE("Invalid command-line specified pass " "of: %s", optarg); exit(13); } break; case '?': default: testPrintE(" %s [options]", basename(argv[0])); testPrintE(" options:"); testPrintE(" -s Starting pass"); testPrintE(" -e Ending pass"); testPrintE(" -p Specific single pass"); testPrintE(" -t Duration"); testPrintE(" -d Delay min"); testPrintE(" -D Delay max"); exit(((optopt == 0) || (optopt == '?')) ? 0 : 6); } } if (delayMax < delayMin) { testPrintE("Unexpected maximum delay less than minimum delay"); testPrintE(" delayMin: %f delayMax: %f", delayMin, delayMax); exit(7); } if (endPass < startPass) { testPrintE("Unexpected ending pass before starting pass"); testPrintE(" startPass: %u endPass: %u", startPass, endPass); exit(8); } if (argc != optind) { testPrintE("Unexpected command-line postional argument"); testPrintE(" %s [-s start_pass] [-e end_pass] [-d duration]", basename(argv[0])); exit(9); } testPrintI("duration: %g", duration); testPrintI("startPass: %u", startPass); testPrintI("endPass: %u", endPass); testPrintI("delayMin: %f", delayMin); testPrintI("delayMax: %f", delayMax); init(); // For each pass gettimeofday(&startTime, NULL); for (pass = startPass; pass <= endPass; pass++) { // Stop if duration of work has already been performed gettimeofday(¤tTime, NULL); delta = tvDelta(&startTime, ¤tTime); if (tv2double(&delta) > duration) { break; } testPrintI("==== Starting pass: %u", pass); // Use a pass dependent sequence of random numbers srand48(pass); // Load WiFi Driver randBind(&availCPU, &cpu); if ((rv = wifi_load_driver()) != 0) { testPrintE("CPU: %i wifi_load_driver() failed, rv: %i\n", cpu, rv); exit(20); } testPrintI("CPU: %i wifi_load_driver succeeded", cpu); // Start Supplicant randBind(&availCPU, &cpu); if ((rv = wifi_start_supplicant(false)) != 0) { testPrintE("CPU: %i wifi_start_supplicant() failed, rv: %i\n", cpu, rv); exit(21); } testPrintI("CPU: %i wifi_start_supplicant succeeded", cpu); // Sleep a random amount of time randDelay(); /* * Obtain WiFi Status * Half the time skip this step, which helps increase the * level of randomization. */ if (testRandBool()) { rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STATUS); if (rv >= (signed) sizeof(cmd) - 1) { testPrintE("Command too long for: %s\n", CMD_STATUS); exit(22); } testExecCmd(cmd); } // Stop Supplicant randBind(&availCPU, &cpu); if ((rv = wifi_stop_supplicant(false)) != 0) { testPrintE("CPU: %i wifi_stop_supplicant() failed, rv: %i\n", cpu, rv); exit(23); } testPrintI("CPU: %i wifi_stop_supplicant succeeded", cpu); // Unload WiFi Module randBind(&availCPU, &cpu); if ((rv = wifi_unload_driver()) != 0) { testPrintE("CPU: %i wifi_unload_driver() failed, rv: %i\n", cpu, rv); exit(24); } testPrintI("CPU: %i wifi_unload_driver succeeded", cpu); testPrintI("==== Completed pass: %u", pass); } // If needed restore WiFi driver to state it was in at the // start of the test. It is assumed that it the driver // was loaded, then the wpa_supplicant was also running. if (driverLoadedAtStart) { // Load driver if ((rv = wifi_load_driver()) != 0) { testPrintE("main load driver failed, rv: %i", rv); exit(25); } // Start supplicant if ((rv = wifi_start_supplicant(false)) != 0) { testPrintE("main start supplicant failed, rv: %i", rv); exit(26); } // Obtain WiFi Status rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STATUS); if (rv >= (signed) sizeof(cmd) - 1) { testPrintE("Command too long for: %s\n", CMD_STATUS); exit(22); } testExecCmd(cmd); } // Start framework rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK); if (rv >= (signed) sizeof(cmd) - 1) { testPrintE("Command too long for: %s\n", CMD_START_FRAMEWORK); exit(27); } testExecCmd(cmd); testPrintI("Successfully completed %u passes", pass - startPass); return 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; }
/*----------------------------------------------------------------*/ int testSocketTagging(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(); 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); max_uint_tag = 1llu << 63 | (((uint64_t)my_pid << 48) ^ max_uint_tag); 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)); total_errors++; goto done; } close(ctrl_fd); dev_fd = open("/dev/xt_qtaguid", O_RDONLY); if (dev_fd < 0) { testPrintE("qtaguid dev open failed: %s", 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) < 0) { testPrintE("socket setup failed: %s", strerror(errno)); total_errors++; goto done; } // --------------- test_name = "setup sock1 and addr via tag"; testPrintI("* test: %s", test_name); if (sock1.setup(valid_tag1) < 0) { testPrintE("socket setup failed: %s", strerror(errno)); total_errors++; goto done; } // --------------- test_name = "insufficient args. Expected failure"; testPrintI("* test: %s", test_name); res = doCtrlCommand("t"); if (res > 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } // --------------- test_name = "bad command. Expected failure"; testPrintI("* test: %s", test_name); res = doCtrlCommand("?"); if (res > 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } // --------------- test_name = "no tag, no uid"; testPrintI("* test: %s", test_name); res = doCtrlCommand("t %d", sock0.fd); if (res < 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } if (!sock0.checkTag(0, my_uid)) { testPrintE("! %s: Unexpected results: tag not found", test_name); total_errors++; } // --------------- test_name = "invalid tag. Expected failure"; testPrintI("* test: %s", test_name); res = doCtrlCommand("t %d %llu", sock0.fd, invalid_tag1); if (res > 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } if (sock0.checkTag(invalid_tag1, my_uid)) { testPrintE("! %s: Unexpected results: tag should not be there", test_name); total_errors++; } // --------------- test_name = "valid tag with no uid"; testPrintI("* test: %s", test_name); res = doCtrlCommand("t %d %llu", sock0.fd, valid_tag1); if (res < 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } if (!sock0.checkTag(valid_tag1, my_uid)) { 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_tag1, my_uid)) { testPrintE("! %s: Unexpected results: tag not removed", test_name); total_errors++; } // --------------- test_name = "valid 1st tag"; testPrintI("* test: %s", test_name); res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid); if (res < 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } if (!sock0.checkTag(valid_tag2, fake_uid)) { testPrintE("! %s: Unexpected results: tag not found", test_name); total_errors++; } // --------------- test_name = "valid re-tag"; testPrintI("* test: %s", test_name); res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid); if (res < 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } if (!sock0.checkTag(valid_tag2, fake_uid)) { testPrintE("! %s: Unexpected results: tag not found", test_name); total_errors++; } // --------------- test_name = "valid re-tag with acct_tag change"; testPrintI("* test: %s", test_name); res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, fake_uid); if (res < 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } if (!sock0.checkTag(valid_tag1, fake_uid)) { testPrintE("! %s: Unexpected results: tag not found", test_name); total_errors++; } // --------------- test_name = "re-tag with uid change"; testPrintI("* test: %s", test_name); res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag2, fake_uid2); if (res < 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } if (!sock0.checkTag(valid_tag2, fake_uid2)) { testPrintE("! %s: Unexpected results: tag not found", test_name); total_errors++; } // --------------- test_name = "valid 64bit acct tag"; testPrintI("* test: %s", test_name); res = doCtrlCommand("t %d %llu", sock0.fd, max_uint_tag); if (res < 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } if (!sock0.checkTag(max_uint_tag, my_uid)) { testPrintE("! %s: Unexpected results: tag not found", test_name); total_errors++; } // --------------- test_name = "tag another socket"; testPrintI("* test: %s", test_name); res = doCtrlCommand("t %d %llu %u", sock1.fd, valid_tag1, fake_uid2); if (res < 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } if (!sock1.checkTag(valid_tag1, 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(max_uint_tag, fake_uid)) { testPrintE("! %s: Unexpected results: tag should not be there", test_name); total_errors++; } if (!sock1.checkTag(valid_tag1, fake_uid2)) { testPrintE("! %s: Unexpected results: tag not found", test_name); total_errors++; } res = doCtrlCommand("u %d", sock1.fd); if (res < 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } if (sock1.checkTag(valid_tag1, fake_uid2)) { testPrintE("! %s: Unexpected results: tag should not be there", test_name); total_errors++; } // --------------- test_name = "invalid sock0.fd. Expected failure"; testPrintI("* test: %s", test_name); close(sock0.fd); res = doCtrlCommand("t %d %llu %u", sock0.fd, valid_tag1, my_uid); if (res > 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } if (sock0.checkTag(valid_tag1, my_uid)) { testPrintE("! %s: Unexpected results: tag should not be there", test_name); total_errors++; } // --------------- test_name = "invalid untag. Expected failure"; testPrintI("* test: %s", test_name); close(sock1.fd); res = doCtrlCommand("u %d", sock1.fd); if (res > 0) { testPrintE("! %s: Unexpected results", test_name); total_errors++; } 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; }
TEST(pcmtest, GetSoundDevs) { int err = getSndDev(pcms); testPrintI(" DEVICES = PCMS:%u CARDS:%u MIXERS:%u TIMERS:%u", pcms, cards, mixers, timers); ASSERT_EQ(0, err); }