Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disjoint Attributes Rule #359

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Prev Previous commit
Next Next commit
libsepol/tests: add test for disjoint attributes
Test assertions are correctly computed and linking and expanding of
modules works correctly.

Signed-off-by: Christian Göttsche <[email protected]>
---
v4:
   rename to disjoint attributes
  • Loading branch information
cgzones committed Apr 29, 2024
commit fbf66c0232466c666e89fae0af87fcaddb844a95
2 changes: 2 additions & 0 deletions libsepol/tests/libsepol-tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "test-deps.h"
#include "test-downgrade.h"
#include "test-neverallow.h"
#include "test-disjointattributes.h"

#include <CUnit/Basic.h>
#include <CUnit/Console.h>
Expand Down Expand Up @@ -73,6 +74,7 @@ static bool do_tests(int interactive, int verbose)
DECLARE_SUITE(deps);
DECLARE_SUITE(downgrade);
DECLARE_SUITE(neverallow);
DECLARE_SUITE(disjointattrs);

if (verbose)
CU_basic_set_mode(CU_BRM_VERBOSE);
Expand Down
87 changes: 87 additions & 0 deletions libsepol/tests/policies/test-disjointattrs/single.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
class process
class blk_file
class chr_file
class dir
class fifo_file
class file
class lnk_file
class sock_file

sid kernel
sid security
sid unlabeled
sid file
sid port
sid netif
sid netmsg
sid node
sid devnull

class process { dyntransition transition }
class file { write }

ifdef(`enable_mls',`
sensitivity s0;
dominance { s0 }
category c0; category c1; category c2; category c3;
category c4; category c5; category c6; category c7;
category c8; category c9; category c10; category c11;
category c12; category c13; category c14; category c15;
category c16; category c17; category c18; category c19;
category c20; category c21; category c22; category c23;

level s0:c0.c23;

mlsconstrain file { write } ( h1 dom h2 );
')

#
# Test start
#

attribute test1_attr1;
attribute test1_attr2;
type test1_type;
typeattribute test1_type test1_attr1;
typeattribute test1_type test1_attr2;
disjoint_attributes test1_attr1, test1_attr2;


attribute test2_attr1;
attribute test2_attr2;
attribute test2_attr3;
type test2_type1;
type test2_type2;
type test2_type3;
type test2_type4;
typeattribute test2_type1 test2_attr1;
typeattribute test2_type1 test2_attr2;
typeattribute test2_type2 test2_attr1;
typeattribute test2_type2 test2_attr3;
typeattribute test2_type3 test2_attr2;
typeattribute test2_type3 test2_attr3;
typeattribute test2_type4 test2_attr1;
typeattribute test2_type4 test2_attr2;
typeattribute test2_type4 test2_attr3;
disjoint_attributes test2_attr1, test2_attr2, test2_attr3;

#
# Test End
#

type sys_isid;
allow sys_isid self : process { dyntransition transition };
role sys_role;
role sys_role types sys_isid;
gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23)
sid kernel gen_context(sys_user:sys_role:sys_isid, s0)
sid security gen_context(sys_user:sys_role:sys_isid, s0)
sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0)
sid file gen_context(sys_user:sys_role:sys_isid, s0)
sid port gen_context(sys_user:sys_role:sys_isid, s0)
sid netif gen_context(sys_user:sys_role:sys_isid, s0)
sid netmsg gen_context(sys_user:sys_role:sys_isid, s0)
sid node gen_context(sys_user:sys_role:sys_isid, s0)
sid devnull gen_context(sys_user:sys_role:sys_isid, s0)
fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0);
fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0);
53 changes: 53 additions & 0 deletions libsepol/tests/policies/test-disjointattrs/split_base.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
class process
class blk_file
class chr_file
class dir
class fifo_file
class file
class lnk_file
class sock_file

sid kernel
sid security
sid unlabeled
sid file
sid port
sid netif
sid netmsg
sid node
sid devnull

class process { dyntransition transition }
class file { write }

ifdef(`enable_mls',`
sensitivity s0;
dominance { s0 }
category c0; category c1; category c2; category c3;
category c4; category c5; category c6; category c7;
category c8; category c9; category c10; category c11;
category c12; category c13; category c14; category c15;
category c16; category c17; category c18; category c19;
category c20; category c21; category c22; category c23;

level s0:c0.c23;

mlsconstrain file { write } ( h1 dom h2 );
')

type sys_isid;
allow sys_isid self : process { dyntransition transition };
role sys_role;
role sys_role types sys_isid;
gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23)
sid kernel gen_context(sys_user:sys_role:sys_isid, s0)
sid security gen_context(sys_user:sys_role:sys_isid, s0)
sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0)
sid file gen_context(sys_user:sys_role:sys_isid, s0)
sid port gen_context(sys_user:sys_role:sys_isid, s0)
sid netif gen_context(sys_user:sys_role:sys_isid, s0)
sid netmsg gen_context(sys_user:sys_role:sys_isid, s0)
sid node gen_context(sys_user:sys_role:sys_isid, s0)
sid devnull gen_context(sys_user:sys_role:sys_isid, s0)
fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0);
fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0);
9 changes: 9 additions & 0 deletions libsepol/tests/policies/test-disjointattrs/split_module1.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module disjointattrs_test_1 1.0;

require {
type test_type_t;
}

attribute attr1;

typeattribute test_type_t attr1;
9 changes: 9 additions & 0 deletions libsepol/tests/policies/test-disjointattrs/split_module2.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module disjointattrs_test_2 1.0;

require {
type test_type_t;
}

attribute attr2;

typeattribute test_type_t attr2;
9 changes: 9 additions & 0 deletions libsepol/tests/policies/test-disjointattrs/split_module3.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module disjointattrs_test_3 1.0;

require {
attribute attr1, attr2;
}

type test_type_t;

disjoint_attributes attr1, attr2;
197 changes: 197 additions & 0 deletions libsepol/tests/test-disjointattributes.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
#define _GNU_SOURCE

#include "test-disjointattributes.h"

#include "helpers.h"
#include "test-common.h"

#include <sepol/debug.h>
#include <sepol/policydb/link.h>
#include <sepol/policydb/expand.h>

#include <stdio.h>
#include <stdarg.h>

extern int mls;

int disjointattrs_test_init(void)
{
return 0;
}

int disjointattrs_test_cleanup(void)
{
return 0;
}

static struct msg_list {
char *msg;
struct msg_list *next;
} *messages;

static void messages_clean(void)
{
while (messages) {
struct msg_list *n = messages->next;
free(messages->msg);
free(messages);
messages = n;
}
}

static void messages_check(unsigned count, const char *const expected[count])
{
unsigned i;
const struct msg_list *m = messages;

for (i = 0; i < count; i++, m = m->next) {
if (!m) {
CU_FAIL("less messages than expected");
return;
}

if (strcmp(expected[i], m->msg) != 0) {
CU_FAIL("messages differs from expected");
fprintf(stderr, "\n<expected: '%s', got: '%s'>\n", expected[i], m->msg);
}
}

if (m) {
CU_FAIL("more messages than expected");
fprintf(stderr, "\n<next message: '%s'>\n", m->msg);
}
}

#ifdef __GNUC__
__attribute__ ((format(printf, 3, 4)))
#endif
static void msg_handler(void *varg __attribute__ ((unused)),
sepol_handle_t * handle __attribute__ ((unused)),
const char *fmt, ...)
{
char *msg;
va_list ap;

va_start(ap, fmt);
vasprintf(&msg, fmt, ap);
va_end(ap);

struct msg_list *new = malloc(sizeof(struct msg_list));
new->msg = msg;
new->next = messages;
messages = new;
}

#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))

static void test_disjointattrs_single(void)
{
policydb_t basemod, base_expanded;
sepol_handle_t *handle;
const char *const expected_messages[] = {
"7 Disjoint Attributes Rule failures occurred",
"Disjoint Attributes Rule violation, type test1_type associated with attributes test1_attr2 and test1_attr1",
"Disjoint Attributes Rule violation, type test2_type3 associated with attributes test2_attr3 and test2_attr2",
"Disjoint Attributes Rule violation, type test2_type4 associated with attributes test2_attr3 and test2_attr2",
"Disjoint Attributes Rule violation, type test2_type1 associated with attributes test2_attr1 and test2_attr2",
"Disjoint Attributes Rule violation, type test2_type4 associated with attributes test2_attr1 and test2_attr2",
"Disjoint Attributes Rule violation, type test2_type2 associated with attributes test2_attr1 and test2_attr3",
"Disjoint Attributes Rule violation, type test2_type4 associated with attributes test2_attr1 and test2_attr3",
};

if (policydb_init(&base_expanded))
CU_FAIL_FATAL("Failed to initialize policy");

if (test_load_policy(&basemod, POLICY_BASE, mls, "test-disjointattrs", "single.conf"))
CU_FAIL_FATAL("Failed to load policy");

if (link_modules(NULL, &basemod, NULL, 0, 0))
CU_FAIL_FATAL("Failed to link base module");

if (expand_module(NULL, &basemod, &base_expanded, 0, 0))
CU_FAIL_FATAL("Failed to expand policy");

if ((handle = sepol_handle_create()) == NULL)
CU_FAIL_FATAL("Failed to initialize handle");

sepol_msg_set_callback(handle, msg_handler, NULL);

if (check_assertions(handle, &base_expanded, NULL) != -1)
CU_FAIL("Assertions did not trigger");

messages_check(ARRAY_SIZE(expected_messages), expected_messages);

sepol_handle_destroy(handle);
messages_clean();
policydb_destroy(&basemod);
policydb_destroy(&base_expanded);
}

#define NUM_MODS 3

static void test_disjointattrs_split(void)
{
policydb_t basemod, base_expanded;
policydb_t *modules[NUM_MODS];
const char *policies[NUM_MODS] = { "split_module1.conf", "split_module2.conf", "split_module3.conf" };
sepol_handle_t *handle;
const char *const expected_messages[] = {
"1 Disjoint Attributes Rule failures occurred",
"Disjoint Attributes Rule violation, type test_type_t associated with attributes attr2 and attr1",
};
unsigned i;

if (policydb_init(&base_expanded))
CU_FAIL_FATAL("Failed to initialize policy");

if (test_load_policy(&basemod, POLICY_BASE, mls, "test-disjointattrs", "split_base.conf"))
CU_FAIL_FATAL("Failed to load policy");

for (i = 0; i < NUM_MODS; i++) {
modules[i] = calloc(1, sizeof(*modules[i]));
if (!modules[i])
CU_FAIL_FATAL("Failed to allocate module");

if (test_load_policy(modules[i], POLICY_MOD, mls, "test-disjointattrs", policies[i]))
CU_FAIL_FATAL("Failed to load module");
}

if (link_modules(NULL, &basemod, modules, 3, 0))
CU_FAIL_FATAL("Failed to link base module");

if (expand_module(NULL, &basemod, &base_expanded, 0, 0))
CU_FAIL_FATAL("Failed to expand policy");

if ((handle = sepol_handle_create()) == NULL)
CU_FAIL_FATAL("Failed to initialize handle");

sepol_msg_set_callback(handle, msg_handler, NULL);

if (check_assertions(handle, &base_expanded, NULL) != -1)
CU_FAIL("Assertions did not trigger");

messages_check(ARRAY_SIZE(expected_messages), expected_messages);

sepol_handle_destroy(handle);
messages_clean();
for (i = 0; i < NUM_MODS; i++) {
policydb_destroy(modules[i]);
free(modules[i]);
}
policydb_destroy(&basemod);
policydb_destroy(&base_expanded);
}

int disjointattrs_add_tests(CU_pSuite suite)
{
if (NULL == CU_add_test(suite, "disjointattrs_single", test_disjointattrs_single)) {
CU_cleanup_registry();
return CU_get_error();
}
if (NULL == CU_add_test(suite, "disjointattrs_split", test_disjointattrs_split)) {
CU_cleanup_registry();
return CU_get_error();
}

return 0;
}
10 changes: 10 additions & 0 deletions libsepol/tests/test-disjointattributes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef TEST_DISJOINTATTRIBUTES_H__
#define TEST_DISJOINTATTRIBUTES_H__

#include <CUnit/Basic.h>

int disjointattrs_test_init(void);
int disjointattrs_test_cleanup(void);
int disjointattrs_add_tests(CU_pSuite suite);

#endif /* TEST_DISJOINTATTRIBUTES_H__ */