Subject: [RFC net-next 18/18] virtio_net: restrict bpf helper calls from offloaded program

From: Prashant Bhole <[email-masked]>
Date: Tue, 26 Nov 2019 19:07:44 +0900

Since we are offloading this program to the host, some of the helper
calls will not make sense. For example get_numa_node_id. Some helpers
can not be used because we don't handle them yet.

So let's allow a small set of helper calls for now.

Signed-off-by: Prashant Bhole <[email-masked]>
---
 drivers/net/virtio_net.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 91a94b787c64..ab5be6b95bbd 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2549,6 +2549,25 @@ static struct virtnet_bpf_map *virtnet_get_bpf_map(struct virtnet_info *vi,
 	return NULL;
 }
 
+static int virtnet_bpf_check_helper_call(struct bpf_insn *insn)
+{
+	switch (insn->imm) {
+	case BPF_FUNC_map_lookup_elem:
+	case BPF_FUNC_map_update_elem:
+	case BPF_FUNC_map_delete_elem:
+	case BPF_FUNC_ktime_get_ns:
+	case BPF_FUNC_get_prandom_u32:
+	case BPF_FUNC_csum_update:
+	case BPF_FUNC_xdp_adjust_head:
+	case BPF_FUNC_xdp_adjust_meta:
+	case BPF_FUNC_xdp_adjust_tail:
+	case BPF_FUNC_strtol:
+	case BPF_FUNC_strtoul:
+		return 0;
+	}
+	return -EOPNOTSUPP;
+}
+
 static int virtnet_bpf_verify_insn(struct bpf_verifier_env *env, int insn_idx,
 				   int prev_insn)
 {
@@ -2830,6 +2849,7 @@ static int virtnet_bpf_verifier_setup(struct bpf_prog *prog)
 	struct virtnet_bpf_bound_prog *state;
 	struct virtnet_bpf_map *virtnet_map;
 	struct bpf_map *map;
+	u8 opcode, class;
 	struct fd mapfd;
 	int i, err = 0;
 
@@ -2846,6 +2866,16 @@ static int virtnet_bpf_verifier_setup(struct bpf_prog *prog)
 	for (i = 0; i < state->len; i++) {
 		struct bpf_insn *insn = &state->insnsi[i];
 
+		opcode = BPF_OP(insn->code);
+		class = BPF_CLASS(insn->code);
+
+		if ((class == BPF_JMP || class == BPF_JMP32) &&
+		    opcode == BPF_CALL && insn->src_reg != BPF_PSEUDO_CALL) {
+			if (virtnet_bpf_check_helper_call(insn))
+				return -EOPNOTSUPP;
+			continue;
+		}
+
 		if (insn->code != (BPF_LD | BPF_IMM | BPF_DW))
 			continue;
 
-- 
2.20.1