Commit 228b0324 authored by David S. Miller's avatar David S. Miller

Merge branch 'bpf-pkt-ptr-align'

David S. Miller says:

====================
bpf: Add alignment tracker to verifier.

First we add the alignment tracking logic to the verifier.

Next, we work on building up infrastructure to facilitate regression
testing of this facility.

Finally, we add the "test_align" test case.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d8b54110 18b3ad90
...@@ -40,6 +40,9 @@ struct bpf_reg_state { ...@@ -40,6 +40,9 @@ struct bpf_reg_state {
*/ */
s64 min_value; s64 min_value;
u64 max_value; u64 max_value;
u32 min_align;
u32 aux_off;
u32 aux_off_align;
}; };
enum bpf_stack_slot_type { enum bpf_stack_slot_type {
...@@ -87,6 +90,7 @@ struct bpf_verifier_env { ...@@ -87,6 +90,7 @@ struct bpf_verifier_env {
struct bpf_prog *prog; /* eBPF program being verified */ struct bpf_prog *prog; /* eBPF program being verified */
struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */ struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */
int stack_size; /* number of states to be processed */ int stack_size; /* number of states to be processed */
bool strict_alignment; /* perform strict pointer alignment checks */
struct bpf_verifier_state cur_state; /* current verifier state */ struct bpf_verifier_state cur_state; /* current verifier state */
struct bpf_verifier_state_list **explored_states; /* search pruning optimization */ struct bpf_verifier_state_list **explored_states; /* search pruning optimization */
const struct bpf_ext_analyzer_ops *analyzer_ops; /* external analyzer ops */ const struct bpf_ext_analyzer_ops *analyzer_ops; /* external analyzer ops */
......
...@@ -132,6 +132,13 @@ enum bpf_attach_type { ...@@ -132,6 +132,13 @@ enum bpf_attach_type {
*/ */
#define BPF_F_ALLOW_OVERRIDE (1U << 0) #define BPF_F_ALLOW_OVERRIDE (1U << 0)
/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
* verifier will perform strict alignment checking as if the kernel
* has been built with CONFIG_EFFICIENT_UNALIGNED_ACCESS not set,
* and NET_IP_ALIGN defined to 2.
*/
#define BPF_F_STRICT_ALIGNMENT (1U << 0)
#define BPF_PSEUDO_MAP_FD 1 #define BPF_PSEUDO_MAP_FD 1
/* flags for BPF_MAP_UPDATE_ELEM command */ /* flags for BPF_MAP_UPDATE_ELEM command */
...@@ -177,6 +184,7 @@ union bpf_attr { ...@@ -177,6 +184,7 @@ union bpf_attr {
__u32 log_size; /* size of user buffer */ __u32 log_size; /* size of user buffer */
__aligned_u64 log_buf; /* user supplied buffer */ __aligned_u64 log_buf; /* user supplied buffer */
__u32 kern_version; /* checked when prog_type=kprobe */ __u32 kern_version; /* checked when prog_type=kprobe */
__u32 prog_flags;
}; };
struct { /* anonymous struct used by BPF_OBJ_* commands */ struct { /* anonymous struct used by BPF_OBJ_* commands */
......
...@@ -783,7 +783,7 @@ struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type) ...@@ -783,7 +783,7 @@ struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
EXPORT_SYMBOL_GPL(bpf_prog_get_type); EXPORT_SYMBOL_GPL(bpf_prog_get_type);
/* last field in 'union bpf_attr' used by this command */ /* last field in 'union bpf_attr' used by this command */
#define BPF_PROG_LOAD_LAST_FIELD kern_version #define BPF_PROG_LOAD_LAST_FIELD prog_flags
static int bpf_prog_load(union bpf_attr *attr) static int bpf_prog_load(union bpf_attr *attr)
{ {
...@@ -796,6 +796,9 @@ static int bpf_prog_load(union bpf_attr *attr) ...@@ -796,6 +796,9 @@ static int bpf_prog_load(union bpf_attr *attr)
if (CHECK_ATTR(BPF_PROG_LOAD)) if (CHECK_ATTR(BPF_PROG_LOAD))
return -EINVAL; return -EINVAL;
if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT)
return -EINVAL;
/* copy eBPF program license from user space */ /* copy eBPF program license from user space */
if (strncpy_from_user(license, u64_to_user_ptr(attr->license), if (strncpy_from_user(license, u64_to_user_ptr(attr->license),
sizeof(license) - 1) < 0) sizeof(license) - 1) < 0)
......
This diff is collapsed.
...@@ -29,6 +29,7 @@ int main(void) ...@@ -29,6 +29,7 @@ int main(void)
attr.log_size = 0; attr.log_size = 0;
attr.log_level = 0; attr.log_level = 0;
attr.kern_version = 0; attr.kern_version = 0;
attr.prog_flags = 0;
/* /*
* Test existence of __NR_bpf and BPF_PROG_LOAD. * Test existence of __NR_bpf and BPF_PROG_LOAD.
......
...@@ -132,6 +132,13 @@ enum bpf_attach_type { ...@@ -132,6 +132,13 @@ enum bpf_attach_type {
*/ */
#define BPF_F_ALLOW_OVERRIDE (1U << 0) #define BPF_F_ALLOW_OVERRIDE (1U << 0)
/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
* verifier will perform strict alignment checking as if the kernel
* has been built with CONFIG_EFFICIENT_UNALIGNED_ACCESS not set,
* and NET_IP_ALIGN defined to 2.
*/
#define BPF_F_STRICT_ALIGNMENT (1U << 0)
#define BPF_PSEUDO_MAP_FD 1 #define BPF_PSEUDO_MAP_FD 1
/* flags for BPF_MAP_UPDATE_ELEM command */ /* flags for BPF_MAP_UPDATE_ELEM command */
...@@ -177,6 +184,7 @@ union bpf_attr { ...@@ -177,6 +184,7 @@ union bpf_attr {
__u32 log_size; /* size of user buffer */ __u32 log_size; /* size of user buffer */
__aligned_u64 log_buf; /* user supplied buffer */ __aligned_u64 log_buf; /* user supplied buffer */
__u32 kern_version; /* checked when prog_type=kprobe */ __u32 kern_version; /* checked when prog_type=kprobe */
__u32 prog_flags;
}; };
struct { /* anonymous struct used by BPF_OBJ_* commands */ struct { /* anonymous struct used by BPF_OBJ_* commands */
...@@ -481,8 +489,7 @@ union bpf_attr { ...@@ -481,8 +489,7 @@ union bpf_attr {
* u32 bpf_get_socket_uid(skb) * u32 bpf_get_socket_uid(skb)
* Get the owner uid of the socket stored inside sk_buff. * Get the owner uid of the socket stored inside sk_buff.
* @skb: pointer to skb * @skb: pointer to skb
* Return: uid of the socket owner on success or 0 if the socket pointer * Return: uid of the socket owner on success or overflowuid if failed.
* inside sk_buff is NULL
*/ */
#define __BPF_FUNC_MAPPER(FN) \ #define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \ FN(unspec), \
......
...@@ -117,6 +117,28 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, ...@@ -117,6 +117,28 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
} }
int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
size_t insns_cnt, int strict_alignment,
const char *license, __u32 kern_version,
char *log_buf, size_t log_buf_sz)
{
union bpf_attr attr;
bzero(&attr, sizeof(attr));
attr.prog_type = type;
attr.insn_cnt = (__u32)insns_cnt;
attr.insns = ptr_to_u64(insns);
attr.license = ptr_to_u64(license);
attr.log_buf = ptr_to_u64(log_buf);
attr.log_size = log_buf_sz;
attr.log_level = 2;
log_buf[0] = 0;
attr.kern_version = kern_version;
attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0;
return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
}
int bpf_map_update_elem(int fd, const void *key, const void *value, int bpf_map_update_elem(int fd, const void *key, const void *value,
__u64 flags) __u64 flags)
{ {
......
...@@ -35,6 +35,10 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, ...@@ -35,6 +35,10 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
size_t insns_cnt, const char *license, size_t insns_cnt, const char *license,
__u32 kern_version, char *log_buf, __u32 kern_version, char *log_buf,
size_t log_buf_sz); size_t log_buf_sz);
int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
size_t insns_cnt, int strict_alignment,
const char *license, __u32 kern_version,
char *log_buf, size_t log_buf_sz);
int bpf_map_update_elem(int fd, const void *key, const void *value, int bpf_map_update_elem(int fd, const void *key, const void *value,
__u64 flags); __u64 flags);
......
...@@ -11,7 +11,8 @@ endif ...@@ -11,7 +11,8 @@ endif
CFLAGS += -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include CFLAGS += -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include
LDLIBS += -lcap -lelf LDLIBS += -lcap -lelf
TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
test_align
TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment