diff options
Diffstat (limited to 'Tests/LibC/TestIo.cpp')
-rw-r--r-- | Tests/LibC/TestIo.cpp | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/Tests/LibC/TestIo.cpp b/Tests/LibC/TestIo.cpp index 5b1bb1b6db..e121876d73 100644 --- a/Tests/LibC/TestIo.cpp +++ b/Tests/LibC/TestIo.cpp @@ -15,6 +15,7 @@ #include <sys/mman.h> #include <sys/stat.h> #include <sys/uio.h> +#include <sys/wait.h> #include <unistd.h> #define EXPECT_ERROR_2(err, syscall, arg1, arg2) \ @@ -356,6 +357,49 @@ TEST_CASE(rmdir_dot_dot) EXPECT_EQ(rc, 0); } +TEST_CASE(rmdir_someone_elses_directory_in_my_sticky_directory) +{ + // NOTE: This test only works when run as root, since it has to chown a directory to someone else. + if (getuid() != 0) + return; + + // Create /tmp/sticky-dir a sticky directory owned by 12345:12345 + // Then, create /tmp/sticky-dir/notmine, a normal directory owned by 23456:23456 + // Then, fork and seteuid to 12345, and try to rmdir the "notmine" directory. This should succeed. + // In the parent, waitpid on the child, and finally rmdir /tmp/sticky-dir + + int rc = mkdir("/tmp/sticky-dir", 01777); + EXPECT_EQ(rc, 0); + + rc = chown("/tmp/sticky-dir", 12345, 12345); + EXPECT_EQ(rc, 0); + + rc = mkdir("/tmp/sticky-dir/notmine", 0700); + EXPECT_EQ(rc, 0); + + rc = chown("/tmp/sticky-dir/notmine", 23456, 23456); + EXPECT_EQ(rc, 0); + + int pid = fork(); + EXPECT(pid >= 0); + + if (pid == 0) { + // We are in the child. + rc = seteuid(12345); + EXPECT_EQ(rc, 0); + + rc = rmdir("/tmp/sticky-dir/notmine"); + EXPECT_EQ(rc, 0); + _exit(0); + } + + int status = 0; + waitpid(pid, &status, 0); + + rc = rmdir("/tmp/sticky-dir"); + EXPECT_EQ(rc, 0); +} + TEST_CASE(rmdir_while_inside_dir) { int rc = mkdir("/home/anon/testdir", 0700); |