/* 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; }
int main(int argc, char *argv[]) { int res = 0; res += testTagData(); res += testSocketTagging(); if (res) { testPrintE("!! %d Errors found", res); } else { testPrintE("No Errors found"); } return res; }
/* * 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"); } }
int openCtrl() { int ctrl; ctrl = open("/proc/net/xt_qtaguid/ctrl", O_RDWR); if (!ctrl) { testPrintE("qtaguid ctrl open failed: %s", strerror(errno)); } return ctrl; }
int writeModuleParam(const char *param, const char *data) { int param_fd; int res; std::string filename("/sys/module/xt_qtaguid/parameters/"); filename += param; param_fd = open(filename.c_str(), O_WRONLY); if (param_fd < 0) { testPrintE("qtaguid param open failed: %s", strerror(errno)); return -1; } res = write(param_fd, data, strlen(data)); if (res < 0) { testPrintE("qtaguid param write failed: %s", strerror(errno)); } close(param_fd); return res; }
static void randBind(const cpu_set_t *availSet, int *chosenCPU) { int rv; cpu_set_t cpuset; int chosenAvail, avail, cpu, currentCPU; // Randomly bind to a CPU // Lower 16 bits from random number generator thrown away, // because the low-order bits tend to have the same sequence for // different seed values. chosenAvail = testRandMod(numAvailCPU); CPU_ZERO(&cpuset); avail = 0; for (cpu = 0; cpu < CPU_SETSIZE; cpu++) { if (CPU_ISSET(cpu, availSet)) { if (chosenAvail == avail) { CPU_SET(cpu, &cpuset); break; } avail++; } } assert(cpu < CPU_SETSIZE); sched_setaffinity(0, sizeof(cpuset), &cpuset); // Confirm executing on requested CPU if ((currentCPU = sched_getcpu()) < 0) { testPrintE("randBind sched_getcpu() failed, rv: %i errno: %i", currentCPU, errno); exit(80); } if (currentCPU != cpu) { testPrintE("randBind executing on unexpected CPU %i, expected %i", currentCPU, cpu); exit(81); } // Let the caller know which CPU was chosen *chosenCPU = cpu; }
/*----------------------------------------------------------------*/ int SockInfo::setup(uint64_t tag) { fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { testPrintE("socket creation failed: %s", strerror(errno)); return -1; } if (doCtrlCommand("t %d %" PRIu64, fd, tag) < 0) { testPrintE("socket setup: failed to tag"); close(fd); return -1; } if (!checkTag(tag, getuid())) { testPrintE("socket setup: Unexpected results: tag not found"); close(fd); return -1; } if (doCtrlCommand("u %d", fd) < 0) { testPrintE("socket setup: Unexpected results"); close(fd); return -1; } return 0; }
/* 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; }
/* * 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; }