1*098bf3beSChristian Brauner // SPDX-License-Identifier: GPL-2.0 2*098bf3beSChristian Brauner /* 3*098bf3beSChristian Brauner * Reading the root of an empty mount namespace holds nothing that anybody 4*098bf3beSChristian Brauner * else waits for: the directory never has an entry, so a readdir stuck in 5*098bf3beSChristian Brauner * the page fault of its buffer stalls neither a create nor a lookup in it. 6*098bf3beSChristian Brauner */ 7*098bf3beSChristian Brauner #define _GNU_SOURCE 8*098bf3beSChristian Brauner #include <errno.h> 9*098bf3beSChristian Brauner #include <fcntl.h> 10*098bf3beSChristian Brauner #include <sched.h> 11*098bf3beSChristian Brauner #include <stdio.h> 12*098bf3beSChristian Brauner #include <stdlib.h> 13*098bf3beSChristian Brauner #include <unistd.h> 14*098bf3beSChristian Brauner 15*098bf3beSChristian Brauner #include "../../kselftest_harness.h" 16*098bf3beSChristian Brauner #include "../readdir_hold.h" 17*098bf3beSChristian Brauner #include "empty_mntns.h" 18*098bf3beSChristian Brauner TEST(readdir_blocks_nobody)19*098bf3beSChristian BraunerTEST(readdir_blocks_nobody) 20*098bf3beSChristian Brauner { 21*098bf3beSChristian Brauner struct readdir_hold hold; 22*098bf3beSChristian Brauner bool stalled; 23*098bf3beSChristian Brauner int dfd; 24*098bf3beSChristian Brauner 25*098bf3beSChristian Brauner if (geteuid()) 26*098bf3beSChristian Brauner SKIP(return, "test requires root"); 27*098bf3beSChristian Brauner if (readdir_hold_init(&hold)) 28*098bf3beSChristian Brauner SKIP(return, "test requires userfaultfd"); 29*098bf3beSChristian Brauner if (unshare(UNSHARE_EMPTY_MNTNS)) { 30*098bf3beSChristian Brauner readdir_hold_destroy(&hold); 31*098bf3beSChristian Brauner if (errno == EINVAL) 32*098bf3beSChristian Brauner SKIP(return, "UNSHARE_EMPTY_MNTNS not supported"); 33*098bf3beSChristian Brauner ASSERT_TRUE(false) 34*098bf3beSChristian Brauner TH_LOG("unshare(UNSHARE_EMPTY_MNTNS): %m"); 35*098bf3beSChristian Brauner } 36*098bf3beSChristian Brauner dfd = open("/", O_RDONLY | O_DIRECTORY | O_CLOEXEC); 37*098bf3beSChristian Brauner ASSERT_GE(dfd, 0); 38*098bf3beSChristian Brauner ASSERT_EQ(readdir_hold_check(&hold, dfd, &stalled), 0); 39*098bf3beSChristian Brauner /* the lookup came back while the readdir was stuck in its fault */ 40*098bf3beSChristian Brauner EXPECT_FALSE(stalled); 41*098bf3beSChristian Brauner close(dfd); 42*098bf3beSChristian Brauner readdir_hold_destroy(&hold); 43*098bf3beSChristian Brauner } 44*098bf3beSChristian Brauner 45*098bf3beSChristian Brauner TEST_HARNESS_MAIN 46