mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add check to pivot_root that ensures the new root is underneath the old root.
Reported-by: syzbot+bb796623970e2eef9a5f@syzkaller.appspotmail.com PiperOrigin-RevId: 589957215
This commit is contained in:
committed by
gVisor bot
parent
a047cde5e6
commit
eaee2b213b
@@ -1131,6 +1131,10 @@ func (vfs *VirtualFilesystem) PivotRoot(ctx context.Context, creds *auth.Credent
|
||||
if !vfs.isPathReachable(ctx, newRoot, putOld) {
|
||||
return newRoot, oldRoot, linuxerr.EINVAL
|
||||
}
|
||||
// the new root must be at or underneath the current root.
|
||||
if !vfs.isPathReachable(ctx, oldRoot, newRoot) {
|
||||
return newRoot, oldRoot, linuxerr.EINVAL
|
||||
}
|
||||
// The current root directory must be a mountpoint
|
||||
// (in the case it has been chrooted).
|
||||
if oldRoot.mount.root != oldRoot.dentry {
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -35,6 +36,7 @@
|
||||
#include "test/util/capability_util.h"
|
||||
#include "test/util/file_descriptor.h"
|
||||
#include "test/util/fs_util.h"
|
||||
#include "test/util/linux_capability_util.h"
|
||||
#include "test/util/logging.h"
|
||||
#include "test/util/mount_util.h"
|
||||
#include "test/util/multiprocess_util.h"
|
||||
@@ -47,6 +49,8 @@ namespace testing {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kTmpfs[] = "tmpfs";
|
||||
|
||||
TEST(PivotRootTest, Success) {
|
||||
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
|
||||
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_CHROOT)));
|
||||
@@ -514,6 +518,37 @@ TEST(PivotRootTest, OnSharedPutOldMountpoint) {
|
||||
EXPECT_THAT(InForkedProcess(rest), IsPosixErrorOkAndHolds(0));
|
||||
}
|
||||
|
||||
TEST(PivotRootTest, UnreachableNewRootFails) {
|
||||
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
|
||||
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_CHROOT)));
|
||||
|
||||
TempPath outside_root = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
|
||||
ASSERT_THAT(mount("", outside_root.path().c_str(), kTmpfs, 0, ""),
|
||||
SyscallSucceeds());
|
||||
TempPath root =
|
||||
ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(outside_root.path()));
|
||||
ASSERT_THAT(mount("", root.path().c_str(), kTmpfs, 0, ""), SyscallSucceeds());
|
||||
TempPath new_root =
|
||||
ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(root.path()));
|
||||
ASSERT_THAT(mount("", new_root.path().c_str(), kTmpfs, 0, ""),
|
||||
SyscallSucceeds());
|
||||
const std::string new_root_path =
|
||||
absl::StrCat("/", Basename(new_root.path()));
|
||||
TempPath put_old =
|
||||
ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(new_root.path()));
|
||||
const std::string put_old_path =
|
||||
JoinPath(new_root_path, Basename(put_old.path()));
|
||||
ASSERT_THAT(chdir(JoinPath(root.path(), "..").c_str()), SyscallSucceeds());
|
||||
|
||||
const std::function<void()> rest = [&] {
|
||||
TEST_CHECK_SUCCESS(chroot(root.path().c_str()));
|
||||
// "." references the directory outside the chroot.
|
||||
TEST_CHECK_ERRNO(syscall(__NR_pivot_root, ".", put_old_path.c_str()),
|
||||
EINVAL);
|
||||
};
|
||||
EXPECT_THAT(InForkedProcess(rest), IsPosixErrorOkAndHolds(0));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace testing
|
||||
|
||||
Reference in New Issue
Block a user