Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2021 Alexey Dobriyan <adobriyan@gmail.com>
0003  *
0004  * Permission to use, copy, modify, and distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 /*
0017  * Test that "mount -t proc -o subset=pid" hides everything but pids,
0018  * /proc/self and /proc/thread-self.
0019  */
0020 #undef NDEBUG
0021 #include <assert.h>
0022 #include <errno.h>
0023 #include <sched.h>
0024 #include <stdbool.h>
0025 #include <stdlib.h>
0026 #include <string.h>
0027 #include <sys/mount.h>
0028 #include <sys/types.h>
0029 #include <sys/stat.h>
0030 #include <fcntl.h>
0031 #include <dirent.h>
0032 #include <unistd.h>
0033 #include <stdio.h>
0034 
0035 static inline bool streq(const char *a, const char *b)
0036 {
0037     return strcmp(a, b) == 0;
0038 }
0039 
0040 static void make_private_proc(void)
0041 {
0042     if (unshare(CLONE_NEWNS) == -1) {
0043         if (errno == ENOSYS || errno == EPERM) {
0044             exit(4);
0045         }
0046         exit(1);
0047     }
0048     if (mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) == -1) {
0049         exit(1);
0050     }
0051     if (mount(NULL, "/proc", "proc", 0, "subset=pid") == -1) {
0052         exit(1);
0053     }
0054 }
0055 
0056 static bool string_is_pid(const char *s)
0057 {
0058     while (1) {
0059         switch (*s++) {
0060         case '0':case '1':case '2':case '3':case '4':
0061         case '5':case '6':case '7':case '8':case '9':
0062             continue;
0063 
0064         case '\0':
0065             return true;
0066 
0067         default:
0068             return false;
0069         }
0070     }
0071 }
0072 
0073 int main(void)
0074 {
0075     make_private_proc();
0076 
0077     DIR *d = opendir("/proc");
0078     assert(d);
0079 
0080     struct dirent *de;
0081 
0082     bool dot = false;
0083     bool dot_dot = false;
0084     bool self = false;
0085     bool thread_self = false;
0086 
0087     while ((de = readdir(d))) {
0088         if (streq(de->d_name, ".")) {
0089             assert(!dot);
0090             dot = true;
0091             assert(de->d_type == DT_DIR);
0092         } else if (streq(de->d_name, "..")) {
0093             assert(!dot_dot);
0094             dot_dot = true;
0095             assert(de->d_type == DT_DIR);
0096         } else if (streq(de->d_name, "self")) {
0097             assert(!self);
0098             self = true;
0099             assert(de->d_type == DT_LNK);
0100         } else if (streq(de->d_name, "thread-self")) {
0101             assert(!thread_self);
0102             thread_self = true;
0103             assert(de->d_type == DT_LNK);
0104         } else {
0105             if (!string_is_pid(de->d_name)) {
0106                 fprintf(stderr, "d_name '%s'\n", de->d_name);
0107                 assert(0);
0108             }
0109             assert(de->d_type == DT_DIR);
0110         }
0111     }
0112 
0113     char c;
0114     int rv = readlink("/proc/cpuinfo", &c, 1);
0115     assert(rv == -1 && errno == ENOENT);
0116 
0117     int fd = open("/proc/cpuinfo", O_RDONLY);
0118     assert(fd == -1 && errno == ENOENT);
0119 
0120     return 0;
0121 }