Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright © 2019 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 setns(CLONE_NEWNET) points to new /proc/net content even
0018  * if old one is in dcache.
0019  *
0020  * FIXME /proc/net/unix is under CONFIG_UNIX which can be disabled.
0021  */
0022 #undef NDEBUG
0023 #include <assert.h>
0024 #include <errno.h>
0025 #include <sched.h>
0026 #include <signal.h>
0027 #include <stdio.h>
0028 #include <stdlib.h>
0029 #include <string.h>
0030 #include <unistd.h>
0031 #include <sys/types.h>
0032 #include <sys/stat.h>
0033 #include <fcntl.h>
0034 #include <sys/socket.h>
0035 
0036 static pid_t pid = -1;
0037 
0038 static void f(void)
0039 {
0040     if (pid > 0) {
0041         kill(pid, SIGTERM);
0042     }
0043 }
0044 
0045 int main(void)
0046 {
0047     int fd[2];
0048     char _ = 0;
0049     int nsfd;
0050 
0051     atexit(f);
0052 
0053     /* Check for priviledges and syscall availability straight away. */
0054     if (unshare(CLONE_NEWNET) == -1) {
0055         if (errno == ENOSYS || errno == EPERM) {
0056             return 4;
0057         }
0058         return 1;
0059     }
0060     /* Distinguisher between two otherwise empty net namespaces. */
0061     if (socket(AF_UNIX, SOCK_STREAM, 0) == -1) {
0062         return 1;
0063     }
0064 
0065     if (pipe(fd) == -1) {
0066         return 1;
0067     }
0068 
0069     pid = fork();
0070     if (pid == -1) {
0071         return 1;
0072     }
0073 
0074     if (pid == 0) {
0075         if (unshare(CLONE_NEWNET) == -1) {
0076             return 1;
0077         }
0078 
0079         if (write(fd[1], &_, 1) != 1) {
0080             return 1;
0081         }
0082 
0083         pause();
0084 
0085         return 0;
0086     }
0087 
0088     if (read(fd[0], &_, 1) != 1) {
0089         return 1;
0090     }
0091 
0092     {
0093         char buf[64];
0094         snprintf(buf, sizeof(buf), "/proc/%u/ns/net", pid);
0095         nsfd = open(buf, O_RDONLY);
0096         if (nsfd == -1) {
0097             return 1;
0098         }
0099     }
0100 
0101     /* Reliably pin dentry into dcache. */
0102     (void)open("/proc/net/unix", O_RDONLY);
0103 
0104     if (setns(nsfd, CLONE_NEWNET) == -1) {
0105         return 1;
0106     }
0107 
0108     kill(pid, SIGTERM);
0109     pid = 0;
0110 
0111     {
0112         char buf[4096];
0113         ssize_t rv;
0114         int fd;
0115 
0116         fd = open("/proc/net/unix", O_RDONLY);
0117         if (fd == -1) {
0118             return 1;
0119         }
0120 
0121 #define S "Num       RefCount Protocol Flags    Type St Inode Path\n"
0122         rv = read(fd, buf, sizeof(buf));
0123 
0124         assert(rv == strlen(S));
0125         assert(memcmp(buf, S, strlen(S)) == 0);
0126     }
0127 
0128     return 0;
0129 }