Test opening file handles with different permissions.

These were problematic for vfs2 gofers before correctly implementing separate
read/write handles.

PiperOrigin-RevId: 329613261
This commit is contained in:
Dean Deng 2020-09-01 17:19:26 -07:00 committed by gVisor bot
parent 2eaf54dd59
commit c67d8ece09
1 changed files with 113 additions and 3 deletions

View File

@ -88,21 +88,21 @@ TEST(CreateTest, CreateExclusively) {
SyscallFailsWithErrno(EEXIST)); SyscallFailsWithErrno(EEXIST));
} }
TEST(CreateTeast, CreatWithOTrunc) { TEST(CreateTest, CreatWithOTrunc) {
std::string dirpath = JoinPath(GetAbsoluteTestTmpdir(), "truncd"); std::string dirpath = JoinPath(GetAbsoluteTestTmpdir(), "truncd");
ASSERT_THAT(mkdir(dirpath.c_str(), 0777), SyscallSucceeds()); ASSERT_THAT(mkdir(dirpath.c_str(), 0777), SyscallSucceeds());
ASSERT_THAT(open(dirpath.c_str(), O_CREAT | O_TRUNC, 0666), ASSERT_THAT(open(dirpath.c_str(), O_CREAT | O_TRUNC, 0666),
SyscallFailsWithErrno(EISDIR)); SyscallFailsWithErrno(EISDIR));
} }
TEST(CreateTeast, CreatDirWithOTruncAndReadOnly) { TEST(CreateTest, CreatDirWithOTruncAndReadOnly) {
std::string dirpath = JoinPath(GetAbsoluteTestTmpdir(), "truncd"); std::string dirpath = JoinPath(GetAbsoluteTestTmpdir(), "truncd");
ASSERT_THAT(mkdir(dirpath.c_str(), 0777), SyscallSucceeds()); ASSERT_THAT(mkdir(dirpath.c_str(), 0777), SyscallSucceeds());
ASSERT_THAT(open(dirpath.c_str(), O_CREAT | O_TRUNC | O_RDONLY, 0666), ASSERT_THAT(open(dirpath.c_str(), O_CREAT | O_TRUNC | O_RDONLY, 0666),
SyscallFailsWithErrno(EISDIR)); SyscallFailsWithErrno(EISDIR));
} }
TEST(CreateTeast, CreatFileWithOTruncAndReadOnly) { TEST(CreateTest, CreatFileWithOTruncAndReadOnly) {
std::string dirpath = JoinPath(GetAbsoluteTestTmpdir(), "truncfile"); std::string dirpath = JoinPath(GetAbsoluteTestTmpdir(), "truncfile");
int dirfd; int dirfd;
ASSERT_THAT(dirfd = open(dirpath.c_str(), O_RDWR | O_CREAT, 0666), ASSERT_THAT(dirfd = open(dirpath.c_str(), O_RDWR | O_CREAT, 0666),
@ -149,6 +149,116 @@ TEST(CreateTest, OpenCreateROThenRW) {
EXPECT_THAT(WriteFd(fd2.get(), &c, 1), SyscallSucceedsWithValue(1)); EXPECT_THAT(WriteFd(fd2.get(), &c, 1), SyscallSucceedsWithValue(1));
} }
TEST(CreateTest, ChmodReadToWriteBetweenOpens_NoRandomSave) {
// Make sure we don't have CAP_DAC_OVERRIDE, since that allows the user to
// override file read/write permissions. CAP_DAC_READ_SEARCH needs to be
// cleared for the same reason.
ASSERT_NO_ERRNO(SetCapability(CAP_DAC_OVERRIDE, false));
ASSERT_NO_ERRNO(SetCapability(CAP_DAC_READ_SEARCH, false));
const TempPath file =
ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileMode(0400));
const FileDescriptor rfd =
ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY));
// Cannot restore after making permissions more restrictive.
const DisableSave ds;
ASSERT_THAT(fchmod(rfd.get(), 0200), SyscallSucceeds());
EXPECT_THAT(open(file.path().c_str(), O_RDONLY),
SyscallFailsWithErrno(EACCES));
const FileDescriptor wfd =
ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_WRONLY));
char c = 'x';
EXPECT_THAT(write(wfd.get(), &c, 1), SyscallSucceedsWithValue(1));
c = 0;
EXPECT_THAT(read(rfd.get(), &c, 1), SyscallSucceedsWithValue(1));
EXPECT_EQ(c, 'x');
}
TEST(CreateTest, ChmodWriteToReadBetweenOpens_NoRandomSave) {
// Make sure we don't have CAP_DAC_OVERRIDE, since that allows the user to
// override file read/write permissions.
ASSERT_NO_ERRNO(SetCapability(CAP_DAC_OVERRIDE, false));
const TempPath file =
ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileMode(0200));
const FileDescriptor wfd =
ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_WRONLY));
// Cannot restore after making permissions more restrictive.
const DisableSave ds;
ASSERT_THAT(fchmod(wfd.get(), 0400), SyscallSucceeds());
EXPECT_THAT(open(file.path().c_str(), O_WRONLY),
SyscallFailsWithErrno(EACCES));
const FileDescriptor rfd =
ASSERT_NO_ERRNO_AND_VALUE(Open(file.path(), O_RDONLY));
char c = 'x';
EXPECT_THAT(write(wfd.get(), &c, 1), SyscallSucceedsWithValue(1));
c = 0;
EXPECT_THAT(read(rfd.get(), &c, 1), SyscallSucceedsWithValue(1));
EXPECT_EQ(c, 'x');
}
TEST(CreateTest, CreateWithReadFlagNotAllowedByMode_NoRandomSave) {
// The only time we can open a file with flags forbidden by its permissions
// is when we are creating the file. We cannot re-open with the same flags,
// so we cannot restore an fd obtained from such an operation.
const DisableSave ds;
// Make sure we don't have CAP_DAC_OVERRIDE, since that allows the user to
// override file read/write permissions. CAP_DAC_READ_SEARCH needs to be
// cleared for the same reason.
ASSERT_NO_ERRNO(SetCapability(CAP_DAC_OVERRIDE, false));
ASSERT_NO_ERRNO(SetCapability(CAP_DAC_READ_SEARCH, false));
// Create and open a file with read flag but without read permissions.
const std::string path = NewTempAbsPath();
const FileDescriptor rfd =
ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_CREAT | O_RDONLY, 0222));
EXPECT_THAT(open(path.c_str(), O_RDONLY), SyscallFailsWithErrno(EACCES));
const FileDescriptor wfd = ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_WRONLY));
char c = 'x';
EXPECT_THAT(write(wfd.get(), &c, 1), SyscallSucceedsWithValue(1));
c = 0;
EXPECT_THAT(read(rfd.get(), &c, 1), SyscallSucceedsWithValue(1));
EXPECT_EQ(c, 'x');
}
TEST(CreateTest, CreateWithWriteFlagNotAllowedByMode_NoRandomSave) {
// The only time we can open a file with flags forbidden by its permissions
// is when we are creating the file. We cannot re-open with the same flags,
// so we cannot restore an fd obtained from such an operation.
const DisableSave ds;
// Make sure we don't have CAP_DAC_OVERRIDE, since that allows the user to
// override file read/write permissions.
ASSERT_NO_ERRNO(SetCapability(CAP_DAC_OVERRIDE, false));
// Create and open a file with write flag but without write permissions.
const std::string path = NewTempAbsPath();
const FileDescriptor wfd =
ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_CREAT | O_WRONLY, 0444));
EXPECT_THAT(open(path.c_str(), O_WRONLY), SyscallFailsWithErrno(EACCES));
const FileDescriptor rfd = ASSERT_NO_ERRNO_AND_VALUE(Open(path, O_RDONLY));
char c = 'x';
EXPECT_THAT(write(wfd.get(), &c, 1), SyscallSucceedsWithValue(1));
c = 0;
EXPECT_THAT(read(rfd.get(), &c, 1), SyscallSucceedsWithValue(1));
EXPECT_EQ(c, 'x');
}
} // namespace } // namespace
} // namespace testing } // namespace testing