cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

setns-dcache.c (2612B)


      1/*
      2 * Copyright © 2019 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 setns(CLONE_NEWNET) points to new /proc/net content even
     18 * if old one is in dcache.
     19 *
     20 * FIXME /proc/net/unix is under CONFIG_UNIX which can be disabled.
     21 */
     22#undef NDEBUG
     23#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}