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_NEWIPC) points to new /proc/sysvipc content even
0018  * if old one is in dcache.
0019  */
0020 #undef NDEBUG
0021 #include <assert.h>
0022 #include <errno.h>
0023 #include <stdio.h>
0024 #include <sched.h>
0025 #include <signal.h>
0026 #include <stdlib.h>
0027 #include <string.h>
0028 #include <unistd.h>
0029 #include <sys/types.h>
0030 #include <sys/stat.h>
0031 #include <fcntl.h>
0032 #include <sys/ipc.h>
0033 #include <sys/shm.h>
0034 
0035 static pid_t pid = -1;
0036 
0037 static void f(void)
0038 {
0039     if (pid > 0) {
0040         kill(pid, SIGTERM);
0041     }
0042 }
0043 
0044 int main(void)
0045 {
0046     int fd[2];
0047     char _ = 0;
0048     int nsfd;
0049 
0050     atexit(f);
0051 
0052     /* Check for priviledges and syscall availability straight away. */
0053     if (unshare(CLONE_NEWIPC) == -1) {
0054         if (errno == ENOSYS || errno == EPERM) {
0055             return 4;
0056         }
0057         return 1;
0058     }
0059     /* Distinguisher between two otherwise empty IPC namespaces. */
0060     if (shmget(IPC_PRIVATE, 1, IPC_CREAT) == -1) {
0061         return 1;
0062     }
0063 
0064     if (pipe(fd) == -1) {
0065         return 1;
0066     }
0067 
0068     pid = fork();
0069     if (pid == -1) {
0070         return 1;
0071     }
0072 
0073     if (pid == 0) {
0074         if (unshare(CLONE_NEWIPC) == -1) {
0075             return 1;
0076         }
0077 
0078         if (write(fd[1], &_, 1) != 1) {
0079             return 1;
0080         }
0081 
0082         pause();
0083 
0084         return 0;
0085     }
0086 
0087     if (read(fd[0], &_, 1) != 1) {
0088         return 1;
0089     }
0090 
0091     {
0092         char buf[64];
0093         snprintf(buf, sizeof(buf), "/proc/%u/ns/ipc", pid);
0094         nsfd = open(buf, O_RDONLY);
0095         if (nsfd == -1) {
0096             return 1;
0097         }
0098     }
0099 
0100     /* Reliably pin dentry into dcache. */
0101     (void)open("/proc/sysvipc/shm", O_RDONLY);
0102 
0103     if (setns(nsfd, CLONE_NEWIPC) == -1) {
0104         return 1;
0105     }
0106 
0107     kill(pid, SIGTERM);
0108     pid = 0;
0109 
0110     {
0111         char buf[4096];
0112         ssize_t rv;
0113         int fd;
0114 
0115         fd = open("/proc/sysvipc/shm", O_RDONLY);
0116         if (fd == -1) {
0117             return 1;
0118         }
0119 
0120 #define S32 "       key      shmid perms       size  cpid  lpid nattch   uid   gid  cuid  cgid      atime      dtime      ctime        rss       swap\n"
0121 #define S64 "       key      shmid perms                  size  cpid  lpid nattch   uid   gid  cuid  cgid      atime      dtime      ctime                   rss                  swap\n"
0122         rv = read(fd, buf, sizeof(buf));
0123         if (rv == strlen(S32)) {
0124             assert(memcmp(buf, S32, strlen(S32)) == 0);
0125         } else if (rv == strlen(S64)) {
0126             assert(memcmp(buf, S64, strlen(S64)) == 0);
0127         } else {
0128             assert(0);
0129         }
0130     }
0131 
0132     return 0;
0133 }