Skip to content

Commit 06e8214

Browse files
authored
Merge pull request #41 from lrowe/net-permissions
Use callbacks for sendto/sendmsg and separate bind callback
2 parents 5ab78c1 + 1352b6b commit 06e8214

2 files changed

Lines changed: 51 additions & 28 deletions

File tree

lib/tinykvm/linux/fds.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ namespace tinykvm
2929
using open_readable_t = std::function<bool(std::string&)>;
3030
using open_writable_t = std::function<bool(std::string&)>;
3131
using connect_socket_t = std::function<bool(int, struct sockaddr_storage&)>;
32+
using bind_socket_t = std::function<bool(int, struct sockaddr_storage&)>;
3233
using listening_socket_t = std::function<bool(int, int)>;
3334
using accept_socket_t = std::function<int(int, int, int, struct sockaddr_storage&, socklen_t&)>;
3435
using resolve_symlink_t = std::function<bool(std::string&)>;
@@ -321,6 +322,7 @@ namespace tinykvm
321322

322323
public:
323324
connect_socket_t connect_socket_callback;
325+
bind_socket_t bind_socket_callback;
324326
accept_socket_t accept_socket_callback;
325327
listening_socket_t listening_socket_callback;
326328
epoll_wait_t epoll_wait_callback;

lib/tinykvm/linux/system_calls.cpp

Lines changed: 49 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,7 +1111,8 @@ void Machine::setup_linux_system_calls(bool unsafe_syscalls)
11111111
{
11121112
cpu.machine().copy_from_guest(&addr, g_addr, addrlen);
11131113
// Validate the address
1114-
if (UNLIKELY(!cpu.machine().fds().validate_socket_address(fd, addr)))
1114+
if (auto& callback = cpu.machine().fds().bind_socket_callback;
1115+
UNLIKELY(callback == nullptr || !callback(fd, addr)))
11151116
{
11161117
regs.rax = -EPERM;
11171118
} else {
@@ -1138,20 +1139,18 @@ void Machine::setup_linux_system_calls(bool unsafe_syscalls)
11381139
const int vfd = regs.rdi;
11391140
const int fd = cpu.machine().fds().translate_writable_vfd(vfd);
11401141
const int backlog = regs.rsi;
1141-
if (UNLIKELY(listen(fd, backlog) < 0))
1142+
if (auto& callback = cpu.machine().fds().listening_socket_callback;
1143+
UNLIKELY(callback == nullptr || !callback(vfd, fd)))
1144+
{
1145+
regs.rax = -EPERM;
1146+
}
1147+
else if (UNLIKELY(listen(fd, backlog) < 0))
11421148
{
11431149
regs.rax = -errno;
11441150
}
11451151
else
11461152
{
1147-
if (auto& callback = cpu.machine().fds().listening_socket_callback;
1148-
callback != nullptr)
1149-
{
1150-
const bool allowed = callback(vfd, fd);
1151-
regs.rax = allowed ? 0 : -EPERM;
1152-
} else {
1153-
regs.rax = 0;
1154-
}
1153+
regs.rax = 0;
11551154
}
11561155
cpu.set_registers(regs);
11571156
SYSPRINT("listen(fd=%d (%d), backlog=%d) = %lld\n",
@@ -1333,7 +1332,7 @@ void Machine::setup_linux_system_calls(bool unsafe_syscalls)
13331332
// Ignore too large buffers
13341333
regs.rax = -ENOMEM;
13351334
}
1336-
else if (UNLIKELY(addrlen > sizeof(struct sockaddr)))
1335+
else if (UNLIKELY(addrlen > sizeof(struct sockaddr_storage)))
13371336
{
13381337
regs.rax = -EINVAL;
13391338
}
@@ -1345,7 +1344,7 @@ void Machine::setup_linux_system_calls(bool unsafe_syscalls)
13451344
const auto bufcount =
13461345
cpu.machine().gather_buffers_from_range(buffers.size(), buffers.data(), g_buf, bytes);
13471346

1348-
struct sockaddr addr;
1347+
struct sockaddr_storage addr {};
13491348
struct msghdr msg {};
13501349
msg.msg_name = nullptr;
13511350
msg.msg_namelen = 0;
@@ -1360,13 +1359,20 @@ void Machine::setup_linux_system_calls(bool unsafe_syscalls)
13601359
msg.msg_name = &addr;
13611360
msg.msg_namelen = addrlen;
13621361
}
1363-
1364-
ssize_t result = sendmsg(fd, &msg, flags);
1365-
if (UNLIKELY(result < 0)) {
1366-
regs.rax = -errno;
1367-
}
1368-
else {
1369-
regs.rax = result;
1362+
// Validate the address
1363+
if (UNLIKELY(addrlen > 0 && g_addr != 0x0 &&
1364+
!cpu.machine().fds().validate_socket_address(fd, addr)))
1365+
{
1366+
regs.rax = -EPERM;
1367+
} else
1368+
{
1369+
ssize_t result = sendmsg(fd, &msg, flags);
1370+
if (UNLIKELY(result < 0)) {
1371+
regs.rax = -errno;
1372+
}
1373+
else {
1374+
regs.rax = result;
1375+
}
13701376
}
13711377
}
13721378
} catch (...) {
@@ -1540,21 +1546,36 @@ void Machine::setup_linux_system_calls(bool unsafe_syscalls)
15401546
g_base, g_len);
15411547
bufcount += this_bufcount;
15421548
}
1543-
struct sockaddr addr {};
1549+
struct sockaddr_storage addr {};
15441550
struct msghdr msg_send {};
1545-
msg_send.msg_name = &addr;
1546-
msg_send.msg_namelen = sizeof(addr);
1551+
msg_send.msg_name = nullptr;
1552+
msg_send.msg_namelen = 0;
15471553
msg_send.msg_iov = (struct iovec *)&buffers[0];
15481554
msg_send.msg_iovlen = bufcount;
15491555
msg_send.msg_control = nullptr;
15501556
msg_send.msg_controllen = 0;
15511557
msg_send.msg_flags = MSG_NOSIGNAL; // Ignore SIGPIPE
1552-
// Perform the sendmsg
1553-
ssize_t result = sendmsg(fd, &msg_send, flags);
1554-
if (UNLIKELY(result < 0)) {
1555-
regs.rax = -errno;
1556-
} else {
1557-
regs.rax = result;
1558+
1559+
if (msg.msg_namelen > 0 && msg.msg_name != 0x0) {
1560+
cpu.machine().copy_from_guest(&addr, reinterpret_cast<uint64_t>(msg.msg_name), msg.msg_namelen);
1561+
msg_send.msg_name = &addr;
1562+
msg_send.msg_namelen = msg.msg_namelen;
1563+
}
1564+
// Validate the address
1565+
if (UNLIKELY(msg.msg_namelen > 0 && msg.msg_name != 0x0 &&
1566+
!cpu.machine().fds().validate_socket_address(fd, addr)))
1567+
{
1568+
regs.rax = -EPERM;
1569+
}
1570+
else
1571+
{
1572+
// Perform the sendmsg
1573+
ssize_t result = sendmsg(fd, &msg_send, flags);
1574+
if (UNLIKELY(result < 0)) {
1575+
regs.rax = -errno;
1576+
} else {
1577+
regs.rax = result;
1578+
}
15581579
}
15591580
} catch (...) {
15601581
regs.rax = -EBADF;

0 commit comments

Comments
 (0)