Skip to content

Commit 64ceec4

Browse files
committed
Allow opening using fd for statx, enforce AT_SYMLINK_NOFOLLOW
1 parent 57e97a3 commit 64ceec4

File tree

1 file changed

+48
-37
lines changed

1 file changed

+48
-37
lines changed

lib/tinykvm/linux/system_calls.cpp

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -856,20 +856,19 @@ void Machine::setup_linux_system_calls()
856856
if (addrlen > sizeof(addr))
857857
{
858858
regs.rax = -EINVAL;
859-
cpu.set_registers(regs);
860-
return;
861-
}
862-
cpu.machine().copy_from_guest(&addr, g_addr, addrlen);
863-
// Validate the address
864-
if (!cpu.machine().fds().validate_socket_address(fd, addr))
865-
{
866-
regs.rax = -EPERM;
867859
} else {
868-
if (connect(fd, &addr, addrlen) < 0) {
869-
regs.rax = -errno;
870-
}
871-
else {
872-
regs.rax = 0;
860+
cpu.machine().copy_from_guest(&addr, g_addr, addrlen);
861+
// Validate the address
862+
if (!cpu.machine().fds().validate_socket_address(fd, addr))
863+
{
864+
regs.rax = -EPERM;
865+
} else {
866+
if (connect(fd, &addr, addrlen) < 0) {
867+
regs.rax = -errno;
868+
}
869+
else {
870+
regs.rax = 0;
871+
}
873872
}
874873
}
875874
SYSPRINT("connect(fd=%d, addr=0x%lX, addrlen=%zu) = %lld\n",
@@ -1156,7 +1155,7 @@ void Machine::setup_linux_system_calls()
11561155
}
11571156
cpu.machine().copy_to_guest(iov.iov_base, buf.data() + offset, len_remaining);
11581157
offset += iov.iov_len;
1159-
if (offset >= result) {
1158+
if (offset >= size_t(result)) {
11601159
break;
11611160
}
11621161
}
@@ -1439,21 +1438,26 @@ void Machine::setup_linux_system_calls()
14391438
Machine::install_syscall_handler(
14401439
SYS_openat, [] (vCPU& cpu) { // OPENAT
14411440
auto& regs = cpu.registers();
1442-
1441+
const int vfd = regs.rdi;
14431442
const auto vpath = regs.rsi;
1444-
const int flags = regs.rdx;
1443+
int flags = regs.rdx | AT_SYMLINK_NOFOLLOW;
14451444

14461445
std::string path = cpu.machine().memcstring(vpath, PATH_MAX);
1446+
std::string real_path;
14471447
bool write_flags = (flags & (O_WRONLY | O_RDWR)) != 0x0;
14481448
if (!write_flags)
14491449
{
14501450
try {
1451-
std::string real_path = path;
1451+
int pfd = AT_FDCWD;
1452+
if (vfd != AT_FDCWD) {
1453+
pfd = cpu.machine().fds().translate(vfd);
1454+
}
1455+
real_path = path;
14521456
if (!cpu.machine().fds().is_readable_path(real_path)) {
14531457
throw std::runtime_error("Path not readable: " + real_path);
14541458
}
14551459

1456-
int fd = openat(AT_FDCWD, real_path.c_str(), flags);
1460+
int fd = openat(pfd, real_path.c_str(), flags);
14571461
if (fd > 0) {
14581462
regs.rax = cpu.machine().fds().manage(fd, false);
14591463
} else {
@@ -1473,12 +1477,18 @@ void Machine::setup_linux_system_calls()
14731477
if (write_flags || regs.rax == (__u64)-1)
14741478
{
14751479
try {
1476-
std::string real_path = path;
1480+
int pfd = AT_FDCWD;
1481+
if (vfd != AT_FDCWD) {
1482+
pfd = cpu.machine().fds().translate(vfd);
1483+
}
1484+
1485+
real_path = path;
14771486
if (!cpu.machine().fds().is_writable_path(real_path)) {
1487+
SYSPRINT("OPENAT path was not writable: %s\n", real_path.c_str());
14781488
throw std::runtime_error("Path not writable: " + real_path);
14791489
}
14801490

1481-
int fd = openat(AT_FDCWD, real_path.c_str(), flags, S_IWUSR | S_IRUSR);
1491+
int fd = openat(pfd, real_path.c_str(), flags, S_IWUSR | S_IRUSR);
14821492
SYSPRINT("OPENAT where=%lld path=%s (real_path=%s) flags=%X = fd %d\n",
14831493
regs.rdi, path.c_str(), real_path.c_str(), flags, fd);
14841494

@@ -1498,7 +1508,7 @@ void Machine::setup_linux_system_calls()
14981508
auto& regs = cpu.registers();
14991509
const auto vpath = regs.rsi;
15001510
const auto buffer = regs.rdx;
1501-
int flags = 0; // regs.r10;
1511+
int flags = AT_SYMLINK_NOFOLLOW; // regs.r10;
15021512
int fd = AT_FDCWD;
15031513
std::string path;
15041514

@@ -1822,31 +1832,32 @@ void Machine::setup_linux_system_calls()
18221832
auto& regs = cpu.registers();
18231833
const int vfd = regs.rdi;
18241834
const auto vpath = regs.rsi;
1825-
const auto flags = regs.rdx;
1835+
const auto flags = regs.rdx | AT_SYMLINK_NOFOLLOW;
18261836
const auto mask = regs.r10;
18271837
const auto buffer = regs.r8;
18281838
std::string path;
18291839
int fd = AT_FDCWD;
18301840

18311841
try {
18321842
path = cpu.machine().memcstring(vpath, PATH_MAX);
1833-
if (!cpu.machine().fds().is_readable_path(path)) {
1834-
regs.rax = -EPERM;
1835-
} else {
1836-
// Translate from vfd when fd != AT_FDCWD
1837-
if (vfd != AT_FDCWD)
1838-
fd = cpu.machine().fds().translate(vfd);
1839-
1840-
struct statx vstat;
1841-
const int result =
1842-
statx(fd, path.c_str(), flags, mask, &vstat);
1843-
if (result == 0) {
1844-
cpu.machine().copy_to_guest(buffer, &vstat, sizeof(vstat));
1845-
regs.rax = 0;
1846-
} else {
1847-
regs.rax = -errno;
1843+
if (!path.empty()) {
1844+
if (!cpu.machine().fds().is_readable_path(path)) {
1845+
regs.rax = -EPERM;
18481846
}
18491847
}
1848+
// Translate from vfd when fd != AT_FDCWD
1849+
if (vfd != AT_FDCWD)
1850+
fd = cpu.machine().fds().translate(vfd);
1851+
1852+
struct statx vstat;
1853+
const int result =
1854+
statx(fd, path.c_str(), flags, mask, &vstat);
1855+
if (result == 0) {
1856+
cpu.machine().copy_to_guest(buffer, &vstat, sizeof(vstat));
1857+
regs.rax = 0;
1858+
} else {
1859+
regs.rax = -errno;
1860+
}
18501861
} catch (...) {
18511862
regs.rax = -1;
18521863
}

0 commit comments

Comments
 (0)