Handle tmpfs with 5 fields in /proc/mounts parsing.

PiperOrigin-RevId: 370565903
This commit is contained in:
Adin Scannell 2021-04-26 16:25:26 -07:00 committed by gVisor bot
parent 5b7b7daa42
commit 36fdc6c9ef
5 changed files with 95 additions and 13 deletions

View File

@ -45,6 +45,7 @@ namespace testing {
namespace {
using ::testing::AnyOf;
using ::testing::Contains;
using ::testing::Pair;
@ -360,7 +361,8 @@ TEST(MountTest, MountInfo) {
if (e.mount_point == dir.path()) {
EXPECT_EQ(e.fstype, "tmpfs");
auto mopts = ParseMountOptions(e.mount_opts);
EXPECT_THAT(mopts, Contains(Pair("mode", "0123")));
EXPECT_THAT(mopts, AnyOf(Contains(Pair("mode", "0123")),
Contains(Pair("mode", "123"))));
}
}
@ -371,7 +373,8 @@ TEST(MountTest, MountInfo) {
if (e.mount_point == dir.path()) {
EXPECT_EQ(e.fstype, "tmpfs");
auto mopts = ParseMountOptions(e.super_opts);
EXPECT_THAT(mopts, Contains(Pair("mode", "0123")));
EXPECT_THAT(mopts, AnyOf(Contains(Pair("mode", "0123")),
Contains(Pair("mode", "123"))));
}
}
}

View File

@ -149,6 +149,18 @@ cc_library(
],
)
cc_test(
name = "mount_util_test",
size = "small",
srcs = ["mount_util_test.cc"],
deps = [
":mount_util",
":test_main",
":test_util",
gtest,
],
)
cc_library(
name = "save_util",
testonly = 1,

View File

@ -26,9 +26,14 @@ namespace testing {
PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntries() {
std::string content;
RETURN_IF_ERRNO(GetContents("/proc/self/mounts", &content));
return ProcSelfMountsEntriesFrom(content);
}
PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntriesFrom(
const std::string& content) {
std::vector<ProcMountsEntry> entries;
std::vector<std::string> lines = absl::StrSplit(content, '\n');
std::vector<std::string> lines =
absl::StrSplit(content, absl::ByChar('\n'), absl::AllowEmpty());
std::cerr << "<contents of /proc/self/mounts>" << std::endl;
for (const std::string& line : lines) {
std::cerr << line << std::endl;
@ -47,11 +52,11 @@ PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntries() {
ProcMountsEntry entry;
std::vector<std::string> fields =
absl::StrSplit(line, absl::ByChar(' '), absl::SkipEmpty());
absl::StrSplit(line, absl::ByChar(' '), absl::AllowEmpty());
if (fields.size() != 6) {
return PosixError(EINVAL,
absl::StrFormat("Not enough tokens, got %d, line: %s",
fields.size(), line));
return PosixError(
EINVAL, absl::StrFormat("Not enough tokens, got %d, content: <<%s>>",
fields.size(), content));
}
entry.spec = fields[0];
@ -71,9 +76,14 @@ PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntries() {
PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntries() {
std::string content;
RETURN_IF_ERRNO(GetContents("/proc/self/mountinfo", &content));
return ProcSelfMountInfoEntriesFrom(content);
}
PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntriesFrom(
const std::string& content) {
std::vector<ProcMountInfoEntry> entries;
std::vector<std::string> lines = absl::StrSplit(content, '\n');
std::vector<std::string> lines =
absl::StrSplit(content, absl::ByChar('\n'), absl::AllowEmpty());
std::cerr << "<contents of /proc/self/mountinfo>" << std::endl;
for (const std::string& line : lines) {
std::cerr << line << std::endl;
@ -92,12 +102,12 @@ PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntries() {
ProcMountInfoEntry entry;
std::vector<std::string> fields =
absl::StrSplit(line, absl::ByChar(' '), absl::SkipEmpty());
absl::StrSplit(line, absl::ByChar(' '), absl::AllowEmpty());
if (fields.size() < 10 || fields.size() > 11) {
return PosixError(
EINVAL,
absl::StrFormat("Unexpected number of tokens, got %d, line: %s",
fields.size(), line));
EINVAL, absl::StrFormat(
"Unexpected number of tokens, got %d, content: <<%s>>",
fields.size(), content));
}
ASSIGN_OR_RETURN_ERRNO(entry.id, Atoi<uint64_t>(fields[0]));
@ -142,7 +152,7 @@ absl::flat_hash_map<std::string, std::string> ParseMountOptions(
std::string mopts) {
absl::flat_hash_map<std::string, std::string> entries;
const std::vector<std::string> tokens =
absl::StrSplit(mopts, absl::ByChar(','), absl::SkipEmpty());
absl::StrSplit(mopts, absl::ByChar(','), absl::AllowEmpty());
for (const auto& token : tokens) {
std::vector<std::string> kv =
absl::StrSplit(token, absl::MaxSplits('=', 1));

View File

@ -58,6 +58,11 @@ struct ProcMountsEntry {
// ProcSelfMountsEntries returns a parsed representation of /proc/self/mounts.
PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntries();
// ProcSelfMountsEntries returns a parsed representation of mounts from the
// provided content.
PosixErrorOr<std::vector<ProcMountsEntry>> ProcSelfMountsEntriesFrom(
const std::string& content);
struct ProcMountInfoEntry {
uint64_t id;
uint64_t parent_id;
@ -76,6 +81,11 @@ struct ProcMountInfoEntry {
// /proc/self/mountinfo.
PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntries();
// ProcSelfMountInfoEntriesFrom returns a parsed representation of
// mountinfo from the provided content.
PosixErrorOr<std::vector<ProcMountInfoEntry>> ProcSelfMountInfoEntriesFrom(
const std::string&);
// Interprets the input string mopts as a comma separated list of mount
// options. A mount option can either be just a value, or a key=value pair. For
// example, the string "rw,relatime,fd=7" will be parsed into a map like { "rw":

View File

@ -0,0 +1,47 @@
// Copyright 2018 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "test/util/mount_util.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test/util/test_util.h"
namespace gvisor {
namespace testing {
namespace {
TEST(ParseMounts, Mounts) {
auto entries = ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountsEntriesFrom(
R"proc(sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
/mnt tmpfs rw,noexec 0 0
)proc"));
EXPECT_EQ(entries.size(), 3);
}
TEST(ParseMounts, MountInfo) {
auto entries = ASSERT_NO_ERRNO_AND_VALUE(ProcSelfMountInfoEntriesFrom(
R"proc(22 28 0:20 / /sys rw,relatime shared:7 - sysfs sysfs rw
23 28 0:21 / /proc rw,relatime shared:14 - proc proc rw
2007 8844 0:278 / /mnt rw,noexec - tmpfs rw,mode=123,uid=268601820,gid=5000
)proc"));
EXPECT_EQ(entries.size(), 3);
}
} // namespace
} // namespace testing
} // namespace gvisor