| From 95e8aad6260e79f8c8f6afc52c5b6b0bb447342f Mon Sep 17 00:00:00 2001 |
| From: Steve Muckle <smuckle@google.com> |
| Date: Fri, 6 Oct 2017 15:18:31 -0700 |
| Subject: [PATCH] selftests/exec: include cwd in long path calculation |
| |
| When creating a pathname close to PATH_MAX to test execveat, factor in |
| the current working directory path otherwise we end up with an absolute |
| path that is longer than PATH_MAX. While execveat() may succeed, subsequent |
| calls to the kernel from the runtime environment which are required to |
| successfully execute the test binary/script may fail because of this. |
| |
| To keep the semantics of the test the same, rework the relative pathname |
| part of the test to be relative to the root directory so it isn't |
| decreased by the length of the current working directory path. |
| |
| Bug: 67016227 |
| Test: run vts-kernel -m VtsKernelLinuxKselftestStaging |
| Change-Id: Ib407d1afc52de7e58cb208fd41ade6e8c38d8bfd |
| Signed-off-by: Steve Muckle <smuckle@google.com> |
| --- |
| tools/testing/selftests/exec/execveat.c | 27 +++++++++++++++++++-------- |
| 1 file changed, 19 insertions(+), 8 deletions(-) |
| |
| diff --git a/tools/testing/selftests/exec/execveat.c b/tools/testing/selftests/exec/execveat.c |
| index 8d5d1d2ee7c1..67cd4597db2b 100644 |
| --- a/tools/testing/selftests/exec/execveat.c |
| +++ b/tools/testing/selftests/exec/execveat.c |
| @@ -147,7 +147,7 @@ static void exe_cp(const char *src, const char *dest) |
| } |
| |
| #define XX_DIR_LEN 200 |
| -static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script) |
| +static int check_execveat_pathmax(int root_dfd, const char *src, int is_script) |
| { |
| int fail = 0; |
| int ii, count, len; |
| @@ -156,20 +156,30 @@ static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script) |
| |
| if (*longpath == '\0') { |
| /* Create a filename close to PATH_MAX in length */ |
| + char *cwd = getcwd(NULL, 0); |
| + |
| + if (!cwd) { |
| + printf("Failed to getcwd(), errno=%d (%s)\n", |
| + errno, strerror(errno)); |
| + return 2; |
| + } |
| + strcpy(longpath, cwd); |
| + strcat(longpath, "/"); |
| memset(longname, 'x', XX_DIR_LEN - 1); |
| longname[XX_DIR_LEN - 1] = '/'; |
| longname[XX_DIR_LEN] = '\0'; |
| - count = (PATH_MAX - 3) / XX_DIR_LEN; |
| + count = (PATH_MAX - 3 - strlen(cwd)) / XX_DIR_LEN; |
| for (ii = 0; ii < count; ii++) { |
| strcat(longpath, longname); |
| mkdir(longpath, 0755); |
| } |
| - len = (PATH_MAX - 3) - (count * XX_DIR_LEN); |
| + len = (PATH_MAX - 3 - strlen(cwd)) - (count * XX_DIR_LEN); |
| if (len <= 0) |
| len = 1; |
| memset(longname, 'y', len); |
| longname[len] = '\0'; |
| strcat(longpath, longname); |
| + free(cwd); |
| } |
| exe_cp(src, longpath); |
| |
| @@ -190,7 +200,7 @@ static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script) |
| } |
| |
| /* |
| - * Execute as a long pathname relative to ".". If this is a script, |
| + * Execute as a long pathname relative to "/". If this is a script, |
| * the interpreter will launch but fail to open the script because its |
| * name ("/dev/fd/5/xxx....") is bigger than PATH_MAX. |
| * |
| @@ -200,10 +210,10 @@ static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script) |
| * the exit status shall be 126."), so allow either. |
| */ |
| if (is_script) |
| - fail += check_execveat_invoked_rc(dot_dfd, longpath, 0, |
| + fail += check_execveat_invoked_rc(root_dfd, longpath + 1, 0, |
| 127, 126); |
| else |
| - fail += check_execveat(dot_dfd, longpath, 0); |
| + fail += check_execveat(root_dfd, longpath + 1, 0); |
| |
| return fail; |
| } |
| @@ -218,6 +228,7 @@ static int run_tests(void) |
| int subdir_dfd_ephemeral = open_or_die("subdir.ephemeral", |
| O_DIRECTORY|O_RDONLY); |
| int dot_dfd = open_or_die(".", O_DIRECTORY|O_RDONLY); |
| + int root_dfd = open_or_die("/", O_DIRECTORY|O_RDONLY); |
| int dot_dfd_path = open_or_die(".", O_DIRECTORY|O_RDONLY|O_PATH); |
| int dot_dfd_cloexec = open_or_die(".", O_DIRECTORY|O_RDONLY|O_CLOEXEC); |
| int fd = open_or_die("execveat", O_RDONLY); |
| @@ -353,8 +364,8 @@ static int run_tests(void) |
| /* Attempt to execute relative to non-directory => ENOTDIR */ |
| fail += check_execveat_fail(fd, "execveat", 0, ENOTDIR); |
| |
| - fail += check_execveat_pathmax(dot_dfd, "execveat", 0); |
| - fail += check_execveat_pathmax(dot_dfd, "script", 1); |
| + fail += check_execveat_pathmax(root_dfd, "execveat", 0); |
| + fail += check_execveat_pathmax(root_dfd, "script", 1); |
| return fail; |
| } |
| |
| -- |
| 2.16.0.rc1.238.g530d649a79-goog |
| |