linux/tools/testing/selftests/proc/setns-sysvipc.c
<<
>>
Prefs
   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_NEWIPC) points to new /proc/sysvipc content even
  18 * if old one is in dcache.
  19 */
  20#undef NDEBUG
  21#include <assert.h>
  22#include <errno.h>
  23#include <stdio.h>
  24#include <sched.h>
  25#include <signal.h>
  26#include <stdlib.h>
  27#include <string.h>
  28#include <unistd.h>
  29#include <sys/types.h>
  30#include <sys/stat.h>
  31#include <fcntl.h>
  32#include <sys/ipc.h>
  33#include <sys/shm.h>
  34
  35static pid_t pid = -1;
  36
  37static void f(void)
  38{
  39        if (pid > 0) {
  40                kill(pid, SIGTERM);
  41        }
  42}
  43
  44int main(void)
  45{
  46        int fd[2];
  47        char _ = 0;
  48        int nsfd;
  49
  50        atexit(f);
  51
  52        /* Check for priviledges and syscall availability straight away. */
  53        if (unshare(CLONE_NEWIPC) == -1) {
  54                if (errno == ENOSYS || errno == EPERM) {
  55                        return 4;
  56                }
  57                return 1;
  58        }
  59        /* Distinguisher between two otherwise empty IPC namespaces. */
  60        if (shmget(IPC_PRIVATE, 1, IPC_CREAT) == -1) {
  61                return 1;
  62        }
  63
  64        if (pipe(fd) == -1) {
  65                return 1;
  66        }
  67
  68        pid = fork();
  69        if (pid == -1) {
  70                return 1;
  71        }
  72
  73        if (pid == 0) {
  74                if (unshare(CLONE_NEWIPC) == -1) {
  75                        return 1;
  76                }
  77
  78                if (write(fd[1], &_, 1) != 1) {
  79                        return 1;
  80                }
  81
  82                pause();
  83
  84                return 0;
  85        }
  86
  87        if (read(fd[0], &_, 1) != 1) {
  88                return 1;
  89        }
  90
  91        {
  92                char buf[64];
  93                snprintf(buf, sizeof(buf), "/proc/%u/ns/ipc", pid);
  94                nsfd = open(buf, O_RDONLY);
  95                if (nsfd == -1) {
  96                        return 1;
  97                }
  98        }
  99
 100        /* Reliably pin dentry into dcache. */
 101        (void)open("/proc/sysvipc/shm", O_RDONLY);
 102
 103        if (setns(nsfd, CLONE_NEWIPC) == -1) {
 104                return 1;
 105        }
 106
 107        kill(pid, SIGTERM);
 108        pid = 0;
 109
 110        {
 111                char buf[4096];
 112                ssize_t rv;
 113                int fd;
 114
 115                fd = open("/proc/sysvipc/shm", O_RDONLY);
 116                if (fd == -1) {
 117                        return 1;
 118                }
 119
 120#define S32 "       key      shmid perms       size  cpid  lpid nattch   uid   gid  cuid  cgid      atime      dtime      ctime        rss       swap\n"
 121#define S64 "       key      shmid perms                  size  cpid  lpid nattch   uid   gid  cuid  cgid      atime      dtime      ctime                   rss                  swap\n"
 122                rv = read(fd, buf, sizeof(buf));
 123                if (rv == strlen(S32)) {
 124                        assert(memcmp(buf, S32, strlen(S32)) == 0);
 125                } else if (rv == strlen(S64)) {
 126                        assert(memcmp(buf, S64, strlen(S64)) == 0);
 127                } else {
 128                        assert(0);
 129                }
 130        }
 131
 132        return 0;
 133}
 134