History

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.

David S. Miller committed 9 years ago

Commit e07b98d1 parent c5fc9696 files · +40 −9Browse files

Unified · Split

6 files
  1. include/linux/bpf_verifier.h +1 −0
  2. include/uapi/linux/bpf.h +8 −0
  3. kernel/bpf/syscall.c +4 −1
  4. kernel/bpf/verifier.c +17 −6
  5. tools/build/feature/test-bpf.c +1 −0
  6. tools/include/uapi/linux/bpf.h +9 −2
include/linux/bpf_verifier.h+1−0
@@ -90,6 +90,7 @@ struct bpf_verifier_env { · 89 unmodified lines
9090 struct bpf_prog *prog; /* eBPF program being verified */
9191 struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */
9292 int stack_size; /* number of states to be processed */
93+ bool strict_alignment; /* perform strict pointer alignment checks */
9394 struct bpf_verifier_state cur_state; /* current verifier state */
9495 struct bpf_verifier_state_list **explored_states; /* search pruning optimization */
9596 const struct bpf_ext_analyzer_ops *analyzer_ops; /* external analyzer ops */
include/uapi/linux/bpf.h+8−0
@@ -132,6 +132,13 @@ enum bpf_attach_type { · 131 unmodified lines
132132 */
133133 #define BPF_F_ALLOW_OVERRIDE (1U << 0)
134134
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+
135142 #define BPF_PSEUDO_MAP_FD 1
136143
137144 /* flags for BPF_MAP_UPDATE_ELEM command */
@@ -177,6 +184,7 @@ union bpf_attr { · 39 unmodified lines
177184 __u32 log_size; /* size of user buffer */
178185 __aligned_u64 log_buf; /* user supplied buffer */
179186 __u32 kern_version; /* checked when prog_type=kprobe */
187+ __u32 prog_flags;
180188 };
181189
182190 struct { /* anonymous struct used by BPF_OBJ_* commands */
kernel/bpf/syscall.c+4−1
@@ -783,7 +783,7 @@ struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type) · 782 unmodified lines
783783 EXPORT_SYMBOL_GPL(bpf_prog_get_type);
784784
785785 /* 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
787787
788788 static int bpf_prog_load(union bpf_attr *attr)
789789 {
@@ -796,6 +796,9 @@ static int bpf_prog_load(union bpf_attr *attr) · 6 unmodified lines
796796 if (CHECK_ATTR(BPF_PROG_LOAD))
797797 return -EINVAL;
798798
799+ if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT)
800+ return -EINVAL;
801+
799802 /* copy eBPF program license from user space */
800803 if (strncpy_from_user(license, u64_to_user_ptr(attr->license),
801804 sizeof(license) - 1) < 0)
kernel/bpf/verifier.c+17−6
@@ -791,6 +791,7 @@ static bool is_pointer_value(struct bpf_verifier_env *env, int regno) · 790 unmodified lines
791791 static int check_pkt_ptr_alignment(const struct bpf_reg_state *reg,
792792 int off, int size, bool strict)
793793 {
794+ int ip_align;
794795 int reg_off;
795796
796797 /* Byte size accesses are always allowed. */
@@ -807,10 +808,14 @@ static int check_pkt_ptr_alignment(const struct bpf_reg_state *reg, · 10 unmodified lines
807808 reg_off += reg->aux_off;
808809 }
809810
810− /* skb->data is NET_IP_ALIGN-ed */
811− if ((NET_IP_ALIGN + reg_off + off) % size != 0) {
811+ /* skb->data is NET_IP_ALIGN-ed, but for strict alignment checking
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) {
812817 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);
814819 return -EACCES;
815820 }
816821
@@ -828,10 +833,11 @@ static int check_val_ptr_alignment(const struct bpf_reg_state *reg, · 11 unmodified lines
828833 return 0;
829834 }
830835
831−static int check_ptr_alignment(const struct bpf_reg_state *reg,
836+static int check_ptr_alignment(struct bpf_verifier_env *env,
837+ const struct bpf_reg_state *reg,
832838 int off, int size)
833839 {
834− bool strict = false;
840+ bool strict = env->strict_alignment;
835841
836842 if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
837843 strict = true;
@@ -873,7 +879,7 @@ static int check_mem_access(struct bpf_verifier_env *env, u32 regno, int off, · 35 unmodified lines
873879 if (size < 0)
874880 return size;
875881
876− err = check_ptr_alignment(reg, off, size);
882+ err = check_ptr_alignment(env, reg, off, size);
877883 if (err)
878884 return err;
879885
@@ -3568,6 +3574,10 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr) · 2688 unmodified lines
35683574 } else {
35693575 log_level = 0;
35703576 }
3577+ if (attr->prog_flags & BPF_F_STRICT_ALIGNMENT)
3578+ env->strict_alignment = true;
3579+ else
3580+ env->strict_alignment = false;
35713581
35723582 ret = replace_map_fd_with_map_ptr(env);
35733583 if (ret < 0)
@@ -3673,6 +3683,7 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops, · 99 unmodified lines
36733683 mutex_lock(&bpf_verifier_lock);
36743684
36753685 log_level = 0;
3686+ env->strict_alignment = false;
36763687
36773688 env->explored_states = kcalloc(env->prog->len,
36783689 sizeof(struct bpf_verifier_state_list *),
tools/build/feature/test-bpf.c+1−0
@@ -29,6 +29,7 @@ int main(void) · 28 unmodified lines
2929 attr.log_size = 0;
3030 attr.log_level = 0;
3131 attr.kern_version = 0;
32+ attr.prog_flags = 0;
3233
3334 /*
3435 * Test existence of __NR_bpf and BPF_PROG_LOAD.
tools/include/uapi/linux/bpf.h+9−2
@@ -132,6 +132,13 @@ enum bpf_attach_type { · 131 unmodified lines
132132 */
133133 #define BPF_F_ALLOW_OVERRIDE (1U << 0)
134134
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+
135142 #define BPF_PSEUDO_MAP_FD 1
136143
137144 /* flags for BPF_MAP_UPDATE_ELEM command */
@@ -177,6 +184,7 @@ union bpf_attr { · 39 unmodified lines
177184 __u32 log_size; /* size of user buffer */
178185 __aligned_u64 log_buf; /* user supplied buffer */
179186 __u32 kern_version; /* checked when prog_type=kprobe */
187+ __u32 prog_flags;
180188 };
181189
182190 struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -481,8 +489,7 @@ union bpf_attr { · 298 unmodified lines
481489 * u32 bpf_get_socket_uid(skb)
482490 * Get the owner uid of the socket stored inside sk_buff.
483491 * @skb: pointer to skb
484− * Return: uid of the socket owner on success or 0 if the socket pointer
485− * inside sk_buff is NULL
492+ * Return: uid of the socket owner on success or overflowuid if failed.
486493 */
487494 #define __BPF_FUNC_MAPPER(FN) \
488495 FN(unspec), \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t