1 /* 2 * Copyright (c) 2021 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 /* 17 * Test that "mount -t proc -o subset=pid" hides everything but pids, 18 * /proc/self and /proc/thread-self. 19 */ 20 #undef NDEBUG 21 #include <assert.h> 22 #include <errno.h> 23 #include <sched.h> 24 #include <stdbool.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <sys/mount.h> 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 #include <fcntl.h> 31 #include <dirent.h> 32 #include <unistd.h> 33 #include <stdio.h> 34 35 static inline bool streq(const char *a, const char *b) 36 { 37 return strcmp(a, b) == 0; 38 } 39 40 static void make_private_proc(void) 41 { 42 if (unshare(CLONE_NEWNS) == -1) { 43 if (errno == ENOSYS || errno == EPERM) { 44 exit(4); 45 } 46 exit(1); 47 } 48 if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) == -1) { 49 exit(1); 50 } 51 if (mount(NULL, "/proc", "proc", 0, "subset=pid") == -1) { 52 exit(1); 53 } 54 } 55 56 static bool string_is_pid(const char *s) 57 { 58 while (1) { 59 switch (*s++) { 60 case '0':case '1':case '2':case '3':case '4': 61 case '5':case '6':case '7':case '8':case '9': 62 continue; 63 64 case '\0': 65 return true; 66 67 default: 68 return false; 69 } 70 } 71 } 72 73 int main(void) 74 { 75 make_private_proc(); 76 77 DIR *d = opendir("/proc"); 78 assert(d); 79 80 struct dirent *de; 81 82 bool dot = false; 83 bool dot_dot = false; 84 bool self = false; 85 bool thread_self = false; 86 87 while ((de = readdir(d))) { 88 if (streq(de->d_name, ".")) { 89 assert(!dot); 90 dot = true; 91 assert(de->d_type == DT_DIR); 92 } else if (streq(de->d_name, "..")) { 93 assert(!dot_dot); 94 dot_dot = true; 95 assert(de->d_type == DT_DIR); 96 } else if (streq(de->d_name, "self")) { 97 assert(!self); 98 self = true; 99 assert(de->d_type == DT_LNK); 100 } else if (streq(de->d_name, "thread-self")) { 101 assert(!thread_self); 102 thread_self = true; 103 assert(de->d_type == DT_LNK); 104 } else { 105 if (!string_is_pid(de->d_name)) { 106 fprintf(stderr, "d_name '%s'\n", de->d_name); 107 assert(0); 108 } 109 assert(de->d_type == DT_DIR); 110 } 111 } 112 113 char c; 114 int rv = readlink("/proc/cpuinfo", &c, 1); 115 assert(rv == -1 && errno == ENOENT); 116 117 int fd = open("/proc/cpuinfo", O_RDONLY); 118 assert(fd == -1 && errno == ENOENT); 119 120 return 0; 121 } 122