Merge tag 'printk-for-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/printk...
[linux-2.6-microblaze.git] / tools / testing / selftests / uevent / uevent_filtering.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #define _GNU_SOURCE
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <linux/netlink.h>
7 #include <signal.h>
8 #include <stdbool.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/prctl.h>
13 #include <sys/socket.h>
14 #include <sched.h>
15 #include <sys/eventfd.h>
16 #include <sys/stat.h>
17 #include <sys/syscall.h>
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21
22 #include "../kselftest_harness.h"
23
24 #define __DEV_FULL "/sys/devices/virtual/mem/full/uevent"
25 #define __UEVENT_BUFFER_SIZE (2048 * 2)
26 #define __UEVENT_HEADER "add@/devices/virtual/mem/full"
27 #define __UEVENT_HEADER_LEN sizeof("add@/devices/virtual/mem/full")
28 #define __UEVENT_LISTEN_ALL -1
29
30 ssize_t read_nointr(int fd, void *buf, size_t count)
31 {
32         ssize_t ret;
33
34 again:
35         ret = read(fd, buf, count);
36         if (ret < 0 && errno == EINTR)
37                 goto again;
38
39         return ret;
40 }
41
42 ssize_t write_nointr(int fd, const void *buf, size_t count)
43 {
44         ssize_t ret;
45
46 again:
47         ret = write(fd, buf, count);
48         if (ret < 0 && errno == EINTR)
49                 goto again;
50
51         return ret;
52 }
53
54 int wait_for_pid(pid_t pid)
55 {
56         int status, ret;
57
58 again:
59         ret = waitpid(pid, &status, 0);
60         if (ret == -1) {
61                 if (errno == EINTR)
62                         goto again;
63
64                 return -1;
65         }
66
67         if (ret != pid)
68                 goto again;
69
70         if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
71                 return -1;
72
73         return 0;
74 }
75
76 static int uevent_listener(unsigned long post_flags, bool expect_uevent,
77                            int sync_fd)
78 {
79         int sk_fd, ret;
80         socklen_t sk_addr_len;
81         int fret = -1, rcv_buf_sz = __UEVENT_BUFFER_SIZE;
82         uint64_t sync_add = 1;
83         struct sockaddr_nl sk_addr = { 0 }, rcv_addr = { 0 };
84         char buf[__UEVENT_BUFFER_SIZE] = { 0 };
85         struct iovec iov = { buf, __UEVENT_BUFFER_SIZE };
86         char control[CMSG_SPACE(sizeof(struct ucred))];
87         struct msghdr hdr = {
88                 &rcv_addr, sizeof(rcv_addr), &iov, 1,
89                 control,   sizeof(control),  0,
90         };
91
92         sk_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC,
93                        NETLINK_KOBJECT_UEVENT);
94         if (sk_fd < 0) {
95                 fprintf(stderr, "%s - Failed to open uevent socket\n", strerror(errno));
96                 return -1;
97         }
98
99         ret = setsockopt(sk_fd, SOL_SOCKET, SO_RCVBUF, &rcv_buf_sz,
100                          sizeof(rcv_buf_sz));
101         if (ret < 0) {
102                 fprintf(stderr, "%s - Failed to set socket options\n", strerror(errno));
103                 goto on_error;
104         }
105
106         sk_addr.nl_family = AF_NETLINK;
107         sk_addr.nl_groups = __UEVENT_LISTEN_ALL;
108
109         sk_addr_len = sizeof(sk_addr);
110         ret = bind(sk_fd, (struct sockaddr *)&sk_addr, sk_addr_len);
111         if (ret < 0) {
112                 fprintf(stderr, "%s - Failed to bind socket\n", strerror(errno));
113                 goto on_error;
114         }
115
116         ret = getsockname(sk_fd, (struct sockaddr *)&sk_addr, &sk_addr_len);
117         if (ret < 0) {
118                 fprintf(stderr, "%s - Failed to retrieve socket name\n", strerror(errno));
119                 goto on_error;
120         }
121
122         if ((size_t)sk_addr_len != sizeof(sk_addr)) {
123                 fprintf(stderr, "Invalid socket address size\n");
124                 goto on_error;
125         }
126
127         if (post_flags & CLONE_NEWUSER) {
128                 ret = unshare(CLONE_NEWUSER);
129                 if (ret < 0) {
130                         fprintf(stderr,
131                                 "%s - Failed to unshare user namespace\n",
132                                 strerror(errno));
133                         goto on_error;
134                 }
135         }
136
137         if (post_flags & CLONE_NEWNET) {
138                 ret = unshare(CLONE_NEWNET);
139                 if (ret < 0) {
140                         fprintf(stderr,
141                                 "%s - Failed to unshare network namespace\n",
142                                 strerror(errno));
143                         goto on_error;
144                 }
145         }
146
147         ret = write_nointr(sync_fd, &sync_add, sizeof(sync_add));
148         close(sync_fd);
149         if (ret != sizeof(sync_add)) {
150                 fprintf(stderr, "Failed to synchronize with parent process\n");
151                 goto on_error;
152         }
153
154         fret = 0;
155         for (;;) {
156                 ssize_t r;
157
158                 r = recvmsg(sk_fd, &hdr, 0);
159                 if (r <= 0) {
160                         fprintf(stderr, "%s - Failed to receive uevent\n", strerror(errno));
161                         ret = -1;
162                         break;
163                 }
164
165                 /* ignore libudev messages */
166                 if (memcmp(buf, "libudev", 8) == 0)
167                         continue;
168
169                 /* ignore uevents we didn't trigger */
170                 if (memcmp(buf, __UEVENT_HEADER, __UEVENT_HEADER_LEN) != 0)
171                         continue;
172
173                 if (!expect_uevent) {
174                         fprintf(stderr, "Received unexpected uevent:\n");
175                         ret = -1;
176                 }
177
178                 if (TH_LOG_ENABLED) {
179                         /* If logging is enabled dump the received uevent. */
180                         (void)write_nointr(STDERR_FILENO, buf, r);
181                         (void)write_nointr(STDERR_FILENO, "\n", 1);
182                 }
183
184                 break;
185         }
186
187 on_error:
188         close(sk_fd);
189
190         return fret;
191 }
192
193 int trigger_uevent(unsigned int times)
194 {
195         int fd, ret;
196         unsigned int i;
197
198         fd = open(__DEV_FULL, O_RDWR | O_CLOEXEC);
199         if (fd < 0) {
200                 if (errno != ENOENT)
201                         return -EINVAL;
202
203                 return -1;
204         }
205
206         for (i = 0; i < times; i++) {
207                 ret = write_nointr(fd, "add\n", sizeof("add\n") - 1);
208                 if (ret < 0) {
209                         fprintf(stderr, "Failed to trigger uevent\n");
210                         break;
211                 }
212         }
213         close(fd);
214
215         return ret;
216 }
217
218 int set_death_signal(void)
219 {
220         int ret;
221         pid_t ppid;
222
223         ret = prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
224
225         /* Check whether we have been orphaned. */
226         ppid = getppid();
227         if (ppid == 1) {
228                 pid_t self;
229
230                 self = getpid();
231                 ret = kill(self, SIGKILL);
232         }
233
234         if (ret < 0)
235                 return -1;
236
237         return 0;
238 }
239
240 static int do_test(unsigned long pre_flags, unsigned long post_flags,
241                    bool expect_uevent, int sync_fd)
242 {
243         int ret;
244         uint64_t wait_val;
245         pid_t pid;
246         sigset_t mask;
247         sigset_t orig_mask;
248         struct timespec timeout;
249
250         sigemptyset(&mask);
251         sigaddset(&mask, SIGCHLD);
252
253         ret = sigprocmask(SIG_BLOCK, &mask, &orig_mask);
254         if (ret < 0) {
255                 fprintf(stderr, "%s- Failed to block SIGCHLD\n", strerror(errno));
256                 return -1;
257         }
258
259         pid = fork();
260         if (pid < 0) {
261                 fprintf(stderr, "%s - Failed to fork() new process\n", strerror(errno));
262                 return -1;
263         }
264
265         if (pid == 0) {
266                 /* Make sure that we go away when our parent dies. */
267                 ret = set_death_signal();
268                 if (ret < 0) {
269                         fprintf(stderr, "Failed to set PR_SET_PDEATHSIG to SIGKILL\n");
270                         _exit(EXIT_FAILURE);
271                 }
272
273                 if (pre_flags & CLONE_NEWUSER) {
274                         ret = unshare(CLONE_NEWUSER);
275                         if (ret < 0) {
276                                 fprintf(stderr,
277                                         "%s - Failed to unshare user namespace\n",
278                                         strerror(errno));
279                                 _exit(EXIT_FAILURE);
280                         }
281                 }
282
283                 if (pre_flags & CLONE_NEWNET) {
284                         ret = unshare(CLONE_NEWNET);
285                         if (ret < 0) {
286                                 fprintf(stderr,
287                                         "%s - Failed to unshare network namespace\n",
288                                         strerror(errno));
289                                 _exit(EXIT_FAILURE);
290                         }
291                 }
292
293                 if (uevent_listener(post_flags, expect_uevent, sync_fd) < 0)
294                         _exit(EXIT_FAILURE);
295
296                 _exit(EXIT_SUCCESS);
297         }
298
299         ret = read_nointr(sync_fd, &wait_val, sizeof(wait_val));
300         if (ret != sizeof(wait_val)) {
301                 fprintf(stderr, "Failed to synchronize with child process\n");
302                 _exit(EXIT_FAILURE);
303         }
304
305         /* Trigger 10 uevents to account for the case where the kernel might
306          * drop some.
307          */
308         ret = trigger_uevent(10);
309         if (ret < 0)
310                 fprintf(stderr, "Failed triggering uevents\n");
311
312         /* Wait for 2 seconds before considering this failed. This should be
313          * plenty of time for the kernel to deliver the uevent even under heavy
314          * load.
315          */
316         timeout.tv_sec = 2;
317         timeout.tv_nsec = 0;
318
319 again:
320         ret = sigtimedwait(&mask, NULL, &timeout);
321         if (ret < 0) {
322                 if (errno == EINTR)
323                         goto again;
324
325                 if (!expect_uevent)
326                         ret = kill(pid, SIGTERM); /* success */
327                 else
328                         ret = kill(pid, SIGUSR1); /* error */
329                 if (ret < 0)
330                         return -1;
331         }
332
333         ret = wait_for_pid(pid);
334         if (ret < 0)
335                 return -1;
336
337         return ret;
338 }
339
340 static void signal_handler(int sig)
341 {
342         if (sig == SIGTERM)
343                 _exit(EXIT_SUCCESS);
344
345         _exit(EXIT_FAILURE);
346 }
347
348 TEST(uevent_filtering)
349 {
350         int ret, sync_fd;
351         struct sigaction act;
352
353         if (geteuid()) {
354                 TH_LOG("Uevent filtering tests require root privileges. Skipping test");
355                 _exit(KSFT_SKIP);
356         }
357
358         ret = access(__DEV_FULL, F_OK);
359         EXPECT_EQ(0, ret) {
360                 if (errno == ENOENT) {
361                         TH_LOG(__DEV_FULL " does not exist. Skipping test");
362                         _exit(KSFT_SKIP);
363                 }
364
365                 _exit(KSFT_FAIL);
366         }
367
368         act.sa_handler = signal_handler;
369         act.sa_flags = 0;
370         sigemptyset(&act.sa_mask);
371
372         ret = sigaction(SIGTERM, &act, NULL);
373         ASSERT_EQ(0, ret);
374
375         sync_fd = eventfd(0, EFD_CLOEXEC);
376         ASSERT_GE(sync_fd, 0);
377
378         /*
379          * Setup:
380          * - Open uevent listening socket in initial network namespace owned by
381          *   initial user namespace.
382          * - Trigger uevent in initial network namespace owned by initial user
383          *   namespace.
384          * Expected Result:
385          * - uevent listening socket receives uevent
386          */
387         ret = do_test(0, 0, true, sync_fd);
388         ASSERT_EQ(0, ret) {
389                 goto do_cleanup;
390         }
391
392         /*
393          * Setup:
394          * - Open uevent listening socket in non-initial network namespace
395          *   owned by initial user namespace.
396          * - Trigger uevent in initial network namespace owned by initial user
397          *   namespace.
398          * Expected Result:
399          * - uevent listening socket receives uevent
400          */
401         ret = do_test(CLONE_NEWNET, 0, true, sync_fd);
402         ASSERT_EQ(0, ret) {
403                 goto do_cleanup;
404         }
405
406         /*
407          * Setup:
408          * - unshare user namespace
409          * - Open uevent listening socket in initial network namespace
410          *   owned by initial user namespace.
411          * - Trigger uevent in initial network namespace owned by initial user
412          *   namespace.
413          * Expected Result:
414          * - uevent listening socket receives uevent
415          */
416         ret = do_test(CLONE_NEWUSER, 0, true, sync_fd);
417         ASSERT_EQ(0, ret) {
418                 goto do_cleanup;
419         }
420
421         /*
422          * Setup:
423          * - Open uevent listening socket in non-initial network namespace
424          *   owned by non-initial user namespace.
425          * - Trigger uevent in initial network namespace owned by initial user
426          *   namespace.
427          * Expected Result:
428          * - uevent listening socket receives no uevent
429          */
430         ret = do_test(CLONE_NEWUSER | CLONE_NEWNET, 0, false, sync_fd);
431         ASSERT_EQ(0, ret) {
432                 goto do_cleanup;
433         }
434
435         /*
436          * Setup:
437          * - Open uevent listening socket in initial network namespace
438          *   owned by initial user namespace.
439          * - unshare network namespace
440          * - Trigger uevent in initial network namespace owned by initial user
441          *   namespace.
442          * Expected Result:
443          * - uevent listening socket receives uevent
444          */
445         ret = do_test(0, CLONE_NEWNET, true, sync_fd);
446         ASSERT_EQ(0, ret) {
447                 goto do_cleanup;
448         }
449
450         /*
451          * Setup:
452          * - Open uevent listening socket in initial network namespace
453          *   owned by initial user namespace.
454          * - unshare user namespace
455          * - Trigger uevent in initial network namespace owned by initial user
456          *   namespace.
457          * Expected Result:
458          * - uevent listening socket receives uevent
459          */
460         ret = do_test(0, CLONE_NEWUSER, true, sync_fd);
461         ASSERT_EQ(0, ret) {
462                 goto do_cleanup;
463         }
464
465         /*
466          * Setup:
467          * - Open uevent listening socket in initial network namespace
468          *   owned by initial user namespace.
469          * - unshare user namespace
470          * - unshare network namespace
471          * - Trigger uevent in initial network namespace owned by initial user
472          *   namespace.
473          * Expected Result:
474          * - uevent listening socket receives uevent
475          */
476         ret = do_test(0, CLONE_NEWUSER | CLONE_NEWNET, true, sync_fd);
477         ASSERT_EQ(0, ret) {
478                 goto do_cleanup;
479         }
480
481 do_cleanup:
482         close(sync_fd);
483 }
484
485 TEST_HARNESS_MAIN