Allow fchown to change the ownership of a pipe file descriptor.

PiperOrigin-RevId: 547636998
This commit is contained in:
Jing Chen
2023-07-12 16:50:25 -07:00
committed by gVisor bot
parent 5774eca799
commit 415845e2a1
2 changed files with 49 additions and 3 deletions
+12 -3
View File
@@ -161,10 +161,19 @@ func (i *inode) Stat(_ context.Context, vfsfs *vfs.Filesystem, opts vfs.StatOpti
// SetStat implements kernfs.Inode.SetStat.
func (i *inode) SetStat(ctx context.Context, vfsfs *vfs.Filesystem, creds *auth.Credentials, opts vfs.SetStatOptions) error {
if opts.Stat.Mask == 0 {
return nil
if opts.Stat.Mask&^(linux.STATX_UID|linux.STATX_GID) != 0 {
return linuxerr.EPERM
}
return linuxerr.EPERM
if err := vfs.CheckSetStat(ctx, creds, &opts, i.Mode(), i.UID(), i.GID()); err != nil {
return err
}
if opts.Stat.Mask&linux.STATX_UID != 0 {
i.uid = auth.KUID(opts.Stat.UID)
}
if opts.Stat.Mask&linux.STATX_GID != 0 {
i.gid = auth.KGID(opts.Stat.GID)
}
return nil
}
// Open implements kernfs.Inode.Open.
+37
View File
@@ -65,6 +65,43 @@ TEST(ChownTest, FchownDirWithOpath) {
SyscallFailsWithErrno(EBADF));
}
TEST(ChownTest, FchownPipeFileSucceeds) {
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_CHOWN)));
const auto uid = absl::GetFlag(FLAGS_scratch_uid1);
const auto gid = absl::GetFlag(FLAGS_scratch_gid);
int fds[2];
ASSERT_THAT(pipe2(fds, O_CLOEXEC), SyscallSucceeds());
for (const auto& fd : fds) {
ASSERT_THAT(fchown(fd, uid, gid), SyscallSucceeds());
struct stat s = {};
ASSERT_THAT(fstat(fd, &s), SyscallSucceeds());
EXPECT_EQ(s.st_uid, uid);
EXPECT_EQ(s.st_gid, gid);
}
}
TEST(ChownTest, FchownPipeFileFails) {
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SETUID)));
int fds[2];
ASSERT_THAT(pipe2(fds, O_CLOEXEC), SyscallSucceeds());
ScopedThread([&] {
// Drop privileges.
AutoCapability cap(CAP_CHOWN, false);
// Change EUID and EGID.
//
// See note about POSIX below.
EXPECT_THAT(
syscall(SYS_setresgid, -1, absl::GetFlag(FLAGS_scratch_gid), -1),
SyscallSucceeds());
EXPECT_THAT(
syscall(SYS_setresuid, -1, absl::GetFlag(FLAGS_scratch_uid1), -1),
SyscallSucceeds());
EXPECT_THAT(fchown(fds[1], geteuid(), getegid()),
SyscallFailsWithErrno(EPERM));
});
}
TEST(ChownTest, FchownatWithOpath) {
const auto dir = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
auto file = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileIn(dir.path()));