summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls/linux/cgroup.cc
diff options
context:
space:
mode:
authorRahat Mahmood <rahat@google.com>2021-05-20 15:07:17 -0700
committergVisor bot <gvisor-bot@google.com>2021-05-20 15:09:41 -0700
commitaf229f46a1496f39b012b4e2b244c32bb7d0667c (patch)
tree6b769529ce355bc33a5af1731275a80286fa9622 /test/syscalls/linux/cgroup.cc
parentb8b43f70c898861a6fd642ded069dd33d35f17f9 (diff)
Fix cgroupfs mount racing with unmount.
Previously, mount could discover a hierarchy being destroyed concurrently, which resulted in mount attempting to take a ref on an already destroyed cgroupfs. Reported-by: syzbot+062c0a67798a200f23ee@syzkaller.appspotmail.com PiperOrigin-RevId: 374959054
Diffstat (limited to 'test/syscalls/linux/cgroup.cc')
-rw-r--r--test/syscalls/linux/cgroup.cc35
1 files changed, 35 insertions, 0 deletions
diff --git a/test/syscalls/linux/cgroup.cc b/test/syscalls/linux/cgroup.cc
index a009ade7e..f29891571 100644
--- a/test/syscalls/linux/cgroup.cc
+++ b/test/syscalls/linux/cgroup.cc
@@ -227,6 +227,41 @@ TEST(Cgroup, MountRace) {
EXPECT_NO_ERRNO(c.ContainsCallingProcess());
}
+TEST(Cgroup, MountUnmountRace) {
+ SKIP_IF(!CgroupsAvailable());
+
+ TempPath mountpoint = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
+
+ const DisableSave ds; // Too many syscalls.
+
+ auto mount_thread = [&mountpoint]() {
+ for (int i = 0; i < 100; ++i) {
+ mount("none", mountpoint.path().c_str(), "cgroup", 0, 0);
+ }
+ };
+ auto unmount_thread = [&mountpoint]() {
+ for (int i = 0; i < 100; ++i) {
+ umount(mountpoint.path().c_str());
+ }
+ };
+ std::list<ScopedThread> threads;
+ for (int i = 0; i < 10; ++i) {
+ threads.emplace_back(mount_thread);
+ }
+ for (int i = 0; i < 10; ++i) {
+ threads.emplace_back(unmount_thread);
+ }
+ for (auto& t : threads) {
+ t.Join();
+ }
+
+ // We don't know how many mount refs are remaining, since the count depends on
+ // the ordering of mount and umount calls. Keep calling unmount until it
+ // returns an error.
+ while (umount(mountpoint.path().c_str()) == 0) {
+ }
+}
+
TEST(Cgroup, UnmountRepeated) {
SKIP_IF(!CgroupsAvailable());