netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [bpf-next PATCH 0/2] SK_MSG programs: read sock fields
@ 2018-05-17 15:53 John Fastabend
  2018-05-17 15:54 ` [bpf-next PATCH 1/2] bpf: allow sk_msg programs to " John Fastabend
  2018-05-17 15:54 ` [bpf-next PATCH 2/2] bpf: add sk_msg prog sk access tests to test_verifier John Fastabend
  0 siblings, 2 replies; 7+ messages in thread
From: John Fastabend @ 2018-05-17 15:53 UTC (permalink / raw)
  To: ast, daniel; +Cc: netdev

In this series we add the ability for sk msg programs to read basic
sock information about the sock they are attached to. The second
patch adds the tests to the selftest test_verifier.

One obseration that I had from writing this seriess is lots of the
./net/core/filter.c code is almost duplicated across program types.
I thought about building a template/macro that we could use as a
single block of code to read sock data out for multiple programs,
but I wasn't convinced it was worth it yet. The result was using a
macro saved a couple lines of code per block but made the code
a bit harder to read IMO. We can probably revisit the idea later
if we get more duplication.

---

John Fastabend (2):
      bpf: allow sk_msg programs to read sock fields
      bpf: add sk_msg prog sk access tests to test_verifier


 include/linux/filter.h                      |    1 
 include/uapi/linux/bpf.h                    |    8 ++
 kernel/bpf/sockmap.c                        |    1 
 net/core/filter.c                           |  114 ++++++++++++++++++++++++++-
 tools/include/uapi/linux/bpf.h              |    8 ++
 tools/testing/selftests/bpf/test_verifier.c |  115 +++++++++++++++++++++++++++
 6 files changed, 244 insertions(+), 3 deletions(-)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [bpf-next PATCH 1/2] bpf: allow sk_msg programs to read sock fields
  2018-05-17 15:53 [bpf-next PATCH 0/2] SK_MSG programs: read sock fields John Fastabend
@ 2018-05-17 15:54 ` John Fastabend
  2018-05-17 18:17   ` Martin KaFai Lau
  2018-05-17 15:54 ` [bpf-next PATCH 2/2] bpf: add sk_msg prog sk access tests to test_verifier John Fastabend
  1 sibling, 1 reply; 7+ messages in thread
From: John Fastabend @ 2018-05-17 15:54 UTC (permalink / raw)
  To: ast, daniel; +Cc: netdev

Currently sk_msg programs only have access to the raw data. However,
it is often useful when building policies to have the policies specific
to the socket endpoint. This allows using the socket tuple as input
into filters, etc.

This patch adds ctx access to the sock fields.

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
---
 include/linux/filter.h   |    1 
 include/uapi/linux/bpf.h |    8 +++
 kernel/bpf/sockmap.c     |    1 
 net/core/filter.c        |  114 +++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 121 insertions(+), 3 deletions(-)

diff --git a/include/linux/filter.h b/include/linux/filter.h
index 9dbcb9d..d358d18 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -517,6 +517,7 @@ struct sk_msg_buff {
 	bool sg_copy[MAX_SKB_FRAGS];
 	__u32 flags;
 	struct sock *sk_redir;
+	struct sock *sk;
 	struct sk_buff *skb;
 	struct list_head list;
 };
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index d94d333..97446bb 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -2176,6 +2176,14 @@ enum sk_action {
 struct sk_msg_md {
 	void *data;
 	void *data_end;
+
+	__u32 family;
+	__u32 remote_ip4;	/* Stored in network byte order */
+	__u32 local_ip4;	/* Stored in network byte order */
+	__u32 remote_ip6[4];	/* Stored in network byte order */
+	__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 */
 };
 
 #define BPF_TAG_SIZE	8
diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c
index c6de139..0ebf157 100644
--- a/kernel/bpf/sockmap.c
+++ b/kernel/bpf/sockmap.c
@@ -523,6 +523,7 @@ static unsigned int smap_do_tx_msg(struct sock *sk,
 	}
 
 	bpf_compute_data_pointers_sg(md);
+	md->sk = sk;
 	rc = (*prog->bpf_func)(md, prog->insnsi);
 	psock->apply_bytes = md->apply_bytes;
 
diff --git a/net/core/filter.c b/net/core/filter.c
index 6d0d156..aec5eba 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -5148,18 +5148,23 @@ static bool sk_msg_is_valid_access(int off, int size,
 	switch (off) {
 	case offsetof(struct sk_msg_md, data):
 		info->reg_type = PTR_TO_PACKET;
+		if (size != sizeof(__u64))
+			return false;
 		break;
 	case offsetof(struct sk_msg_md, data_end):
 		info->reg_type = PTR_TO_PACKET_END;
+		if (size != sizeof(__u64))
+			return false;
 		break;
+	default:
+		if (size != sizeof(__u32))
+			return false;
 	}
 
 	if (off < 0 || off >= sizeof(struct sk_msg_md))
 		return false;
 	if (off % size != 0)
 		return false;
-	if (size != sizeof(__u64))
-		return false;
 
 	return true;
 }
@@ -5835,7 +5840,8 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
 		break;
 
 	case offsetof(struct bpf_sock_ops, local_ip4):
-		BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_rcv_saddr) != 4);
+		BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+					  skc_rcv_saddr) != 4);
 
 		*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
 					      struct bpf_sock_ops_kern, sk),
@@ -6152,6 +6158,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
 				     struct bpf_prog *prog, u32 *target_size)
 {
 	struct bpf_insn *insn = insn_buf;
+	int off;
 
 	switch (si->off) {
 	case offsetof(struct sk_msg_md, data):
@@ -6164,6 +6171,107 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
 				      si->dst_reg, si->src_reg,
 				      offsetof(struct sk_msg_buff, data_end));
 		break;
+	case offsetof(struct sk_msg_md, family):
+		BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_family) != 2);
+
+		*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+					      struct sk_msg_buff, sk),
+				      si->dst_reg, si->src_reg,
+				      offsetof(struct sk_msg_buff, sk));
+		*insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
+				      offsetof(struct sock_common, skc_family));
+		break;
+
+	case offsetof(struct sk_msg_md, remote_ip4):
+		BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_daddr) != 4);
+
+		*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+						struct sk_msg_buff, sk),
+				      si->dst_reg, si->src_reg,
+				      offsetof(struct sk_msg_buff, sk));
+		*insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
+				      offsetof(struct sock_common, skc_daddr));
+		break;
+
+	case offsetof(struct sk_msg_md, local_ip4):
+		BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+					  skc_rcv_saddr) != 4);
+
+		*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+					      struct sk_msg_buff, sk),
+				      si->dst_reg, si->src_reg,
+				      offsetof(struct sk_msg_buff, sk));
+		*insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
+				      offsetof(struct sock_common,
+					       skc_rcv_saddr));
+		break;
+
+	case offsetof(struct sk_msg_md, remote_ip6[0]) ...
+	     offsetof(struct sk_msg_md, remote_ip6[3]):
+#if IS_ENABLED(CONFIG_IPV6)
+		BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+					  skc_v6_daddr.s6_addr32[0]) != 4);
+
+		off = si->off;
+		off -= offsetof(struct sk_msg_md, remote_ip6[0]);
+		*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+						struct sk_msg_buff, sk),
+				      si->dst_reg, si->src_reg,
+				      offsetof(struct sk_msg_buff, sk));
+		*insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
+				      offsetof(struct sock_common,
+					       skc_v6_daddr.s6_addr32[0]) +
+				      off);
+#else
+		*insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
+#endif
+		break;
+
+	case offsetof(struct sk_msg_md, local_ip6[0]) ...
+	     offsetof(struct sk_msg_md, local_ip6[3]):
+#if IS_ENABLED(CONFIG_IPV6)
+		BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+					  skc_v6_rcv_saddr.s6_addr32[0]) != 4);
+
+		off = si->off;
+		off -= offsetof(struct sk_msg_md, local_ip6[0]);
+		*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+						struct sk_msg_buff, sk),
+				      si->dst_reg, si->src_reg,
+				      offsetof(struct sk_msg_buff, sk));
+		*insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
+				      offsetof(struct sock_common,
+					       skc_v6_rcv_saddr.s6_addr32[0]) +
+				      off);
+#else
+		*insn++ = BPF_MOV32_IMM(si->dst_reg, 0);
+#endif
+		break;
+
+	case offsetof(struct sk_msg_md, remote_port):
+		BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_dport) != 2);
+
+		*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+						struct sk_msg_buff, sk),
+				      si->dst_reg, si->src_reg,
+				      offsetof(struct sk_msg_buff, sk));
+		*insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
+				      offsetof(struct sock_common, skc_dport));
+#ifndef __BIG_ENDIAN_BITFIELD
+		*insn++ = BPF_ALU32_IMM(BPF_LSH, si->dst_reg, 16);
+#endif
+		break;
+
+	case offsetof(struct sk_msg_md, local_port):
+		BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_num) != 2);
+
+		*insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
+						struct sk_msg_buff, sk),
+				      si->dst_reg, si->src_reg,
+				      offsetof(struct sk_msg_buff, sk));
+		*insn++ = BPF_LDX_MEM(BPF_H, si->dst_reg, si->dst_reg,
+				      offsetof(struct sock_common, skc_num));
+		break;
 	}
 
 	return insn - insn_buf;

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [bpf-next PATCH 2/2] bpf: add sk_msg prog sk access tests to test_verifier
  2018-05-17 15:53 [bpf-next PATCH 0/2] SK_MSG programs: read sock fields John Fastabend
  2018-05-17 15:54 ` [bpf-next PATCH 1/2] bpf: allow sk_msg programs to " John Fastabend
@ 2018-05-17 15:54 ` John Fastabend
  2018-05-17 18:57   ` Martin KaFai Lau
  1 sibling, 1 reply; 7+ messages in thread
From: John Fastabend @ 2018-05-17 15:54 UTC (permalink / raw)
  To: ast, daniel; +Cc: netdev

Add tests for BPF_PROG_TYPE_SK_MSG to test_verifier for read access
to new sk fields.

Signed-off-by: John Fastabend <john.fastabend@gmail.com>
---
 tools/include/uapi/linux/bpf.h              |    8 ++
 tools/testing/selftests/bpf/test_verifier.c |  115 +++++++++++++++++++++++++++
 2 files changed, 123 insertions(+)

diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index d94d333..97446bb 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -2176,6 +2176,14 @@ enum sk_action {
 struct sk_msg_md {
 	void *data;
 	void *data_end;
+
+	__u32 family;
+	__u32 remote_ip4;	/* Stored in network byte order */
+	__u32 local_ip4;	/* Stored in network byte order */
+	__u32 remote_ip6[4];	/* Stored in network byte order */
+	__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 */
 };
 
 #define BPF_TAG_SIZE	8
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index a877af0..1ac7630 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -1686,6 +1686,121 @@ static void bpf_fill_rand_ld_dw(struct bpf_test *self)
 		.prog_type = BPF_PROG_TYPE_SK_SKB,
 	},
 	{
+		"valid access family in SK_MSG",
+		.insns = {
+			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+				    offsetof(struct sk_msg_md, family)),
+			BPF_EXIT_INSN(),
+		},
+		.result = ACCEPT,
+		.prog_type = BPF_PROG_TYPE_SK_MSG,
+	},
+	{
+		"valid access remote_ip4 in SK_MSG",
+		.insns = {
+			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+				    offsetof(struct sk_msg_md, remote_ip4)),
+			BPF_EXIT_INSN(),
+		},
+		.result = ACCEPT,
+		.prog_type = BPF_PROG_TYPE_SK_MSG,
+	},
+	{
+		"valid access local_ip4 in SK_MSG",
+		.insns = {
+			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+				    offsetof(struct sk_msg_md, local_ip4)),
+			BPF_EXIT_INSN(),
+		},
+		.result = ACCEPT,
+		.prog_type = BPF_PROG_TYPE_SK_MSG,
+	},
+	{
+		"valid access remote_port in SK_MSG",
+		.insns = {
+			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+				    offsetof(struct sk_msg_md, remote_port)),
+			BPF_EXIT_INSN(),
+		},
+		.result = ACCEPT,
+		.prog_type = BPF_PROG_TYPE_SK_MSG,
+	},
+	{
+		"valid access local_port in SK_MSG",
+		.insns = {
+			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+				    offsetof(struct sk_msg_md, local_port)),
+			BPF_EXIT_INSN(),
+		},
+		.result = ACCEPT,
+		.prog_type = BPF_PROG_TYPE_SK_MSG,
+	},
+	{
+		"valid access remote_ip6 in SK_MSG",
+		.insns = {
+			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+				    offsetof(struct sk_msg_md, remote_ip6[0])),
+			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+				    offsetof(struct sk_msg_md, remote_ip6[1])),
+			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+				    offsetof(struct sk_msg_md, remote_ip6[2])),
+			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+				    offsetof(struct sk_msg_md, remote_ip6[3])),
+			BPF_EXIT_INSN(),
+		},
+		.result = ACCEPT,
+		.prog_type = BPF_PROG_TYPE_SK_SKB,
+	},
+	{
+		"valid access local_ip6 in SK_MSG",
+		.insns = {
+			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+				    offsetof(struct sk_msg_md, local_ip6[0])),
+			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+				    offsetof(struct sk_msg_md, local_ip6[1])),
+			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+				    offsetof(struct sk_msg_md, local_ip6[2])),
+			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
+				    offsetof(struct sk_msg_md, local_ip6[3])),
+			BPF_EXIT_INSN(),
+		},
+		.result = ACCEPT,
+		.prog_type = BPF_PROG_TYPE_SK_SKB,
+	},
+	{
+		"invalid 64B read of family in SK_MSG",
+		.insns = {
+			BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1,
+				    offsetof(struct sk_msg_md, family)),
+			BPF_EXIT_INSN(),
+		},
+		.errstr = "invalid bpf_context access",
+		.result = REJECT,
+		.prog_type = BPF_PROG_TYPE_SK_MSG,
+	},
+	{
+		"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),
+			BPF_EXIT_INSN(),
+		},
+		.errstr = "",
+		.result = REJECT,
+		.prog_type = BPF_PROG_TYPE_SK_MSG,
+	},
+	{
+		"invalid read offset in SK_MSG",
+		.insns = {
+			BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
+				    offsetof(struct sk_msg_md, family) + 1),
+			BPF_EXIT_INSN(),
+		},
+		.errstr = "",
+		.result = REJECT,
+		.prog_type = BPF_PROG_TYPE_SK_MSG,
+	},
+	{
 		"direct packet read for SK_MSG",
 		.insns = {
 			BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1,

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [bpf-next PATCH 1/2] bpf: allow sk_msg programs to read sock fields
  2018-05-17 15:54 ` [bpf-next PATCH 1/2] bpf: allow sk_msg programs to " John Fastabend
@ 2018-05-17 18:17   ` Martin KaFai Lau
  2018-05-17 20:16     ` John Fastabend
  0 siblings, 1 reply; 7+ messages in thread
From: Martin KaFai Lau @ 2018-05-17 18:17 UTC (permalink / raw)
  To: John Fastabend; +Cc: ast, daniel, netdev

On Thu, May 17, 2018 at 08:54:04AM -0700, John Fastabend wrote:
> Currently sk_msg programs only have access to the raw data. However,
> it is often useful when building policies to have the policies specific
> to the socket endpoint. This allows using the socket tuple as input
> into filters, etc.
> 
> This patch adds ctx access to the sock fields.
> 
> Signed-off-by: John Fastabend <john.fastabend@gmail.com>
> ---
>  include/linux/filter.h   |    1 
>  include/uapi/linux/bpf.h |    8 +++
>  kernel/bpf/sockmap.c     |    1 
>  net/core/filter.c        |  114 +++++++++++++++++++++++++++++++++++++++++++++-
It is indeed a lot of dup lines with sock_ops_convert_ctx_access()
as you mentioned in the cover.

Other than that, LGTM.

Acked-by: Martin KaFai Lau <kafafi@fb.com>

>  4 files changed, 121 insertions(+), 3 deletions(-)
> 
> diff --git a/include/linux/filter.h b/include/linux/filter.h
> index 9dbcb9d..d358d18 100644
> --- a/include/linux/filter.h
> +++ b/include/linux/filter.h
> @@ -517,6 +517,7 @@ struct sk_msg_buff {
>  	bool sg_copy[MAX_SKB_FRAGS];
>  	__u32 flags;
>  	struct sock *sk_redir;
> +	struct sock *sk;
>  	struct sk_buff *skb;
>  	struct list_head list;
>  };
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index d94d333..97446bb 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -2176,6 +2176,14 @@ enum sk_action {
>  struct sk_msg_md {
>  	void *data;
>  	void *data_end;
> +
> +	__u32 family;
> +	__u32 remote_ip4;	/* Stored in network byte order */
> +	__u32 local_ip4;	/* Stored in network byte order */
> +	__u32 remote_ip6[4];	/* Stored in network byte order */
> +	__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 */
This ordering inconsistency could be a trap to write bpf_prog
but I guess it is too late to change now considering
bpf_sock_ops is also using this convention.

Just curious, we cannot always assume inet_sk and then uses
its inet_sport?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [bpf-next PATCH 2/2] bpf: add sk_msg prog sk access tests to test_verifier
  2018-05-17 15:54 ` [bpf-next PATCH 2/2] bpf: add sk_msg prog sk access tests to test_verifier John Fastabend
@ 2018-05-17 18:57   ` Martin KaFai Lau
  2018-05-17 20:12     ` John Fastabend
  0 siblings, 1 reply; 7+ messages in thread
From: Martin KaFai Lau @ 2018-05-17 18:57 UTC (permalink / raw)
  To: John Fastabend; +Cc: ast, daniel, netdev

On Thu, May 17, 2018 at 08:54:10AM -0700, John Fastabend wrote:
> Add tests for BPF_PROG_TYPE_SK_MSG to test_verifier for read access
> to new sk fields.
> 
> Signed-off-by: John Fastabend <john.fastabend@gmail.com>
> ---
>  tools/include/uapi/linux/bpf.h              |    8 ++
>  tools/testing/selftests/bpf/test_verifier.c |  115 +++++++++++++++++++++++++++
>  2 files changed, 123 insertions(+)
> 
> diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
> index d94d333..97446bb 100644
> --- a/tools/include/uapi/linux/bpf.h
> +++ b/tools/include/uapi/linux/bpf.h
> @@ -2176,6 +2176,14 @@ enum sk_action {
>  struct sk_msg_md {
>  	void *data;
>  	void *data_end;
> +
> +	__u32 family;
> +	__u32 remote_ip4;	/* Stored in network byte order */
> +	__u32 local_ip4;	/* Stored in network byte order */
> +	__u32 remote_ip6[4];	/* Stored in network byte order */
> +	__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 */
>  };
>  
>  #define BPF_TAG_SIZE	8
> diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
> index a877af0..1ac7630 100644
> --- a/tools/testing/selftests/bpf/test_verifier.c
> +++ b/tools/testing/selftests/bpf/test_verifier.c
> @@ -1686,6 +1686,121 @@ static void bpf_fill_rand_ld_dw(struct bpf_test *self)
>  		.prog_type = BPF_PROG_TYPE_SK_SKB,
>  	},
>  	{
> +		"valid access family in SK_MSG",
> +		.insns = {
> +			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, family)),
> +			BPF_EXIT_INSN(),
> +		},
> +		.result = ACCEPT,
> +		.prog_type = BPF_PROG_TYPE_SK_MSG,
> +	},
> +	{
> +		"valid access remote_ip4 in SK_MSG",
> +		.insns = {
> +			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, remote_ip4)),
> +			BPF_EXIT_INSN(),
> +		},
> +		.result = ACCEPT,
> +		.prog_type = BPF_PROG_TYPE_SK_MSG,
> +	},
> +	{
> +		"valid access local_ip4 in SK_MSG",
> +		.insns = {
> +			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, local_ip4)),
> +			BPF_EXIT_INSN(),
> +		},
> +		.result = ACCEPT,
> +		.prog_type = BPF_PROG_TYPE_SK_MSG,
> +	},
> +	{
> +		"valid access remote_port in SK_MSG",
> +		.insns = {
> +			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, remote_port)),
> +			BPF_EXIT_INSN(),
> +		},
> +		.result = ACCEPT,
> +		.prog_type = BPF_PROG_TYPE_SK_MSG,
> +	},
> +	{
> +		"valid access local_port in SK_MSG",
> +		.insns = {
> +			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, local_port)),
> +			BPF_EXIT_INSN(),
> +		},
> +		.result = ACCEPT,
> +		.prog_type = BPF_PROG_TYPE_SK_MSG,
> +	},
> +	{
> +		"valid access remote_ip6 in SK_MSG",
> +		.insns = {
> +			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, remote_ip6[0])),
> +			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, remote_ip6[1])),
> +			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, remote_ip6[2])),
> +			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, remote_ip6[3])),
> +			BPF_EXIT_INSN(),
> +		},
> +		.result = ACCEPT,
> +		.prog_type = BPF_PROG_TYPE_SK_SKB,
> +	},
> +	{
> +		"valid access local_ip6 in SK_MSG",
> +		.insns = {
> +			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, local_ip6[0])),
> +			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, local_ip6[1])),
> +			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, local_ip6[2])),
> +			BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, local_ip6[3])),
> +			BPF_EXIT_INSN(),
> +		},
> +		.result = ACCEPT,
> +		.prog_type = BPF_PROG_TYPE_SK_SKB,
> +	},
> +	{
> +		"invalid 64B read of family in SK_MSG",
> +		.insns = {
> +			BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, family)),
> +			BPF_EXIT_INSN(),
> +		},
> +		.errstr = "invalid bpf_context access",
> +		.result = REJECT,
> +		.prog_type = BPF_PROG_TYPE_SK_MSG,
> +	},
> +	{
> +		"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),
> +			BPF_EXIT_INSN(),
> +		},
> +		.errstr = "",
no errstr in this case?

> +		.result = REJECT,
> +		.prog_type = BPF_PROG_TYPE_SK_MSG,
> +	},
> +	{
> +		"invalid read offset in SK_MSG",
> +		.insns = {
> +			BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
> +				    offsetof(struct sk_msg_md, family) + 1),
> +			BPF_EXIT_INSN(),
> +		},
> +		.errstr = "",
same here.

> +		.result = REJECT,
> +		.prog_type = BPF_PROG_TYPE_SK_MSG,
> +	},
> +	{
>  		"direct packet read for SK_MSG",
>  		.insns = {
>  			BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1,
> 
Other than the above,

Acked-by: Martin KaFai Lau <kafai@fb.com>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [bpf-next PATCH 2/2] bpf: add sk_msg prog sk access tests to test_verifier
  2018-05-17 18:57   ` Martin KaFai Lau
@ 2018-05-17 20:12     ` John Fastabend
  0 siblings, 0 replies; 7+ messages in thread
From: John Fastabend @ 2018-05-17 20:12 UTC (permalink / raw)
  To: Martin KaFai Lau; +Cc: ast, daniel, netdev

On 05/17/2018 11:57 AM, Martin KaFai Lau wrote:
> On Thu, May 17, 2018 at 08:54:10AM -0700, John Fastabend wrote:
>> Add tests for BPF_PROG_TYPE_SK_MSG to test_verifier for read access
>> to new sk fields.
>>
>> Signed-off-by: John Fastabend <john.fastabend@gmail.com>
>> ---


[...]

>> +	{
>> +		"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),
>> +			BPF_EXIT_INSN(),
>> +		},
>> +		.errstr = "",
> no errstr in this case?
> 
>> +		.result = REJECT,
>> +		.prog_type = BPF_PROG_TYPE_SK_MSG,
>> +	},
>> +	{
>> +		"invalid read offset in SK_MSG",
>> +		.insns = {
>> +			BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
>> +				    offsetof(struct sk_msg_md, family) + 1),
>> +			BPF_EXIT_INSN(),
>> +		},
>> +		.errstr = "",
> same here.
> 
>> +		.result = REJECT,
>> +		.prog_type = BPF_PROG_TYPE_SK_MSG,
>> +	},
>> +	{
>>  		"direct packet read for SK_MSG",
>>  		.insns = {
>>  			BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1,
>>
> Other than the above,
> 

For completeness I guess we should have the err string
included. I'll send a v2 and push ACKs forward.

> Acked-by: Martin KaFai Lau <kafai@fb.com>
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [bpf-next PATCH 1/2] bpf: allow sk_msg programs to read sock fields
  2018-05-17 18:17   ` Martin KaFai Lau
@ 2018-05-17 20:16     ` John Fastabend
  0 siblings, 0 replies; 7+ messages in thread
From: John Fastabend @ 2018-05-17 20:16 UTC (permalink / raw)
  To: Martin KaFai Lau; +Cc: ast, daniel, netdev

On 05/17/2018 11:17 AM, Martin KaFai Lau wrote:
> On Thu, May 17, 2018 at 08:54:04AM -0700, John Fastabend wrote:
>> Currently sk_msg programs only have access to the raw data. However,
>> it is often useful when building policies to have the policies specific
>> to the socket endpoint. This allows using the socket tuple as input
>> into filters, etc.
>>
>> This patch adds ctx access to the sock fields.
>>
>> Signed-off-by: John Fastabend <john.fastabend@gmail.com>
>> ---
>>  include/linux/filter.h   |    1 
>>  include/uapi/linux/bpf.h |    8 +++
>>  kernel/bpf/sockmap.c     |    1 
>>  net/core/filter.c        |  114 +++++++++++++++++++++++++++++++++++++++++++++-
> It is indeed a lot of dup lines with sock_ops_convert_ctx_access()
> as you mentioned in the cover.
> 
> Other than that, LGTM.
> 
> Acked-by: Martin KaFai Lau <kafafi@fb.com>
> 
>>  4 files changed, 121 insertions(+), 3 deletions(-)
>>
>> diff --git a/include/linux/filter.h b/include/linux/filter.h
>> index 9dbcb9d..d358d18 100644
>> --- a/include/linux/filter.h
>> +++ b/include/linux/filter.h
>> @@ -517,6 +517,7 @@ struct sk_msg_buff {
>>  	bool sg_copy[MAX_SKB_FRAGS];
>>  	__u32 flags;
>>  	struct sock *sk_redir;
>> +	struct sock *sk;
>>  	struct sk_buff *skb;
>>  	struct list_head list;
>>  };
>> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
>> index d94d333..97446bb 100644
>> --- a/include/uapi/linux/bpf.h
>> +++ b/include/uapi/linux/bpf.h
>> @@ -2176,6 +2176,14 @@ enum sk_action {
>>  struct sk_msg_md {
>>  	void *data;
>>  	void *data_end;
>> +
>> +	__u32 family;
>> +	__u32 remote_ip4;	/* Stored in network byte order */
>> +	__u32 local_ip4;	/* Stored in network byte order */
>> +	__u32 remote_ip6[4];	/* Stored in network byte order */
>> +	__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 */
> This ordering inconsistency could be a trap to write bpf_prog
> but I guess it is too late to change now considering
> bpf_sock_ops is also using this convention.
> 

Yep, when writing both bpf_sock_ops programs and sk_msg based
programs its nice to have them both use the same semantics. The
two programs, at least in my experience, are used together
typically sharing maps and heavily dependent on one another.

> Just curious, we cannot always assume inet_sk and then uses
> its inet_sport?
> 

For now we only support SOCK_STREAM so I guess we could also
use inet_sport but then it wouldn't align with bpf_sock_ops.
If we want to add it later we can put another field in there
to use it "__u32 source_port". For now though I prefer to keep
the bpf_sock_ops and sk_msg_md sock field access aligned.

.John

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-05-17 20:16 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-05-17 15:53 [bpf-next PATCH 0/2] SK_MSG programs: read sock fields John Fastabend
2018-05-17 15:54 ` [bpf-next PATCH 1/2] bpf: allow sk_msg programs to " John Fastabend
2018-05-17 18:17   ` Martin KaFai Lau
2018-05-17 20:16     ` John Fastabend
2018-05-17 15:54 ` [bpf-next PATCH 2/2] bpf: add sk_msg prog sk access tests to test_verifier John Fastabend
2018-05-17 18:57   ` Martin KaFai Lau
2018-05-17 20:12     ` John Fastabend

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).