diff options
Diffstat (limited to 'test/util')
-rw-r--r-- | test/util/BUILD | 11 | ||||
-rw-r--r-- | test/util/fs_util.cc | 20 | ||||
-rw-r--r-- | test/util/fs_util.h | 9 | ||||
-rw-r--r-- | test/util/multiprocess_util.cc | 46 | ||||
-rw-r--r-- | test/util/multiprocess_util.h | 16 | ||||
-rw-r--r-- | test/util/proc_util.cc | 2 | ||||
-rw-r--r-- | test/util/uid_util.cc | 44 | ||||
-rw-r--r-- | test/util/uid_util.h | 29 |
8 files changed, 170 insertions, 7 deletions
diff --git a/test/util/BUILD b/test/util/BUILD index 25ed9c944..5d2a9cc2c 100644 --- a/test/util/BUILD +++ b/test/util/BUILD @@ -324,3 +324,14 @@ cc_library( ":test_util", ], ) + +cc_library( + name = "uid_util", + testonly = 1, + srcs = ["uid_util.cc"], + hdrs = ["uid_util.h"], + deps = [ + ":posix_error", + ":save_util", + ], +) diff --git a/test/util/fs_util.cc b/test/util/fs_util.cc index f7d231b14..88b1e7911 100644 --- a/test/util/fs_util.cc +++ b/test/util/fs_util.cc @@ -163,6 +163,26 @@ PosixError Chmod(absl::string_view path, int mode) { return NoError(); } +PosixError MknodAt(const FileDescriptor& dfd, absl::string_view path, int mode, + dev_t dev) { + int res = mknodat(dfd.get(), std::string(path).c_str(), mode, dev); + if (res < 0) { + return PosixError(errno, absl::StrCat("mknod ", path)); + } + + return NoError(); +} + +PosixError UnlinkAt(const FileDescriptor& dfd, absl::string_view path, + int flags) { + int res = unlinkat(dfd.get(), std::string(path).c_str(), flags); + if (res < 0) { + return PosixError(errno, absl::StrCat("unlink ", path)); + } + + return NoError(); +} + PosixError Mkdir(absl::string_view path, int mode) { int res = mkdir(std::string(path).c_str(), mode); if (res < 0) { diff --git a/test/util/fs_util.h b/test/util/fs_util.h index e5b555891..ee1b341d7 100644 --- a/test/util/fs_util.h +++ b/test/util/fs_util.h @@ -21,6 +21,7 @@ #include <unistd.h> #include "absl/strings/string_view.h" +#include "test/util/file_descriptor.h" #include "test/util/posix_error.h" namespace gvisor { @@ -44,6 +45,14 @@ PosixError Delete(absl::string_view path); // Changes the mode of a file or returns an error. PosixError Chmod(absl::string_view path, int mode); +// Create a special or ordinary file. +PosixError MknodAt(const FileDescriptor& dfd, absl::string_view path, int mode, + dev_t dev); + +// Unlink the file. +PosixError UnlinkAt(const FileDescriptor& dfd, absl::string_view path, + int flags); + // Truncates a file to the given length or returns an error. PosixError Truncate(absl::string_view path, int length); diff --git a/test/util/multiprocess_util.cc b/test/util/multiprocess_util.cc index 95f5f3b4f..8b676751b 100644 --- a/test/util/multiprocess_util.cc +++ b/test/util/multiprocess_util.cc @@ -14,6 +14,7 @@ #include "test/util/multiprocess_util.h" +#include <asm/unistd.h> #include <errno.h> #include <fcntl.h> #include <signal.h> @@ -30,11 +31,12 @@ namespace gvisor { namespace testing { -PosixErrorOr<Cleanup> ForkAndExec(const std::string& filename, - const ExecveArray& argv, - const ExecveArray& envv, - const std::function<void()>& fn, pid_t* child, - int* execve_errno) { +namespace { + +// exec_fn wraps a variant of the exec family, e.g. execve or execveat. +PosixErrorOr<Cleanup> ForkAndExecHelper(const std::function<void()>& exec_fn, + const std::function<void()>& fn, + pid_t* child, int* execve_errno) { int pfds[2]; int ret = pipe2(pfds, O_CLOEXEC); if (ret < 0) { @@ -76,7 +78,9 @@ PosixErrorOr<Cleanup> ForkAndExec(const std::string& filename, fn(); } - execve(filename.c_str(), argv.get(), envv.get()); + // Call variant of exec function. + exec_fn(); + int error = errno; if (WriteFd(pfds[1], &error, sizeof(error)) != sizeof(error)) { // We can't do much if the write fails, but we can at least exit with a @@ -116,6 +120,36 @@ PosixErrorOr<Cleanup> ForkAndExec(const std::string& filename, return std::move(cleanup); } +} // namespace + +PosixErrorOr<Cleanup> ForkAndExec(const std::string& filename, + const ExecveArray& argv, + const ExecveArray& envv, + const std::function<void()>& fn, pid_t* child, + int* execve_errno) { + char* const* argv_data = argv.get(); + char* const* envv_data = envv.get(); + const std::function<void()> exec_fn = [=] { + execve(filename.c_str(), argv_data, envv_data); + }; + return ForkAndExecHelper(exec_fn, fn, child, execve_errno); +} + +PosixErrorOr<Cleanup> ForkAndExecveat(const int32_t dirfd, + const std::string& pathname, + const ExecveArray& argv, + const ExecveArray& envv, const int flags, + const std::function<void()>& fn, + pid_t* child, int* execve_errno) { + char* const* argv_data = argv.get(); + char* const* envv_data = envv.get(); + const std::function<void()> exec_fn = [=] { + syscall(__NR_execveat, dirfd, pathname.c_str(), argv_data, envv_data, + flags); + }; + return ForkAndExecHelper(exec_fn, fn, child, execve_errno); +} + PosixErrorOr<int> InForkedProcess(const std::function<void()>& fn) { pid_t pid = fork(); if (pid == 0) { diff --git a/test/util/multiprocess_util.h b/test/util/multiprocess_util.h index 0aecd3439..61526b4e7 100644 --- a/test/util/multiprocess_util.h +++ b/test/util/multiprocess_util.h @@ -102,6 +102,22 @@ inline PosixErrorOr<Cleanup> ForkAndExec(const std::string& filename, return ForkAndExec(filename, argv, envv, [] {}, child, execve_errno); } +// Equivalent to ForkAndExec, except using dirfd and flags with execveat. +PosixErrorOr<Cleanup> ForkAndExecveat(int32_t dirfd, const std::string& pathname, + const ExecveArray& argv, + const ExecveArray& envv, int flags, + const std::function<void()>& fn, + pid_t* child, int* execve_errno); + +inline PosixErrorOr<Cleanup> ForkAndExecveat(int32_t dirfd, + const std::string& pathname, + const ExecveArray& argv, + const ExecveArray& envv, int flags, + pid_t* child, int* execve_errno) { + return ForkAndExecveat( + dirfd, pathname, argv, envv, flags, [] {}, child, execve_errno); +} + // Calls fn in a forked subprocess and returns the exit status of the // subprocess. // diff --git a/test/util/proc_util.cc b/test/util/proc_util.cc index 75b24da37..34d636ba9 100644 --- a/test/util/proc_util.cc +++ b/test/util/proc_util.cc @@ -88,7 +88,7 @@ PosixErrorOr<std::vector<ProcMapsEntry>> ParseProcMaps( std::vector<ProcMapsEntry> entries; auto lines = absl::StrSplit(contents, '\n', absl::SkipEmpty()); for (const auto& l : lines) { - std::cout << "line: " << l; + std::cout << "line: " << l << std::endl; ASSIGN_OR_RETURN_ERRNO(auto entry, ParseProcMapsLine(l)); entries.push_back(entry); } diff --git a/test/util/uid_util.cc b/test/util/uid_util.cc new file mode 100644 index 000000000..b131b4b99 --- /dev/null +++ b/test/util/uid_util.cc @@ -0,0 +1,44 @@ +// 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/posix_error.h" +#include "test/util/save_util.h" + +namespace gvisor { +namespace testing { + +PosixErrorOr<bool> IsRoot() { + uid_t ruid, euid, suid; + int rc = getresuid(&ruid, &euid, &suid); + MaybeSave(); + if (rc < 0) { + return PosixError(errno, "getresuid"); + } + if (ruid != 0 || euid != 0 || suid != 0) { + return false; + } + gid_t rgid, egid, sgid; + rc = getresgid(&rgid, &egid, &sgid); + MaybeSave(); + if (rc < 0) { + return PosixError(errno, "getresgid"); + } + if (rgid != 0 || egid != 0 || sgid != 0) { + return false; + } + return true; +} + +} // namespace testing +} // namespace gvisor diff --git a/test/util/uid_util.h b/test/util/uid_util.h new file mode 100644 index 000000000..2cd387fb0 --- /dev/null +++ b/test/util/uid_util.h @@ -0,0 +1,29 @@ +// 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. + +#ifndef GVISOR_TEST_SYSCALLS_UID_UTIL_H_ +#define GVISOR_TEST_SYSCALLS_UID_UTIL_H_ + +#include "test/util/posix_error.h" + +namespace gvisor { +namespace testing { + +// Returns true if the caller's real/effective/saved user/group IDs are all 0. +PosixErrorOr<bool> IsRoot(); + +} // namespace testing +} // namespace gvisor + +#endif // GVISOR_TEST_SYSCALLS_UID_UTIL_H_ |