mirror of
https://github.com/RGBCube/serenity
synced 2025-05-16 19:05:08 +00:00
Kernel+Tests: Allow deleting someone else's file in my sticky directory
This should be allowed according to Dr. POSIX. :^)
This commit is contained in:
parent
47b9e8e651
commit
16f934474f
2 changed files with 50 additions and 1 deletions
|
@ -868,8 +868,13 @@ ErrorOr<void> VirtualFileSystem::rmdir(Credentials const& credentials, StringVie
|
||||||
return EACCES;
|
return EACCES;
|
||||||
|
|
||||||
if (parent_metadata.is_sticky()) {
|
if (parent_metadata.is_sticky()) {
|
||||||
if (!credentials.is_superuser() && inode.metadata().uid != credentials.euid())
|
// [EACCES] The S_ISVTX flag is set on the directory containing the file referred to by the path argument
|
||||||
|
// and the process does not satisfy the criteria specified in XBD Directory Protection.
|
||||||
|
if (!credentials.is_superuser()
|
||||||
|
&& inode.metadata().uid != credentials.euid()
|
||||||
|
&& parent_metadata.uid != credentials.euid()) {
|
||||||
return EACCES;
|
return EACCES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t child_count = 0;
|
size_t child_count = 0;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define EXPECT_ERROR_2(err, syscall, arg1, arg2) \
|
#define EXPECT_ERROR_2(err, syscall, arg1, arg2) \
|
||||||
|
@ -356,6 +357,49 @@ TEST_CASE(rmdir_dot_dot)
|
||||||
EXPECT_EQ(rc, 0);
|
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)
|
TEST_CASE(rmdir_while_inside_dir)
|
||||||
{
|
{
|
||||||
int rc = mkdir("/home/anon/testdir", 0700);
|
int rc = mkdir("/home/anon/testdir", 0700);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue