Skip to content

Commit

Permalink
Merge branch 'bpf-sk-msg-size-member'
Browse files Browse the repository at this point in the history
John Fastabend says:

====================
This adds a size field to the sk_msg_md data structure used by SK_MSG
programs. Without this in the zerocopy case and in the copy case
where multiple iovs are in use its difficult to know how much data
can be pulled in. The normal method of reading data and data_end
only give the current contiguous buffer. BPF programs can attempt to
pull in extra data but have to guess if it exists. This can result
in multiple "guesses" its much better if we know upfront the size
of the sk_msg.
====================

Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
  • Loading branch information
Daniel Borkmann committed Dec 18, 2018
2 parents 0bae2d4 + 945a47d commit dd4bfda
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 3 deletions.
3 changes: 3 additions & 0 deletions include/linux/skmsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ struct sk_msg_sg {
struct scatterlist data[MAX_MSG_FRAGS + 1];
};

/* UAPI in filter.c depends on struct sk_msg_sg being first element. If
* this is moved filter.c also must be updated.
*/
struct sk_msg {
struct sk_msg_sg sg;
void *data;
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -2665,6 +2665,7 @@ struct sk_msg_md {
__u32 local_ip6[4]; /* Stored in network byte order */
__u32 remote_port; /* Stored in network byte order */
__u32 local_port; /* stored in host byte order */
__u32 size; /* Total size of sk_msg */
};

struct sk_reuseport_md {
Expand Down
6 changes: 6 additions & 0 deletions net/core/filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -7530,6 +7530,12 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
*insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
offsetof(struct sock_common, skc_num));
break;

case offsetof(struct sk_msg_md, size):
*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_msg_sg, size),
si->dst_reg, si->src_reg,
offsetof(struct sk_msg_sg, size));
break;
}

return insn - insn_buf;
Expand Down
1 change: 1 addition & 0 deletions tools/include/uapi/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -2665,6 +2665,7 @@ struct sk_msg_md {
__u32 local_ip6[4]; /* Stored in network byte order */
__u32 remote_port; /* Stored in network byte order */
__u32 local_port; /* stored in host byte order */
__u32 size; /* Total size of sk_msg */
};

struct sk_reuseport_md {
Expand Down
16 changes: 13 additions & 3 deletions tools/testing/selftests/bpf/test_verifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -1843,10 +1843,20 @@ static struct bpf_test tests[] = {
.prog_type = BPF_PROG_TYPE_SK_SKB,
},
{
"invalid 64B read of family in SK_MSG",
"valid access size in SK_MSG",
.insns = {
BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
offsetof(struct sk_msg_md, size)),
BPF_EXIT_INSN(),
},
.result = ACCEPT,
.prog_type = BPF_PROG_TYPE_SK_MSG,
},
{
"invalid 64B read of size in SK_MSG",
.insns = {
BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1,
offsetof(struct sk_msg_md, family)),
offsetof(struct sk_msg_md, size)),
BPF_EXIT_INSN(),
},
.errstr = "invalid bpf_context access",
Expand All @@ -1857,7 +1867,7 @@ static struct bpf_test tests[] = {
"invalid read past end of SK_MSG",
.insns = {
BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
offsetof(struct sk_msg_md, local_port) + 4),
offsetof(struct sk_msg_md, size) + 4),
BPF_EXIT_INSN(),
},
.errstr = "R0 !read_ok",
Expand Down

0 comments on commit dd4bfda

Please sign in to comment.