summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorDean Deng <deandeng@google.com>2019-10-29 13:58:09 -0700
committergVisor bot <gvisor-bot@google.com>2019-10-29 13:59:28 -0700
commit38330e93774e68324d8f43adb27178453dee18b6 (patch)
tree4e9ac6de2c56a4fb7b40f1947918987b244756da /test
parentc0b8fd4b6a9fcb595f3200577b93d07737cfaacd (diff)
Update symlink traversal limit when resolving interpreter path.
When execveat is called on an interpreter script, the symlink count for resolving the script path should be separate from the count for resolving the the corresponding interpreter. An ELOOP error should not occur if we do not hit the symlink limit along any individual path, even if the total number of symlinks encountered exceeds the limit. Closes #574 PiperOrigin-RevId: 277358474
Diffstat (limited to 'test')
-rw-r--r--test/syscalls/linux/exec.cc41
1 files changed, 41 insertions, 0 deletions
diff --git a/test/syscalls/linux/exec.cc b/test/syscalls/linux/exec.cc
index a9067df2a..581f03533 100644
--- a/test/syscalls/linux/exec.cc
+++ b/test/syscalls/linux/exec.cc
@@ -533,6 +533,47 @@ TEST(ExecTest, CloexecEventfd) {
W_EXITCODE(0, 0), "");
}
+constexpr int kLinuxMaxSymlinks = 40;
+
+TEST(ExecTest, SymlinkLimitExceeded) {
+ std::string path = WorkloadPath(kBasicWorkload);
+
+ // Hold onto TempPath objects so they are not destructed prematurely.
+ std::vector<TempPath> symlinks;
+ for (int i = 0; i < kLinuxMaxSymlinks + 1; i++) {
+ symlinks.push_back(
+ ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateSymlinkTo("/tmp", path)));
+ path = symlinks[i].path();
+ }
+
+ int execve_errno;
+ ASSERT_NO_ERRNO_AND_VALUE(
+ ForkAndExec(path, {path}, {}, /*child=*/nullptr, &execve_errno));
+ EXPECT_EQ(execve_errno, ELOOP);
+}
+
+TEST(ExecTest, SymlinkLimitRefreshedForInterpreter) {
+ std::string tmp_dir = "/tmp";
+ std::string interpreter_path = "/bin/echo";
+ TempPath script = ASSERT_NO_ERRNO_AND_VALUE(TempPath::CreateFileWith(
+ tmp_dir, absl::StrCat("#!", interpreter_path), 0755));
+ std::string script_path = script.path();
+
+ // Hold onto TempPath objects so they are not destructed prematurely.
+ std::vector<TempPath> interpreter_symlinks;
+ std::vector<TempPath> script_symlinks;
+ for (int i = 0; i < kLinuxMaxSymlinks; i++) {
+ interpreter_symlinks.push_back(ASSERT_NO_ERRNO_AND_VALUE(
+ TempPath::CreateSymlinkTo(tmp_dir, interpreter_path)));
+ interpreter_path = interpreter_symlinks[i].path();
+ script_symlinks.push_back(ASSERT_NO_ERRNO_AND_VALUE(
+ TempPath::CreateSymlinkTo(tmp_dir, script_path)));
+ script_path = script_symlinks[i].path();
+ }
+
+ CheckExec(script_path, {script_path}, {}, ArgEnvExitStatus(0, 0), "");
+}
+
TEST(ExecveatTest, BasicWithFDCWD) {
std::string path = WorkloadPath(kBasicWorkload);
CheckExecveat(AT_FDCWD, path, {path}, {}, /*flags=*/0, ArgEnvExitStatus(0, 0),