Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

exec selftests: test ->recursion_depth

Test that trivially recursing script onto itself doesn't work.

Note: this is different test from ELOOP tests in execveat.c Those test
that execveat(2) doesn't follow symlinks when told to do so.

Link: http://lkml.kernel.org/r/20190423192720.GA21433@avx2
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Shuah Khan <shuah@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Alexey Dobriyan and committed by
Linus Torvalds
4e7301e6 a6231d19

+72
+1
tools/testing/selftests/exec/.gitignore
··· 6 6 execveat.path.ephemeral 7 7 execveat.ephemeral 8 8 execveat.denatured 9 + /recursion-depth 9 10 xxxxxxxx*
+4
tools/testing/selftests/exec/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 CFLAGS = -Wall 3 + CFLAGS += -Wno-nonnull 4 + CFLAGS += -D_GNU_SOURCE 3 5 4 6 TEST_GEN_PROGS := execveat 5 7 TEST_GEN_FILES := execveat.symlink execveat.denatured script subdir 6 8 # Makefile is a run-time dependency, since it's accessed by the execveat test 7 9 TEST_FILES := Makefile 10 + 11 + TEST_GEN_PROGS += recursion-depth 8 12 9 13 EXTRA_CLEAN := $(OUTPUT)/subdir.moved $(OUTPUT)/execveat.moved $(OUTPUT)/xxxxx* 10 14
+67
tools/testing/selftests/exec/recursion-depth.c
··· 1 + /* 2 + * Copyright (c) 2019 Alexey Dobriyan <adobriyan@gmail.com> 3 + * 4 + * Permission to use, copy, modify, and distribute this software for any 5 + * purpose with or without fee is hereby granted, provided that the above 6 + * copyright notice and this permission notice appear in all copies. 7 + * 8 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 + */ 16 + /* Test that pointing #! script interpreter to self doesn't recurse. */ 17 + #include <errno.h> 18 + #include <sched.h> 19 + #include <stdio.h> 20 + #include <string.h> 21 + #include <sys/types.h> 22 + #include <sys/stat.h> 23 + #include <fcntl.h> 24 + #include <sys/mount.h> 25 + #include <unistd.h> 26 + 27 + int main(void) 28 + { 29 + if (unshare(CLONE_NEWNS) == -1) { 30 + if (errno == ENOSYS || errno == EPERM) { 31 + fprintf(stderr, "error: unshare, errno %d\n", errno); 32 + return 4; 33 + } 34 + fprintf(stderr, "error: unshare, errno %d\n", errno); 35 + return 1; 36 + } 37 + if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) == -1) { 38 + fprintf(stderr, "error: mount '/', errno %d\n", errno); 39 + return 1; 40 + } 41 + /* Require "exec" filesystem. */ 42 + if (mount(NULL, "/tmp", "ramfs", 0, NULL) == -1) { 43 + fprintf(stderr, "error: mount ramfs, errno %d\n", errno); 44 + return 1; 45 + } 46 + 47 + #define FILENAME "/tmp/1" 48 + 49 + int fd = creat(FILENAME, 0700); 50 + if (fd == -1) { 51 + fprintf(stderr, "error: creat, errno %d\n", errno); 52 + return 1; 53 + } 54 + #define S "#!" FILENAME "\n" 55 + if (write(fd, S, strlen(S)) != strlen(S)) { 56 + fprintf(stderr, "error: write, errno %d\n", errno); 57 + return 1; 58 + } 59 + close(fd); 60 + 61 + int rv = execve(FILENAME, NULL, NULL); 62 + if (rv == -1 && errno == ELOOP) { 63 + return 0; 64 + } 65 + fprintf(stderr, "error: execve, rv %d, errno %d\n", rv, errno); 66 + return 1; 67 + }