@@ -23,7 +23,7 @@ TARGETS = \
test_task_getsid.te test_task_setpgid.te test_task_setsched.te \
test_transition.te test_inet_socket.te test_unix_socket.te \
test_mmap.te test_overlayfs.te test_mqueue.te test_mac_admin.te \
- test_ibpkey.te test_atsecure.te
+ test_ibpkey.te test_atsecure.te test_nosuid.te
ifeq ($(shell [ $(POL_VERS) -ge 24 ] && echo true),true)
TARGETS += test_bounds.te
@@ -57,6 +57,10 @@ ifeq ($(shell grep -q all_file_perms.*map $(POLDEV)/include/support/all_perms.sp
export M4PARAM = -Dmap_permission_defined
endif
+ifeq ($(shell grep -q nnp_transition $(POLDEV)/include/support/all_perms.spt && echo true),true)
+export M4PARAM += -Dnnp_transition_permission_defined
+endif
+
ifeq (x$(DISTRO),$(filter x$(DISTRO),xRHEL4 xRHEL5 xRHEL6))
TARGETS:=$(filter-out test_overlayfs.te test_mqueue.te, $(TARGETS))
endif
@@ -32,3 +32,20 @@ domain_entry_file(test_nnp_notbounded_t, test_nnp_notbounded_exec_t)
# Run it! This should fail always.
unconfined_runs_test(test_nnp_notbounded_t)
unconfined_run_to(test_nnp_notbounded_t, test_nnp_notbounded_exec_t)
+
+# A domain to which the unconfined domain is allowed nnp_transition.
+type test_nnp_nnptransition_t;
+domain_type(test_nnp_nnptransition_t)
+typeattribute test_nnp_nnptransition_t testdomain;
+
+# The entrypoint type for this domain.
+type test_nnp_nnptransition_exec_t;
+files_type(test_nnp_nnptransition_exec_t)
+domain_entry_file(test_nnp_nnptransition_t, test_nnp_nnptransition_exec_t)
+
+# Run it! This should succeed on v4.14 or later.
+unconfined_runs_test(test_nnp_nnptransition_t)
+unconfined_run_to(test_nnp_nnptransition_t, test_nnp_nnptransition_exec_t)
+ifdef(`nnp_transition_permission_defined', `
+allow unconfined_t test_nnp_nnptransition_t:process nnp_transition;
+')
new file mode 100644
@@ -0,0 +1,51 @@
+#################################
+#
+# Policy for testing nosuid transitions.
+#
+
+# A domain bounded by the unconfined domain.
+type test_nosuid_bounded_t;
+domain_type(test_nosuid_bounded_t)
+typeattribute test_nosuid_bounded_t testdomain;
+typebounds unconfined_t test_nosuid_bounded_t;
+
+# The entrypoint type for this domain.
+type test_nosuid_bounded_exec_t;
+files_type(test_nosuid_bounded_exec_t)
+domain_entry_file(test_nosuid_bounded_t, test_nosuid_bounded_exec_t)
+domain_entry_file(unconfined_t, test_nosuid_bounded_exec_t)
+
+# Run it! This should succeed on v3.18 or later, fail on older kernels.
+unconfined_runs_test(test_nosuid_bounded_t)
+unconfined_run_to(test_nosuid_bounded_t, test_nosuid_bounded_exec_t)
+
+# A domain that is not bounded by the unconfined domain.
+type test_nosuid_notbounded_t;
+domain_type(test_nosuid_notbounded_t)
+typeattribute test_nosuid_notbounded_t testdomain;
+
+# The entrypoint type for this domain.
+type test_nosuid_notbounded_exec_t;
+files_type(test_nosuid_notbounded_exec_t)
+domain_entry_file(test_nosuid_notbounded_t, test_nosuid_notbounded_exec_t)
+
+# Run it! This should fail always.
+unconfined_runs_test(test_nosuid_notbounded_t)
+unconfined_run_to(test_nosuid_notbounded_t, test_nosuid_notbounded_exec_t)
+
+# A domain to which the unconfined domain is allowed nosuid_transition.
+type test_nosuid_nosuidtransition_t;
+domain_type(test_nosuid_nosuidtransition_t)
+typeattribute test_nosuid_nosuidtransition_t testdomain;
+
+# The entrypoint type for this domain.
+type test_nosuid_nosuidtransition_exec_t;
+files_type(test_nosuid_nosuidtransition_exec_t)
+domain_entry_file(test_nosuid_nosuidtransition_t, test_nosuid_nosuidtransition_exec_t)
+
+# Run it! This should succeed on v4.14 or later.
+unconfined_runs_test(test_nosuid_nosuidtransition_t)
+unconfined_run_to(test_nosuid_nosuidtransition_t, test_nosuid_nosuidtransition_exec_t)
+ifdef(`nnp_transition_permission_defined', `
+allow unconfined_t test_nosuid_nosuidtransition_t:process2 nosuid_transition;
+')
@@ -11,7 +11,7 @@ SUBDIRS:= domain_trans entrypoint execshare exectrace execute_no_trans \
task_getpgid task_setpgid file ioctl capable_file capable_net \
capable_sys dyntrans dyntrace bounds nnp mmap unix_socket inet_socket \
overlay checkreqprot mqueue mac_admin infiniband_pkey \
- infiniband_endport atsecure
+ infiniband_endport atsecure nosuid
ifeq ($(shell grep -q cap_userns $(POLDEV)/include/support/all_perms.spt && echo true),true)
ifneq ($(shell ./kvercmp $$(uname -r) 4.7),-1)
@@ -1,7 +1,23 @@
#!/usr/bin/perl
use Test;
-BEGIN { plan tests => 4 }
+
+BEGIN {
+ $test_count = 4;
+ $test_nnp_transition = 0;
+
+ if (
+ system(
+"grep -q 1 /sys/fs/selinux/policy_capabilities/nnp_nosuid_transition 2> /dev/null"
+ ) == 0
+ )
+ {
+ $test_nnp_transition = 1;
+ $test_count += 2;
+ }
+
+ plan tests => $test_count;
+}
$basedir = $0;
$basedir =~ s|(.*)/[^/]*|$1|;
@@ -38,6 +54,28 @@ $result =
system("$basedir/execnnp $basedir/checkcon test_nnp_notbounded_t 2>&1");
ok($result); #this should fail
+if ($test_nnp_transition) {
+
+ # Set entrypoint type for nnptransition domain.
+ system(
+ "chcon -t test_nnp_nnptransition_exec_t $basedir/checkcon $basedir/true"
+ );
+
+ # Transition to nnptransition domain via setexec.
+ $result =
+ system(
+ "$basedir/execnnp runcon -t test_nnp_nnptransition_t $basedir/true 2>&1"
+ );
+ ok( $result, 0 ); #this should succeed
+
+ # Automatic transition to nnptransition domain via exec.
+ $result =
+ system(
+ "$basedir/execnnp $basedir/checkcon test_nnp_nnptransition_t 2>&1");
+ ok( $result, 0 ); #this should succeed
+
+}
+
# Cleanup.
system("rm -f $basedir/true");
new file mode 100644
@@ -0,0 +1,7 @@
+TARGETS=execnosuid checkcon
+
+LDLIBS += -lselinux
+
+all: $(TARGETS)
+clean:
+ rm -f $(TARGETS)
new file mode 100644
@@ -0,0 +1,41 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <selinux/selinux.h>
+#include <selinux/context.h>
+
+int main(int argc, char **argv)
+{
+ char *con = NULL;
+ context_t c;
+ const char *type;
+ int rc;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s expected-type\n", argv[0]);
+ exit(-1);
+ }
+
+ if (getcon(&con) < 0) {
+ perror("getcon");
+ exit(-1);
+ }
+
+ c = context_new(con);
+ if (!c) {
+ perror("context_new");
+ exit(-1);
+ }
+
+ type = context_type_get(c);
+ if (!type) {
+ perror("context_type_get");
+ exit(-1);
+
+ }
+
+ rc = strcmp(type, argv[1]);
+ exit(rc);
+}
new file mode 100644
@@ -0,0 +1,55 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+int main(int argc, char **argv)
+{
+ bool nobounded;
+ struct utsname uts;
+ pid_t pid;
+ int rc, status;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s command [args...]\n", argv[0]);
+ exit(-1);
+ }
+
+ if (uname(&uts) < 0) {
+ perror("uname");
+ exit(-1);
+ }
+
+ nobounded = ((strcmp(argv[argc - 1], "test_nosuid_bounded_t") == 0) &&
+ (strverscmp(uts.release, "3.18") < 0));
+
+ pid = fork();
+ if (pid < 0) {
+ perror("fork");
+ exit(-1);
+ }
+
+ if (pid == 0) {
+ execvp(argv[1], &argv[1]);
+ perror(argv[1]);
+ exit(-1);
+ }
+
+ pid = wait(&status);
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) && nobounded) {
+ printf("%s: Kernels < v3.18 do not support bounded transitions under NNP.\n",
+ argv[0]);
+ /* pass the test */
+ exit(0);
+ }
+ exit(WEXITSTATUS(status));
+ }
+
+ fprintf(stderr, "Unexpected exit status 0x%x\n", status);
+ exit(-1);
+}
new file mode 100755
@@ -0,0 +1,93 @@
+#!/usr/bin/perl
+
+use Test;
+
+BEGIN {
+ $test_count = 4;
+ $test_nosuid_transition = 0;
+
+ if (
+ system(
+"grep -q 1 /sys/fs/selinux/policy_capabilities/nnp_nosuid_transition 2> /dev/null"
+ ) == 0
+ )
+ {
+ $test_nosuid_transition = 1;
+ $test_count += 2;
+ }
+
+ plan tests => $test_count;
+}
+
+$basedir = $0;
+$basedir =~ s|(.*)/[^/]*|$1|;
+
+# Create nosuid mount.
+system("mkdir -p $basedir/testdir");
+system("mount -t tmpfs -o nosuid none $basedir/testdir");
+
+# Set entrypoint type for bounded domain.
+system("cp $basedir/checkcon $basedir/testdir");
+system("chcon -t test_nosuid_bounded_exec_t $basedir/testdir/checkcon");
+
+# Transition to bounded type via setexec.
+$result = system(
+"$basedir/execnosuid runcon -t test_nosuid_bounded_t $basedir/testdir/checkcon test_nosuid_bounded_t 2>&1"
+);
+ok( $result, 0 ); #this should pass
+
+# Automatic transition to bounded domain via exec.
+$result = system(
+ "$basedir/execnosuid $basedir/testdir/checkcon test_nosuid_bounded_t 2>&1");
+ok( $result, 0 ); #this should pass
+
+# Use true as an entrypoint program to test ability to exec at all.
+system("cp /bin/true $basedir/testdir/true");
+
+# Set entrypoint type for notbounded domain.
+system(
+"chcon -t test_nosuid_notbounded_exec_t $basedir/testdir/checkcon $basedir/testdir/true"
+);
+
+# Transition to notbounded domain via setexec.
+$result =
+ system(
+"$basedir/execnosuid runcon -t test_nosuid_notbounded_t $basedir/testdir/true 2>&1"
+ );
+ok($result); #this should fail
+
+# Automatic transition to notbounded domain via exec.
+$result =
+ system(
+"$basedir/execnosuid $basedir/testdir/checkcon test_nosuid_notbounded_t 2>&1"
+ );
+ok($result); #this should fail
+
+if ($test_nosuid_transition) {
+
+ # Set entrypoint type for nosuid domain.
+ system(
+"chcon -t test_nosuid_nosuidtransition_exec_t $basedir/testdir/checkcon $basedir/testdir/true"
+ );
+
+ # Transition to nosuid domain via setexec.
+ $result =
+ system(
+"$basedir/execnosuid runcon -t test_nosuid_nosuidtransition_t $basedir/testdir/true 2>&1"
+ );
+ ok( $result, 0 ); #this should succeed
+
+ # Automatic transition to nosuid domain via exec.
+ $result =
+ system(
+"$basedir/execnosuid $basedir/testdir/checkcon test_nosuid_nosuidtransition_t 2>&1"
+ );
+ ok( $result, 0 ); #this should succeed
+
+}
+
+# Cleanup.
+system("umount $basedir/testdir");
+system("rmdir $basedir/testdir");
+
+exit;
Duplicate the existing tests for transitions under NNP for transitions on a nosuid mount, and then augment both the NNP and nosuid tests to also test the new support for allowing transitions based on nnp_transition and/or nosuid_transition permission if the nnp_nosuid_transition policy capability is enabled. Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov> --- policy/Makefile | 6 ++- policy/test_nnp.te | 17 +++++++++ policy/test_nosuid.te | 51 ++++++++++++++++++++++++++ tests/Makefile | 2 +- tests/nnp/test | 40 +++++++++++++++++++- tests/nosuid/Makefile | 7 ++++ tests/nosuid/checkcon.c | 41 +++++++++++++++++++++ tests/nosuid/execnosuid.c | 55 ++++++++++++++++++++++++++++ tests/nosuid/test | 93 +++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 309 insertions(+), 3 deletions(-) create mode 100644 policy/test_nosuid.te create mode 100644 tests/nosuid/Makefile create mode 100644 tests/nosuid/checkcon.c create mode 100644 tests/nosuid/execnosuid.c create mode 100755 tests/nosuid/test