Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Add strict alignment flag for BPF_PROG_LOAD.

Add a new field, "prog_flags", and an initial flag value
BPF_F_STRICT_ALIGNMENT.

When set, the verifier will enforce strict pointer alignment
regardless of the setting of CONFIG_EFFICIENT_UNALIGNED_ACCESS.

The verifier, in this mode, will also use a fixed value of "2" in
place of NET_IP_ALIGN.

This facilitates test cases that will exercise and validate this part
of the verifier even when run on architectures where alignment doesn't
matter.

Signed-off-by: David S. Miller <davem@davemloft.net>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>

+40 -9
+1
include/linux/bpf_verifier.h
··· 90 90 struct bpf_prog *prog; /* eBPF program being verified */ 91 91 struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */ 92 92 int stack_size; /* number of states to be processed */ 93 + bool strict_alignment; /* perform strict pointer alignment checks */ 93 94 struct bpf_verifier_state cur_state; /* current verifier state */ 94 95 struct bpf_verifier_state_list **explored_states; /* search pruning optimization */ 95 96 const struct bpf_ext_analyzer_ops *analyzer_ops; /* external analyzer ops */
+8
include/uapi/linux/bpf.h
··· 132 132 */ 133 133 #define BPF_F_ALLOW_OVERRIDE (1U << 0) 134 134 135 + /* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the 136 + * verifier will perform strict alignment checking as if the kernel 137 + * has been built with CONFIG_EFFICIENT_UNALIGNED_ACCESS not set, 138 + * and NET_IP_ALIGN defined to 2. 139 + */ 140 + #define BPF_F_STRICT_ALIGNMENT (1U << 0) 141 + 135 142 #define BPF_PSEUDO_MAP_FD 1 136 143 137 144 /* flags for BPF_MAP_UPDATE_ELEM command */ ··· 184 177 __u32 log_size; /* size of user buffer */ 185 178 __aligned_u64 log_buf; /* user supplied buffer */ 186 179 __u32 kern_version; /* checked when prog_type=kprobe */ 180 + __u32 prog_flags; 187 181 }; 188 182 189 183 struct { /* anonymous struct used by BPF_OBJ_* commands */
+4 -1
kernel/bpf/syscall.c
··· 783 783 EXPORT_SYMBOL_GPL(bpf_prog_get_type); 784 784 785 785 /* last field in 'union bpf_attr' used by this command */ 786 - #define BPF_PROG_LOAD_LAST_FIELD kern_version 786 + #define BPF_PROG_LOAD_LAST_FIELD prog_flags 787 787 788 788 static int bpf_prog_load(union bpf_attr *attr) 789 789 { ··· 794 794 bool is_gpl; 795 795 796 796 if (CHECK_ATTR(BPF_PROG_LOAD)) 797 + return -EINVAL; 798 + 799 + if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT) 797 800 return -EINVAL; 798 801 799 802 /* copy eBPF program license from user space */
+17 -6
kernel/bpf/verifier.c
··· 791 791 static int check_pkt_ptr_alignment(const struct bpf_reg_state *reg, 792 792 int off, int size, bool strict) 793 793 { 794 + int ip_align; 794 795 int reg_off; 795 796 796 797 /* Byte size accesses are always allowed. */ ··· 808 807 reg_off += reg->aux_off; 809 808 } 810 809 811 - /* skb->data is NET_IP_ALIGN-ed */ 812 - if ((NET_IP_ALIGN + reg_off + off) % size != 0) { 810 + /* skb->data is NET_IP_ALIGN-ed, but for strict alignment checking 811 + * we force this to 2 which is universally what architectures use 812 + * when they don't set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS. 813 + */ 814 + ip_align = strict ? 2 : NET_IP_ALIGN; 815 + if ((ip_align + reg_off + off) % size != 0) { 813 816 verbose("misaligned packet access off %d+%d+%d size %d\n", 814 - NET_IP_ALIGN, reg_off, off, size); 817 + ip_align, reg_off, off, size); 815 818 return -EACCES; 816 819 } 817 820 ··· 833 828 return 0; 834 829 } 835 830 836 - static int check_ptr_alignment(const struct bpf_reg_state *reg, 831 + static int check_ptr_alignment(struct bpf_verifier_env *env, 832 + const struct bpf_reg_state *reg, 837 833 int off, int size) 838 834 { 839 - bool strict = false; 835 + bool strict = env->strict_alignment; 840 836 841 837 if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) 842 838 strict = true; ··· 879 873 if (size < 0) 880 874 return size; 881 875 882 - err = check_ptr_alignment(reg, off, size); 876 + err = check_ptr_alignment(env, reg, off, size); 883 877 if (err) 884 878 return err; 885 879 ··· 3574 3568 } else { 3575 3569 log_level = 0; 3576 3570 } 3571 + if (attr->prog_flags & BPF_F_STRICT_ALIGNMENT) 3572 + env->strict_alignment = true; 3573 + else 3574 + env->strict_alignment = false; 3577 3575 3578 3576 ret = replace_map_fd_with_map_ptr(env); 3579 3577 if (ret < 0) ··· 3683 3673 mutex_lock(&bpf_verifier_lock); 3684 3674 3685 3675 log_level = 0; 3676 + env->strict_alignment = false; 3686 3677 3687 3678 env->explored_states = kcalloc(env->prog->len, 3688 3679 sizeof(struct bpf_verifier_state_list *),
+1
tools/build/feature/test-bpf.c
··· 29 29 attr.log_size = 0; 30 30 attr.log_level = 0; 31 31 attr.kern_version = 0; 32 + attr.prog_flags = 0; 32 33 33 34 /* 34 35 * Test existence of __NR_bpf and BPF_PROG_LOAD.
+9 -2
tools/include/uapi/linux/bpf.h
··· 132 132 */ 133 133 #define BPF_F_ALLOW_OVERRIDE (1U << 0) 134 134 135 + /* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the 136 + * verifier will perform strict alignment checking as if the kernel 137 + * has been built with CONFIG_EFFICIENT_UNALIGNED_ACCESS not set, 138 + * and NET_IP_ALIGN defined to 2. 139 + */ 140 + #define BPF_F_STRICT_ALIGNMENT (1U << 0) 141 + 135 142 #define BPF_PSEUDO_MAP_FD 1 136 143 137 144 /* flags for BPF_MAP_UPDATE_ELEM command */ ··· 184 177 __u32 log_size; /* size of user buffer */ 185 178 __aligned_u64 log_buf; /* user supplied buffer */ 186 179 __u32 kern_version; /* checked when prog_type=kprobe */ 180 + __u32 prog_flags; 187 181 }; 188 182 189 183 struct { /* anonymous struct used by BPF_OBJ_* commands */ ··· 489 481 * u32 bpf_get_socket_uid(skb) 490 482 * Get the owner uid of the socket stored inside sk_buff. 491 483 * @skb: pointer to skb 492 - * Return: uid of the socket owner on success or 0 if the socket pointer 493 - * inside sk_buff is NULL 484 + * Return: uid of the socket owner on success or overflowuid if failed. 494 485 */ 495 486 #define __BPF_FUNC_MAPPER(FN) \ 496 487 FN(unspec), \