130 lines · c
1/*2 * Copyright © 2019 Alexey Dobriyan <adobriyan@gmail.com>3 *4 * Permission to use, copy, modify, and distribute this software for any5 * purpose with or without fee is hereby granted, provided that the above6 * copyright notice and this permission notice appear in all copies.7 *8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.15 */16/*17 * Test that setns(CLONE_NEWNET) points to new /proc/net content even18 * if old one is in dcache.19 *20 * FIXME /proc/net/unix is under CONFIG_UNIX which can be disabled.21 */22#undef NDEBUG23#include <assert.h>24#include <errno.h>25#include <sched.h>26#include <signal.h>27#include <stdio.h>28#include <stdlib.h>29#include <string.h>30#include <unistd.h>31#include <sys/types.h>32#include <sys/stat.h>33#include <fcntl.h>34#include <sys/socket.h>35 36static pid_t pid = -1;37 38static void f(void)39{40 if (pid > 0) {41 kill(pid, SIGTERM);42 }43}44 45int main(void)46{47 int fd[2];48 char _ = 0;49 int nsfd;50 51 atexit(f);52 53 /* Check for priviledges and syscall availability straight away. */54 if (unshare(CLONE_NEWNET) == -1) {55 if (errno == ENOSYS || errno == EPERM) {56 return 4;57 }58 return 1;59 }60 /* Distinguisher between two otherwise empty net namespaces. */61 if (socket(AF_UNIX, SOCK_STREAM, 0) == -1) {62 return 1;63 }64 65 if (pipe(fd) == -1) {66 return 1;67 }68 69 pid = fork();70 if (pid == -1) {71 return 1;72 }73 74 if (pid == 0) {75 if (unshare(CLONE_NEWNET) == -1) {76 return 1;77 }78 79 if (write(fd[1], &_, 1) != 1) {80 return 1;81 }82 83 pause();84 85 return 0;86 }87 88 if (read(fd[0], &_, 1) != 1) {89 return 1;90 }91 92 {93 char buf[64];94 snprintf(buf, sizeof(buf), "/proc/%u/ns/net", pid);95 nsfd = open(buf, O_RDONLY);96 if (nsfd == -1) {97 return 1;98 }99 }100 101 /* Reliably pin dentry into dcache. */102 (void)open("/proc/net/unix", O_RDONLY);103 104 if (setns(nsfd, CLONE_NEWNET) == -1) {105 return 1;106 }107 108 kill(pid, SIGTERM);109 pid = 0;110 111 {112 char buf[4096];113 ssize_t rv;114 int fd;115 116 fd = open("/proc/net/unix", O_RDONLY);117 if (fd == -1) {118 return 1;119 }120 121#define S "Num RefCount Protocol Flags Type St Inode Path\n"122 rv = read(fd, buf, sizeof(buf));123 124 assert(rv == strlen(S));125 assert(memcmp(buf, S, strlen(S)) == 0);126 }127 128 return 0;129}130