Display the proper root path in mountinfo.

PiperOrigin-RevId: 492323370
This commit is contained in:
Lucas Manning
2022-12-01 16:05:00 -08:00
committed by gVisor bot
parent 600066a9bb
commit 99cc6c2dea
4 changed files with 63 additions and 12 deletions
+1 -1
View File
@@ -920,7 +920,7 @@ func (fs *filesystem) PrependPath(ctx context.Context, vfsroot, vd vfs.VirtualDe
if mnt == vfsroot.Mount() && &d.vfsd == vfsroot.Dentry() {
return vfs.PrependPathAtVFSRootError{}
}
if &d.vfsd == mnt.Root() {
if mnt != nil && &d.vfsd == mnt.Root() {
return nil
}
if d.parent == nil {
+19 -11
View File
@@ -1161,16 +1161,27 @@ func (vfs *VirtualFilesystem) GenerateProcMountInfo(ctx context.Context, taskRoo
mount: mnt,
dentry: mnt.root,
}
path, err := vfs.PathnameReachable(ctx, taskRootDir, mntRootVD)
pathFromRoot, err := vfs.PathnameReachable(ctx, taskRootDir, mntRootVD)
if err != nil {
// For some reason we didn't get a path. Log a warning
// and run with empty path.
ctx.Warningf("VFS.GenerateProcMountInfo: error getting pathname for mount root %+v: %v", mnt.root, err)
path = ""
continue
}
if path == "" {
// Either an error occurred, or path is not reachable
// from root.
if pathFromRoot == "" {
// The path is not reachable from root.
continue
}
var pathFromFS string
pathFromFS, err = vfs.PathnameInFilesystem(ctx, mntRootVD)
if err != nil {
// For some reason we didn't get a path. Log a warning
// and run with empty path.
ctx.Warningf("VFS.GenerateProcMountInfo: error getting pathname for mount root %+v: %v", mnt.root, err)
continue
}
if pathFromFS == "" {
// The path is not reachable from root.
continue
}
// Stat the mount root to get the major/minor device numbers.
@@ -1208,13 +1219,10 @@ func (vfs *VirtualFilesystem) GenerateProcMountInfo(ctx context.Context, taskRoo
// (4) Root: the pathname of the directory in the filesystem
// which forms the root of this mount.
//
// NOTE(b/78135857): This will always be "/" until we implement
// bind mounts.
fmt.Fprintf(buf, "/ ")
fmt.Fprintf(buf, "%s ", manglePath(pathFromFS))
// (5) Mount point (relative to process root).
fmt.Fprintf(buf, "%s ", manglePath(path))
fmt.Fprintf(buf, "%s ", manglePath(pathFromRoot))
// (6) Mount options.
opts := "rw"
@@ -1241,7 +1249,7 @@ func (vfs *VirtualFilesystem) GenerateProcMountInfo(ctx context.Context, taskRoo
fmt.Fprintf(buf, "none ")
// (11) Superblock options, and final newline.
fmt.Fprintf(buf, "%s\n", superBlockOpts(path, mnt))
fmt.Fprintf(buf, "%s\n", superBlockOpts(pathFromRoot, mnt))
}
}
+23
View File
@@ -133,6 +133,29 @@ loop:
return b.String(), nil
}
// PathnameInFilesystem returns an absolute path to vd relative to vd's
// Filesystem root. It also appends //deleted to for disowned entries. It is
// equivalent to Linux's dentry_path().
func (vfs *VirtualFilesystem) PathnameInFilesystem(ctx context.Context, vd VirtualDentry) (string, error) {
b := getFSPathBuilder()
defer putFSPathBuilder(b)
if vd.dentry.IsDead() {
b.PrependString("//deleted")
}
if err := vd.mount.fs.impl.PrependPath(ctx, VirtualDentry{}, VirtualDentry{dentry: vd.dentry}, b); err != nil {
// PrependPath returns an error if it encounters a filesystem root before
// the provided vfsroot. We don't provide a vfsroot, so encountering this
// error is expected and can be ignored.
switch err.(type) {
case PrependPathAtNonMountRootError:
default:
return "", err
}
}
b.PrependByte('/')
return b.String(), nil
}
// PathnameForGetcwd returns an absolute pathname to vd, consistent with
// Linux's sys_getcwd().
func (vfs *VirtualFilesystem) PathnameForGetcwd(ctx context.Context, vfsroot, vd VirtualDentry) (string, error) {
+20
View File
@@ -1397,6 +1397,26 @@ TEST(MountTest, BindParentToChild) {
ASSERT_EQ(opt2, opt3);
}
TEST(MountTest, MountInfoHasRoot) {
SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_SYS_ADMIN)));
auto const parent = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDir());
auto const mount = ASSERT_NO_ERRNO_AND_VALUE(
Mount("", parent.path(), "tmpfs", 0, "mode=0123", 0));
auto const child =
ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateDirIn(parent.path()));
auto const bind_mount = Mount(child.path(), child.path(), "", MS_BIND, "", 0);
std::vector<ProcMountInfoEntry> mounts =
ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntries());
for (const auto& e : mounts) {
if (e.mount_point == child.path()) {
ASSERT_EQ(e.root, JoinPath("/", Basename(child.path())));
}
if (e.mount_point == parent.path()) {
ASSERT_EQ(e.root, "/");
}
}
}
} // namespace
} // namespace testing