Skip to content

Commit 4b0dfcc

Browse files
committed
Pretend not a symlink or is a directory under certain circumstances
Deno looks at a chain of directories for symlinks during startup and import. We avoid having to give more access than we'd like by papering over the issue.
1 parent cd76e4f commit 4b0dfcc

File tree

1 file changed

+19
-4
lines changed

1 file changed

+19
-4
lines changed

lib/tinykvm/linux/system_calls.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,7 +1409,10 @@ void Machine::setup_linux_system_calls()
14091409
if (bufsiz > buf.size()) {
14101410
regs.rax = -EINVAL;
14111411
} else if (!cpu.machine().fds().is_readable_path(path)) {
1412-
regs.rax = -EACCES;
1412+
// This should be a permission error or EACCES, but some run-times
1413+
// like to recurse from root up to the path, which we don't want to
1414+
// allow. So instead we return EINVAL to pretend the path is not a link.
1415+
regs.rax = -EINVAL;
14131416
} else {
14141417
// Read the link
14151418
ssize_t result = readlink(path.c_str(), buf.data(), bufsiz);
@@ -1782,12 +1785,23 @@ void Machine::setup_linux_system_calls()
17821785
}
17831786

17841787
if (!cpu.machine().fds().is_readable_path(path) && !path.empty()) {
1785-
regs.rax = -EPERM;
1788+
// Path is not readable, however, if this is a "readlink" attempt,
1789+
// we should pretend the path is not a link instead.
1790+
if (regs.r10 & AT_SYMLINK_NOFOLLOW) {
1791+
// Create a fictional stat structure, pretending it's a directory
1792+
struct stat64 vstat {};
1793+
vstat.st_mode = S_IFDIR | 0644;
1794+
vstat.st_blksize = 512;
1795+
cpu.machine().copy_to_guest(buffer, &vstat, sizeof(vstat));
1796+
regs.rax = 0;
1797+
} else {
1798+
regs.rax = -EPERM;
1799+
}
17861800
} else {
17871801
// If path is empty, use AT_EMPTY_PATH to operate on the fd
17881802
flags = (path.empty() && vfd != AT_FDCWD) ? AT_EMPTY_PATH : 0;
17891803

1790-
struct stat64 vstat;
1804+
struct stat64 vstat {};
17911805
// Path is in allow-list
17921806
const int result = fstatat64(fd, path.c_str(), &vstat, flags);
17931807
if (result == 0) {
@@ -2134,7 +2148,8 @@ void Machine::setup_linux_system_calls()
21342148
try {
21352149
path = cpu.machine().memcstring(vpath, PATH_MAX);
21362150
if (!cpu.machine().fds().is_readable_path(path)) {
2137-
regs.rax = -EPERM;
2151+
// Pretend the path is not a link
2152+
regs.rax = -EINVAL;
21382153
} else {
21392154
int fd = cpu.machine().fds().current_working_directory_fd();
21402155
// Translate from vfd when fd != AT_FDCWD

0 commit comments

Comments
 (0)