1515#include " protocol.h"
1616#include < sys/mman.h>
1717
18+ #ifdef DEBUG_SUPERVISOR
19+ #define dbgprint (...) fprintf(stdout, __VA_ARGS__)
20+ #else
21+ #define dbgprint (...)
22+ #endif
23+
1824struct Config {
1925 uintptr_t sensitive_lo;
2026 uintptr_t sensitive_hi;
2127 std::vector<AllowedSite> allowed;
2228};
2329
30+ static void recv_all (int sock, void * buf, size_t len) {
31+ auto * p = static_cast <char *>(buf);
32+ while (len > 0 ) {
33+ ssize_t n = recv (sock, p, len, MSG_WAITALL);
34+ if (n < 0 ) {
35+ if (errno == EINTR) continue ;
36+ throw std::system_error (errno, std::system_category (), " recv" );
37+ }
38+ if (n == 0 )
39+ throw std::runtime_error (" supervisor: connection closed unexpectedly" );
40+ p += n;
41+ len -= n;
42+ }
43+ }
44+
2445static int recv_setup (int sock, Config& cfg) {
2546 SupervisorSetupMsg setup;
26- ssize_t n = recv (sock, &setup, sizeof (setup), MSG_WAITALL);
27- if (n != sizeof (setup)) {
28- fprintf (stderr, " supervisor: short read on SupervisorSetupMsg\n " );
29- return -1 ;
30- }
47+ recv_all (sock, &setup, sizeof (setup));
3148
3249 cfg.sensitive_lo = setup.sensitive_lo ;
3350 cfg.sensitive_hi = setup.sensitive_hi ;
34- cfg.allowed .resize (setup.n_allowed_sites );
51+ if (setup.n_allowed_sites > MAX_ALLOWED_SITES)
52+ throw std::runtime_error (" supervisor: too many allowed sites" );
53+
54+ if (cfg.sensitive_lo >= cfg.sensitive_hi )
55+ throw std::runtime_error (" supervisor: invalid sensitive range" );
3556
57+ cfg.allowed .resize (setup.n_allowed_sites );
3658 if (setup.n_allowed_sites > 0 ) {
3759 size_t sites_sz = setup.n_allowed_sites * sizeof (AllowedSite);
38- n = recv (sock, cfg.allowed .data (), sites_sz, MSG_WAITALL);
39- if ((size_t )n != sites_sz) {
40- fprintf (stderr, " supervisor: short read on AllowedSite[]\n " );
41- return -1 ;
42- }
60+ recv_all (sock, cfg.allowed .data (), sites_sz);
4361 }
4462
4563 char dummy;
@@ -56,15 +74,16 @@ static int recv_setup(int sock, Config& cfg) {
5674 msg.msg_control = cmsg_buf.buf ;
5775 msg.msg_controllen = sizeof (cmsg_buf.buf );
5876
59- n = recvmsg (sock, &msg, MSG_CMSG_CLOEXEC);
60- if (n < 0 ) { perror (" supervisor: recvmsg" ); return -1 ; }
77+ ssize_t n = recvmsg (sock, &msg, MSG_CMSG_CLOEXEC);
78+ if (n < 0 ) {
79+ throw std::system_error (errno, std::system_category (), " recvmsg" );
80+ }
6181
6282 struct cmsghdr * cmsg = CMSG_FIRSTHDR (&msg);
6383 if (!cmsg || cmsg->cmsg_level != SOL_SOCKET ||
6484 cmsg->cmsg_type != SCM_RIGHTS ||
6585 cmsg->cmsg_len != CMSG_LEN (sizeof (int ))) {
66- fprintf (stderr, " supervisor: missing SCM_RIGHTS\n " );
67- return -1 ;
86+ throw std::runtime_error (" supervisor: invalid SCM_RIGHTS" );
6887 }
6988
7089 int unotify_fd;
@@ -75,7 +94,10 @@ static int recv_setup(int sock, Config& cfg) {
7594static bool overlaps (uintptr_t addr, uintptr_t size, uintptr_t lo, uintptr_t hi) {
7695 uintptr_t end = addr + size;
7796 bool wrapped = (end < addr);
78- return (wrapped || end > lo) && (addr < hi);
97+ if (wrapped) {
98+ return (addr < hi) || (end > lo);
99+ }
100+ return (end > lo) && (addr < hi);
79101}
80102
81103static bool ip_is_allowed (uintptr_t ip, const Config& cfg) {
@@ -110,10 +132,7 @@ static bool handle_notification(int unotify_fd, const Config& cfg) {
110132 int prot = (int )req.data .args [2 ];
111133
112134 bool ip_ok = ip_is_allowed (ip, cfg);
113- bool contained = (addr >= cfg.sensitive_lo )
114- && (len <= cfg.sensitive_hi - cfg.sensitive_lo )
115- && (addr + len <= cfg.sensitive_hi )
116- && (addr + len >= addr);
135+ bool contained = overlaps (addr, len, cfg.sensitive_lo , cfg.sensitive_hi );
117136 bool prot_safe = prot == PROT_NONE;
118137
119138 if (!contained) {
@@ -124,12 +143,11 @@ static bool handle_notification(int unotify_fd, const Config& cfg) {
124143 // touches our memory, but either makes it PROT_NONE or is from a whitelisted instruction
125144 resp.error = 0 ;
126145 resp.flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE;
127- fprintf (stdout, " Allowed mprotect from ip=0x%lx addr=[0x%lx,0x%lx) prot=%d\n " ,ip, addr, addr + len, prot);
146+ dbgprint ( " Allowed mprotect from ip=0x%lx addr=[0x%lx,0x%lx) prot=%d\n " ,ip, addr, addr + len, prot);
128147 } else {
129- fprintf (stderr,
130- " supervisor: DENIED syscall %d from ip=0x%lx addr=[0x%lx,0x%lx) prot=%d "
131- " (ip_ok=%d contained=%d)\n " ,
132- req.data .nr , ip, addr, addr + len, prot, ip_ok, contained);
148+ dbgprint (" supervisor: DENIED syscall %d from ip=0x%lx addr=[0x%lx,0x%lx) prot=%d "
149+ " (ip_ok=%d contained=%d)\n " ,
150+ req.data .nr , ip, addr, addr + len, prot, ip_ok, contained);
133151 }
134152
135153 if (ioctl (unotify_fd, SECCOMP_IOCTL_NOTIF_SEND, &resp) < 0 )
@@ -151,10 +169,10 @@ int supervisor_main(int sock_fd) {
151169
152170 if (unotify_fd < 0 ) return 1 ;
153171
154- fprintf (stderr, " supervisor: sensitive=[0x%lx, 0x%lx), %zu allowed sites\n " ,
172+ dbgprint ( " supervisor: sensitive=[0x%lx, 0x%lx), %zu allowed sites\n " ,
155173 cfg.sensitive_lo , cfg.sensitive_hi , cfg.allowed .size ());
156174 for (AllowedSite site : cfg.allowed )
157- fprintf (stderr, " supervisor: allowed site: 0x%lx\n " , site);
175+ dbgprint ( " supervisor: allowed site: 0x%lx\n " , site);
158176
159177 while (handle_notification (unotify_fd, cfg))
160178 ;
0 commit comments