aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-05-10 14:38:07 -0400
committerDavid S. Miller <davem@davemloft.net>2017-05-11 14:19:00 -0400
commite07b98d9bffe410019dfcf62c3428d4a96c56a2c (patch)
tree52a3aede39b1bac6a409586bcdd272d9aa958868
parentc5fc9692d101d1318b0f53f9f691cd88ac029317 (diff)
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>
-rw-r--r--include/linux/bpf_verifier.h1
-rw-r--r--include/uapi/linux/bpf.h8
-rw-r--r--kernel/bpf/syscall.c5
-rw-r--r--kernel/bpf/verifier.c23
-rw-r--r--tools/build/feature/test-bpf.c1
-rw-r--r--tools/include/uapi/linux/bpf.h11
6 files changed, 40 insertions, 9 deletions
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 7c6a51924afc..d5093b52b485 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -90,6 +90,7 @@ struct bpf_verifier_env {
90 struct bpf_prog *prog; /* eBPF program being verified */ 90 struct bpf_prog *prog; /* eBPF program being verified */
91 struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */ 91 struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */
92 int stack_size; /* number of states to be processed */ 92 int stack_size; /* number of states to be processed */
93 bool strict_alignment; /* perform strict pointer alignment checks */
93 struct bpf_verifier_state cur_state; /* current verifier state */ 94 struct bpf_verifier_state cur_state; /* current verifier state */
94 struct bpf_verifier_state_list **explored_states; /* search pruning optimization */ 95 struct bpf_verifier_state_list **explored_states; /* search pruning optimization */
95 const struct bpf_ext_analyzer_ops *analyzer_ops; /* external analyzer ops */ 96 const struct bpf_ext_analyzer_ops *analyzer_ops; /* external analyzer ops */
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 945a1f5f63c5..94dfa9def355 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -132,6 +132,13 @@ enum bpf_attach_type {
132 */ 132 */
133#define BPF_F_ALLOW_OVERRIDE (1U << 0) 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#define BPF_PSEUDO_MAP_FD 1 142#define BPF_PSEUDO_MAP_FD 1
136 143
137/* flags for BPF_MAP_UPDATE_ELEM command */ 144/* flags for BPF_MAP_UPDATE_ELEM command */
@@ -177,6 +184,7 @@ union bpf_attr {
177 __u32 log_size; /* size of user buffer */ 184 __u32 log_size; /* size of user buffer */
178 __aligned_u64 log_buf; /* user supplied buffer */ 185 __aligned_u64 log_buf; /* user supplied buffer */
179 __u32 kern_version; /* checked when prog_type=kprobe */ 186 __u32 kern_version; /* checked when prog_type=kprobe */
187 __u32 prog_flags;
180 }; 188 };
181 189
182 struct { /* anonymous struct used by BPF_OBJ_* commands */ 190 struct { /* anonymous struct used by BPF_OBJ_* commands */
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index fd2411fd6914..265a0d854e33 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -783,7 +783,7 @@ struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
783EXPORT_SYMBOL_GPL(bpf_prog_get_type); 783EXPORT_SYMBOL_GPL(bpf_prog_get_type);
784 784
785/* last field in 'union bpf_attr' used by this command */ 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
788static int bpf_prog_load(union bpf_attr *attr) 788static int bpf_prog_load(union bpf_attr *attr)
789{ 789{
@@ -796,6 +796,9 @@ static int bpf_prog_load(union bpf_attr *attr)
796 if (CHECK_ATTR(BPF_PROG_LOAD)) 796 if (CHECK_ATTR(BPF_PROG_LOAD))
797 return -EINVAL; 797 return -EINVAL;
798 798
799 if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT)
800 return -EINVAL;
801
799 /* copy eBPF program license from user space */ 802 /* copy eBPF program license from user space */
800 if (strncpy_from_user(license, u64_to_user_ptr(attr->license), 803 if (strncpy_from_user(license, u64_to_user_ptr(attr->license),
801 sizeof(license) - 1) < 0) 804 sizeof(license) - 1) < 0)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index ff2bfe1d656a..e74fb1b87855 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -791,6 +791,7 @@ static bool is_pointer_value(struct bpf_verifier_env *env, int regno)
791static int check_pkt_ptr_alignment(const struct bpf_reg_state *reg, 791static int check_pkt_ptr_alignment(const struct bpf_reg_state *reg,
792 int off, int size, bool strict) 792 int off, int size, bool strict)
793{ 793{
794 int ip_align;
794 int reg_off; 795 int reg_off;
795 796
796 /* Byte size accesses are always allowed. */ 797 /* Byte size accesses are always allowed. */
@@ -807,10 +808,14 @@ static int check_pkt_ptr_alignment(const struct bpf_reg_state *reg,
807 reg_off += reg->aux_off; 808 reg_off += reg->aux_off;
808 } 809 }
809 810
810 /* skb->data is NET_IP_ALIGN-ed */ 811 /* skb->data is NET_IP_ALIGN-ed, but for strict alignment checking
811 if ((NET_IP_ALIGN + reg_off + off) % size != 0) { 812 * we force this to 2 which is universally what architectures use
813 * when they don't set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS.
814 */
815 ip_align = strict ? 2 : NET_IP_ALIGN;
816 if ((ip_align + reg_off + off) % size != 0) {
812 verbose("misaligned packet access off %d+%d+%d size %d\n", 817 verbose("misaligned packet access off %d+%d+%d size %d\n",
813 NET_IP_ALIGN, reg_off, off, size); 818 ip_align, reg_off, off, size);
814 return -EACCES; 819 return -EACCES;
815 } 820 }
816 821
@@ -828,10 +833,11 @@ static int check_val_ptr_alignment(const struct bpf_reg_state *reg,
828 return 0; 833 return 0;
829} 834}
830 835
831static int check_ptr_alignment(const struct bpf_reg_state *reg, 836static int check_ptr_alignment(struct bpf_verifier_env *env,
837 const struct bpf_reg_state *reg,
832 int off, int size) 838 int off, int size)
833{ 839{
834 bool strict = false; 840 bool strict = env->strict_alignment;
835 841
836 if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) 842 if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
837 strict = true; 843 strict = true;
@@ -873,7 +879,7 @@ static int check_mem_access(struct bpf_verifier_env *env, u32 regno, int off,
873 if (size < 0) 879 if (size < 0)
874 return size; 880 return size;
875 881
876 err = check_ptr_alignment(reg, off, size); 882 err = check_ptr_alignment(env, reg, off, size);
877 if (err) 883 if (err)
878 return err; 884 return err;
879 885
@@ -3568,6 +3574,10 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
3568 } else { 3574 } else {
3569 log_level = 0; 3575 log_level = 0;
3570 } 3576 }
3577 if (attr->prog_flags & BPF_F_STRICT_ALIGNMENT)
3578 env->strict_alignment = true;
3579 else
3580 env->strict_alignment = false;
3571 3581
3572 ret = replace_map_fd_with_map_ptr(env); 3582 ret = replace_map_fd_with_map_ptr(env);
3573 if (ret < 0) 3583 if (ret < 0)
@@ -3673,6 +3683,7 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
3673 mutex_lock(&bpf_verifier_lock); 3683 mutex_lock(&bpf_verifier_lock);
3674 3684
3675 log_level = 0; 3685 log_level = 0;
3686 env->strict_alignment = false;
3676 3687
3677 env->explored_states = kcalloc(env->prog->len, 3688 env->explored_states = kcalloc(env->prog->len,
3678 sizeof(struct bpf_verifier_state_list *), 3689 sizeof(struct bpf_verifier_state_list *),
diff --git a/tools/build/feature/test-bpf.c b/tools/build/feature/test-bpf.c
index ebc6dceddb58..7598361ef1f1 100644
--- a/tools/build/feature/test-bpf.c
+++ b/tools/build/feature/test-bpf.c
@@ -29,6 +29,7 @@ int main(void)
29 attr.log_size = 0; 29 attr.log_size = 0;
30 attr.log_level = 0; 30 attr.log_level = 0;
31 attr.kern_version = 0; 31 attr.kern_version = 0;
32 attr.prog_flags = 0;
32 33
33 /* 34 /*
34 * Test existence of __NR_bpf and BPF_PROG_LOAD. 35 * Test existence of __NR_bpf and BPF_PROG_LOAD.
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index e553529929f6..94dfa9def355 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -132,6 +132,13 @@ enum bpf_attach_type {
132 */ 132 */
133#define BPF_F_ALLOW_OVERRIDE (1U << 0) 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#define BPF_PSEUDO_MAP_FD 1 142#define BPF_PSEUDO_MAP_FD 1
136 143
137/* flags for BPF_MAP_UPDATE_ELEM command */ 144/* flags for BPF_MAP_UPDATE_ELEM command */
@@ -177,6 +184,7 @@ union bpf_attr {
177 __u32 log_size; /* size of user buffer */ 184 __u32 log_size; /* size of user buffer */
178 __aligned_u64 log_buf; /* user supplied buffer */ 185 __aligned_u64 log_buf; /* user supplied buffer */
179 __u32 kern_version; /* checked when prog_type=kprobe */ 186 __u32 kern_version; /* checked when prog_type=kprobe */
187 __u32 prog_flags;
180 }; 188 };
181 189
182 struct { /* anonymous struct used by BPF_OBJ_* commands */ 190 struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -481,8 +489,7 @@ union bpf_attr {
481 * u32 bpf_get_socket_uid(skb) 489 * u32 bpf_get_socket_uid(skb)
482 * Get the owner uid of the socket stored inside sk_buff. 490 * Get the owner uid of the socket stored inside sk_buff.
483 * @skb: pointer to skb 491 * @skb: pointer to skb
484 * Return: uid of the socket owner on success or 0 if the socket pointer 492 * Return: uid of the socket owner on success or overflowuid if failed.
485 * inside sk_buff is NULL
486 */ 493 */
487#define __BPF_FUNC_MAPPER(FN) \ 494#define __BPF_FUNC_MAPPER(FN) \
488 FN(unspec), \ 495 FN(unspec), \