Skip to content

Commit

Permalink
Trigger ARP requests via sockets, not rtnetlink
Browse files Browse the repository at this point in the history
Improves sandbox architecture
  • Loading branch information
riptl authored and ripatel-fd committed Feb 13, 2025
1 parent 71be7d1 commit 229ec83
Show file tree
Hide file tree
Showing 17 changed files with 405 additions and 164 deletions.
6 changes: 4 additions & 2 deletions book/api/metrics-generated.md
Original file line number Diff line number Diff line change
Expand Up @@ -501,5 +501,7 @@
| netlnk_​interface_​count | `gauge` | Number of network interfaces |
| netlnk_​route_​count_​local | `gauge` | Number of IPv4 routes (Local) |
| netlnk_​route_​count_​main | `gauge` | Number of IPv4 routes (Main) |
| netlnk_​neighbor_​solicits_​sent | `counter` | Number of neighbor solicit requests sent to kernel |
| netlnk_​neighbor_​solicits_​fails | `counter` | Number of neighbor solicit requests that failed to send |
| netlnk_​neigh_​probe_​sent | `counter` | Number of neighbor solicit requests sent to kernel |
| netlnk_​neigh_​probe_​fails | `counter` | Number of neighbor solicit requests that failed to send (kernel too slow) |
| netlnk_​neigh_​probe_​rate_​limit_​host | `counter` | Number of neighbor solicit that exceeded the per-host rate limit |
| netlnk_​neigh_​probe_​rate_​limit_​global | `counter` | Number of neighbor solicit that exceeded the global rate limit |
6 changes: 4 additions & 2 deletions src/disco/metrics/generated/fd_metrics_netlnk.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const fd_metrics_meta_t FD_METRICS_NETLNK[FD_METRICS_NETLNK_TOTAL] = {
DECLARE_METRIC( NETLNK_INTERFACE_COUNT, GAUGE ),
DECLARE_METRIC_ENUM( NETLNK_ROUTE_COUNT, GAUGE, ROUTE_TABLE, LOCAL ),
DECLARE_METRIC_ENUM( NETLNK_ROUTE_COUNT, GAUGE, ROUTE_TABLE, MAIN ),
DECLARE_METRIC( NETLNK_NEIGHBOR_SOLICITS_SENT, COUNTER ),
DECLARE_METRIC( NETLNK_NEIGHBOR_SOLICITS_FAILS, COUNTER ),
DECLARE_METRIC( NETLNK_NEIGH_PROBE_SENT, COUNTER ),
DECLARE_METRIC( NETLNK_NEIGH_PROBE_FAILS, COUNTER ),
DECLARE_METRIC( NETLNK_NEIGH_PROBE_RATE_LIMIT_HOST, COUNTER ),
DECLARE_METRIC( NETLNK_NEIGH_PROBE_RATE_LIMIT_GLOBAL, COUNTER ),
};
34 changes: 23 additions & 11 deletions src/disco/metrics/generated/fd_metrics_netlnk.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,29 @@
#define FD_METRICS_GAUGE_NETLNK_ROUTE_COUNT_LOCAL_OFF (23UL)
#define FD_METRICS_GAUGE_NETLNK_ROUTE_COUNT_MAIN_OFF (24UL)

#define FD_METRICS_COUNTER_NETLNK_NEIGHBOR_SOLICITS_SENT_OFF (25UL)
#define FD_METRICS_COUNTER_NETLNK_NEIGHBOR_SOLICITS_SENT_NAME "netlnk_neighbor_solicits_sent"
#define FD_METRICS_COUNTER_NETLNK_NEIGHBOR_SOLICITS_SENT_TYPE (FD_METRICS_TYPE_COUNTER)
#define FD_METRICS_COUNTER_NETLNK_NEIGHBOR_SOLICITS_SENT_DESC "Number of neighbor solicit requests sent to kernel"
#define FD_METRICS_COUNTER_NETLNK_NEIGHBOR_SOLICITS_SENT_CVT (FD_METRICS_CONVERTER_NONE)
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_SENT_OFF (25UL)
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_SENT_NAME "netlnk_neigh_probe_sent"
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_SENT_TYPE (FD_METRICS_TYPE_COUNTER)
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_SENT_DESC "Number of neighbor solicit requests sent to kernel"
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_SENT_CVT (FD_METRICS_CONVERTER_NONE)

#define FD_METRICS_COUNTER_NETLNK_NEIGHBOR_SOLICITS_FAILS_OFF (26UL)
#define FD_METRICS_COUNTER_NETLNK_NEIGHBOR_SOLICITS_FAILS_NAME "netlnk_neighbor_solicits_fails"
#define FD_METRICS_COUNTER_NETLNK_NEIGHBOR_SOLICITS_FAILS_TYPE (FD_METRICS_TYPE_COUNTER)
#define FD_METRICS_COUNTER_NETLNK_NEIGHBOR_SOLICITS_FAILS_DESC "Number of neighbor solicit requests that failed to send"
#define FD_METRICS_COUNTER_NETLNK_NEIGHBOR_SOLICITS_FAILS_CVT (FD_METRICS_CONVERTER_NONE)
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_FAILS_OFF (26UL)
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_FAILS_NAME "netlnk_neigh_probe_fails"
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_FAILS_TYPE (FD_METRICS_TYPE_COUNTER)
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_FAILS_DESC "Number of neighbor solicit requests that failed to send (kernel too slow)"
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_FAILS_CVT (FD_METRICS_CONVERTER_NONE)

#define FD_METRICS_NETLNK_TOTAL (11UL)
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_RATE_LIMIT_HOST_OFF (27UL)
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_RATE_LIMIT_HOST_NAME "netlnk_neigh_probe_rate_limit_host"
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_RATE_LIMIT_HOST_TYPE (FD_METRICS_TYPE_COUNTER)
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_RATE_LIMIT_HOST_DESC "Number of neighbor solicit that exceeded the per-host rate limit"
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_RATE_LIMIT_HOST_CVT (FD_METRICS_CONVERTER_NONE)

#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_RATE_LIMIT_GLOBAL_OFF (28UL)
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_RATE_LIMIT_GLOBAL_NAME "netlnk_neigh_probe_rate_limit_global"
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_RATE_LIMIT_GLOBAL_TYPE (FD_METRICS_TYPE_COUNTER)
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_RATE_LIMIT_GLOBAL_DESC "Number of neighbor solicit that exceeded the global rate limit"
#define FD_METRICS_COUNTER_NETLNK_NEIGH_PROBE_RATE_LIMIT_GLOBAL_CVT (FD_METRICS_CONVERTER_NONE)

#define FD_METRICS_NETLNK_TOTAL (13UL)
extern const fd_metrics_meta_t FD_METRICS_NETLNK[FD_METRICS_NETLNK_TOTAL];
6 changes: 4 additions & 2 deletions src/disco/metrics/metrics.xml
Original file line number Diff line number Diff line change
Expand Up @@ -642,8 +642,10 @@ metric introduced.
<counter name="Updates" enum="NetlinkMsg" summary="Number of netlink live updates processed" />
<gauge name="InterfaceCount" summary="Number of network interfaces" />
<gauge name="RouteCount" enum="RouteTable" summary="Number of IPv4 routes" />
<counter name="NeighborSolicitsSent" summary="Number of neighbor solicit requests sent to kernel" />
<counter name="NeighborSolicitsFails" summary="Number of neighbor solicit requests that failed to send" />
<counter name="NeighProbeSent" summary="Number of neighbor solicit requests sent to kernel" />
<counter name="NeighProbeFails" summary="Number of neighbor solicit requests that failed to send (kernel too slow)" />
<counter name="NeighProbeRateLimitHost" summary="Number of neighbor solicit that exceeded the per-host rate limit" />
<counter name="NeighProbeRateLimitGlobal" summary="Number of neighbor solicit that exceeded the global rate limit" />
</tile>

</metrics>
30 changes: 19 additions & 11 deletions src/disco/netlink/fd_netlink_tile.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@

#include <errno.h>
#include <net/if.h>
#include <netinet/in.h> /* MSG_DONTWAIT */
#include <sys/socket.h> /* SOL_{...} */
#include <sys/random.h> /* getrandom */
#include <sys/time.h> /* struct timeval */
#include <linux/rtnetlink.h> /* RTM_{...} */

#define FD_SOCKADDR_IN_SZ sizeof(struct sockaddr_in)
#include "generated/netlink_seccomp.h"

/* Hardcoded limits */
Expand Down Expand Up @@ -103,7 +105,7 @@ populate_allowed_seccomp( fd_topo_t const * topo,
struct sock_filter * out ) {
fd_netlink_tile_ctx_t * ctx = fd_topo_obj_laddr( topo, tile->tile_obj_id );
FD_TEST( ctx->magic==FD_NETLINK_TILE_CTX_MAGIC );
populate_sock_filter_policy_netlink( out_cnt, out, (uint)fd_log_private_logfile_fd(), (uint)ctx->nl_monitor->fd, (uint)ctx->nl_req->fd );
populate_sock_filter_policy_netlink( out_cnt, out, (uint)fd_log_private_logfile_fd(), (uint)ctx->nl_monitor->fd, (uint)ctx->nl_req->fd, (uint)ctx->prober->sock_fd );
return sock_filter_policy_netlink_instr_cnt;
}

Expand All @@ -115,14 +117,15 @@ populate_allowed_fds( fd_topo_t const * topo,
fd_netlink_tile_ctx_t * ctx = fd_topo_obj_laddr( topo, tile->tile_obj_id );
FD_TEST( ctx->magic==FD_NETLINK_TILE_CTX_MAGIC );

if( FD_UNLIKELY( out_fds_cnt<4UL ) ) FD_LOG_ERR(( "out_fds_cnt too low (%lu)", out_fds_cnt ));
if( FD_UNLIKELY( out_fds_cnt<5UL ) ) FD_LOG_ERR(( "out_fds_cnt too low (%lu)", out_fds_cnt ));

ulong out_cnt = 0UL;
out_fds[ out_cnt++ ] = 2; /* stderr */
if( FD_LIKELY( -1!=fd_log_private_logfile_fd() ) )
out_fds[ out_cnt++ ] = fd_log_private_logfile_fd(); /* logfile */
out_fds[ out_cnt++ ] = ctx->nl_monitor->fd;
out_fds[ out_cnt++ ] = ctx->nl_req->fd;
out_fds[ out_cnt++ ] = ctx->prober->sock_fd;
return out_cnt;
}

Expand Down Expand Up @@ -160,6 +163,11 @@ privileged_init( fd_topo_t * topo,
FD_LOG_ERR(( "bind(sock,RT_NETLINK,RTMGRP_{LINK,NEIGH,IPV4_ROUTE}) failed (%i-%s)", errno, fd_io_strerror( errno ) ));
}

float const max_probes_per_second = 3.f;
ulong const max_probe_burst = 128UL;
float const probe_delay_seconds = 15.f;
fd_neigh4_prober_init( ctx->prober, max_probes_per_second, max_probe_burst, probe_delay_seconds );

/* Set duration of blocking reads in before_credit */
struct timeval tv = { .tv_usec = 3753, }; /* 3.75ms */
if( FD_UNLIKELY( 0!=setsockopt( ctx->nl_monitor->fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval) ) ) ) {
Expand Down Expand Up @@ -219,8 +227,10 @@ metrics_write( fd_netlink_tile_ctx_t * ctx ) {
FD_MGAUGE_SET( NETLNK, INTERFACE_COUNT, ctx->netdev_tbl->hdr->dev_cnt );
FD_MGAUGE_SET( NETLNK, ROUTE_COUNT_LOCAL, fd_fib4_cnt( ctx->fib4_local ) );
FD_MGAUGE_SET( NETLNK, ROUTE_COUNT_MAIN, fd_fib4_cnt( ctx->fib4_main ) );
FD_MCNT_SET( NETLNK, NEIGHBOR_SOLICITS_SENT, ctx->metrics.neigh_solicits_sent );
FD_MCNT_SET( NETLNK, NEIGHBOR_SOLICITS_FAILS, ctx->metrics.neigh_solicits_fails );
FD_MCNT_SET( NETLNK, NEIGH_PROBE_SENT, ctx->metrics.neigh_solicits_sent );
FD_MCNT_SET( NETLNK, NEIGH_PROBE_FAILS, ctx->metrics.neigh_solicits_fails );
FD_MCNT_SET( NETLNK, NEIGH_PROBE_RATE_LIMIT_HOST, ctx->prober->local_rate_limited_cnt );
FD_MCNT_SET( NETLNK, NEIGH_PROBE_RATE_LIMIT_GLOBAL, ctx->prober->global_rate_limited_cnt );
}

/* netlink_monitor_read calls recvfrom to process a link, route, or
Expand Down Expand Up @@ -344,6 +354,7 @@ after_frag( fd_netlink_tile_ctx_t * ctx,
fd_stem_context_t * stem ) {
(void)in_idx; (void)seq; (void)tsorig; (void)stem;

long now = fd_tickcount();
ctx->idle_cnt = -1L;

/* Parse request (fully contained in sig field) */
Expand Down Expand Up @@ -386,16 +397,13 @@ after_frag( fd_netlink_tile_ctx_t * ctx,

/* Trigger neighbor solicit via netlink */

int netlink_res = fd_neigh4_netlink_solicit( ctx->nl_req, if_idx, ip4_addr );
if( FD_UNLIKELY( netlink_res!=0 ) ) {
FD_LOG_WARNING(( "`ip neigh add " FD_IP4_ADDR_FMT " dev %u use nud incomplete` failed (%i-%s)",
FD_IP4_ADDR_FMT_ARGS( ip4_addr ), if_idx, netlink_res, fd_io_strerror( netlink_res ) ));
int probe_res = fd_neigh4_probe_rate_limited( ctx->prober, ele, ip4_addr, now );
if( probe_res==0 ) {
ctx->metrics.neigh_solicits_sent++;
} else if( probe_res>0 ) {
ctx->metrics.neigh_solicits_fails++;
return;
}

ctx->metrics.neigh_solicits_sent++;

}

#define STEM_BURST (1UL)
Expand Down
4 changes: 4 additions & 0 deletions src/disco/netlink/fd_netlink_tile_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "../../waltz/mib/fd_dbl_buf.h"
#include "../../waltz/mib/fd_netdev_tbl.h"
#include "../../waltz/neigh/fd_neigh4_map.h"
#include "../../waltz/neigh/fd_neigh4_probe.h"

/* FD_NETLINK_TILE_CTX_MAGIC uniquely identifies a fd_netlink_tile_ctx_t.
CHange this whenever the fd_netlink_tile_ctx_t struct changes. */
Expand Down Expand Up @@ -45,6 +46,9 @@ struct fd_netlink_tile_ctx {
uint neigh4_ifidx;
long idle_cnt;

/* Neighbor table prober */
fd_neigh4_prober_t prober[1];

struct {
ulong link_full_syncs;
ulong route_full_syncs;
Expand Down
74 changes: 47 additions & 27 deletions src/disco/netlink/generated/netlink_seccomp.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@
#else
# error "Target architecture is unsupported by seccomp."
#endif
static const unsigned int sock_filter_policy_netlink_instr_cnt = 36;
static const unsigned int sock_filter_policy_netlink_instr_cnt = 46;

static void populate_sock_filter_policy_netlink( ulong out_cnt, struct sock_filter * out, unsigned int logfile_fd, unsigned int nl_mon_fd, unsigned int nl_req_fd) {
FD_TEST( out_cnt >= 36 );
struct sock_filter filter[36] = {
static void populate_sock_filter_policy_netlink( ulong out_cnt, struct sock_filter * out, uint logfile_fd, uint nl_mon_fd, uint nl_req_fd, uint arp_probe_fd) {
FD_TEST( out_cnt >= 46 );
struct sock_filter filter[46] = {
/* Check: Jump to RET_KILL_PROCESS if the script's arch != the runtime arch */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, ( offsetof( struct seccomp_data, arch ) ) ),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ARCH_NR, 0, /* RET_KILL_PROCESS */ 32 ),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, ARCH_NR, 0, /* RET_KILL_PROCESS */ 42 ),
/* loading syscall number in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, ( offsetof( struct seccomp_data, nr ) ) ),
/* allow write based on expression */
Expand All @@ -38,58 +38,78 @@ static void populate_sock_filter_policy_netlink( ulong out_cnt, struct sock_filt
/* allow sendto based on expression */
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_sendto, /* check_sendto */ 8, 0 ),
/* allow recvfrom based on expression */
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_recvfrom, /* check_recvfrom */ 15, 0 ),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, SYS_recvfrom, /* check_recvfrom */ 25, 0 ),
/* none of the syscalls matched */
{ BPF_JMP | BPF_JA, 0, 0, /* RET_KILL_PROCESS */ 26 },
{ BPF_JMP | BPF_JA, 0, 0, /* RET_KILL_PROCESS */ 36 },
// check_write:
/* load syscall argument 0 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_ALLOW */ 25, /* lbl_1 */ 0 ),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 2, /* RET_ALLOW */ 35, /* lbl_1 */ 0 ),
// lbl_1:
/* load syscall argument 0 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_ALLOW */ 23, /* RET_KILL_PROCESS */ 22 ),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_ALLOW */ 33, /* RET_KILL_PROCESS */ 32 ),
// check_fsync:
/* load syscall argument 0 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_ALLOW */ 21, /* RET_KILL_PROCESS */ 20 ),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, logfile_fd, /* RET_ALLOW */ 31, /* RET_KILL_PROCESS */ 30 ),
// check_sendto:
/* load syscall argument 0 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, nl_req_fd, /* lbl_2 */ 0, /* RET_KILL_PROCESS */ 18 ),
// lbl_2:
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, nl_req_fd, /* lbl_3 */ 0, /* lbl_2 */ 6 ),
// lbl_3:
/* load syscall argument 3 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[3])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* lbl_3 */ 0, /* RET_KILL_PROCESS */ 16 ),
// lbl_3:
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* lbl_4 */ 0, /* lbl_2 */ 4 ),
// lbl_4:
/* load syscall argument 4 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[4])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* lbl_4 */ 0, /* RET_KILL_PROCESS */ 14 ),
// lbl_4:
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* lbl_5 */ 0, /* lbl_2 */ 2 ),
// lbl_5:
/* load syscall argument 5 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[5])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* RET_ALLOW */ 13, /* RET_KILL_PROCESS */ 12 ),
// check_recvfrom:
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* RET_ALLOW */ 23, /* lbl_2 */ 0 ),
// lbl_2:
/* load syscall argument 0 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, nl_mon_fd, /* lbl_5 */ 2, /* lbl_6 */ 0 ),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, arp_probe_fd, /* lbl_6 */ 0, /* RET_KILL_PROCESS */ 20 ),
// lbl_6:
/* load syscall argument 1 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[1])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* lbl_7 */ 0, /* RET_KILL_PROCESS */ 18 ),
// lbl_7:
/* load syscall argument 2 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[2])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* lbl_8 */ 0, /* RET_KILL_PROCESS */ 16 ),
// lbl_8:
/* load syscall argument 3 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[3])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, MSG_DONTWAIT, /* lbl_9 */ 0, /* RET_KILL_PROCESS */ 14 ),
// lbl_9:
/* load syscall argument 5 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[5])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, FD_SOCKADDR_IN_SZ, /* RET_ALLOW */ 13, /* RET_KILL_PROCESS */ 12 ),
// check_recvfrom:
/* load syscall argument 0 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, nl_req_fd, /* lbl_5 */ 0, /* RET_KILL_PROCESS */ 8 ),
// lbl_5:
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, nl_mon_fd, /* lbl_10 */ 2, /* lbl_11 */ 0 ),
// lbl_11:
/* load syscall argument 0 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[0])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, nl_req_fd, /* lbl_10 */ 0, /* RET_KILL_PROCESS */ 8 ),
// lbl_10:
/* load syscall argument 3 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[3])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* lbl_7 */ 2, /* lbl_8 */ 0 ),
// lbl_8:
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* lbl_12 */ 2, /* lbl_13 */ 0 ),
// lbl_13:
/* load syscall argument 3 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[3])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, MSG_DONTWAIT, /* lbl_7 */ 0, /* RET_KILL_PROCESS */ 4 ),
// lbl_7:
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, MSG_DONTWAIT, /* lbl_12 */ 0, /* RET_KILL_PROCESS */ 4 ),
// lbl_12:
/* load syscall argument 4 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[4])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* lbl_9 */ 0, /* RET_KILL_PROCESS */ 2 ),
// lbl_9:
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* lbl_14 */ 0, /* RET_KILL_PROCESS */ 2 ),
// lbl_14:
/* load syscall argument 5 in accumulator */
BPF_STMT( BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[5])),
BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 0, /* RET_ALLOW */ 1, /* RET_KILL_PROCESS */ 0 ),
Expand Down
27 changes: 20 additions & 7 deletions src/disco/netlink/netlink.seccomppolicy
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
#
# nl_mon_fd: An rtnetlink socket used to monitor updates
# nl_req_fd: An rtnetlink socket used for request-reply
unsigned int logfile_fd, unsigned int nl_mon_fd, unsigned int nl_req_fd
# arp_probe_fd: A UDP socket used to indirectly generate ARP probes
uint logfile_fd, uint nl_mon_fd, uint nl_req_fd, uint arp_probe_fd

# logging: all log messages are written to a file and/or pipe
#
Expand All @@ -21,14 +22,26 @@ write: (or (eq (arg 0) 2)
# descriptor 3 is always the logfile.
fsync: (eq (arg 0) logfile_fd)

# sendto(2) is used to send netlink requests to the kernel
# nl_req_fd: Periodically send read-only/unprivileged rtnetlink requests
#
# arp_probe_fd: Send UDP packets that cause the kernel to generate ARP
# requests
#
# (In theory could use send(2) but that syscall doesn't exist on arm64)
sendto: (and (eq (arg 0) nl_req_fd)
(eq (arg 3) 0)
(eq (arg 4) 0)
(eq (arg 5) 0))
sendto: (or (and (eq (arg 0) nl_req_fd)
(eq (arg 3) 0)
(eq (arg 4) 0)
(eq (arg 5) 0))
(and (eq (arg 0) arp_probe_fd)
(eq (arg 1) 0)
(eq (arg 2) 0)
(eq (arg 3) MSG_DONTWAIT)
(eq (arg 5) FD_SOCKADDR_IN_SZ)))

# recvfrom(2) is used to receive netlink responses from the kernel
# nl_mon_fd: Monitor for asynchronous rtnetlink updates
#
# nl_req_fd: Read replies to rtnetlink requests
#
# (Using recvfrom(2) instead of recv(2) for same ABI reasons as above)
recvfrom: (and (or (eq (arg 0) nl_mon_fd)
(eq (arg 0) nl_req_fd))
Expand Down
Loading

0 comments on commit 229ec83

Please sign in to comment.