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