From 0a329273b7a297d3ee8ae2fa8c3fed7fd66f6b2a Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Wed, 7 Aug 2013 15:18:06 +0200 Subject: [PATCH] Add libsmack tests for NOSMACK environment. [Issue#] SSDWSSP-417 [Feature] Add new libsmack tests that test libsmack behaviour on NOSMACK environment. [Cause] When previous tests were launched on NOSMACK environment they returned false errors because the system behaved differently with SMACK turned off. [Solution] Creating new tests that would expect different behaviour from libsmack. [Verification] After successful compilation launch libsmack tests on NOSMACK environment. Tests that previously failed and were turned off in one of my previous commits should appear with "_nosmack" ending in name. Change-Id: I8a8df3d92efb2a373aeef10c73c24e635d85229f --- tests/libsmack-tests/test_cases.cpp | 293 ++++++++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) diff --git a/tests/libsmack-tests/test_cases.cpp b/tests/libsmack-tests/test_cases.cpp index 326c417..2acd01e 100644 --- a/tests/libsmack-tests/test_cases.cpp +++ b/tests/libsmack-tests/test_cases.cpp @@ -46,6 +46,8 @@ std::vector accessesBasic = { "r", "w", "x", "wx", "rx", "rw", "rwx", "rwxat" }; +typedef std::unique_ptr > AccessesUniquePtr; + @@ -1457,3 +1459,294 @@ RUNNER_TEST_SMACK(smack09_new_label_from_socket) waitpid(pid, NULL, 0); } } + +///////////////////////////////////////// +//////NOSMACK ENVIRONMENT TESTS////////// +///////////////////////////////////////// + +/** + * NOSMACK version of smack02 test. Functions, that should return error instead of success: + * - smack_accesses_apply + * - smack_have_access + * - smack_revoke_subject + * - smack_acceesses_clear + * + * Tests smack03, smack04, smack10, smack_accesses_clear, smack_revoke_subject all use functions + * tested in smack02 test. Results from those functions (smack_have_access, smack_accesses_apply, + * smack_accesses_clear, smack_revoke_subject) would be the same as in this test. Tests mentioned + * above doesn't make much sense on NOSMACK environment when test smack02 exists and passes + * correctly, thus those tests are are not implemented. + */ +RUNNER_TEST_NOSMACK(smack02_aplying_rules_into_kernel_nosmack) +{ + + smack_accesses *tmp = NULL; + int result; + + //init rules + result = smack_accesses_new(&tmp); + RUNNER_ASSERT_MSG(result == 0, "Unable to create smack_accesses instance"); + + //pass rules to unique_ptr + AccessesUniquePtr rules(tmp, smack_accesses_free); + + //adding test rules to struct (same as SMACK version of smack02 test) + result = smack_accesses_add(rules.get(), "writer", "book", "rwx"); + RUNNER_ASSERT_MSG(result == 0, "Unable to add smack rules"); + result = smack_accesses_add(rules.get(), "reader", "book", "r"); + RUNNER_ASSERT_MSG(result == 0, "Unable to add smack rules"); + result = smack_accesses_add(rules.get(), "spy", "book", "rwx"); + RUNNER_ASSERT_MSG(result == 0, "Unable to add smack rules"); + + //applying rules to kernel (should fail) + result = smack_accesses_apply(rules.get()); + RUNNER_ASSERT_MSG(result == -1, "Unable to apply rules into kernel"); + + //calls from SMACK version of this test - all should fail because of SMACK being turned off + result = smack_have_access("spy", "book", "rwx"); + RUNNER_ASSERT_MSG(result == -1, "smack_have_access should return error (SMACK is off)"); + result = smack_have_access("reader", "book", "rwx"); + RUNNER_ASSERT_MSG(result == -1, "smack_have_access should return error (SMACK is off)"); + result = smack_have_access("mars", "book", "rwx"); + RUNNER_ASSERT_MSG(result == -1, "smack_have_access should return error (SMACK is off)"); + + //testing subject revoking - should return error (no accesses applied = no subjects to revoke) + result = smack_revoke_subject("snickers"); + RUNNER_ASSERT_MSG(result == -1, "smack_revoke_subject error - subject doesn't exist."); + result = smack_revoke_subject("spy"); + RUNNER_ASSERT_MSG(result == -1, "smack_revoke_subject error - subject doesn't exist."); + + //after revoking smack_have_access still should return error + result = smack_have_access("spy", "book", "rwx"); + RUNNER_ASSERT_MSG(result == -1, "smack_have_access should return error (SMACK is off)."); + + result = smack_accesses_add(rules.get(), "twix", "book", "rwx"); + RUNNER_ASSERT_MSG(result == 0, "Unable to add smack rules"); + + //smack_accesses_clear should return error aswell + result = smack_accesses_clear(rules.get()); + RUNNER_ASSERT_MSG(result == -1, "Clearing rules should return error - no SMACK on system."); + + result = smack_have_access("writer", "book", "rwx"); + RUNNER_ASSERT_MSG(result == -1, "smack_have_access should return error (SMACK is off)."); +} + +/** + * NOSMACK version of smack11 test. Tests functions: + * - smack_accesses_add_from_file + * + * Since other SMACK functions were tested in smack02 test, the only function needed to be checked + * is applying rules loaded from file. + */ +RUNNER_TEST_NOSMACK(smack03_saving_loading_rules_nosmack) +{ + int result; + int fd; + + smack_accesses* tmp = NULL; + + result = smack_accesses_new(&tmp); + RUNNER_ASSERT_MSG(result == 0, "Error during rules creation."); + + AccessesUniquePtr rules(tmp, smack_accesses_free); + + //open file with rules + fd = open("/etc/smack/test_smack_rules_full", O_RDONLY, 0644); + RUNNER_ASSERT_MSG(fd >= 0, + "Unable to open /etc/smack/test_smack_rules_full. Errno: " << strerror(errno)); + + //load accesses from file + result = smack_accesses_add_from_file(rules.get(), fd); + close(fd); + RUNNER_ASSERT_MSG(result == 0, "Error while importing accesses from file. Result: " << result); +} + +/** + * NOSMACK version of smack05 test. Tests if functions getting, or + * setting self label work correctly (that is, return error). + */ +RUNNER_TEST_NOSMACK(smack04_self_label_nosmack) +{ + char* label = NULL; + int result; + int fd; + + const int B_SIZE = 8; + char buff[B_SIZE]; + + //smack_new_label_from_self should fail + result = smack_new_label_from_self(&label); + RUNNER_ASSERT_MSG(result == -1, "new_label_from_self should return error (SMACK is off)."); + RUNNER_ASSERT_MSG(label == NULL, "new_label_from_self shouldn't allocate memory to label."); + + //We don't need to remember about freeing label - smack_new_label_from_self must return NULL + //label if it's working properly. + + // /proc/self/attr/current shouldn't keep any rules inside + fd = open("/proc/self/attr/current", O_RDONLY, 0644); //file exists, so it should open + RUNNER_ASSERT_MSG(fd >= 0, "/proc/self/attr/current failed to open."); + + result = read(fd, buff, B_SIZE); //however reading it should return error + if(result >= 0) { + close(fd); + RUNNER_ASSERT_MSG(false, "Reading /proc/self/attr/current should return error."); + } + + //setting label for self should fail + result = smack_set_label_for_self("fanta"); + if(result != -1) { + close(fd); + RUNNER_ASSERT_MSG(false, "set_label_for_self should return error (SMACK is off)."); + } + + //getting previously set label should also fail + result = smack_new_label_from_self(&label); + if(result != -1) { + close(fd); + RUNNER_ASSERT_MSG(false, "new_label_from_self should return error (SMACK is off)."); + } + if(label != NULL) { + close(fd); + RUNNER_ASSERT_MSG(false, "new_label_from_self shouldn't allocate memory to label."); + } + + // /proc/self/attr/current still shouldn't keep any rules inside + result = lseek(fd, 0, SEEK_SET); //going to the file beginning + if(result != 0) { + close(fd); + RUNNER_ASSERT_MSG(false, "lseek() error."); + } + + result = read(fd, buff, B_SIZE); //however it should return error + if(result >= 0) { + close(fd); + RUNNER_ASSERT_MSG(false, "Reading /proc/self/attr/current should return error."); + } + + close(fd); +} + +/** + * NOSMACK version of smack_accesses_add_modify_x tests. + * + * Because all smack_accesses_add_modify tests are basically the same (all use smack_accesses_apply + * and smack_have_access, which return -1 when SMACK is turned off), it makes much more sense to + * write one test which will create rules using smack_accesses_add_modify and then check if + * smack_accesses_apply and smack_have_access indeed return -1 when SMACK is turned off. + */ +RUNNER_TEST_NOSMACK(smack05_accesses_add_modify_nosmack) +{ + int result; + smack_accesses* tmp = NULL; + + result = smack_accesses_new(&tmp); + RUNNER_ASSERT_MSG(result == 0, "Unable to allocate memory for rules. Result: " << result); + + AccessesUniquePtr rules(tmp, smack_accesses_free); + + //Not doing clean_up() every RUNNER_ASSERT_MSG - what clean_up does is just a creation of new + //rule struct and removal of currenctly added and applied rules. clean_up() must be done only + //after smack_accesses_apply(). + result = smack_accesses_add_modify(rules.get(), TEST_SUBJECT, TEST_OBJECT, "rwx", ""); + RUNNER_ASSERT_MSG(result == 0, "Unable to modify rule. Result: " << result); + + result = smack_accesses_add_modify(rules.get(), TEST_SUBJECT, TEST_OBJECT, "rwx", ""); + RUNNER_ASSERT_MSG(result == 0, "Unable to modify rule. Result: " << result); + + result = smack_accesses_apply(rules.get()); + RUNNER_ASSERT_MSG(result == -1, + "smack_accesses_apply should return error (SMACK is off). Result: " << result); + + result = smack_have_access(TEST_SUBJECT, TEST_OBJECT, "rwx"); + if(result != -1) { + clean_up(); + RUNNER_ASSERT_MSG(false, + "smack_have_access should return error (SMACK is off). Result: " << result); + } + + clean_up(); +} + +/** + * NOSMACK version of smack09 test. + * + * This test checks if smack_new_label_from_socket reacts correctly. Since label should be + * acquired from getsockopt, and it should fail, we must only set up socket and call + * smack_new_label_from_socket. It should return error. + */ +RUNNER_TEST_NOSMACK(smack09_new_label_from_socket_nosmack) +{ + int pid; + struct sockaddr_un sockaddr = {AF_UNIX, SOCK_PATH}; + unlink(SOCK_PATH); + char* smack_label; + + pid = fork(); + RUNNER_ASSERT_MSG(pid >= 0, "Fork failed"); + if (!pid) { //child (server) + int sock, result; + int fd; + + //Create new socket + sock = socket(AF_UNIX, SOCK_STREAM, 0); + RUNNER_ASSERT_MSG(sock >= 0, "socket failed: " << strerror(errno)); + + //Bind it to sockaddr + result = bind(sock, (struct sockaddr*) &sockaddr, sizeof(struct sockaddr_un)); + if (result != 0) { + close(sock); + RUNNER_ASSERT_MSG(false, "bind failed: " << strerror(errno)); + } + + //Prepare for listening + result = listen(sock, 1); + if (result != 0) { + close(sock); + RUNNER_ASSERT_MSG(false, "listen failed: " << strerror(errno)); + } + + //Accept client + alarm(2); + fd = accept(sock, NULL, NULL); + alarm(0); + if (fd < 0) { + close(sock); + RUNNER_ASSERT_MSG(false, "Failed when accepting connection from client."); + } + + //wait for smack_new_label_from_socket execution + usleep(200); + + //Close socket and server + close(sock); + exit(0); + } + else { //parent (client) + //Wait a little bit until server is set up + sleep(1); + int sock, result; + + //Create socket + sock = socket(AF_UNIX, SOCK_STREAM, 0); + RUNNER_ASSERT_MSG(sock >= 0, "socket failed: " << strerror(errno)); + + //Connect to sockaddr + result = connect(sock, (struct sockaddr*) &sockaddr, + sizeof(struct sockaddr_un)); + if (result != 0) { + close(sock); + RUNNER_ASSERT_MSG(false, "connect failed: " << strerror(errno)); + } + + //Try getting label, should fail beacuse getsockopt won't get anything + result = smack_new_label_from_socket(sock, &smack_label); + if (result != -1) { + close(sock); + RUNNER_ASSERT_MSG(false, "smack_new_label_from_socket should fail."); + } + + //Close socket, wait for server shutdown + close(sock); + waitpid(pid, NULL, 0); + } +} -- 2.7.4