#include <string>
#include <sstream>
#include <fcntl.h>
+#include <unistd.h>
#include <dpl/test/test_runner.h>
+#include <dpl/test/test_runner_multiprocess.h>
#include <dpl/log/log.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/xattr.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <sys/wait.h>
+#include "tests_common.h"
#define TEST_SUBJECT "test_subject"
#define TEST_OBJECT "test_oject"
std::vector<std::string> accessesBasic = { "r", "w", "x", "wx", "rx", "rw", "rwx", "rwxat" };
-
-
-
int files_compare(int fd1, int fd2)
{
int result = 0;
return true;
}
-int removeAccessesAll()
+void removeAccessesAll()
{
struct smack_accesses *rules = NULL;
int result = smack_accesses_new(&rules);
/**
* Add a new access with smack_accesses_add_modify()
*/
-RUNNER_TEST(smack_accesses_add_modify_test_1){
+RUNNER_TEST_SMACK(smack_accesses_add_modify_test_1){
int result;
clean_up();
/**
* Test if rules are applied in the right order, and modification works.
*/
-RUNNER_TEST(smack_accesses_add_modify_test_2){
+RUNNER_TEST_SMACK(smack_accesses_add_modify_test_2){
int result;
struct smack_accesses *rules = NULL;
result = smack_accesses_new(&rules);
* Test if rules are applied in the right order, and modification works.
* Using different smack_accesses list to add and delete.
*/
-RUNNER_TEST(smack_accesses_add_modify_test_3){
+RUNNER_TEST_SMACK(smack_accesses_add_modify_test_3){
int result;
struct smack_accesses *rules = NULL;
result = smack_accesses_new(&rules);
/**
* Add a list of privileges and then revoke just ONE of them.
*/
-RUNNER_TEST(smack_accesses_add_modify_test_4){
+RUNNER_TEST_SMACK(smack_accesses_add_modify_test_4){
int result;
struct smack_accesses *rules = NULL;
result = smack_accesses_new(&rules);
* Add a list of privileges and then revoke just ONE of them.
* Without applying privileges in between those actions.
*/
-RUNNER_TEST(smack_accesses_add_modify_test_5){
+RUNNER_TEST_SMACK(smack_accesses_add_modify_test_5){
int result;
struct smack_accesses *rules = NULL;
result = smack_accesses_new(&rules);
/**
* Add a list of privileges and then revoke just TWO of them.
*/
-RUNNER_TEST(smack_accesses_add_modify_test_6){
+RUNNER_TEST_SMACK(smack_accesses_add_modify_test_6){
int result;
struct smack_accesses *rules = NULL;
result = smack_accesses_new(&rules);
/**
* Run smack_accesses_add_modify with the same accesses_add and accesses_del.
*/
-RUNNER_TEST(smack_accesses_add_modify_test_7){
+RUNNER_TEST_SMACK(smack_accesses_add_modify_test_7){
unsigned int i;
int result;
/**
* Revoke subject with previously added rules and revoke it again.
*/
-RUNNER_TEST(smack_revoke_subject_test_1){
+RUNNER_TEST_SMACK(smack_revoke_subject_test_1){
unsigned int i;
int result;
/**
* Clearing accesses
*/
-RUNNER_TEST(smack_accesses_clear_test_1){
+RUNNER_TEST_SMACK(smack_accesses_clear_test_1){
unsigned int i;
int result;
close(sample);
}
-RUNNER_TEST(smack02_aplying_rules_into_kernel)
+RUNNER_TEST_SMACK(smack02_aplying_rules_into_kernel)
{
/*
* author: Pawel Polawski
RUNNER_ASSERT_MSG(result == 1, "Error while checking Smack access");
result = smack_have_access("reader", "book", "rwx"); //should have no access - wrong rule, should be "r" only
RUNNER_ASSERT_MSG(result == 0, "Error while checking Smack access");
- result = smack_have_access("mars", "book", "rwx"); //should have no acces - rule not exist
- RUNNER_ASSERT_MSG(result == 0, "Error while checking Smack access");
+ result = smack_have_access("mars", "book", "rwx"); //should fail - rule not exist
+ RUNNER_ASSERT_MSG(result == -1, "Error while checking Smack access");
//int smack_revoke_subject(const char *subject);
result = smack_revoke_subject("snickers"); //this subject do not exist in kernel rules
result = smack_have_access("spy", "book", "rwx"); //testing access after revoke_subject() from kernel
RUNNER_ASSERT_MSG(result == 0, "Error in acces aplied to kernel"); //now spy should have no access
- result = smack_have_access("spy", "book", "-----"); //and should have "-----" rule
- RUNNER_ASSERT_MSG(result == 1, "Error in acces aplied to kernel");
result = smack_accesses_add(rules, "twix", "book", "rwx"); //for create new rule as a consequence of use accesses_clear() below
RUNNER_ASSERT_MSG(result == 0, "Unable to add smack rules");
result = smack_have_access("writer", "book", "rwx"); //testing acces after acces_clear()
RUNNER_ASSERT_MSG(result == 0, "Error in acces aplied to kernel"); //now writer also should have no access
- result = smack_have_access("writer", "book", "-----"); //and should have "-----" rule
- RUNNER_ASSERT_MSG(result == 1, "Error in acces aplied to kernel");
- result = smack_have_access("twix", "book", "-----"); //rule created by calling accesses_clear()
- RUNNER_ASSERT_MSG(result == 1, "Error in acces aplied to kernel");
//free resources
smack_accesses_free(rules);
}
//pairs of rules for test with mixed cases, different length and mixed order
-char *rules_tab[] = {
+const char *rules_tab[] = {
"reader1", "-", "-----",
"reader2", "--------", "-----",
"reader3", "RwXaT", "rwxat",
"reader8", "#Ax[T].!~W@1}", "-wxat"
};
-RUNNER_TEST(smack03_mixed_rule_string_add)
+RUNNER_TEST_SMACK(smack03_mixed_rule_string_add)
{
/*
* author: Pawel Polawski
struct smack_accesses *rules = NULL; //rules prepared in this test case
int result; //for storing functions results
int i;
+ int expected;
result = smack_accesses_new(&rules); //rules struct init
RUNNER_ASSERT_MSG(result == 0, "Unable to create smack_accesses instance");
//checking accesses using normal rules
for (i = 0; i < (3 * 8); i += 3) {
+ if (!strcmp(rules_tab[i + 2], "-----"))
+ expected = 0;
+ else
+ expected = 1;
result = smack_have_access(rules_tab[i], "book", rules_tab[i + 2]); //using normal rules from table
- RUNNER_ASSERT_MSG(result == 1, "Error while checking Smack access");
+ RUNNER_ASSERT_MSG(result == expected, "Error while checking Smack access");
}
//free resources
smack_accesses_free(rules);
}
-RUNNER_TEST(smack04_mixed_rule_string_have_access)
+RUNNER_TEST_SMACK(smack04_mixed_rule_string_have_access)
{
/*
* author: Pawel Polawski
int result;
int i;
+ int expected;
//rules were added in previous RUNNER_TEST section
//checking accesses using mixed rules
for (i = 0; i < (3 * 8); i += 3) {
+ if (!strcmp(rules_tab[i + 2], "-----"))
+ expected = 0;
+ else
+ expected = 1;
result = smack_have_access(rules_tab[i], "book", rules_tab[i + 1]); //using mixed rules from table
- RUNNER_ASSERT_MSG(result == 1, "Error while checking Smack access");
+ RUNNER_ASSERT_MSG(result == expected, "Error while checking Smack access");
}
}
// - smack_accesses_add_modify("subject", "object", "rwx", "rwx") should create empty rule
//}
-RUNNER_TEST(smack05_self_label)
+RUNNER_TEST_SMACK(smack05_self_label)
{
/*
* author: Pawel Polawski
const int B_SIZE = 8;
char buff[B_SIZE];
- char *def_rule = "_";
+ const char *def_rule = "_";
//int smack_new_label_from_self(char **label);
result = smack_new_label_from_self(&label);
- RUNNER_ASSERT_MSG(result == 0, "Error in getting self label");
+ RUNNER_ASSERT_MSG(result >= 0, "Error in getting self label");
//comparing this label with default one "_"
result = strcmp(label, def_rule);
//checking new label using smack function
result = smack_new_label_from_self(&label);
- RUNNER_ASSERT_MSG(result == 0, "Error in getting self label");
+ RUNNER_ASSERT_MSG(result >= 0, "Error in getting self label");
result = strcmp(label, "cola");
RUNNER_ASSERT_MSG(result == 0, "Wrong process label");
//}
//bellow function is from libsmack.c witch changed name
-char *xattr(enum smack_label_type type)
+const char *xattr(enum smack_label_type type)
{
switch (type) {
case SMACK_LABEL_ACCESS:
const int B_SIZE = 8;
char buff[B_SIZE];
- char *file_path = "/etc/smack/test_smack_rules";
+ const char *file_path = "/etc/smack/test_smack_rules";
//preparing environment by restoring default "_" label
const int B_SIZE = 8;
char buff[B_SIZE];
- char *file_path = "/etc/smack/test_smack_rules_lnk";
+ const char *file_path = "/etc/smack/test_smack_rules_lnk";
//preparing environment by restoring default "_" label
char buff[B_SIZE];
int fd;
- char *file_path = "/etc/smack/test_smack_rules";
+ const char *file_path = "/etc/smack/test_smack_rules";
fd = open(file_path, O_RDWR, 0644); //reference preinstalled rules
RUNNER_ASSERT_MSG(fd >= 0, "Unable to open /etc/smack/test_smack_rules");
close(fd);
}
-RUNNER_TEST(smack10_adding_removing_rules)
+RUNNER_TEST_SMACK(smack10_adding_removing_rules)
{
unsigned int i;
int result;
}
}
-RUNNER_TEST(smack11_saving_loading_rules)
+RUNNER_TEST_SMACK(smack11_saving_loading_rules)
{
int result;
int fd;
char *smack_label;
number++;
- result = asprintf(&smack_label, "s%ld", number);
+ result = asprintf(&smack_label, "s%d", number);
RUNNER_ASSERT_MSG(result > 0, "asprintf failed");
result = smack_set_label_for_self(smack_label);
RUNNER_ASSERT_MSG(result == 0, "smack_set_label_for_self(" << smack_label << ") failed");
if (fd < 0)
return;
result = smack_new_label_from_self(&smack_label);
- RUNNER_ASSERT_MSG(result == 0, "smack_new_label_from_self() failed");
+ RUNNER_ASSERT_MSG(result >= 0, "smack_new_label_from_self() failed");
result = write(fd, smack_label, strlen(smack_label));
- RUNNER_ASSERT_MSG(result == strlen(smack_label), "write() failed");
+ RUNNER_ASSERT_MSG(result == (int)strlen(smack_label), "write() failed");
close(fd);
free(smack_label);
}
-RUNNER_TEST(smack09_new_label_from_socket)
+RUNNER_MULTIPROCESS_TEST_SMACK(smack09_new_label_from_socket)
{
int pid;
struct sockaddr_un sockaddr = {AF_UNIX, SOCK_PATH};
smack_unix_sock_server(sock);
}
close(sock);
- if (pid)
- waitpid(pid, NULL, 0);
+
exit(0);
} else { /* parent process, client */
sleep(1); /* Give server some time to setup listening socket */
alarm(0);
smack_label1[result] = '\0';
result = smack_new_label_from_socket(sock, &smack_label2);
- RUNNER_ASSERT_MSG(result == 0, "smack_label_from_socket failed");
+ RUNNER_ASSERT_MSG(result >= 0, "smack_label_from_socket failed");
result = strcmp(smack_label1, smack_label2);
if (i < 3)
RUNNER_ASSERT_MSG(result == 0, "smack labels differ: '" << smack_label1 << "' != '" << smack_label2 << "' i == " << i);
RUNNER_ASSERT_MSG(result != 0, "smack labels do not differ: '" << smack_label1 << "' != '" << smack_label2 << "' i == " << i);
close(sock);
}
- 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_MULTIPROCESS_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);
+ close(sock);
+ RUNNER_ASSERT_MSG(result == -1, "smack_new_label_from_socket should fail.");
}
}