Skip to content

Commit 57e97a3

Browse files
committed
Initial support for sockets
Most have very simple and low-performing implementations, but still aim for sandbox safety
1 parent c09c347 commit 57e97a3

File tree

3 files changed

+566
-29
lines changed

3 files changed

+566
-29
lines changed

lib/tinykvm/linux/fds.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <fcntl.h>
66
#include <cstring>
77
#include <sys/stat.h>
8+
#include <sys/types.h>
89
#include <stdexcept>
910
#include <unistd.h>
1011

@@ -238,4 +239,13 @@ namespace tinykvm
238239
return false;
239240
}
240241

242+
bool FileDescriptors::validate_socket_address(const int socket_fd, struct sockaddr& socket_address) const noexcept
243+
{
244+
if (m_connect_socket) {
245+
return m_connect_socket(socket_fd, socket_address);
246+
}
247+
// If no callback is set, we disallow all connect() calls.
248+
return false;
249+
}
250+
241251
} // tinykvm

lib/tinykvm/linux/fds.hpp

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77
#include <optional>
88
#include <string>
99
#include <unordered_set>
10+
struct sockaddr;
1011

1112
namespace tinykvm
1213
{
1314
struct Machine;
1415

1516
struct FileDescriptors
1617
{
17-
static constexpr unsigned DEFAULT_MAX_FILES = 64;
18+
static constexpr unsigned DEFAULT_MAX_FILES = 256;
19+
static constexpr unsigned DEFAULT_TOTAL_FILES = 4096;
1820
static constexpr int SOCKET_BIT = 0x40000000;
1921
struct Entry
2022
{
@@ -24,6 +26,7 @@ namespace tinykvm
2426
};
2527
using open_readable_t = std::function<bool(std::string&)>;
2628
using open_writable_t = std::function<bool(std::string&)>;
29+
using connect_socket_t = std::function<bool(int, struct sockaddr&)>;
2730
using find_readonly_master_vm_fd_t = std::function<std::optional<const Entry*>(int)>;
2831

2932
FileDescriptors(Machine& machine);
@@ -102,6 +105,91 @@ namespace tinykvm
102105
/// may be modified by the callback, indicating which real path to open.
103106
bool is_writable_path(std::string& modifiable_path) const noexcept;
104107

108+
/// @brief Set the maximum number of file descriptors that can be opened.
109+
/// @param max_files The maximum number of file descriptors that can be
110+
/// opened.
111+
void set_max_files(uint16_t max_files) noexcept {
112+
m_max_files = max_files;
113+
}
114+
115+
/// @brief Get the maximum number of file descriptors that can be opened.
116+
/// @return The maximum number of file descriptors that can be opened.
117+
uint16_t get_max_files() const noexcept {
118+
return m_max_files;
119+
}
120+
121+
/// @brief Set the maximum number of sockets that can be opened.
122+
/// @param max_sockets The maximum number of sockets that can be opened.
123+
void set_max_sockets(uint16_t max_sockets) noexcept {
124+
m_max_sockets = max_sockets;
125+
}
126+
127+
/// @brief Get the maximum number of sockets that can be opened.
128+
/// @return The maximum number of sockets that can be opened.
129+
uint16_t get_max_sockets() const noexcept {
130+
return m_max_sockets;
131+
}
132+
133+
/// @brief Set the maximum number of file descriptors that can be opened
134+
/// in total. This is the sum of the maximum number of files and sockets
135+
/// that can be opened.
136+
/// @param max_total_fds_opened The maximum number of file descriptors
137+
/// that can be opened in total.
138+
void set_max_total_fds_opened(uint16_t max_total_fds_opened) noexcept {
139+
m_max_total_fds_opened = max_total_fds_opened;
140+
}
141+
142+
/// @brief Get the maximum number of file descriptors that can be opened
143+
/// in total. This is the sum of the maximum number of files and sockets
144+
/// that can be opened.
145+
/// @return The maximum number of file descriptors that can be opened
146+
/// in total.
147+
uint16_t get_max_total_fds_opened() const noexcept {
148+
return m_max_total_fds_opened;
149+
}
150+
151+
/// @brief Get the number of file descriptors that have been opened
152+
/// since the last reset. This is the number of file descriptors that
153+
/// are currently open, plus the number of file descriptors that have
154+
/// been closed. Includes files and sockets.
155+
/// @return The number of file descriptors that have been opened since
156+
/// the last reset. Includes files and sockets.
157+
uint16_t get_total_fds_opened() const noexcept {
158+
return m_total_fds_opened;
159+
}
160+
161+
/// @brief Get the number of file descriptors that are currently open.
162+
/// Does not include sockets.
163+
/// @return The number of file descriptors that are currently open.
164+
uint16_t get_current_fds_opened() const noexcept {
165+
return m_fds.size();
166+
}
167+
168+
/// @brief Get the number of sockets that are currently open.
169+
/// @return The number of sockets that are currently open.
170+
uint16_t get_current_sockets_opened() const noexcept {
171+
return m_fds.size() - m_stdout_redirects.size();
172+
}
173+
174+
/// @brief Set a callback for connecting a socket. This is used to check if a
175+
/// socket is allowed to be connected. The callback should return true if the
176+
/// socket is allowed, and false otherwise. The socket may be modified by the
177+
/// callback, indicating which real socket to connect to. The argument is
178+
/// a vector of bytes that contains the socket address, eg. a struct sockaddr.
179+
/// @param callback The callback to set.
180+
void set_connect_socket_callback(connect_socket_t callback) noexcept {
181+
m_connect_socket = callback;
182+
}
183+
184+
/// @brief Validate and modify the socket address. This is used to check if a
185+
/// socket is allowed to be connected. The callback should return true if the
186+
/// socket is allowed, and false otherwise. The socket may be modified by the
187+
/// callback, indicating which real socket to connect to. The argument is
188+
/// a vector of bytes that contains the socket address, eg. a struct sockaddr.
189+
/// @param socket_address The socket address to validate and modify.
190+
/// @return True if the socket address is allowed, false otherwise.
191+
bool validate_socket_address(const int socket_fd, struct sockaddr& socket_address) const noexcept;
192+
105193
/// @brief Set verbose mode. This will print out information about
106194
/// file descriptor management.
107195
/// @param verbose True to enable verbose mode, false to disable it.
@@ -128,10 +216,11 @@ namespace tinykvm
128216
bool m_verbose = false;
129217
open_readable_t m_open_readable;
130218
open_writable_t m_open_writable;
219+
connect_socket_t m_connect_socket;
131220
find_readonly_master_vm_fd_t m_find_ro_master_vm_fd;
132221
uint16_t m_max_files = DEFAULT_MAX_FILES;
133222
uint16_t m_max_sockets = DEFAULT_MAX_FILES;
134223
uint16_t m_total_fds_opened = 0;
135-
uint16_t m_max_total_fds_opened = DEFAULT_MAX_FILES;
224+
uint16_t m_max_total_fds_opened = DEFAULT_TOTAL_FILES;
136225
};
137226
}

0 commit comments

Comments
 (0)