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

Showing the changes to kernel (2 of 6 files). Show all

Unified · Split

2 files
  1. kernel/bpf/syscall.c +4 −1
  2. kernel/bpf/verifier.c +17 −6
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
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_version786#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) · 6 unmodified lines
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)
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
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, · 10 unmodified lines
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, · 11 unmodified lines
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, · 35 unmodified lines
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) · 2688 unmodified lines
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, · 99 unmodified lines
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 *),

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