#include #include #include #include #define _GNU_SOURCE #define __USE_GNU #include #include #include #include #include #include #include #include static void do_unshare(int num, int flags) { int res; printf(" %d) unshare(0x%x).\n", num, flags); res = unshare(flags); if (res != 0) { printf(" %d: unshare(0x%x) failed, errno %d.\n", num, flags, errno); exit(3); } } static void set_rmid_forced(char *value) { int fd; int i; fd=open("/proc/sys/kernel/shm_rmid_forced", O_RDWR); if (fd == -1) { printf("open shm_rmid_forced failed, errno %d.\n", errno); exit (1); } i = write(fd, value, 2); if (i != 2) { printf("unexpected result when writing %s to shm_rmid_forced: %d, errno %d.\n", value, i, errno); exit (2); } close(fd); } static void *do_shmget(bool map_it) { int seg; void *ptr; if ((seg = shmget (IPC_PRIVATE, 1, IPC_CREAT| 0600)) == -1) { perror("shmget"); exit(3); } if (map_it) { if ((ptr = shmat (seg, 0, 0)) == (void*)-1) { perror ("shmat"); exit(4); } } else { ptr = NULL; } return ptr; } int main (int argc, char **argv) { pid_t child; (void)argv; (void)argc; printf("shmns4:\n"); printf(" One process creates and maps shm segments in multiple namespaces.\n"); printf(" The namespaces are replaced before unmapping the segments.\n"); do_unshare(1, CLONE_NEWIPC); set_rmid_forced("1\n"); child = fork(); if (child == -1) { perror ("fork"); exit(5); } if (child == 0) { printf("create a namespace, create 2 shm segments, do not map them.\n"); do_unshare(2, CLONE_NEWIPC); set_rmid_forced("1\n"); do_shmget(false); do_shmget(false); do_unshare(2, CLONE_NEWIPC); set_rmid_forced("0\n"); sleep(5); /* namespace destruction is done in a worker, thus wait a bit */ printf("create a namespace, create 2 shm segments, do not map them, no auto-rm.\n"); do_shmget(false); do_shmget(false); do_unshare(2, CLONE_NEWIPC); set_rmid_forced("1\n"); sleep(5); /* namespace destruction is done in a worker, thus wait a bit */ printf("create a namespace, create 2 shm segments, map them.\n"); do_shmget(true); do_shmget(true); do_unshare(2, CLONE_NEWIPC); set_rmid_forced("0\n"); sleep(5); /* namespace destruction is done in a worker, thus wait a bit */ printf("Once more: Create a namespace, create 2 shm segments, map them, no auto-rm.\n"); do_shmget(true); do_shmget(true); printf("Orphan namespace (switch back to parent namespace).\n"); { char path[255]; int fd; sprintf(path, "/proc/%d/ns/ipc", getppid()); fd = open(path, O_RDONLY); if (fd == -1) { perror("open ipc ns"); exit(6); } if (setns(fd, 0) == -1) { perror("setns to parent"); exit(7); } } sleep(5); /* namespace destruction is done in a worker, thus wait a bit */ printf("Before exit of child: 4 mappings exist in 2 namespaces.\n"); exit(0); } else { int status; int ret; sleep(1); ret = waitpid(child, &status, 0); sleep(10); printf("parent:waitpid returned %d, status %d.\n", ret, status); } return 0; }