| 750 | } |
| 751 | |
| 752 | static const char * |
| 753 | eval_ptr(struct bpf_verifier *bvf, struct bpf_reg_val *rm, uint32_t opsz, |
| 754 | uint32_t align, int16_t off) |
| 755 | { |
| 756 | struct bpf_reg_val rv; |
| 757 | |
| 758 | /* calculate reg + offset */ |
| 759 | eval_fill_imm(&rv, rm->mask, off); |
| 760 | eval_add(rm, &rv, rm->mask); |
| 761 | |
| 762 | if (RTE_BPF_ARG_PTR_TYPE(rm->v.type) == 0) |
| 763 | return "destination is not a pointer"; |
| 764 | |
| 765 | if (rm->mask != UINT64_MAX) |
| 766 | return "pointer truncation"; |
| 767 | |
| 768 | if (rm->u.max + opsz > rm->v.size || |
| 769 | (uint64_t)rm->s.max + opsz > rm->v.size || |
| 770 | rm->s.min < 0) |
| 771 | return "memory boundary violation"; |
| 772 | |
| 773 | if (rm->u.max % align != 0) |
| 774 | return "unaligned memory access"; |
| 775 | |
| 776 | if (rm->v.type == BPF_ARG_PTR_STACK) { |
| 777 | |
| 778 | if (rm->u.max != rm->u.min || rm->s.max != rm->s.min || |
| 779 | rm->u.max != (uint64_t)rm->s.max) |
| 780 | return "stack access with variable offset"; |
| 781 | |
| 782 | bvf->stack_sz = RTE_MAX(bvf->stack_sz, rm->v.size - rm->u.max); |
| 783 | |
| 784 | /* pointer to mbuf */ |
| 785 | } else if (rm->v.type == RTE_BPF_ARG_PTR_MBUF) { |
| 786 | |
| 787 | if (rm->u.max != rm->u.min || rm->s.max != rm->s.min || |
| 788 | rm->u.max != (uint64_t)rm->s.max) |
| 789 | return "mbuf access with variable offset"; |
| 790 | } |
| 791 | |
| 792 | return NULL; |
| 793 | } |
| 794 | |
| 795 | static void |
| 796 | eval_max_load(struct bpf_reg_val *rv, uint64_t mask) |
no test coverage detected