diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/.gitignore | 5 | ||||
-rw-r--r-- | tests/Makefile.am | 11 | ||||
-rw-r--r-- | tests/access.c | 23 | ||||
-rw-r--r-- | tests/chmod.c | 35 | ||||
-rw-r--r-- | tests/execve.c | 53 | ||||
-rwxr-xr-x | tests/execve.test | 2 | ||||
-rw-r--r-- | tests/execveat.c | 122 | ||||
-rw-r--r-- | tests/faccessat.c | 137 | ||||
-rwxr-xr-x | tests/faccessat.test | 2 | ||||
-rw-r--r-- | tests/fanotify_mark.c | 121 | ||||
-rw-r--r-- | tests/fchmod.c | 23 | ||||
-rw-r--r-- | tests/fchmodat.c | 67 | ||||
-rw-r--r-- | tests/fchownat.c | 73 | ||||
-rw-r--r-- | tests/file_handle.c | 204 | ||||
-rwxr-xr-x | tests/gen_secontext.sh | 72 | ||||
-rw-r--r-- | tests/gen_tests.in | 30 | ||||
-rw-r--r-- | tests/linkat.c | 150 | ||||
-rw-r--r-- | tests/open.c | 18 | ||||
-rw-r--r-- | tests/openat.c | 91 | ||||
-rwxr-xr-x | tests/options-syntax.test | 11 | ||||
-rw-r--r-- | tests/secontext.c | 201 | ||||
-rw-r--r-- | tests/secontext.h | 46 | ||||
-rwxr-xr-x | tests/strace-V.test | 4 |
23 files changed, 1309 insertions, 192 deletions
diff --git a/tests/.gitignore b/tests/.gitignore index bed7c5b7f..6532542b5 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,3 +1,7 @@ +*--secontext +*--secontext.c +*--secontext_full +*--secontext_full.c *.dir *.gen.test *.log @@ -711,6 +715,7 @@ seccomp-filter seccomp-filter-v seccomp-strict seccomp_get_action_avail +secontext.am select select-P semop diff --git a/tests/Makefile.am b/tests/Makefile.am index 8327e84cf..cb6e7ef1c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -31,6 +31,12 @@ AM_CPPFLAGS = $(ARCH_MFLAGS) \ -DTESTS_SIZEOF_LONG=$(SIZEOF_LONG) AM_LDFLAGS = $(ARCH_MFLAGS) +if HAVE_SELINUX_RUNTIME +libselinux_LDADD = $(libselinux_LIBS) +else +libselinux_LDADD = +endif + libtests_a_SOURCES = \ create_nl_socket.c \ create_tmpfile.c \ @@ -57,6 +63,8 @@ libtests_a_SOURCES = \ printxval-Xabbrev.c \ printxval-Xraw.c \ printxval-Xverbose.c \ + secontext.c \ + secontext.h \ signal2name.c \ skip_unavailable.c \ sprintrc.c \ @@ -79,7 +87,10 @@ LDADD = libtests.a include pure_executables.am +include secontext.am + check_PROGRAMS = $(PURE_EXECUTABLES) \ + $(secontext_EXECUTABLES) \ _newselect-P \ answer \ attach-f-p \ diff --git a/tests/access.c b/tests/access.c index fe7e21d5b..5d37ba534 100644 --- a/tests/access.c +++ b/tests/access.c @@ -10,9 +10,12 @@ #ifdef __NR_access +# include <fcntl.h> # include <stdio.h> # include <unistd.h> +# include "secontext.h" + int main(void) { @@ -22,15 +25,27 @@ main(void) */ create_and_enter_subdir("access_subdir"); + char *my_secontext = SECONTEXT_PID_MY(); + static const char sample[] = "access_sample"; + (void) unlink(sample); + if (open(sample, O_CREAT|O_RDONLY, 0400) == -1) + perror_msg_and_fail("open: %s", sample); long rc = syscall(__NR_access, sample, F_OK); - printf("access(\"%s\", F_OK) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("%s%s(\"%s\"%s, F_OK) = %s\n", + my_secontext, "access", + sample, SECONTEXT_FILE(sample), + sprintrc(rc)); + + if (unlink(sample)) + perror_msg_and_fail("unlink: %s", sample); rc = syscall(__NR_access, sample, R_OK|W_OK|X_OK); - printf("access(\"%s\", R_OK|W_OK|X_OK) = %ld %s (%m)\n", - sample, rc, errno2name()); + printf("%s%s(\"%s\", R_OK|W_OK|X_OK) = %s\n", + my_secontext, "access", + sample, + sprintrc(rc)); leave_and_remove_subdir(); diff --git a/tests/chmod.c b/tests/chmod.c index 845e54aac..7d0ef5657 100644 --- a/tests/chmod.c +++ b/tests/chmod.c @@ -16,6 +16,8 @@ # include <stdio.h> # include <unistd.h> +# include "secontext.h" + int main(void) { @@ -25,22 +27,33 @@ main(void) */ create_and_enter_subdir("chmod_subdir"); - static const char fname[] = "chmod_test_file"; + char *my_secontext = SECONTEXT_PID_MY(); - if (open(fname, O_CREAT|O_RDONLY, 0400) < 0) - perror_msg_and_fail("open"); + static const char sample[] = "chmod_test_file"; + (void) unlink(sample); + if (open(sample, O_CREAT|O_RDONLY, 0400) < 0) + perror_msg_and_fail("open: %s", sample); - long rc = syscall(__NR_chmod, fname, 0600); - printf("chmod(\"%s\", 0600) = %s\n", fname, sprintrc(rc)); + long rc = syscall(__NR_chmod, sample, 0600); + printf("%s%s(\"%s\"%s, 0600) = %s\n", + my_secontext, "chmod", + sample, SECONTEXT_FILE(sample), + sprintrc(rc)); - if (unlink(fname)) - perror_msg_and_fail("unlink"); + if (unlink(sample)) + perror_msg_and_fail("unlink: %s", sample); - rc = syscall(__NR_chmod, fname, 051); - printf("chmod(\"%s\", 051) = %s\n", fname, sprintrc(rc)); + rc = syscall(__NR_chmod, sample, 051); + printf("%s%s(\"%s\", 051) = %s\n", + my_secontext, "chmod", + sample, + sprintrc(rc)); - rc = syscall(__NR_chmod, fname, 004); - printf("chmod(\"%s\", 004) = %s\n", fname, sprintrc(rc)); + rc = syscall(__NR_chmod, sample, 004); + printf("%s%s(\"%s\", 004) = %s\n", + my_secontext, "chmod", + sample, + sprintrc(rc)); leave_and_remove_subdir(); diff --git a/tests/execve.c b/tests/execve.c index 961d284a1..baf3eeb61 100644 --- a/tests/execve.c +++ b/tests/execve.c @@ -9,9 +9,12 @@ */ #include "tests.h" +#include <fcntl.h> #include <stdio.h> #include <unistd.h> +#include "secontext.h" + static const char *errstr; static int @@ -52,9 +55,16 @@ main(void) char ** const tail_argv = tail_memdup(argv, sizeof(argv)); char ** const tail_envp = tail_memdup(envp, sizeof(envp)); + char *my_secontext = SECONTEXT_PID_MY(); + + (void) unlink(FILENAME); + if (open(FILENAME, O_RDONLY | O_CREAT, 0400) < 0) + perror_msg_and_fail("open"); + + char *FILENAME_secontext = SECONTEXT_FILE(FILENAME); call_execve(FILENAME, tail_argv, tail_envp); - printf("execve(\"%s\"" + printf("%s%s(\"%s\"%s" ", [\"%s\", \"%s\", \"%s\", %p, %p, %p, ... /* %p */]" #if VERBOSE ", [\"%s\", \"%s\", %p, %p, %p, ... /* %p */]" @@ -62,7 +72,9 @@ main(void) ", %p /* 5 vars, unterminated */" #endif ") = %s\n", - Q_FILENAME, q_argv[0], q_argv[1], q_argv[2], + my_secontext, "execve", + Q_FILENAME, FILENAME_secontext, + q_argv[0], q_argv[1], q_argv[2], argv[3], argv[4], argv[5], (char *) tail_argv + sizeof(argv) #if VERBOSE , q_envp[0], q_envp[1], envp[2], envp[3], envp[4], @@ -77,14 +89,16 @@ main(void) (void) q_envp; /* workaround for clang bug #33068 */ call_execve(FILENAME, tail_argv, tail_envp); - printf("execve(\"%s\", [\"%s\", \"%s\", \"%s\"]" + printf("%s%s(\"%s\"%s, [\"%s\", \"%s\", \"%s\"]" #if VERBOSE ", [\"%s\", \"%s\"]" #else ", %p /* 2 vars */" #endif ") = %s\n", - Q_FILENAME, q_argv[0], q_argv[1], q_argv[2] + my_secontext, "execve", + Q_FILENAME, FILENAME_secontext, + q_argv[0], q_argv[1], q_argv[2] #if VERBOSE , q_envp[0], q_envp[1] #else @@ -93,14 +107,16 @@ main(void) , errstr); call_execve(FILENAME, tail_argv + 2, tail_envp + 1); - printf("execve(\"%s\", [\"%s\"]" + printf("%s%s(\"%s\"%s, [\"%s\"]" #if VERBOSE ", [\"%s\"]" #else ", %p /* 1 var */" #endif ") = %s\n", - Q_FILENAME, q_argv[2] + my_secontext, "execve", + Q_FILENAME, FILENAME_secontext, + q_argv[2] #if VERBOSE , q_envp[1] #else @@ -113,13 +129,15 @@ main(void) *empty = NULL; call_execve(FILENAME, empty, empty); - printf("execve(\"%s\", []" + printf("%s%s(\"%s\"%s, []" #if VERBOSE ", []" #else ", %p /* 0 vars */" #endif - ") = %s\n", Q_FILENAME + ") = %s\n", + my_secontext, "execve", + Q_FILENAME, FILENAME_secontext #if !VERBOSE , empty #endif @@ -143,7 +161,10 @@ main(void) a[i] = b[i] = NULL; call_execve(FILENAME, a, b); - printf("execve(\"%s\", [\"%.*s\"...", Q_FILENAME, DEFAULT_STRLEN, a[0]); + printf("%s%s(\"%s\"%s, [\"%.*s\"...", + my_secontext, "execve", + Q_FILENAME, FILENAME_secontext, + DEFAULT_STRLEN, a[0]); for (i = 1; i < DEFAULT_STRLEN; ++i) printf(", \"%s\"", a[i]); #if VERBOSE @@ -162,7 +183,10 @@ main(void) printf(") = %s\n", errstr); call_execve(FILENAME, a + 1, b + 1); - printf("execve(\"%s\", [\"%s\"", Q_FILENAME, a[1]); + printf("%s%s(\"%s\"%s, [\"%s\"", + my_secontext, "execve", + Q_FILENAME, FILENAME_secontext, + a[1]); for (i = 2; i <= DEFAULT_STRLEN; ++i) printf(", \"%s\"", a[i]); #if VERBOSE @@ -175,12 +199,17 @@ main(void) #endif printf(") = %s\n", errstr); + if (unlink(FILENAME)) + perror_msg_and_fail("unlink"); + call_execve(FILENAME, (char **) tail_argv[ARRAY_SIZE(q_argv)], efault); - printf("execve(\"%s\", NULL, %p) = %s\n", + printf("%s%s(\"%s\", NULL, %p) = %s\n", + my_secontext, "execve", Q_FILENAME, efault, errstr); call_execve(FILENAME, efault, NULL); - printf("execve(\"%s\", %p, NULL) = %s\n", + printf("%s%s(\"%s\", %p, NULL) = %s\n", + my_secontext, "execve", Q_FILENAME, efault, errstr); leave_and_remove_subdir(); diff --git a/tests/execve.test b/tests/execve.test index 0824bab48..3275226ae 100755 --- a/tests/execve.test +++ b/tests/execve.test @@ -11,7 +11,7 @@ check_prog grep run_prog > /dev/null -run_strace -eexecve $args > "$EXP" +run_strace -eexecve "$@" $args > "$EXP" # Filter out execve() call made by strace. grep -F test.execve < "$LOG" > "$OUT" diff --git a/tests/execveat.c b/tests/execveat.c index 43b53edb1..a41c42319 100644 --- a/tests/execveat.c +++ b/tests/execveat.c @@ -13,9 +13,102 @@ #ifdef __NR_execveat +# include <fcntl.h> # include <stdio.h> # include <unistd.h> +# include "secontext.h" + +static void +tests_with_existing_file(void) +{ + /* + * Make sure the current workdir of the tracee + * is different from the current workdir of the tracer. + */ + create_and_enter_subdir("execveat_subdir"); + + char *my_secontext = SECONTEXT_PID_MY(); + + static const char sample[] = "execveat_sample"; + (void) unlink(sample); + if (open(sample, O_RDONLY | O_CREAT, 0400) < 0) + perror_msg_and_fail("open"); + + char *sample_secontext = SECONTEXT_FILE(sample); + static const char *argv[] = { sample, NULL }; + + /* + * Tests with AT_FDCWD. + */ + + long rc = syscall(__NR_execveat, -100, sample, argv, NULL, 0); + printf("%s%s(AT_FDCWD, \"%s\"%s, [\"%s\"], NULL, 0) = %s\n", + my_secontext, "execveat", + sample, sample_secontext, + argv[0], + sprintrc(rc)); + + if (unlink(sample)) + perror_msg_and_fail("unlink"); + + rc = syscall(__NR_execveat, -100, sample, argv, NULL, 0); + printf("%s%s(AT_FDCWD, \"%s\", [\"%s\"], NULL, 0) = %s\n", + my_secontext, "execveat", + sample, + argv[0], + sprintrc(rc)); + + /* + * Tests with dirfd. + */ + + int cwd_fd = get_dir_fd("."); + char *cwd = get_fd_path(cwd_fd); + char *cwd_secontext = SECONTEXT_FILE("."); + char *sample_realpath = xasprintf("%s/%s", cwd, sample); + + /* no file */ + rc = syscall(__NR_execveat, cwd_fd, sample, argv, NULL, 0); + printf("%s%s(%d%s, \"%s\", [\"%s\"], NULL, 0) = %s\n", + my_secontext, "execveat", + cwd_fd, cwd_secontext, + sample, + argv[0], + sprintrc(rc)); + + if (open(sample, O_RDONLY | O_CREAT, 0400) < 0) + perror_msg_and_fail("open"); + + rc = syscall(__NR_execveat, cwd_fd, sample, argv, NULL, 0); + printf("%s%s(%d%s, \"%s\"%s, [\"%s\"], NULL, 0) = %s\n", + my_secontext, "execveat", + cwd_fd, cwd_secontext, + sample, sample_secontext, + argv[0], + sprintrc(rc)); + + /* cwd_fd ignored when path is absolute */ + if (chdir("../..")) + perror_msg_and_fail("chdir"); + + rc = syscall(__NR_execveat, cwd_fd, sample_realpath, argv, NULL, 0); + printf("%s%s(%d%s, \"%s\"%s, [\"%s\"], NULL, 0) = %s\n", + my_secontext, "execveat", + cwd_fd, cwd_secontext, + sample_realpath, sample_secontext, + argv[0], + sprintrc(rc)); + + if (fchdir(cwd_fd)) + perror_msg_and_fail("fchdir"); + + if (unlink(sample)) + perror_msg_and_fail("unlink"); + + leave_and_remove_subdir(); +} + # define FILENAME "test.execveat\nfilename" # define Q_FILENAME "test.execveat\\nfilename" @@ -40,9 +133,10 @@ main(void) { const char ** const tail_argv = tail_memdup(argv, sizeof(argv)); const char ** const tail_envp = tail_memdup(envp, sizeof(envp)); + char *my_secontext = SECONTEXT_PID_MY(); syscall(__NR_execveat, -100, FILENAME, tail_argv, tail_envp, 0x1100); - printf("execveat(AT_FDCWD, \"%s\"" + printf("%s%s(AT_FDCWD, \"%s\"" ", [\"%s\", \"%s\", \"%s\", %p, %p, %p, ... /* %p */]" # if VERBOSE ", [\"%s\", \"%s\", %p, %p, %p, ... /* %p */]" @@ -50,6 +144,7 @@ main(void) ", %p /* 5 vars, unterminated */" # endif ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n", + my_secontext, "execveat", Q_FILENAME, q_argv[0], q_argv[1], q_argv[2], argv[3], argv[4], argv[5], (char *) tail_argv + sizeof(argv), # if VERBOSE @@ -65,13 +160,14 @@ main(void) (void) q_envp; /* workaround for clang bug #33068 */ syscall(__NR_execveat, -100, FILENAME, tail_argv, tail_envp, 0x1100); - printf("execveat(AT_FDCWD, \"%s\", [\"%s\", \"%s\", \"%s\"]" + printf("%s%s(AT_FDCWD, \"%s\", [\"%s\", \"%s\", \"%s\"]" # if VERBOSE ", [\"%s\", \"%s\"]" # else ", %p /* 2 vars */" # endif ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n", + my_secontext, "execveat", Q_FILENAME, q_argv[0], q_argv[1], q_argv[2], # if VERBOSE q_envp[0], q_envp[1], @@ -81,13 +177,14 @@ main(void) errno2name()); syscall(__NR_execveat, -100, FILENAME, tail_argv + 2, tail_envp + 1, 0x1100); - printf("execveat(AT_FDCWD, \"%s\", [\"%s\"]" + printf("%s%s(AT_FDCWD, \"%s\", [\"%s\"]" # if VERBOSE ", [\"%s\"]" # else ", %p /* 1 var */" # endif ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n", + my_secontext, "execveat", Q_FILENAME, q_argv[2], # if VERBOSE q_envp[1], @@ -101,13 +198,14 @@ main(void) *empty = NULL; syscall(__NR_execveat, -100, FILENAME, empty, empty, 0x1100); - printf("execveat(AT_FDCWD, \"%s\", []" + printf("%s%s(AT_FDCWD, \"%s\", []" # if VERBOSE ", []" # else ", %p /* 0 vars */" # endif ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n", + my_secontext, "execveat", Q_FILENAME, # if !VERBOSE empty, @@ -132,7 +230,9 @@ main(void) a[i] = b[i] = NULL; syscall(__NR_execveat, -100, FILENAME, a, b, 0x1100); - printf("execveat(AT_FDCWD, \"%s\", [\"%.*s\"...", Q_FILENAME, DEFAULT_STRLEN, a[0]); + printf("%s%s(AT_FDCWD, \"%s\", [\"%.*s\"...", + my_secontext, "execveat", + Q_FILENAME, DEFAULT_STRLEN, a[0]); for (i = 1; i < DEFAULT_STRLEN; ++i) printf(", \"%s\"", a[i]); # if VERBOSE @@ -152,7 +252,9 @@ main(void) errno2name()); syscall(__NR_execveat, -100, FILENAME, a + 1, b + 1, 0x1100); - printf("execveat(AT_FDCWD, \"%s\", [\"%s\"", Q_FILENAME, a[1]); + printf("%s%s(AT_FDCWD, \"%s\", [\"%s\"", + my_secontext, "execveat", + Q_FILENAME, a[1]); for (i = 2; i <= DEFAULT_STRLEN; ++i) printf(", \"%s\"", a[i]); # if VERBOSE @@ -167,15 +269,19 @@ main(void) errno2name()); syscall(__NR_execveat, -100, FILENAME, NULL, efault, 0x1100); - printf("execveat(AT_FDCWD, \"%s\", NULL, %p" + printf("%s%s(AT_FDCWD, \"%s\", NULL, %p" ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n", + my_secontext, "execveat", Q_FILENAME, efault, errno2name()); syscall(__NR_execveat, -100, FILENAME, efault, NULL, 0x1100); - printf("execveat(AT_FDCWD, \"%s\", %p, NULL" + printf("%s%s(AT_FDCWD, \"%s\", %p, NULL" ", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n", + my_secontext, "execveat", Q_FILENAME, efault, errno2name()); + tests_with_existing_file(); + puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/faccessat.c b/tests/faccessat.c index 670e9b21f..2b05a8b5a 100644 --- a/tests/faccessat.c +++ b/tests/faccessat.c @@ -12,12 +12,16 @@ #ifdef __NR_faccessat -# include "xmalloc.h" # include <fcntl.h> # include <stdio.h> # include <unistd.h> -# ifndef FD_PATH +# include "secontext.h" +# include "xmalloc.h" + +# ifdef FD_PATH +# define YFLAG +# else # define FD_PATH "" # endif # ifndef SKIP_IF_PROC_IS_UNAVAILABLE @@ -43,11 +47,130 @@ k_faccessat(const unsigned int dirfd, return rc; } +# ifndef PATH_TRACING +static void +tests_with_existing_file(void) +{ + /* + * Make sure the current workdir of the tracee + * is different from the current workdir of the tracer. + */ + create_and_enter_subdir("faccessat_subdir"); + + char *my_secontext = SECONTEXT_PID_MY(); + + k_faccessat(-1, NULL, F_OK); + printf("%s%s(-1, NULL, F_OK) = %s\n", + my_secontext, "faccessat", errstr); + + static const char sample[] = "faccessat_sample"; + (void) unlink(sample); + int fd = open(sample, O_CREAT|O_RDONLY, 0400); + if (fd == -1) + perror_msg_and_fail("open"); + close(fd); + char *sample_secontext = SECONTEXT_FILE(sample); + + /* + * Tests with AT_FDCWD. + */ + + k_faccessat(-100, sample, F_OK); + printf("%s%s(AT_FDCWD, \"%s\"%s, F_OK) = %s\n", + my_secontext, "faccessat", + sample, sample_secontext, + errstr); + + if (unlink(sample)) + perror_msg_and_fail("unlink"); + + k_faccessat(-100, sample, F_OK); + printf("%s%s(AT_FDCWD, \"%s\", F_OK) = %s\n", + my_secontext, "faccessat", + sample, + errstr); + + /* + * Tests with dirfd. + */ + + int cwd_fd = get_dir_fd("."); + char *cwd = get_fd_path(cwd_fd); + char *cwd_secontext = SECONTEXT_FILE("."); + char *sample_realpath = xasprintf("%s/%s", cwd, sample); + + /* no file */ + k_faccessat(cwd_fd, sample, F_OK); +# ifdef YFLAG + printf("%s%s(%d<%s>%s, \"%s\", F_OK) = %s\n", +# else + printf("%s%s(%d%s, \"%s\", F_OK) = %s\n", +# endif + my_secontext, "faccessat", + cwd_fd, +# ifdef YFLAG + cwd, +# endif + cwd_secontext, + sample, + errstr); + + fd = open(sample, O_CREAT|O_RDONLY, 0400); + if (fd == -1) + perror_msg_and_fail("open"); + close(fd); + + k_faccessat(cwd_fd, sample, F_OK); +# ifdef YFLAG + printf("%s%s(%d<%s>%s, \"%s\"%s, F_OK) = %s\n", +# else + printf("%s%s(%d%s, \"%s\"%s, F_OK) = %s\n", +# endif + my_secontext, "faccessat", + cwd_fd, +# ifdef YFLAG + cwd, +# endif + cwd_secontext, + sample, sample_secontext, + errstr); + + /* cwd_fd ignored when path is absolute */ + if (chdir("../..")) + perror_msg_and_fail("chdir"); + + k_faccessat(cwd_fd, sample_realpath, F_OK); +# ifdef YFLAG + printf("%s%s(%d<%s>%s, \"%s\"%s, F_OK) = %s\n", +# else + printf("%s%s(%d%s, \"%s\"%s, F_OK) = %s\n", +# endif + my_secontext, "faccessat", + cwd_fd, +# ifdef YFLAG + cwd, +# endif + cwd_secontext, + sample_realpath, sample_secontext, + errstr); + + if (fchdir(cwd_fd)) + perror_msg_and_fail("fchdir"); + + if (unlink(sample)) + perror_msg_and_fail("unlink"); + + leave_and_remove_subdir(); +} +# endif + int main(void) { SKIP_IF_PROC_IS_UNAVAILABLE; +# ifndef TEST_SECONTEXT + TAIL_ALLOC_OBJECT_CONST_PTR(const char, unterminated); char *unterminated_str = xasprintf("%p", unterminated); const void *const efault = unterminated + 1; @@ -120,10 +243,10 @@ main(void) k_faccessat(dirfds[dirfd_i].val, paths[path_i].val, modes[mode_i].val); -# ifdef PATH_TRACING +# ifdef PATH_TRACING if (dirfds[dirfd_i].val == fd || paths[path_i].val == fd_path) -# endif +# endif printf("faccessat(%s, %s, %s) = %s\n", dirfds[dirfd_i].str, paths[path_i].str, @@ -133,6 +256,12 @@ main(void) } } +# endif /* !TEST_SECONTEXT */ + +# ifndef PATH_TRACING + tests_with_existing_file(); +# endif + puts("+++ exited with 0 +++"); return 0; } diff --git a/tests/faccessat.test b/tests/faccessat.test index 83f94ba40..325e343b7 100755 --- a/tests/faccessat.test +++ b/tests/faccessat.test @@ -15,5 +15,5 @@ run_prog > /dev/null run_strace -a23 --trace=faccessat "$@" $args > "$EXP" # Filter out faccessat() calls made by ld.so and libc. -sed -n '/^faccessat(-1, NULL,/,$p' < "$LOG" > "$OUT" +sed -n '/faccessat(-1, NULL,/,$p' < "$LOG" > "$OUT" match_diff "$OUT" "$EXP" diff --git a/tests/fanotify_mark.c b/tests/fanotify_mark.c index bd14f4790..15eab3e01 100644 --- a/tests/fanotify_mark.c +++ b/tests/fanotify_mark.c @@ -3,7 +3,7 @@ * * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@strace.io> * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com> - * Copyright (c) 2015-2020 The strace developers. + * Copyright (c) 2015-2021 The strace developers. * All rights reserved. * * SPDX-License-Identifier: GPL-2.0-or-later @@ -21,6 +21,8 @@ # include <unistd.h> # include <sys/fanotify.h> +# include "secontext.h" + # if XLAT_RAW # define str_fan_mark_add "0x1" # define str_fan_modify_ondir "0x40000002" @@ -35,6 +37,7 @@ # define str_at_fdcwd "AT_FDCWD" # endif +# ifndef TEST_SECONTEXT /* Performs fanotify_mark call via the syscall interface. */ static void do_call(kernel_ulong_t fd, kernel_ulong_t flags, const char *flags_str, @@ -44,18 +47,18 @@ do_call(kernel_ulong_t fd, kernel_ulong_t flags, const char *flags_str, long rc; rc = syscall(__NR_fanotify_mark, fd, flags, -# if (LONG_MAX > INT_MAX) \ - || (defined __x86_64__ && defined __ILP32__) \ - || defined LINUX_MIPSN32 +# if (LONG_MAX > INT_MAX) \ + || (defined __x86_64__ && defined __ILP32__) \ + || defined LINUX_MIPSN32 mask, -# else +# else /* arch/parisc/kernel/sys_parisc32.c, commit ab8a261b */ -# ifdef HPPA +# ifdef HPPA LL_VAL_TO_PAIR((mask << 32) | (mask >> 32)), -# else +# else LL_VAL_TO_PAIR(mask), +# endif # endif -# endif dirfd, path); printf("fanotify_mark(%d, %s, %s, %s, %s) = %s\n", @@ -68,12 +71,14 @@ struct strval { const char *str; }; -# define STR16 "0123456789abcdef" -# define STR64 STR16 STR16 STR16 STR16 +# define STR16 "0123456789abcdef" +# define STR64 STR16 STR16 STR16 STR16 +# endif /* !TEST_SECONTEXT */ int main(void) { +# ifndef TEST_SECONTEXT enum { PATH1_SIZE = 64, }; @@ -87,47 +92,47 @@ main(void) { F8ILL_KULONG_MASK, "0" }, { (kernel_ulong_t) 0xdec0deddefacec00ULL, "0xefacec00" -# if !XLAT_RAW +# if !XLAT_RAW " /* FAN_MARK_??? */" -# endif +# endif }, { (kernel_ulong_t) 0xda7a105700000040ULL, -# if XLAT_RAW +# if XLAT_RAW "0x40" -# elif XLAT_VERBOSE +# elif XLAT_VERBOSE "0x40 /* FAN_MARK_IGNORED_SURV_MODIFY */" -# else +# else "FAN_MARK_IGNORED_SURV_MODIFY" -# endif +# endif }, { (kernel_ulong_t) 0xbadc0deddeadffffULL, -# if XLAT_RAW || XLAT_VERBOSE +# if XLAT_RAW || XLAT_VERBOSE "0xdeadffff" -# endif -# if XLAT_VERBOSE +# endif +# if XLAT_VERBOSE " /* " -# endif -# if !XLAT_RAW +# endif +# if !XLAT_RAW "FAN_MARK_ADD|FAN_MARK_REMOVE|FAN_MARK_DONT_FOLLOW|" "FAN_MARK_ONLYDIR|FAN_MARK_MOUNT|FAN_MARK_IGNORED_MASK|" "FAN_MARK_IGNORED_SURV_MODIFY|FAN_MARK_FLUSH|" "FAN_MARK_FILESYSTEM|0xdeadfe00" -# endif -# if XLAT_VERBOSE +# endif +# if XLAT_VERBOSE " */" -# endif +# endif }, }; static const struct strval64 masks[] = { { ARG_ULL_STR(0) }, { 0xdeadfeedffffffffULL, -# if XLAT_RAW || XLAT_VERBOSE +# if XLAT_RAW || XLAT_VERBOSE "0xdeadfeedffffffff" -# endif -# if XLAT_VERBOSE +# endif +# if XLAT_VERBOSE " /* " -# endif -# if !XLAT_RAW +# endif +# if !XLAT_RAW "FAN_ACCESS|" "FAN_MODIFY|" "FAN_ATTRIB|" @@ -149,27 +154,27 @@ main(void) "FAN_ONDIR|" "FAN_EVENT_ON_CHILD|" "0xdeadfeedb7f0a000" -# endif -# if XLAT_VERBOSE +# endif +# if XLAT_VERBOSE " */" -# endif +# endif }, { ARG_ULL_STR(0xffffffffb7f0a000) -# if !XLAT_RAW +# if !XLAT_RAW " /* FAN_??? */" -# endif +# endif }, }; static const struct strval dirfds[] = { { (kernel_ulong_t) 0xfacefeed00000001ULL, "1" }, { (kernel_ulong_t) 0xdec0ded0ffffffffULL, -# if XLAT_RAW +# if XLAT_RAW "-1" -# elif XLAT_VERBOSE +# elif XLAT_VERBOSE "-1 /* FAN_NOFD */" -# else +# else "FAN_NOFD" -# endif +# endif }, { (kernel_ulong_t) 0xbadfacedffffff9cULL, str_at_fdcwd }, { (kernel_ulong_t) 0xdefaced1beeff00dULL, "-1091571699" }, @@ -202,12 +207,6 @@ main(void) snprintf(bogus_path1_after_addr, sizeof(bogus_path1_after_addr), "%p", bogus_path1 + PATH1_SIZE); - rc = fanotify_mark(-1, FAN_MARK_ADD, FAN_MODIFY | FAN_ONDIR, - -100, "."); - printf("fanotify_mark(-1, %s, %s, %s, \".\") = %s\n", - str_fan_mark_add, str_fan_modify_ondir, str_at_fdcwd, - sprintrc(rc)); - for (i = 0; i < ARRAY_SIZE(fds); i++) { for (j = 0; j < ARRAY_SIZE(flags); j++) { for (k = 0; k < ARRAY_SIZE(masks); k++) { @@ -226,6 +225,40 @@ main(void) } } } +# else /* TEST_SECONTEXT */ + int rc; +# endif + /* + * Test with AT_FDCWD. + */ + + char *my_secontext = SECONTEXT_PID_MY(); + char path[] = "."; + char *path_secontext = SECONTEXT_FILE(path); + + rc = fanotify_mark(-1, FAN_MARK_ADD, FAN_MODIFY | FAN_ONDIR, + -100, path); + printf("%s%s(-1, %s, %s, %s, \"%s\"%s) = %s\n", + my_secontext, "fanotify_mark", + str_fan_mark_add, str_fan_modify_ondir, str_at_fdcwd, + path, path_secontext, + sprintrc(rc)); + + /* + * Test with dirfd. + */ + + int cwd_fd = get_dir_fd("."); + char *cwd_secontext = SECONTEXT_FILE("."); + + rc = fanotify_mark(-1, FAN_MARK_ADD, FAN_MODIFY | FAN_ONDIR, + cwd_fd, path); + printf("%s%s(-1, %s, %s, %d%s, \"%s\"%s) = %s\n", + my_secontext, "fanotify_mark", + str_fan_mark_add, str_fan_modify_ondir, + cwd_fd, cwd_secontext, + path, path_secontext, + sprintrc(rc)); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/fchmod.c b/tests/fchmod.c index 4da4f0658..0b0570cfe 100644 --- a/tests/fchmod.c +++ b/tests/fchmod.c @@ -18,6 +18,8 @@ # include <stdio.h> # include <unistd.h> +# include "secontext.h" + int main(void) { @@ -27,6 +29,8 @@ main(void) */ create_and_enter_subdir("fchmod_subdir"); + char *my_secontext = SECONTEXT_PID_MY(); + static const char sample[] = "fchmod_sample_file"; (void) unlink(sample); int fd = open(sample, O_CREAT|O_RDONLY, 0400); @@ -37,16 +41,19 @@ main(void) char *sample_realpath = get_fd_path(fd); # endif + const char *sample_secontext = SECONTEXT_FILE(sample); long rc = syscall(__NR_fchmod, fd, 0600); # ifdef YFLAG - printf("fchmod(%d<%s>, 0600) = %s\n", + printf("%s%s(%d<%s>%s, 0600) = %s\n", # else - printf("fchmod(%d, 0600) = %s\n", + printf("%s%s(%d%s, 0600) = %s\n", # endif + my_secontext, "fchmod", fd, # ifdef YFLAG sample_realpath, # endif + sample_secontext, sprintrc(rc)); if (unlink(sample)) @@ -54,26 +61,30 @@ main(void) rc = syscall(__NR_fchmod, fd, 051); # ifdef YFLAG - printf("fchmod(%d<%s (deleted)>, 051) = %s\n", + printf("%s%s(%d<%s (deleted)>%s, 051) = %s\n", # else - printf("fchmod(%d, 051) = %s\n", + printf("%s%s(%d%s, 051) = %s\n", # endif + my_secontext, "fchmod", fd, # ifdef YFLAG sample_realpath, # endif + sample_secontext, sprintrc(rc)); rc = syscall(__NR_fchmod, fd, 004); # ifdef YFLAG - printf("fchmod(%d<%s (deleted)>, 004) = %s\n", + printf("%s%s(%d<%s (deleted)>%s, 004) = %s\n", # else - printf("fchmod(%d, 004) = %s\n", + printf("%s%s(%d%s, 004) = %s\n", # endif + my_secontext, "fchmod", fd, # ifdef YFLAG sample_realpath, # endif + sample_secontext, sprintrc(rc)); leave_and_remove_subdir(); diff --git a/tests/fchmodat.c b/tests/fchmodat.c index 37dc6b563..2c69f4624 100644 --- a/tests/fchmodat.c +++ b/tests/fchmodat.c @@ -17,6 +17,8 @@ # include <stdio.h> # include <unistd.h> +# include "secontext.h" + int main(void) { @@ -26,26 +28,81 @@ main(void) */ create_and_enter_subdir("fchmodat_subdir"); - static const char sample[] = "fchmodat_sample"; + char *my_secontext = SECONTEXT_PID_MY(); + static const char sample[] = "fchmodat_sample_file"; if (open(sample, O_RDONLY | O_CREAT, 0400) < 0) perror_msg_and_fail("open"); + char *sample_secontext = SECONTEXT_FILE(sample); + + /* + * Tests with AT_FDCWD. + */ + long rc = syscall(__NR_fchmodat, -100, sample, 0600); - printf("fchmodat(AT_FDCWD, \"%s\", 0600) = %s\n", - sample, sprintrc(rc)); + printf("%s%s(AT_FDCWD, \"%s\"%s, 0600) = %s\n", + my_secontext, "fchmodat", + sample, sample_secontext, + sprintrc(rc)); if (unlink(sample)) perror_msg_and_fail("unlink"); rc = syscall(__NR_fchmodat, -100, sample, 051); - printf("fchmodat(AT_FDCWD, \"%s\", 051) = %s\n", + printf("%s%s(AT_FDCWD, \"%s\", 051) = %s\n", + my_secontext, "fchmodat", sample, sprintrc(rc)); rc = syscall(__NR_fchmodat, -100, sample, 004); - printf("fchmodat(AT_FDCWD, \"%s\", 004) = %s\n", + printf("%s%s(AT_FDCWD, \"%s\", 004) = %s\n", + my_secontext, "fchmodat", sample, sprintrc(rc)); + /* + * Tests with dirfd. + */ + + int cwd_fd = get_dir_fd("."); + char *cwd = get_fd_path(cwd_fd); + char *cwd_secontext = SECONTEXT_FILE("."); + char *sample_realpath = xasprintf("%s/%s", cwd, sample); + + /* no file */ + rc = syscall(__NR_fchmodat, cwd_fd, sample, 0400); + printf("%s%s(%d%s, \"%s\", 0400) = %s\n", + my_secontext, "fchmodat", + cwd_fd, cwd_secontext, + sample, + sprintrc(rc)); + + if (open(sample, O_RDONLY | O_CREAT, 0400) < 0) + perror_msg_and_fail("open"); + + rc = syscall(__NR_fchmodat, cwd_fd, sample, 0400); + printf("%s%s(%d%s, \"%s\"%s, 0400) = %s\n", + my_secontext, "fchmodat", + cwd_fd, cwd_secontext, + sample, sample_secontext, + sprintrc(rc)); + + /* cwd_fd ignored when path is absolute */ + if (chdir("../..")) + perror_msg_and_fail("chdir"); + + rc = syscall(__NR_fchmodat, cwd_fd, sample_realpath, 0400); + printf("%s%s(%d%s, \"%s\"%s, 0400) = %s\n", + my_secontext, "fchmodat", + cwd_fd, cwd_secontext, + sample_realpath, sample_secontext, + sprintrc(rc)); + + if (fchdir(cwd_fd)) + perror_msg_and_fail("fchdir"); + + if (unlink(sample)) + perror_msg_and_fail("unlink"); + leave_and_remove_subdir(); puts("+++ exited with 0 +++"); diff --git a/tests/fchownat.c b/tests/fchownat.c index 766fd0241..bebb25445 100644 --- a/tests/fchownat.c +++ b/tests/fchownat.c @@ -17,6 +17,8 @@ # include <stdio.h> # include <unistd.h> +# include "secontext.h" + int main(void) { @@ -26,25 +28,86 @@ main(void) */ create_and_enter_subdir("fchownat_subdir"); - static const char sample[] = "fchownat_sample"; + char *my_secontext = SECONTEXT_PID_MY(); uid_t uid = geteuid(); uid_t gid = getegid(); - if (open(sample, O_RDONLY | O_CREAT, 0400) == -1) + static const char sample[] = "fchownat_sample"; + int fd = open(sample, O_RDONLY | O_CREAT, 0400); + if (fd == -1) perror_msg_and_fail("open"); + close(fd); + + char *sample_secontext = SECONTEXT_FILE(sample); + + /* + * Tests with AT_FDCWD. + */ long rc = syscall(__NR_fchownat, AT_FDCWD, sample, uid, gid, 0); - printf("fchownat(AT_FDCWD, \"%s\", %d, %d, 0) = %s\n", - sample, uid, gid, sprintrc(rc)); + printf("%s%s(AT_FDCWD, \"%s\"%s, %d, %d, 0) = %s\n", + my_secontext, "fchownat", + sample, sample_secontext, + uid, gid, sprintrc(rc)); if (unlink(sample)) perror_msg_and_fail("unlink"); rc = syscall(__NR_fchownat, AT_FDCWD, sample, -1, -1L, AT_SYMLINK_NOFOLLOW); - printf("fchownat(AT_FDCWD, \"%s\", -1, -1, AT_SYMLINK_NOFOLLOW) = %s\n", + printf("%s%s(AT_FDCWD, \"%s\", -1, -1, AT_SYMLINK_NOFOLLOW) = %s\n", + my_secontext, "fchownat", sample, sprintrc(rc)); + /* + * Tests with dirfd. + */ + + int cwd_fd = get_dir_fd("."); + char *cwd = get_fd_path(cwd_fd); + char *cwd_secontext = SECONTEXT_FILE("."); + char *sample_realpath = xasprintf("%s/%s", cwd, sample); + + /* no file */ + rc = syscall(__NR_fchownat, cwd_fd, sample, uid, gid, 0); + printf("%s%s(%d%s, \"%s\", %d, %d, 0) = %s\n", + my_secontext, "fchownat", + cwd_fd, cwd_secontext, + sample, + uid, gid, + sprintrc(rc)); + + fd = open(sample, O_RDONLY | O_CREAT, 0400); + if (fd == -1) + perror_msg_and_fail("open"); + close(fd); + + rc = syscall(__NR_fchownat, cwd_fd, sample, uid, gid, 0); + printf("%s%s(%d%s, \"%s\"%s, %d, %d, 0) = %s\n", + my_secontext, "fchownat", + cwd_fd, cwd_secontext, + sample, sample_secontext, + uid, gid, + sprintrc(rc)); + + /* cwd_fd ignored when path is absolute */ + if (chdir("../..")) + perror_msg_and_fail("chdir"); + + rc = syscall(__NR_fchownat, cwd_fd, sample_realpath, uid, gid, 0); + printf("%s%s(%d%s, \"%s\"%s, %d, %d, 0) = %s\n", + my_secontext, "fchownat", + cwd_fd, cwd_secontext, + sample_realpath, sample_secontext, + uid, gid, + sprintrc(rc)); + + if (fchdir(cwd_fd)) + perror_msg_and_fail("fchdir"); + + if (unlink(sample)) + perror_msg_and_fail("unlink"); + leave_and_remove_subdir(); puts("+++ exited with 0 +++"); diff --git a/tests/file_handle.c b/tests/file_handle.c index e6a69910b..86d51b636 100644 --- a/tests/file_handle.c +++ b/tests/file_handle.c @@ -21,6 +21,8 @@ # include <stdio.h> # include <unistd.h> +# include "secontext.h" + enum assert_rc { ASSERT_NONE, ASSERT_SUCCESS, @@ -48,6 +50,7 @@ print_handle_data(unsigned char *bytes, unsigned int size) printf("..."); } +# ifndef TEST_SECONTEXT void do_name_to_handle_at(kernel_ulong_t dirfd, const char *dirfd_str, kernel_ulong_t pathname, const char *pathname_str, @@ -129,6 +132,7 @@ do_open_by_handle_at(kernel_ulong_t mount_fd, printf("%s\n", sprintrc(rc)); } +# endif /* !TEST_SECONTEXT */ struct strval { kernel_ulong_t val; @@ -141,12 +145,86 @@ struct strval { int main(void) { + char *my_secontext = SECONTEXT_PID_MY(); enum { PATH1_SIZE = 64, }; static const kernel_ulong_t fdcwd = (kernel_ulong_t) 0x87654321ffffff9cULL; + + struct file_handle *handle = + tail_alloc(sizeof(struct file_handle) + MAX_HANDLE_SZ); + struct file_handle *handle_0 = + tail_alloc(sizeof(struct file_handle) + 0); + struct file_handle *handle_8 = + tail_alloc(sizeof(struct file_handle) + 8); + struct file_handle *handle_128 = + tail_alloc(sizeof(struct file_handle) + 128); + struct file_handle *handle_256 = + tail_alloc(sizeof(struct file_handle) + 256); + TAIL_ALLOC_OBJECT_CONST_PTR(int, bogus_mount_id); + + char handle_0_addr[sizeof("0x") + sizeof(void *) * 2]; + + const int flags = 0x400; + int mount_id; + + handle_0->handle_bytes = 256; + handle_8->handle_bytes = 0; + handle_128->handle_bytes = 128; + handle_256->handle_bytes = 256; + + fill_memory((char *) handle_128 + sizeof(struct file_handle), 128); + fill_memory((char *) handle_256 + sizeof(struct file_handle), 256); + + snprintf(handle_0_addr, sizeof(handle_0_addr), "%p", + handle_0 + sizeof(struct file_handle)); + + handle->handle_bytes = 0; + + char path[] = "."; + char *path_secontext = SECONTEXT_FILE(path); + + assert(syscall(__NR_name_to_handle_at, fdcwd, path, handle, &mount_id, + flags | 1) == -1); + if (EINVAL != errno) + perror_msg_and_skip("name_to_handle_at"); + printf("%s%s(AT_FDCWD, \"%s\"%s, {handle_bytes=0}, %p" + ", AT_SYMLINK_FOLLOW|0x1) = -1 EINVAL (%m)\n", + my_secontext, "name_to_handle_at", + path, path_secontext, + &mount_id); + + assert(syscall(__NR_name_to_handle_at, fdcwd, path, handle, &mount_id, + flags) == -1); + if (EOVERFLOW != errno) + perror_msg_and_skip("name_to_handle_at"); + printf("%s%s(AT_FDCWD, \"%s\"%s, {handle_bytes=0 => %u}" + ", %p, AT_SYMLINK_FOLLOW) = -1 EOVERFLOW (%m)\n", + my_secontext, "name_to_handle_at", + path, path_secontext, + handle->handle_bytes, &mount_id); + + assert(syscall(__NR_name_to_handle_at, fdcwd, path, handle, &mount_id, + flags) == 0); + printf("%s%s(AT_FDCWD, \"%s\"%s, {handle_bytes=%u" + ", handle_type=%d, f_handle=", + my_secontext, "name_to_handle_at", + path, path_secontext, + handle->handle_bytes, handle->handle_type); + print_handle_data(handle->f_handle, handle->handle_bytes); + printf("}, [%d], AT_SYMLINK_FOLLOW) = 0\n", mount_id); + + printf("%s%s(-1, {handle_bytes=%u, handle_type=%d, f_handle=", + my_secontext, "open_by_handle_at", + handle->handle_bytes, handle->handle_type); + print_handle_data(handle->f_handle, handle->handle_bytes); + int rc = syscall(__NR_open_by_handle_at, -1, handle, + O_RDONLY | O_DIRECTORY); + printf("}, O_RDONLY|O_DIRECTORY) = %d %s (%m)\n", rc, errno2name()); + +# ifndef TEST_SECONTEXT static const struct strval dirfds[] = { { (kernel_ulong_t) 0xdeadca57badda7a1ULL, "-1159878751" }, { (kernel_ulong_t) 0x12345678ffffff9cULL, "AT_FDCWD" }, @@ -171,29 +249,11 @@ main(void) }; static const char str64[] = STR64; - - char *bogus_path1 = tail_memdup(str64, PATH1_SIZE); char *bogus_path2 = tail_memdup(str64, sizeof(str64)); - - struct file_handle *handle = - tail_alloc(sizeof(struct file_handle) + MAX_HANDLE_SZ); - struct file_handle *handle_0 = - tail_alloc(sizeof(struct file_handle) + 0); - struct file_handle *handle_8 = - tail_alloc(sizeof(struct file_handle) + 8); - struct file_handle *handle_128 = - tail_alloc(sizeof(struct file_handle) + 128); - struct file_handle *handle_256 = - tail_alloc(sizeof(struct file_handle) + 256); - TAIL_ALLOC_OBJECT_CONST_PTR(int, bogus_mount_id); - - char handle_0_addr[sizeof("0x") + sizeof(void *) * 2]; - char bogus_path1_addr[sizeof("0x") + sizeof(void *) * 2]; char bogus_path1_after_addr[sizeof("0x") + sizeof(void *) * 2]; - struct strval paths[] = { { (kernel_ulong_t) 0, "NULL" }, { (kernel_ulong_t) (uintptr_t) (bogus_path1 + PATH1_SIZE), @@ -229,62 +289,16 @@ main(void) (kernel_ulong_t) (uintptr_t) bogus_mount_id, }; - const int flags = 0x400; - int mount_id; unsigned int i; unsigned int j; unsigned int k; unsigned int l; unsigned int m; - snprintf(bogus_path1_addr, sizeof(bogus_path1_addr), "%p", bogus_path1); snprintf(bogus_path1_after_addr, sizeof(bogus_path1_after_addr), "%p", bogus_path1 + PATH1_SIZE); - handle_0->handle_bytes = 256; - handle_8->handle_bytes = 0; - handle_128->handle_bytes = 128; - handle_256->handle_bytes = 256; - - fill_memory((char *) handle_128 + sizeof(struct file_handle), 128); - fill_memory((char *) handle_256 + sizeof(struct file_handle), 256); - - snprintf(handle_0_addr, sizeof(handle_0_addr), "%p", - handle_0 + sizeof(struct file_handle)); - - handle->handle_bytes = 0; - - assert(syscall(__NR_name_to_handle_at, fdcwd, ".", handle, &mount_id, - flags | 1) == -1); - if (EINVAL != errno) - perror_msg_and_skip("name_to_handle_at"); - printf("name_to_handle_at(AT_FDCWD, \".\", {handle_bytes=0}, %p" - ", AT_SYMLINK_FOLLOW|0x1) = -1 EINVAL (%m)\n", &mount_id); - - assert(syscall(__NR_name_to_handle_at, fdcwd, ".", handle, &mount_id, - flags) == -1); - if (EOVERFLOW != errno) - perror_msg_and_skip("name_to_handle_at"); - printf("name_to_handle_at(AT_FDCWD, \".\", {handle_bytes=0 => %u}" - ", %p, AT_SYMLINK_FOLLOW) = -1 EOVERFLOW (%m)\n", - handle->handle_bytes, &mount_id); - - assert(syscall(__NR_name_to_handle_at, fdcwd, ".", handle, &mount_id, - flags) == 0); - printf("name_to_handle_at(AT_FDCWD, \".\", {handle_bytes=%u" - ", handle_type=%d, f_handle=", - handle->handle_bytes, handle->handle_type); - print_handle_data(handle->f_handle, handle->handle_bytes); - printf("}, [%d], AT_SYMLINK_FOLLOW) = 0\n", mount_id); - - printf("open_by_handle_at(-1, {handle_bytes=%u, handle_type=%d" - ", f_handle=", handle->handle_bytes, handle->handle_type); - print_handle_data(handle->f_handle, handle->handle_bytes); - int rc = syscall(__NR_open_by_handle_at, -1, handle, - O_RDONLY | O_DIRECTORY); - printf("}, O_RDONLY|O_DIRECTORY) = %d %s (%m)\n", rc, errno2name()); - for (i = 0; i < ARRAY_SIZE(dirfds); i++) { for (j = 0; j < ARRAY_SIZE(paths); j++) { for (k = 0; k < ARRAY_SIZE(name_handles); k++) { @@ -320,6 +334,68 @@ main(void) } } } +# endif + + /* + * Tests with dirfd. + */ + + int cwd_fd = get_dir_fd("."); + char *cwd = get_fd_path(cwd_fd); + char *cwd_secontext = SECONTEXT_FILE("."); + + assert(syscall(__NR_name_to_handle_at, cwd_fd, path, handle, &mount_id, + flags) == 0); + printf("%s%s(%d%s, \"%s\"%s, {handle_bytes=%u, handle_type=%d" + ", f_handle=", + my_secontext, "name_to_handle_at", + cwd_fd, cwd_secontext, + path, path_secontext, + handle->handle_bytes, handle->handle_type); + print_handle_data((unsigned char *) handle + + sizeof(struct file_handle), + handle->handle_bytes); + printf("}, [%d], AT_SYMLINK_FOLLOW) = 0\n", mount_id); + + printf("%s%s(-1, {handle_bytes=%u, handle_type=%d, f_handle=", + my_secontext, "open_by_handle_at", + handle->handle_bytes, handle->handle_type); + print_handle_data((unsigned char *) handle + + sizeof(struct file_handle), + handle->handle_bytes); + rc = syscall(__NR_open_by_handle_at, -1, handle, + O_RDONLY | O_DIRECTORY); + printf("}, O_RDONLY|O_DIRECTORY) = %s\n", sprintrc(rc)); + + /* cwd_fd ignored when path is absolute */ + if (chdir("..")) + perror_msg_and_fail("chdir"); + + assert(syscall(__NR_name_to_handle_at, cwd_fd, cwd, handle, &mount_id, + flags) == 0); + printf("%s%s(%d%s, \"%s\"%s, {handle_bytes=%u" + ", handle_type=%d, f_handle=", + my_secontext, "name_to_handle_at", + cwd_fd, cwd_secontext, + cwd, cwd_secontext, + handle->handle_bytes, handle->handle_type); + print_handle_data((unsigned char *) handle + + sizeof(struct file_handle), + handle->handle_bytes); + printf("}, [%d], AT_SYMLINK_FOLLOW) = 0\n", mount_id); + + printf("%s%s(-1, {handle_bytes=%u, handle_type=%d, f_handle=", + my_secontext, "open_by_handle_at", + handle->handle_bytes, handle->handle_type); + print_handle_data((unsigned char *) handle + + sizeof(struct file_handle), + handle->handle_bytes); + rc = syscall(__NR_open_by_handle_at, -1, handle, + O_RDONLY | O_DIRECTORY); + printf("}, O_RDONLY|O_DIRECTORY) = %s\n", sprintrc(rc)); + + if (fchdir(cwd_fd)) + perror_msg_and_fail("fchdir"); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/gen_secontext.sh b/tests/gen_secontext.sh new file mode 100755 index 000000000..407a39b9f --- /dev/null +++ b/tests/gen_secontext.sh @@ -0,0 +1,72 @@ +#!/bin/sh -efu +# +# Copyright (c) 2021 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +usage() +{ + cat >&2 <<EOF +Usage: $0 [<input>] + +Generate secontext files from <input> list. +EOF + exit 1 +} + +if [ $# -eq 0 ]; then + input="${0%/*}/gen_tests.in" +else + input="$1" + shift +fi +dir="$(dirname "$input")" +[ $# -eq 0 ] || usage + +{ + cat <<EOF +# Generated by $0 from $input; do not edit. + +secontext_EXECUTABLES = \\ +EOF + sed -r -n 's/^([^#[:space:]]+--secontext(_full)?)[[:space:]].*/ \1 \\/p' < "$input" + cat <<EOF + # + +EOF + sed -r -n 's/-/_/g; s/^([^#[:space:]]+__secontext(_full)?)[[:space:]].*/\1_LDADD = \$(LDADD) \$(libselinux_LDADD)/p' < "$input" +} > "$dir/secontext.am" + +sed -r -n 's/^([^#[:space:]]+--secontext)[[:space:]].*/\1/p' < "$input" | +while read -r name; do { + cat <<-EOF > "$dir/$name.c" + /* + * Copyright (c) 2021 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + #include "tests.h" + + #ifdef HAVE_SELINUX_RUNTIME + + # define TEST_SECONTEXT + # include "${name%--secontext}.c" + + #else + + SKIP_MAIN_UNDEFINED("HAVE_SELINUX_RUNTIME") + + #endif + EOF +} < /dev/null; done + +sed -r -n 's/^([^#[:space:]]+--secontext_full)[[:space:]].*/\1/p' < "$input" | +while read -r name; do { + cat <<-EOF > "$dir/$name.c" + #define PRINT_SECONTEXT_FULL + #include "${name%_full}.c" + EOF +} < /dev/null; done diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 93702bafe..5ca88e29a 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -10,6 +10,8 @@ _newselect-P -e trace=_newselect -P /dev/full 9>>/dev/full accept -a22 accept4 -a37 access -a30 --trace-path=access_sample +access--secontext -a30 --secontext --trace-path=access_sample -e trace=access +access--secontext_full -a30 --secontext=full --trace-path=access_sample -e trace=access acct -a20 add_key -a30 -s12 adjtimex -a15 @@ -25,6 +27,8 @@ bpf-v -a20 -v -e trace=bpf btrfs +ioctl.test chdir -a10 chmod -a28 +chmod--secontext -a28 --secontext -e trace=chmod +chmod--secontext_full -a28 --secontext=full -e trace=chmod chown -a28 chown32 -a31 chroot -a13 @@ -81,10 +85,18 @@ epoll_pwait2-P --trace=epoll_pwait2 -P /dev/full epoll_pwait2-y --trace=epoll_pwait2 -y epoll_wait -a26 erestartsys -a34 -e signal=none -e trace=recvfrom +execve--secontext +execve.test --secontext +execve--secontext_full +execve.test --secontext=full execveat +execveat--secontext --secontext --trace=execveat +execveat--secontext_full --secontext=full --trace=execveat execveat-v -v -e trace=execveat +faccessat--secontext +faccessat.test -a24 --secontext +faccessat--secontext_full +faccessat.test -a24 --secontext=full faccessat-P -a23 --trace=faccessat -P /dev/full faccessat-y +faccessat.test -a24 -y +faccessat-y--secontext +faccessat.test -a24 -y --secontext +faccessat-y--secontext_full +faccessat.test -a24 -y --secontext=full faccessat-yy +faccessat.test -a24 -yy faccessat2-P -a27 --trace=faccessat2 -P /dev/full faccessat2-y +faccessat2.test -a28 -y @@ -93,22 +105,34 @@ fadvise64_64 +fadvise64.test fallocate -a18 fanotify_init fanotify_mark -a32 +fanotify_mark--secontext -a32 --secontext -e trace=fanotify_mark +fanotify_mark--secontext_full -a32 --secontext=full -e trace=fanotify_mark fanotify_mark-Xabbrev -a32 -Xabbrev -e trace=fanotify_mark fanotify_mark-Xraw -a32 -Xraw -e trace=fanotify_mark fanotify_mark-Xverbose -a32 -Xverbose -e trace=fanotify_mark fchdir -a11 fchmod -a15 +fchmod--secontext -a15 --secontext -e trace=fchmod +fchmod--secontext_full -a15 --secontext=full -e trace=fchmod fchmod-y -y -e trace=fchmod +fchmod-y--secontext -a15 -y --secontext -e trace=fchmod +fchmod-y--secontext_full -a15 -y --secontext=full -e trace=fchmod fchmodat +fchmodat--secontext --secontext -e trace=fchmodat +fchmodat--secontext_full --secontext=full -e trace=fchmodat fchown -a16 fchown32 -a18 fchownat +fchownat--secontext --secontext -e trace=fchownat +fchownat--secontext_full --secontext=full -e trace=fchownat fcntl -a8 fcntl--pidns-translation test_pidns -a8 -e trace=fcntl fcntl64 -a8 fcntl64--pidns-translation test_pidns -a8 -e trace=fcntl64 fdatasync -a14 file_handle -e trace=name_to_handle_at,open_by_handle_at +file_handle--secontext --secontext -e trace=name_to_handle_at,open_by_handle_at +file_handle--secontext_full --secontext=full -e trace=name_to_handle_at,open_by_handle_at filter_seccomp . "${srcdir=.}/filter_seccomp.sh"; test_prog_set --seccomp-bpf -f filter_seccomp-flag ../$NAME finit_module -a25 @@ -353,6 +377,8 @@ lchown -a30 lchown32 -a32 link linkat +linkat--secontext --secontext -e trace=linkat +linkat--secontext_full --secontext=full -e trace=linkat lookup_dcookie -a27 lstat -a31 --no-abbrev --trace-path=stat.sample --trace-path=/dev/full lstat64 -a32 --no-abbrev --trace-path=stat.sample --trace-path=/dev/full @@ -492,9 +518,13 @@ oldselect-efault -a13 -e trace=select oldselect-efault-P -a13 -e trace=select -P /dev/full 9>>/dev/full oldstat -a32 -v -P stat.sample -P /dev/full open -a30 -P $NAME.sample +open--secontext -a30 -P open.sample --secontext --trace=open +open--secontext_full -a30 -P open.sample --secontext=full --trace=open open_tree -a30 -y open_tree-P -a30 --decode-fds -P /dev/full -e trace=open_tree openat -a36 -P $NAME.sample +openat--secontext -a36 -P openat.sample -P $PWD/openat.sample --secontext -e trace=openat +openat--secontext_full -a36 -P openat.sample -P $PWD/openat.sample --secontext=full -e trace=openat openat2 -a35 openat2-Xabbrev --trace=openat2 -a35 -Xabbrev openat2-Xraw --trace=openat2 -a32 -Xraw diff --git a/tests/linkat.c b/tests/linkat.c index 6fcc6b4cf..bf6b6e39e 100644 --- a/tests/linkat.c +++ b/tests/linkat.c @@ -10,8 +10,14 @@ #ifdef __NR_linkat +# include <fcntl.h> # include <stdio.h> +# include <stdlib.h> # include <unistd.h> +# include <sys/stat.h> + +# include "secontext.h" +# include "xmalloc.h" int main(void) @@ -27,18 +33,158 @@ main(void) const long fd_old = (long) 0xdeadbeefffffffffULL; const long fd_new = (long) 0xdeadbeeffffffffeULL; + char *my_secontext = SECONTEXT_PID_MY(); + + (void) unlink(sample_1); + (void) unlink(sample_2); + long rc = syscall(__NR_linkat, fd_old, sample_1, fd_new, sample_2, 0); - printf("linkat(%d, \"%s\", %d, \"%s\", 0) = %ld %s (%m)\n", + printf("%s%s(%d, \"%s\", %d, \"%s\", 0) = %ld %s (%m)\n", + my_secontext, "linkat", (int) fd_old, sample_1, (int) fd_new, sample_2, rc, errno2name()); rc = syscall(__NR_linkat, -100, sample_1, -100, sample_2, -1L); - printf("linkat(%s, \"%s\", %s, \"%s\", %s) = %ld %s (%m)\n", + printf("%s%s(%s, \"%s\", %s, \"%s\", %s) = %ld %s (%m)\n", + my_secontext, "linkat", "AT_FDCWD", sample_1, "AT_FDCWD", sample_2, "AT_SYMLINK_NOFOLLOW|AT_REMOVEDIR|AT_SYMLINK_FOLLOW" "|AT_NO_AUTOMOUNT|AT_EMPTY_PATH|AT_RECURSIVE|0xffff60ff", rc, errno2name()); + /* + * Tests with AT_FDCWD. + */ + + int fd_sample_1 = open(sample_1, O_RDONLY | O_CREAT, 0400); + if (fd_sample_1 < 0) + perror_msg_and_fail("open"); + if (close(fd_sample_1)) + perror_msg_and_fail("close"); + + char *sample_1_secontext = SECONTEXT_FILE(sample_1); + + rc = syscall(__NR_linkat, -100, sample_1, -100, sample_2, 0); + /* no context printed for sample_2 since file doesn't exist yet */ + printf("%s%s(AT_FDCWD, \"%s\"%s, AT_FDCWD, \"%s\", 0) = %s\n", + my_secontext, "linkat", + sample_1, sample_1_secontext, + sample_2, + sprintrc(rc)); + + const char *sample_2_secontext = sample_1_secontext; + + rc = syscall(__NR_linkat, -100, sample_1, -100, sample_2, 0); + printf("%s%s(AT_FDCWD, \"%s\"%s, AT_FDCWD, \"%s\"%s, 0) = %s\n", + my_secontext, "linkat", + sample_1, sample_1_secontext, + sample_2, sample_2_secontext, + sprintrc(rc)); + + int fd_sample_2 = open(sample_2, O_RDONLY | O_CREAT, 0400); + if (fd_sample_2 < 0) + perror_msg_and_fail("open"); + if (close(fd_sample_2)) + perror_msg_and_fail("close"); + + free(sample_1_secontext); + update_secontext_type(sample_1, "default_t"); + sample_1_secontext = SECONTEXT_FILE(sample_1); + sample_2_secontext = sample_1_secontext; + + rc = syscall(__NR_linkat, -100, sample_1, -100, sample_2, 0); + printf("%s%s(AT_FDCWD, \"%s\"%s, AT_FDCWD, \"%s\"%s, 0) = %s\n", + my_secontext, "linkat", + sample_1, sample_1_secontext, + sample_2, sample_2_secontext, + sprintrc(rc)); + + if (unlink(sample_2)) + perror_msg_and_fail("unlink: %s", sample_2); + + /* + * Tests with dirfd. + */ + + int dfd_old = get_dir_fd("."); + char *cwd = get_fd_path(dfd_old); + char *dfd_old_secontext = SECONTEXT_FILE("."); + + rc = syscall(__NR_linkat, dfd_old, sample_1, -100, sample_2, 0); + /* no context printed for sample_2 since file doesn't exist yet */ + printf("%s%s(%d%s, \"%s\"%s, AT_FDCWD, \"%s\", 0) = %s\n", + my_secontext, "linkat", + dfd_old, dfd_old_secontext, + sample_1, sample_1_secontext, + sample_2, + sprintrc(rc)); + + rc = syscall(__NR_linkat, dfd_old, sample_1, -100, sample_2, 0); + printf("%s%s(%d%s, \"%s\"%s, AT_FDCWD, \"%s\"%s, 0) = %s\n", + my_secontext, "linkat", + dfd_old, dfd_old_secontext, + sample_1, sample_1_secontext, + sample_2, sample_2_secontext, + sprintrc(rc)); + + if (unlink(sample_2)) + perror_msg_and_fail("unlink: %s", sample_2); + + static const char new_dir[] = "new"; + char *new_sample_2 = xasprintf("%s/%s", new_dir, sample_2); + + (void) unlink(new_sample_2); + (void) rmdir(new_dir); + + if (mkdir(new_dir, 0700)) + perror_msg_and_fail("mkdir"); + char *new_dir_realpath = xasprintf("%s/%s", cwd, new_dir); + char *new_dir_secontext = SECONTEXT_FILE(new_dir); + int dfd_new = get_dir_fd(new_dir); + + rc = syscall(__NR_linkat, dfd_old, sample_1, dfd_new, sample_2, 0); + /* no context printed for sample_2 since file doesn't exist yet */ + printf("%s%s(%d%s, \"%s\"%s, %d%s, \"%s\", 0) = %s\n", + my_secontext, "linkat", + dfd_old, dfd_old_secontext, + sample_1, sample_1_secontext, + dfd_new, new_dir_secontext, + sample_2, + sprintrc(rc)); + + rc = syscall(__NR_linkat, dfd_old, sample_1, dfd_new, sample_2, 0); + printf("%s%s(%d%s, \"%s\"%s, %d%s, \"%s\"%s, 0) = %s\n", + my_secontext, "linkat", + dfd_old, dfd_old_secontext, + sample_1, sample_1_secontext, + dfd_new, new_dir_secontext, + sample_2, SECONTEXT_FILE(new_sample_2), + sprintrc(rc)); + + char *new_sample_2_realpath = xasprintf("%s/%s", new_dir_realpath, sample_2); + + /* dfd ignored when path is absolute */ + if (chdir("../..")) + perror_msg_and_fail("chdir"); + + rc = syscall(__NR_linkat, dfd_old, sample_1, -100, new_sample_2_realpath, 0); + printf("%s%s(%d%s, \"%s\"%s, AT_FDCWD, \"%s\"%s, 0) = %s\n", + my_secontext, "linkat", + dfd_old, dfd_old_secontext, + sample_1, sample_1_secontext, + new_sample_2_realpath, SECONTEXT_FILE(new_sample_2_realpath), + sprintrc(rc)); + + if (fchdir(dfd_old)) + perror_msg_and_fail("fchdir"); + + if (unlink(sample_1)) + perror_msg_and_fail("unlink: %s", sample_1); + if (unlink(new_sample_2)) + perror_msg_and_fail("unlink: %s", new_sample_2); + if (rmdir(new_dir)) + perror_msg_and_fail("rmdir: %s", new_dir); + leave_and_remove_subdir(); puts("+++ exited with 0 +++"); diff --git a/tests/open.c b/tests/open.c index 3fce327ba..5c7295395 100644 --- a/tests/open.c +++ b/tests/open.c @@ -15,6 +15,8 @@ # include <stdio.h> # include <unistd.h> +# include "secontext.h" + int main(void) { @@ -25,10 +27,12 @@ main(void) create_and_enter_subdir("open_subdir"); static const char sample[] = "open.sample"; + char *my_secontext = SECONTEXT_PID_MY(); long fd = syscall(__NR_open, sample, O_RDONLY|O_CREAT, 0400); - printf("open(\"%s\", O_RDONLY|O_CREAT, 0400) = %s\n", - sample, sprintrc(fd)); + printf("%s%s(\"%s\", O_RDONLY|O_CREAT, 0400) = %s%s\n", + my_secontext, "open", + sample, sprintrc(fd), SECONTEXT_FILE(sample)); if (fd != -1) { close(fd); @@ -36,16 +40,18 @@ main(void) perror_msg_and_fail("unlink"); fd = syscall(__NR_open, sample, O_RDONLY); - printf("open(\"%s\", O_RDONLY) = %s\n", sample, sprintrc(fd)); + printf("%s%s(\"%s\", O_RDONLY) = %s\n", + my_secontext, "open", sample, sprintrc(fd)); fd = syscall(__NR_open, sample, O_WRONLY|O_NONBLOCK|0x80000000); - printf("open(\"%s\", O_WRONLY|O_NONBLOCK|0x80000000) = %s\n", - sample, sprintrc(fd)); + printf("%s%s(\"%s\", O_WRONLY|O_NONBLOCK|0x80000000) = %s\n", + my_secontext, "open", sample, sprintrc(fd)); } # ifdef O_TMPFILE fd = syscall(__NR_open, sample, O_WRONLY|O_TMPFILE, 0600); - printf("open(\"%s\", O_WRONLY|O_TMPFILE, 0600) = %s\n", + printf("%s%s(\"%s\", O_WRONLY|O_TMPFILE, 0600) = %s\n", + my_secontext, "open", sample, sprintrc(fd)); # endif /* O_TMPFILE */ diff --git a/tests/openat.c b/tests/openat.c index 0c4bb3d10..b43055d3c 100644 --- a/tests/openat.c +++ b/tests/openat.c @@ -15,6 +15,8 @@ # include <stdio.h> # include <unistd.h> +# include "secontext.h" + # ifdef O_TMPFILE /* The kernel & C libraries often inline O_DIRECTORY. */ # define STRACE_O_TMPFILE (O_TMPFILE & ~O_DIRECTORY) @@ -26,10 +28,12 @@ static const char sample[] = "openat.sample"; static void test_mode_flag(unsigned int mode_val, const char *mode_str, - unsigned int flag_val, const char *flag_str) + unsigned int flag_val, const char *flag_str, + const char *my_secontext) { long rc = syscall(__NR_openat, -1, sample, mode_val | flag_val, 0); - printf("openat(-1, \"%s\", %s%s%s%s) = %s\n", + printf("%s%s(-1, \"%s\", %s%s%s%s) = %s\n", + my_secontext, "openat", sample, mode_str, flag_val ? "|" : "", flag_str, flag_val & (O_CREAT | STRACE_O_TMPFILE) ? ", 000" : "", @@ -45,20 +49,7 @@ main(void) */ create_and_enter_subdir("openat_subdir"); - long fd = syscall(__NR_openat, -100, sample, O_RDONLY|O_CREAT, 0400); - printf("openat(AT_FDCWD, \"%s\", O_RDONLY|O_CREAT, 0400) = %s\n", - sample, sprintrc(fd)); - - if (fd != -1) { - close(fd); - if (unlink(sample) == -1) - perror_msg_and_fail("unlink"); - - fd = syscall(__NR_openat, -100, sample, O_RDONLY); - printf("openat(AT_FDCWD, \"%s\", O_RDONLY) = %s\n", - sample, sprintrc(fd)); - } - + char *my_secontext = SECONTEXT_PID_MY(); struct { unsigned int val; const char *str; @@ -105,7 +96,73 @@ main(void) for (unsigned int m = 0; m < ARRAY_SIZE(modes); ++m) for (unsigned int f = 0; f < ARRAY_SIZE(flags); ++f) test_mode_flag(modes[m].val, modes[m].str, - flags[f].val, flags[f].str); + flags[f].val, flags[f].str, + my_secontext); + + /* + * Tests with AT_FDCWD. + */ + + (void) unlink(sample); + long fd = syscall(__NR_openat, -100, sample, O_RDONLY|O_CREAT, 0400); + + char *sample_secontext = SECONTEXT_FILE(sample); + + /* + * File context in openat() is not displayed because file doesn't exist + * yet, but is displayed in return value since the file got created. + */ + printf("%s%s(AT_FDCWD, \"%s\", O_RDONLY|O_CREAT, 0400) = %s%s\n", + my_secontext, "openat", + sample, + sprintrc(fd), sample_secontext); + + close(fd); + + fd = syscall(__NR_openat, -100, sample, O_RDONLY); + printf("%s%s(AT_FDCWD, \"%s\"%s, O_RDONLY) = %s%s\n", + my_secontext, "openat", + sample, sample_secontext, + sprintrc(fd), sample_secontext); + if (fd != -1) { + close(fd); + if (unlink(sample)) + perror_msg_and_fail("unlink"); + } + + /* + * Tests with dirfd. + */ + + int cwd_fd = get_dir_fd("."); + char *cwd_secontext = SECONTEXT_FILE("."); + + fd = syscall(__NR_openat, cwd_fd, sample, O_RDONLY|O_CREAT, 0400); + if (fd == -1) + perror_msg_and_fail("openat"); + close(fd); + + /* + * File context in openat() is not displayed because file doesn't exist + * yet, but is displayed in return value since the file got created. + */ + printf("%s%s(%d%s, \"%s\", O_RDONLY|O_CREAT, 0400) = %s%s\n", + my_secontext, "openat", + cwd_fd, cwd_secontext, + sample, + sprintrc(fd), sample_secontext); + + fd = syscall(__NR_openat, cwd_fd, sample, O_RDONLY); + printf("%s%s(%d%s, \"%s\"%s, O_RDONLY) = %s%s\n", + my_secontext, "openat", + cwd_fd, cwd_secontext, + sample, sample_secontext, + sprintrc(fd), sample_secontext); + if (fd != -1) { + close(fd); + if (unlink(sample)) + perror_msg_and_fail("unlink"); + } leave_and_remove_subdir(); diff --git a/tests/options-syntax.test b/tests/options-syntax.test index 4c071ac5a..765b2f867 100755 --- a/tests/options-syntax.test +++ b/tests/options-syntax.test @@ -3,13 +3,15 @@ # Check strace options syntax. # # Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io> -# Copyright (c) 2016-2020 The strace developers. +# Copyright (c) 2016-2021 The strace developers. # All rights reserved. # # SPDX-License-Identifier: GPL-2.0-or-later . "${srcdir=.}/syntax.sh" +compiled_with_secontext=$(get_config_option ENABLE_SECONTEXT "y") + check_e "Invalid process id: '0'" -p 0 check_e "Invalid process id: '0'" --attach=0 check_e "Invalid process id: '-42'" -p -42 @@ -46,6 +48,8 @@ check_e '-t and --absolute-timestamps cannot be provided simultaneously' -t --ti check_e '-t and --absolute-timestamps cannot be provided simultaneously' --absolute-timestamps -ttt -p $$ check_e '-t and --absolute-timestamps cannot be provided simultaneously' -t --timestamps=ns -t -p $$ check_e '-t and --absolute-timestamps cannot be provided simultaneously' --timestamps=ns -t --absolute-timestamps=unix -p $$ +[ -z "$compiled_with_secontext" ] || + check_h "invalid --secontext argument: 'ss'" --secontext=ss check_h 'PROG [ARGS] must be specified with -D/--daemonize' -D -p $$ check_h 'PROG [ARGS] must be specified with -D/--daemonize' -DD -p $$ check_h 'PROG [ARGS] must be specified with -D/--daemonize' -DDD -p $$ @@ -282,6 +286,11 @@ $STRACE_EXE: -y/--decode-fds has no effect with -c/--summary-only $STRACE_EXE: Only the last of -z/--successful-only/-Z/--failed-only options will take effect. See status qualifier for more complex filters. $STRACE_EXE: $umsg" -u :nosuchuser: -cinrtTyzZ true + if [ -n "$compiled_with_secontext" ]; then + check_e "--secontext has no effect with -c/--summary-only +$STRACE_EXE: $umsg" -u :nosuchuser: -c --secontext true + fi + for c in --output-separately -A/--output-append-mode; do check_e "$c has no effect without -o/--output $STRACE_EXE: $umsg" -u :nosuchuser: ${c%%/*} true diff --git a/tests/secontext.c b/tests/secontext.c new file mode 100644 index 000000000..21c6370c9 --- /dev/null +++ b/tests/secontext.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2021 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" + +#ifdef HAVE_SELINUX_RUNTIME + +# include <assert.h> +# include <errno.h> +# include <stdlib.h> +# include <string.h> +# include <unistd.h> +# include <selinux/selinux.h> + +# include "xmalloc.h" + +# define TEST_SECONTEXT +# include "secontext.h" + +static char * +secontext_format(char *context, const char *fmt) + ATTRIBUTE_FORMAT((printf, 2, 0)) ATTRIBUTE_MALLOC; + +static char * +secontext_format(char *context, const char *fmt) +{ + int saved_errno = errno; + char *res = context ? xasprintf(fmt, context) : xstrdup(""); + free(context); + errno = saved_errno; + return res; +} + +# define FORMAT_SPACE_BEFORE(string) secontext_format(string, " [%s]") +# define FORMAT_SPACE_AFTER(string) secontext_format(string, "[%s] ") + +static char * +strip_trailing_newlines(char *context) +{ + /* + * On the CI at least, the context may have a trailing \n, + * let's remove it just in case. + */ + size_t len = strlen(context); + for (; len > 0; --len) { + if (context[len - 1] != '\n') + break; + } + context[len] = '\0'; + return context; +} + +static char * +raw_secontext_full_file(const char *filename) +{ + int saved_errno = errno; + char *full_secontext = NULL; + char *secontext; + + if (getfilecon(filename, &secontext) >= 0) { + full_secontext = strip_trailing_newlines(xstrdup(secontext)); + freecon(secontext); + } + errno = saved_errno; + return full_secontext; +} + +static char * +raw_secontext_short_file(const char *filename) +{ + int saved_errno = errno; + + char *ctx = raw_secontext_full_file(filename); + if (ctx == NULL) + return ctx; + + char *saveptr = NULL; + const char *token; + unsigned int i; + + char *ctx_copy = xstrdup(ctx); + char *context = NULL; + for (token = strtok_r(ctx_copy, ":", &saveptr), i = 0; + token; token = strtok_r(NULL, ":", &saveptr), i++) { + if (i == 2) { + context = xstrdup(token); + break; + } + } + if (context == NULL) + context = xstrdup(ctx); + free(ctx_copy); + free(ctx); + + errno = saved_errno; + return context; +} + +static char * +raw_secontext_full_pid(pid_t pid) +{ + int saved_errno = errno; + char *full_secontext = NULL; + char *secontext; + + if (getpidcon(pid, &secontext) == 0) { + full_secontext = strip_trailing_newlines(xstrdup(secontext)); + freecon(secontext); + } + errno = saved_errno; + return full_secontext; +} + +static char * +raw_secontext_short_pid(pid_t pid) +{ + int saved_errno = errno; + + char *ctx = raw_secontext_full_pid(pid); + if (ctx == NULL) + return ctx; + + char *saveptr = NULL; + const char *token; + int i; + + char *ctx_copy = xstrdup(ctx); + char *context = NULL; + for (token = strtok_r(ctx_copy, ":", &saveptr), i = 0; + token; token = strtok_r(NULL, ":", &saveptr), i++) { + if (i == 2) { + context = xstrdup(token); + break; + } + } + if (context == NULL) + context = xstrdup(ctx); + free(ctx_copy); + free(ctx); + + errno = saved_errno; + return context; +} + +char * +secontext_full_file(const char *filename) +{ + return FORMAT_SPACE_BEFORE(raw_secontext_full_file(filename)); +} + +char * +secontext_full_pid(pid_t pid) +{ + return FORMAT_SPACE_AFTER(raw_secontext_full_pid(pid)); +} + +char * +secontext_short_file(const char *filename) +{ + return FORMAT_SPACE_BEFORE(raw_secontext_short_file(filename)); +} + +char * +secontext_short_pid(pid_t pid) +{ + return FORMAT_SPACE_AFTER(raw_secontext_short_pid(pid)); +} + +void +update_secontext_type(const char *file, const char *newtype) +{ + char *ctx = raw_secontext_full_file(file); + if (ctx == NULL) + return; + + char *saveptr = NULL; + char *token; + int field; + char *split[4]; + + for (token = strtok_r(ctx, ":", &saveptr), field = 0; + token; token = strtok_r(NULL, ":", &saveptr), field++) { + assert(field < 4); + split[field] = token; + } + assert(field == 4); + + char *newcontext = xasprintf("%s:%s:%s:%s", split[0], split[1], + newtype, split[3]); + + (void) setfilecon(file, newcontext); + + free(newcontext); + free(ctx); +} + +#endif /* HAVE_SELINUX_RUNTIME */ diff --git a/tests/secontext.h b/tests/secontext.h new file mode 100644 index 000000000..64bcd060f --- /dev/null +++ b/tests/secontext.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "xmalloc.h" +#include <unistd.h> + +#if defined TEST_SECONTEXT && defined HAVE_SELINUX_RUNTIME + +void update_secontext_type(const char *file, const char *newtype); + +# ifdef PRINT_SECONTEXT_FULL + +char *secontext_full_file(const char *) ATTRIBUTE_MALLOC; +char *secontext_full_pid(pid_t) ATTRIBUTE_MALLOC; + +# define SECONTEXT_FILE(filename) secontext_full_file(filename) +# define SECONTEXT_PID(pid) secontext_full_pid(pid) + +# else + +char *secontext_short_file(const char *) ATTRIBUTE_MALLOC; +char *secontext_short_pid(pid_t) ATTRIBUTE_MALLOC; + +# define SECONTEXT_FILE(filename) secontext_short_file(filename) +# define SECONTEXT_PID(pid) secontext_short_pid(pid) + +# endif + +#else + +static inline void +update_secontext_type(const char *file, const char *newtype) +{ +} + +# define SECONTEXT_FILE(filename) xstrdup("") +# define SECONTEXT_PID(pid) xstrdup("") + +#endif + +#define SECONTEXT_PID_MY() SECONTEXT_PID(getpid()) diff --git a/tests/strace-V.test b/tests/strace-V.test index 30f10808c..fdac7a3e4 100755 --- a/tests/strace-V.test +++ b/tests/strace-V.test @@ -33,7 +33,9 @@ aarch64|powerpc64|s390x|sparc64|tile|x32) ;; esac -features="${option_unwind}${option_demangle}${option_m32}${option_mx32}" +option_secontext=$(get_config_option ENABLE_SECONTEXT " secontext") + +features="${option_unwind}${option_demangle}${option_m32}${option_mx32}${option_secontext}" [ -n "$features" ] || features=" (none)" cat > "$EXP" << __EOF__ |