diff --git a/src/open.c b/src/open.c index 1dd79e9dc0..ec8ae6b5e3 100644 --- a/src/open.c +++ b/src/open.c @@ -19,6 +19,7 @@ #include #include +#include "number_set.h" #include "xlat/open_access_modes.h" #include "xlat/open_mode_flags.h" #include "xlat/open_resolve_flags.h" @@ -29,9 +30,29 @@ void print_dirfd(struct tcb *tcp, int fd) { - if (fd == AT_FDCWD) + if (fd == AT_FDCWD) { print_xlat_d(AT_FDCWD); - else + if (number_set_array_is_empty(decode_fd_set, 0)) + goto done; + + char linkpath[sizeof("/proc/%u/cwd") + sizeof(int)*3]; + char buf[PATH_MAX]; + ssize_t n; + int proc_pid = get_proc_pid(tcp->pid); + if (!proc_pid) + goto done; + + xsprintf(linkpath, "/proc/%u/cwd", proc_pid); + n = readlink(linkpath, buf, sizeof (buf)); + if (n == -1 || n == sizeof (buf)) + goto done; + + tprints("<"); + print_quoted_string_ex(buf, n, + QUOTE_OMIT_LEADING_TRAILING_QUOTES, "<>"); + tprints(">"); +done: ; + } else printfd(tcp, fd); #ifdef ENABLE_SECONTEXT tcp->last_dirfd = fd; diff --git a/tests/.gitignore b/tests/.gitignore index 9501a8d861..da59bfebc2 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -563,6 +563,7 @@ open open_tree open_tree-P openat +openat-y openat2 openat2-Xabbrev openat2-Xraw @@ -575,6 +576,7 @@ openat2-v-y-Xverbose openat2-y orphaned_process_group osf_utimes +pathmax pause pc perf_event_open diff --git a/tests/dev-yy.c b/tests/dev-yy.c index f149496dbc..9a62605e3c 100644 --- a/tests/dev-yy.c +++ b/tests/dev-yy.c @@ -34,6 +34,7 @@ int main(void) { skip_if_unavailable("/proc/self/fd/"); + char *cwd = get_fd_path(get_dir_fd(".")); static const struct { const char *path; @@ -56,8 +57,8 @@ main(void) long fd = syscall(__NR_openat, AT_FDCWD, checks[i].path, O_RDONLY|O_PATH); - printf("openat(AT_FDCWD, \"%s\", O_RDONLY|O_PATH) = %s", - checks[i].path, sprintrc(fd)); + printf("openat(AT_FDCWD<%s>, \"%s\", O_RDONLY|O_PATH) = %s", + cwd, checks[i].path, sprintrc(fd)); if (fd >= 0) printf(DEV_FMT, checks[i].path diff --git a/tests/faccessat.c b/tests/faccessat.c index 9ce7a07ce4..d3e42f27d4 100644 --- a/tests/faccessat.c +++ b/tests/faccessat.c @@ -57,6 +57,9 @@ tests_with_existing_file(void) */ create_and_enter_subdir("faccessat_subdir"); + int cwd_fd = get_dir_fd("."); + char *cwd = get_fd_path(cwd_fd); + char *my_secontext = SECONTEXT_PID_MY(); k_faccessat(-1, NULL, F_OK); @@ -76,8 +79,15 @@ tests_with_existing_file(void) */ k_faccessat(-100, sample, F_OK); +# ifdef YFLAG + printf("%s%s(AT_FDCWD<%s>, \"%s\"%s, F_OK) = %s\n", +# else printf("%s%s(AT_FDCWD, \"%s\"%s, F_OK) = %s\n", +# endif my_secontext, "faccessat", +# ifdef YFLAG + cwd, +# endif sample, sample_secontext, errstr); @@ -85,8 +95,15 @@ tests_with_existing_file(void) perror_msg_and_fail("unlink"); k_faccessat(-100, sample, F_OK); +# ifdef YFLAG + printf("%s%s(AT_FDCWD<%s>, \"%s\", F_OK) = %s\n", +# else printf("%s%s(AT_FDCWD, \"%s\", F_OK) = %s\n", +# endif my_secontext, "faccessat", +# ifdef YFLAG + cwd, +# endif sample, errstr); @@ -94,8 +111,6 @@ tests_with_existing_file(void) * 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); @@ -203,7 +218,9 @@ main(void) const char *str; } dirfds[] = { { ARG_STR(-1) }, +# ifndef YFLAG { -100, "AT_FDCWD" }, +# endif { fd, fd_str }, }, modes[] = { { ARG_STR(F_OK) }, diff --git a/tests/faccessat2.c b/tests/faccessat2.c index d35b9d8e88..553164b4d3 100644 --- a/tests/faccessat2.c +++ b/tests/faccessat2.c @@ -21,6 +21,8 @@ #ifndef FD_PATH # define FD_PATH "" +#else +# define YFLAG #endif #ifndef SKIP_IF_PROC_IS_UNAVAILABLE # define SKIP_IF_PROC_IS_UNAVAILABLE @@ -84,7 +86,9 @@ main(void) const char *str; } dirfds[] = { { ARG_STR(-1) }, +#ifndef YFLAG { -100, "AT_FDCWD" }, +#endif { fd, fd_str }, }, modes[] = { { ARG_STR(F_OK) }, diff --git a/tests/fsconfig.c b/tests/fsconfig.c index 2cd14452de..8f0cc1b5fd 100644 --- a/tests/fsconfig.c +++ b/tests/fsconfig.c @@ -187,11 +187,13 @@ test_fsconfig_set_binary(const unsigned int cmd, const char *cmd_str) static void test_fsconfig_set_path(const unsigned int cmd, const char *cmd_str) { + char *cwd = get_fd_path(get_dir_fd(".")); + fill_memory_ex(fname, PATH_MAX, '0', 10); k_fsconfig(fd, cmd, key, fname, -100); #ifndef PATH_TRACING - printf("fsconfig(%d<%s>, %s, \"%s\", \"%.*s\"..., AT_FDCWD) = %s\n", - fd, fd_path, cmd_str, key, (int) PATH_MAX - 1, fname, errstr); + printf("fsconfig(%d<%s>, %s, \"%s\", \"%.*s\"..., AT_FDCWD<%s>) = %s\n", + fd, fd_path, cmd_str, key, (int) PATH_MAX - 1, fname, cwd, errstr); #endif fname[PATH_MAX - 1] = '\0'; @@ -206,8 +208,8 @@ test_fsconfig_set_path(const unsigned int cmd, const char *cmd_str) cmd_str, key, fd, fd_path, errstr); k_fsconfig(-1, cmd, 0, fd_path, -100); - printf("fsconfig(-1, %s, NULL, \"%s\", AT_FDCWD) = %s\n", - cmd_str, fd_path, errstr); + printf("fsconfig(-1, %s, NULL, \"%s\", AT_FDCWD<%s>) = %s\n", + cmd_str, fd_path, cwd, errstr); k_fsconfig(-1, cmd, efault, efault + 1, fd); printf("fsconfig(-1, %s, %p, %p, %d<%s>) = %s\n", diff --git a/tests/fspick.c b/tests/fspick.c index 9dd6c9c8fa..7d7f48de1a 100644 --- a/tests/fspick.c +++ b/tests/fspick.c @@ -38,6 +38,9 @@ main(void) { skip_if_unavailable("/proc/self/fd/"); +#ifndef PATH_TRACING + char *cwd = get_fd_path(get_dir_fd(".")); +#endif static const char path_full[] = "/dev/full"; const char *const path = tail_memdup(path_full, sizeof(path_full)); char *const fname = tail_alloc(PATH_MAX); @@ -56,8 +59,8 @@ main(void) k_fspick(-100, fname, 0); #ifndef PATH_TRACING - printf("fspick(%s, \"%.*s\"..., 0) = %s\n", - "AT_FDCWD", (int) PATH_MAX - 1, fname, errstr); + printf("fspick(AT_FDCWD<%s>, \"%.*s\"..., 0) = %s\n", + cwd, (int) PATH_MAX - 1, fname, errstr); #endif fname[PATH_MAX - 1] = '\0'; diff --git a/tests/gen_tests.in b/tests/gen_tests.in index cafb4a7080..bd2f60aa61 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -538,6 +538,7 @@ 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-y -a36 -P openat.sample -P $PWD/openat_subdir/openat.sample -y -e trace=openat 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 @@ -552,6 +553,7 @@ openat2-v-y-Xverbose --trace=openat2 -a44 -v -y -Xverbose , \"%.*s\"..., 0, %p, %u) = %s\n", + cwd, (int) PATH_MAX - 1, fname, attr, MOUNT_ATTR_SIZE_VER0 - 1, rcstr); #endif diff --git a/tests/move_mount.c b/tests/move_mount.c index 68d14e4b2f..eca35b7808 100644 --- a/tests/move_mount.c +++ b/tests/move_mount.c @@ -41,6 +41,7 @@ main(void) { skip_if_unavailable("/proc/self/fd/"); + char *cwd = get_fd_path(get_dir_fd(".")); static const char path_full[] = "/dev/full"; const char *const path = tail_memdup(path_full, sizeof(path_full)); const void *const efault = path + sizeof(path_full); @@ -54,40 +55,40 @@ main(void) k_move_mount(-1, 0, -100, efault, 0); #ifndef PATH_TRACING - printf("move_mount(-1, NULL, AT_FDCWD, %p, 0) = %s\n", efault, errstr); + printf("move_mount(-1, NULL, AT_FDCWD<%s>, %p, 0) = %s\n", cwd, efault, errstr); #endif k_move_mount(-100, efault, -1, 0, 0); #ifndef PATH_TRACING - printf("move_mount(AT_FDCWD, %p, -1, NULL, 0) = %s\n", efault, errstr); + printf("move_mount(AT_FDCWD<%s>, %p, -1, NULL, 0) = %s\n", cwd, efault, errstr); #endif k_move_mount(dfd, fname, -100, empty, 1); - printf("move_mount(%d<%s>, \"%.*s\"..., AT_FDCWD, \"\", %s) = %s\n", - dfd, path, (int) PATH_MAX - 1, fname, "MOVE_MOUNT_F_SYMLINKS", errstr); + printf("move_mount(%d<%s>, \"%.*s\"..., AT_FDCWD<%s>, \"\", %s) = %s\n", + dfd, path, (int) PATH_MAX - 1, fname, cwd, "MOVE_MOUNT_F_SYMLINKS", errstr); k_move_mount(-100, empty, dfd, fname, 0x10); - printf("move_mount(AT_FDCWD, \"\", %d<%s>, \"%.*s\"..., %s) = %s\n", - dfd, path, (int) PATH_MAX - 1, fname, "MOVE_MOUNT_T_SYMLINKS", errstr); + printf("move_mount(AT_FDCWD<%s>, \"\", %d<%s>, \"%.*s\"..., %s) = %s\n", + cwd, dfd, path, (int) PATH_MAX - 1, fname, "MOVE_MOUNT_T_SYMLINKS", errstr); #define f_flags_str "MOVE_MOUNT_F_SYMLINKS|MOVE_MOUNT_F_AUTOMOUNTS|MOVE_MOUNT_F_EMPTY_PATH" fname[PATH_MAX - 1] = '\0'; k_move_mount(dfd, fname, -100, empty, 7); - printf("move_mount(%d<%s>, \"%s\", AT_FDCWD, \"\", %s) = %s\n", - dfd, path, fname, f_flags_str, errstr); + printf("move_mount(%d<%s>, \"%s\", AT_FDCWD<%s>, \"\", %s) = %s\n", + dfd, path, fname, cwd, f_flags_str, errstr); #define t_flags_str "MOVE_MOUNT_T_SYMLINKS|MOVE_MOUNT_T_AUTOMOUNTS|MOVE_MOUNT_T_EMPTY_PATH" k_move_mount(-100, empty, dfd, fname, 0x70); - printf("move_mount(AT_FDCWD, \"\", %d<%s>, \"%s\", %s) = %s\n", - dfd, path, fname, t_flags_str, errstr); + printf("move_mount(AT_FDCWD<%s>, \"\", %d<%s>, \"%s\", %s) = %s\n", + cwd, dfd, path, fname, t_flags_str, errstr); k_move_mount(-1, path, -100, empty, 0x77); - printf("move_mount(-1, \"%s\", AT_FDCWD, \"\", %s) = %s\n", - path, f_flags_str "|" t_flags_str, errstr); + printf("move_mount(-1, \"%s\", AT_FDCWD<%s>, \"\", %s) = %s\n", + path, cwd, f_flags_str "|" t_flags_str, errstr); k_move_mount(-100, empty, -1, path, -1); - printf("move_mount(AT_FDCWD, \"\", -1, \"%s\", %s) = %s\n", - path, f_flags_str "|" t_flags_str "|0xffffff88", errstr); + printf("move_mount(AT_FDCWD<%s>, \"\", -1, \"%s\", %s) = %s\n", + cwd, path, f_flags_str "|" t_flags_str "|0xffffff88", errstr); puts("+++ exited with 0 +++"); return 0; diff --git a/tests/open_tree.c b/tests/open_tree.c index f88d1dd010..a2025fc7dc 100644 --- a/tests/open_tree.c +++ b/tests/open_tree.c @@ -39,6 +39,9 @@ main(void) { skip_if_unavailable("/proc/self/fd/"); +#ifndef PATH_TRACING + char *cwd = get_fd_path(get_dir_fd(".")); +#endif static const char path_full[] = "/dev/full"; const char *const path = tail_memdup(path_full, sizeof(path_full)); char *const fname = tail_alloc(PATH_MAX); @@ -57,8 +60,8 @@ main(void) k_open_tree(-100, fname, 0); #ifndef PATH_TRACING - printf("open_tree(%s, \"%.*s\"..., 0) = %s\n", - "AT_FDCWD", (int) PATH_MAX - 1, fname, errstr); + printf("open_tree(AT_FDCWD<%s>, \"%.*s\"..., 0) = %s\n", + cwd, (int) PATH_MAX - 1, fname, errstr); #endif fname[PATH_MAX - 1] = '\0'; diff --git a/tests/openat-y.c b/tests/openat-y.c new file mode 100644 index 0000000000..e578508090 --- /dev/null +++ b/tests/openat-y.c @@ -0,0 +1,2 @@ +#define YFLAG +#include "openat.c" diff --git a/tests/openat.c b/tests/openat.c index b43055d3ca..b3229b95c5 100644 --- a/tests/openat.c +++ b/tests/openat.c @@ -15,6 +15,10 @@ # include # include +# ifdef YFLAG +# include +# endif + # include "secontext.h" # ifdef O_TMPFILE @@ -103,6 +107,10 @@ main(void) * Tests with AT_FDCWD. */ +# ifdef YFLAG + char *cwd = get_fd_path(get_dir_fd(".")); +#endif + (void) unlink(sample); long fd = syscall(__NR_openat, -100, sample, O_RDONLY|O_CREAT, 0400); @@ -112,23 +120,45 @@ main(void) * File context in openat() is not displayed because file doesn't exist * yet, but is displayed in return value since the file got created. */ +# ifdef YFLAG + char *sample_rp = get_fd_path(fd); + + printf("%s%s(AT_FDCWD<%s>, \"%s\", O_RDONLY|O_CREAT, 0400) = %s<%s>%s\n", +# else printf("%s%s(AT_FDCWD, \"%s\", O_RDONLY|O_CREAT, 0400) = %s%s\n", +# endif my_secontext, "openat", - sample, - sprintrc(fd), sample_secontext); +# ifdef YFLAG + cwd, +# endif + sample, sprintrc(fd), +# ifdef YFLAG + sample_rp, +# endif + sample_secontext); close(fd); fd = syscall(__NR_openat, -100, sample, O_RDONLY); +# ifdef YFLAG + printf("%s%s(AT_FDCWD<%s>, \"%s\"%s, O_RDONLY) = %s<%s>%s\n", +# else printf("%s%s(AT_FDCWD, \"%s\"%s, O_RDONLY) = %s%s\n", +# endif my_secontext, "openat", +# ifdef YFLAG + cwd, +# endif sample, sample_secontext, - sprintrc(fd), sample_secontext); - if (fd != -1) { - close(fd); - if (unlink(sample)) - perror_msg_and_fail("unlink"); - } + sprintrc(fd), +# ifdef YFLAG + sample_rp, +# endif + sample_secontext); + close(fd); + + if (unlink(sample)) + perror_msg_and_fail("unlink"); /* * Tests with dirfd. @@ -146,18 +176,42 @@ main(void) * File context in openat() is not displayed because file doesn't exist * yet, but is displayed in return value since the file got created. */ +# ifdef YFLAG + printf("%s%s(%d<%s>%s, \"%s\", O_RDONLY|O_CREAT, 0400) = %s<%s>%s\n", +# else printf("%s%s(%d%s, \"%s\", O_RDONLY|O_CREAT, 0400) = %s%s\n", +# endif my_secontext, "openat", - cwd_fd, cwd_secontext, + cwd_fd, +# ifdef YFLAG + cwd, +# endif + cwd_secontext, sample, - sprintrc(fd), sample_secontext); + sprintrc(fd), +# ifdef YFLAG + sample_rp, +# endif + sample_secontext); fd = syscall(__NR_openat, cwd_fd, sample, O_RDONLY); +# ifdef YFLAG + printf("%s%s(%d<%s>%s, \"%s\"%s, O_RDONLY) = %s<%s>%s\n", +# else printf("%s%s(%d%s, \"%s\"%s, O_RDONLY) = %s%s\n", +# endif my_secontext, "openat", - cwd_fd, cwd_secontext, + cwd_fd, +# ifdef YFLAG + cwd, +# endif + cwd_secontext, sample, sample_secontext, - sprintrc(fd), sample_secontext); + sprintrc(fd), +# ifdef YFLAG + sample_rp, +# endif + sample_secontext); if (fd != -1) { close(fd); if (unlink(sample)) diff --git a/tests/openat2.c b/tests/openat2.c index 2b6511463b..e42b551669 100644 --- a/tests/openat2.c +++ b/tests/openat2.c @@ -23,6 +23,8 @@ #endif #ifndef FD0_PATH # define FD0_PATH "" +#else +# define YFLAG #endif #ifndef SKIP_IF_PROC_IS_UNAVAILABLE # define SKIP_IF_PROC_IS_UNAVAILABLE @@ -35,6 +37,9 @@ main(void) { SKIP_IF_PROC_IS_UNAVAILABLE; +# ifdef YFLAG + char *cwd = get_fd_path(get_dir_fd(".")); +# endif long rc; const char *rcstr; struct open_how *how = tail_alloc(sizeof(*how)); @@ -47,8 +52,14 @@ main(void) sprintrc(rc)); rc = syscall(__NR_openat2, -100, "", how + 1, sizeof(*how)); +# ifdef YFLAG + printf("openat2(%s<%s>, \"\", %p, %zu) = %s\n", + XLAT_KNOWN(-100, "AT_FDCWD"), cwd, +# else printf("openat2(%s, \"\", %p, %zu) = %s\n", - XLAT_KNOWN(-100, "AT_FDCWD"), how + 1, sizeof(*how), + XLAT_KNOWN(-100, "AT_FDCWD"), +# endif + how + 1, sizeof(*how), sprintrc(rc)); rc = syscall(__NR_openat2, -1, sample, how, 11); @@ -121,9 +132,16 @@ main(void) how->mode = 0; how->resolve = 0; rc = syscall(__NR_openat2, -100, "/dev/full", how, sizeof(*how)); +# ifdef YFLAG + printf("openat2(%s<%s>, \"/dev/full\", {flags=%s, resolve=0}, %zu)" + " = %s%s\n", + XLAT_KNOWN(-100, "AT_FDCWD"), cwd, +# else printf("openat2(%s, \"/dev/full\", {flags=%s, resolve=0}, %zu)" " = %s%s\n", - XLAT_KNOWN(-100, "AT_FDCWD"), XLAT_STR(O_RDONLY|O_NOCTTY), + XLAT_KNOWN(-100, "AT_FDCWD"), +# endif + XLAT_STR(O_RDONLY|O_NOCTTY), sizeof(*how), sprintrc(rc), rc >= 0 ? FD0_PATH : ""); puts("+++ exited with 0 +++"); diff --git a/tests/pathmax.c b/tests/pathmax.c new file mode 100644 index 0000000000..fa658f132c --- /dev/null +++ b/tests/pathmax.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2021 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" + +#include +#include +#include +#include +#include +#include +#include + +/* + * This test is designed to cover cases where decoding cannot happen because + * paths length exceed PATH_MAX. + * It is designed to execute with -y or similar option. + */ + +int main(void) +{ + /* + * Make sure the current workdir of the tracee + * is different from the current workdir of the tracer. + */ + create_and_enter_subdir("pathmax_subdir"); + + char *topdir = get_fd_path(get_dir_fd(".")); + + /* + * AT_FDCWD decoding + */ + + char name[NAME_MAX + 1]; + unsigned int i; + for (i = 0; i < sizeof(name)-1; i++) + name[i] = 'x'; + name[sizeof(name)-1] = '\0'; + + unsigned long cwdlen = strlen(topdir); + unsigned int count = 0; + + for (cwdlen = strlen(topdir); + cwdlen <= PATH_MAX; + cwdlen += strlen(name) + 1, count++) { + if (mkdir(name, 0700) == -1) + perror_msg_and_fail("mkdir"); + if (chdir(name) == -1) + perror_msg_and_fail("chdir"); + } + + /* AT_FDCWD is not be printed since path cannot be resolved */ + + int fd = openat(AT_FDCWD, "sample", O_RDONLY); + printf("openat(AT_FDCWD, \"sample\", O_RDONLY) = %s\n", + sprintrc(fd)); + + /* Go back one dir and verify it's printed */ + + count--; + if (chdir("..") == -1) + perror_msg_and_fail("chdir"); + if (rmdir(name) == -1) + perror_msg_and_fail("rmdir"); + + char *cwd = get_fd_path(get_dir_fd(".")); + + fd = openat(AT_FDCWD, "sample", O_RDONLY); + printf("openat(AT_FDCWD<%s>, \"sample\", O_RDONLY) = %s\n", + cwd, sprintrc(fd)); + + /* Create a dir for which exact PATH_MAX size is returned */ + + char dir[NAME_MAX + 1]; + for (i = 0; i < sizeof(dir)-1; i++) + dir[i] = 'x'; + dir[PATH_MAX - (strlen(cwd) + 1)] = '\0'; + if (mkdir(dir, 0700) == -1) + perror_msg_and_fail("mkdir"); + if (chdir(dir) == -1) + perror_msg_and_fail("chdir"); + + /* AT_FDCWD is not preinted since path cannot be resolved fully */ + + fd = openat(AT_FDCWD, "sample", O_RDONLY); + printf("openat(AT_FDCWD, \"sample\", O_RDONLY) = %s\n", + sprintrc(fd)); + + if (chdir("..") == -1) + perror_msg_and_fail("chdir"); + if (rmdir(dir) == -1) + perror_msg_and_fail("rmdir"); + + for (i = count; i > 0; i--) { + if (chdir("..") == -1) + perror_msg_and_fail("chdir"); + if (rmdir(name) == -1) + perror_msg_and_fail("rmdir"); + } + + leave_and_remove_subdir(); + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/pure_executables.list b/tests/pure_executables.list index f2402d1466..5bd304d95e 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -422,6 +422,7 @@ open open_tree open_tree-P openat +openat-y openat2 openat2-Xabbrev openat2-Xraw @@ -433,6 +434,7 @@ openat2-v-y-Xraw openat2-v-y-Xverbose openat2-y osf_utimes +pathmax pause perf_event_open personality