Skip to content

Commit

Permalink
selinux-testsuite: Add filesystem tests
Browse files Browse the repository at this point in the history
Test filesystem permissions, setfscreatecon(3), file { quotaon } and
changing file context via non and name-based type_transition rules.
The name-based rules only apply to:
  (MOD_POL_VERS >= 11 and POL_VERS >= 25 and MAX_KERNEL_POLICY >= 25)

From kernels 5.5 filesystem { watch } is also tested.

Signed-off-by: Richard Haines <richard_c_haines@btinternet.com>
  • Loading branch information
Richard Haines authored and stephensmalley committed Jan 21, 2020
1 parent 7fd02b1 commit 0fa0507
Show file tree
Hide file tree
Showing 19 changed files with 2,601 additions and 0 deletions.
6 changes: 6 additions & 0 deletions defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,9 @@ CONFIG_TUN=m
CONFIG_HAVE_PERF_EVENTS=y
CONFIG_PERF_EVENTS=y
CONFIG_TRACEPOINTS=y

# Test filesystem permissions.
# This is not required for SELinux operation itself.
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_LOOP_MIN_COUNT=0
CONFIG_QFMT_V2=y
7 changes: 7 additions & 0 deletions policy/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ TARGETS += test_lockdown.te
export M4PARAM += -Dlockdown_defined
endif

ifeq ($(shell grep -q filesystem $(POLDEV)/include/support/all_perms.spt && echo true),true)
TARGETS += test_filesystem.te
ifeq ($(shell [ $(MOD_POL_VERS) -ge 11 -a $(POL_VERS) -ge 25 ] && echo true),true)
TARGETS += test_filesystem_name_trans.te
endif
endif

ifeq (x$(DISTRO),$(filter x$(DISTRO),xRHEL4 xRHEL5 xRHEL6))
TARGETS:=$(filter-out test_overlayfs.te test_mqueue.te test_ibpkey.te, $(TARGETS))
endif
Expand Down
373 changes: 373 additions & 0 deletions policy/test_filesystem.te

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions policy/test_filesystem_name_trans.te
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#
######### Test filesystem name-base transition policy module ##########
#

# Name-based type transition context:
type test_filesystem_filenametranscon1_t;
files_type(test_filesystem_filenametranscon1_t)
type test_filesystem_filenametranscon2_t;
files_type(test_filesystem_filenametranscon2_t)

# Create file and change context via name-based type_transition rule:
fs_associate(test_filesystem_filenametranscon1_t)
type_transition test_filesystem_t test_filesystem_file_t:file test_filesystem_filenametranscon1_t "name_trans_test_file1";
allow test_filesystem_t test_filesystem_filenametranscon1_t:file { create getattr open write };
dontaudit unconfined_t test_filesystem_filenametranscon1_t:file { getattr read };
#
fs_associate(test_filesystem_filenametranscon2_t)
type_transition test_filesystem_t test_filesystem_file_t:file test_filesystem_filenametranscon2_t "name_trans_test_file2";
allow test_filesystem_t test_filesystem_filenametranscon2_t:file { create getattr open write };
dontaudit unconfined_t test_filesystem_filenametranscon2_t:file { getattr read };
7 changes: 7 additions & 0 deletions tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ ifeq ($(shell grep -q lockdown $(POLDEV)/include/support/all_perms.spt && echo t
SUBDIRS += lockdown
endif

ifeq ($(shell grep -q filesystem $(POLDEV)/include/support/all_perms.spt && echo true),true)
SUBDIRS += filesystem
ifeq ($(shell grep -q all_filesystem_perms.*watch $(POLDEV)/include/support/all_perms.spt && echo true),true)
export CFLAGS += -DHAVE_FS_WATCH_PERM
endif
endif

ifeq ($(DISTRO),RHEL4)
SUBDIRS:=$(filter-out bounds dyntrace dyntrans inet_socket mmap nnp_nosuid overlay unix_socket, $(SUBDIRS))
endif
Expand Down
11 changes: 11 additions & 0 deletions tests/filesystem/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
mount
umount
quotas_test
statfs_test
fanotify_fs
create_file_change_context
fs_relabel
check_file_context
check_mount_context
create_file
grim_reaper
16 changes: 16 additions & 0 deletions tests/filesystem/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Required for local building
#export CFLAGS += -DHAVE_FS_WATCH_PERM

TARGETS = mount umount quotas_test statfs_test create_file_change_context \
fs_relabel check_file_context grim_reaper check_mount_context create_file

LDLIBS += -lselinux

ifneq (,$(findstring -DHAVE_FS_WATCH_PERM,$(CFLAGS)))
TARGETS += fanotify_fs
endif

all: $(TARGETS)

clean:
rm -f $(TARGETS)
75 changes: 75 additions & 0 deletions tests/filesystem/check_file_context.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <linux/unistd.h>
#include <selinux/selinux.h>

static void print_usage(char *progname)
{
fprintf(stderr,
"usage: %s -f file -e cxt [-v]\n"
"Where:\n\t"
"-f File to check its context\n\t"
"-e Expected context\n\t"
"-v Print information.\n", progname);
exit(-1);
}

int main(int argc, char **argv)
{
int opt, result, fd;
char *context = NULL, *expected = NULL, *file = NULL;
bool verbose = false;

while ((opt = getopt(argc, argv, "f:e:v")) != -1) {
switch (opt) {
case 'f':
file = optarg;
break;
case 'e':
expected = optarg;
break;
case 'v':
verbose = true;
break;
default:
print_usage(argv[0]);
}
}

if (!file || !expected)
print_usage(argv[0]);

fd = open(file, O_RDWR);
if (fd < 0) {
fprintf(stderr, "open(2) Failed: %s\n", strerror(errno));
return -1;
}

result = fgetfilecon(fd, &context);
if (result < 0) {
fprintf(stderr, "fgetfilecon(3) Failed: %s\n",
strerror(errno));
result = -1;
goto err;
}
result = 0;

if (strcmp(expected, context)) {
fprintf(stderr, "File context error, expected:\n\t%s\ngot:\n\t%s\n",
expected, context);
result = -1;
} else {
if (verbose)
printf("Pass - File contexts match: %s\n", context);
}
err:
free(context);
close(fd);

return result;
}
127 changes: 127 additions & 0 deletions tests/filesystem/check_mount_context.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <linux/unistd.h>
#include <selinux/selinux.h>
#include <selinux/context.h>

static void print_usage(char *progname)
{
fprintf(stderr,
"usage: %s -m mp [-e ctx] [-r] [-v]\n"
"Where:\n\t"
"-m Mount point\n\t"
"-e Expected MP context\n\t"
"-r Reset MP context to 'unlabeled_t'\n\t"
"-v Print information.\n", progname);
exit(-1);
}

int main(int argc, char **argv)
{
int opt, result;
char *context = NULL, *expected = NULL, *mount = NULL, *newcon = NULL;
bool verbose = false, reset = false;
const char *type = "unlabeled_t";
context_t con_t;

while ((opt = getopt(argc, argv, "m:e:rv")) != -1) {
switch (opt) {
case 'm':
mount = optarg;
break;
case 'e':
expected = optarg;
break;
case 'r':
reset = true;
break;
case 'v':
verbose = true;
break;
default:
print_usage(argv[0]);
}
}

if (!mount)
print_usage(argv[0]);

result = getfilecon(mount, &context);
if (result < 0) {
fprintf(stderr, "getfilecon(3) Failed: %s\n",
strerror(errno));
result = -1;
goto err;
}
if (verbose)
printf("Current MP context: %s\n", context);

result = 0;

if (reset) {
/* Set context to unlabeled_t */
con_t = context_new(context);
if (!con_t) {
fprintf(stderr, "Unable to create context structure\n");
result = -1;
goto err;
}

if (context_type_set(con_t, type)) {
fprintf(stderr, "Unable to set new type\n");
free(con_t);
result = -1;
goto err;
}

newcon = context_str(con_t);
free(con_t);
if (!newcon) {
fprintf(stderr, "Unable to obtain new context string\n");
result = -1;
goto err;
}

result = setfilecon(mount, newcon);
free(newcon);
if (result < 0) {
fprintf(stderr, "setfilecon(3) Failed: %s\n",
strerror(errno));
result = -1;
goto err;
}

free(context);

result = getfilecon(mount, &context);
if (result < 0) {
fprintf(stderr, "getfilecon(3) Failed: %s\n",
strerror(errno));
return result;
}
result = 0;

if (verbose)
printf("Set new MP context: %s\n", context);

} else {
if (strcmp(expected, context)) {
fprintf(stderr, "Mount context error, expected:\n\t%s\ngot:\n\t%s\n",
expected, context);
result = -1;
} else {
if (verbose)
printf("Pass - Mountpoint contexts match: %s\n",
context);
}
}

err:
free(context);
return result;
}

0 comments on commit 0fa0507

Please sign in to comment.