diff options
author | Rahat Mahmood <rahat@google.com> | 2021-05-20 15:07:17 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-05-20 15:09:41 -0700 |
commit | af229f46a1496f39b012b4e2b244c32bb7d0667c (patch) | |
tree | 6b769529ce355bc33a5af1731275a80286fa9622 /test/syscalls/linux | |
parent | b8b43f70c898861a6fd642ded069dd33d35f17f9 (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')
-rw-r--r-- | test/syscalls/linux/cgroup.cc | 35 |
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()); |