]> granicus.if.org Git - strace/blob - tests/ioctl_nsfs.c
Update copyright headers
[strace] / tests / ioctl_nsfs.c
1 /*
2  * Check decoding of NS_* commands of ioctl syscall.
3  *
4  * Copyright (c) 2017 Nikolay Marchuk <marchuk.nikolay.a@gmail.com>
5  * Copyright (c) 2017-2018 The strace developers.
6  * All rights reserved.
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10
11 #include "tests.h"
12
13 #include <fcntl.h>
14 #include <sched.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <sys/ioctl.h>
18 #include <sys/wait.h>
19 #include <unistd.h>
20 #include "nsfs.h"
21
22 #ifndef CLONE_NEWUSER
23 # define CLONE_NEWUSER 0x10000000
24 #endif
25
26 static void
27 test_no_namespace(void)
28 {
29         ioctl(-1, NS_GET_USERNS);
30         printf("ioctl(-1, NS_GET_USERNS) = -1 EBADF (%m)\n");
31         ioctl(-1, NS_GET_PARENT);
32         printf("ioctl(-1, NS_GET_PARENT) = -1 EBADF (%m)\n");
33         ioctl(-1, NS_GET_NSTYPE);
34         printf("ioctl(-1, NS_GET_NSTYPE) = -1 EBADF (%m)\n");
35         ioctl(-1, NS_GET_OWNER_UID, NULL);
36         printf("ioctl(-1, NS_GET_OWNER_UID, NULL) = -1 EBADF (%m)\n");
37 }
38
39 static void
40 test_clone(pid_t pid)
41 {
42         char path[sizeof("/proc/%d/ns/user") + sizeof(int)*3];
43         snprintf(path, sizeof(path), "/proc/%d/ns/user", pid);
44
45         int ns_fd = open(path, O_RDONLY);
46         if (ns_fd == -1)
47                 perror_msg_and_skip("open: %s", path);
48
49         int userns_fd = ioctl(ns_fd, NS_GET_USERNS);
50         printf("ioctl(%d, NS_GET_USERNS) = %s\n", ns_fd, sprintrc(userns_fd));
51
52         int parent_ns_fd = ioctl(userns_fd, NS_GET_PARENT);
53         printf("ioctl(%d, NS_GET_PARENT) = %s\n",
54                userns_fd, sprintrc(parent_ns_fd));
55
56         int nstype = ioctl(userns_fd, NS_GET_NSTYPE);
57         if (nstype == -1) {
58                 printf("ioctl(%d, NS_GET_NSTYPE) = %s\n",
59                        userns_fd, sprintrc(nstype));
60         } else {
61                 printf("ioctl(%d, NS_GET_NSTYPE) = %d (CLONE_NEWUSER)\n",
62                        userns_fd, nstype);
63         }
64
65         TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, uid);
66         int rc = ioctl(userns_fd, NS_GET_OWNER_UID, uid);
67         if (rc == -1) {
68                 printf("ioctl(%d, NS_GET_OWNER_UID, %p) = %s\n",
69                        userns_fd, uid, sprintrc(rc));
70         } else {
71                 printf("ioctl(%d, NS_GET_OWNER_UID, [%u]) = %d\n",
72                        userns_fd, *uid, rc);
73         }
74 }
75
76 static int
77 child(void *arg)
78 {
79         int *pipefd = (int *) arg;
80         close(pipefd[1]);
81         /* Wait for EOF from pipe. */
82         if (read(pipefd[0], &pipefd[1], 1))
83                 perror_msg_and_fail("read");
84         return 0;
85 }
86
87 #ifdef IA64
88 extern int __clone2(int (*)(void *), void *, size_t, int, void *, ...);
89 # define clone(fn, child_stack, flags, arg)     \
90                 __clone2(fn, child_stack, get_page_size() / 2, flags, arg)
91 #endif
92
93 static void
94 test_user_namespace(void)
95 {
96         pid_t pid;
97         int pipefd[2];
98         int status;
99
100         if (pipe(pipefd))
101                 perror_msg_and_fail("pipe");
102
103         pid = clone(child, tail_alloc(get_page_size() / 2),
104                     CLONE_NEWUSER | CLONE_UNTRACED | SIGCHLD, pipefd);
105         if (pid == -1) {
106                 perror("clone");
107                 return;
108         }
109         close(pipefd[0]);
110         test_clone(pid);
111         close(pipefd[1]);
112         if (wait(&status) != pid) {
113                 perror_msg_and_fail("wait");
114         } else if (status != 0) {
115                 error_msg_and_fail("unexpected child exit status %d", status);
116         }
117 }
118
119 int
120 main(void)
121 {
122         test_no_namespace();
123         test_user_namespace();
124         puts("+++ exited with 0 +++");
125         return 0;
126 }