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 <prashantbhole.li...@gmail.com>
---
 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


Reply via email to