Re: [PATCH net-next v2 1/2] Add a helper function to get socket cookie in eBPF

2017-02-06 Thread Daniel Borkmann

On 02/06/2017 03:17 AM, Chenbo Feng wrote:

From: Chenbo Feng 

Retrieve the socket cookie generated by sock_gen_cookie() from a sk_buff
with a known socket. Generates a new cookie if one was not yet set.If
the socket pointer inside sk_buff is NULL, 0 is returned. The helper
function coud be useful in monitoring per socket networking traffic
statistics and provide a unique socket identifier per namespace.

Signed-off-by: Chenbo Feng 

[...]

diff --git a/net/core/filter.c b/net/core/filter.c
index 0b753cb..632fb91 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -26,6 +26,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -2599,6 +2600,18 @@ static const struct bpf_func_proto 
bpf_xdp_event_output_proto = {
.arg5_type  = ARG_CONST_SIZE,
  };

+BPF_CALL_1(bpf_get_socket_cookie, struct sk_buff *, skb)
+{
+   return skb->sk ? sock_gen_cookie(skb->sk) : 0;
+}
+
+static const struct bpf_func_proto bpf_get_socket_cookie_proto = {
+   .func   = bpf_get_socket_cookie,
+   .gpl_only   = false,
+   .ret_type   = RET_INTEGER,
+   .arg1_type  = ARG_PTR_TO_CTX,
+};
+
  static const struct bpf_func_proto *
  bpf_base_func_proto(enum bpf_func_id func_id)
  {
@@ -2622,6 +2635,8 @@ bpf_base_func_proto(enum bpf_func_id func_id)
case BPF_FUNC_trace_printk:
if (capable(CAP_SYS_ADMIN))
return bpf_get_trace_printk_proto();
+   case BPF_FUNC_get_socket_cookie:
+   return _get_socket_cookie_proto;
default:
return NULL;
}


This still has one issue that would need to be addressed, otherwise
looks good and ready to me.

Issue is that it cannot be added to bpf_base_func_proto(), because
that is also used by cg_sock_ops, which has struct sock as input
instead of struct sk_buff.

I suggest, we initially add this to both, sk_filter_func_proto() and
tc_cls_act_func_proto() and, if needed, we could follow-up with other
prog types at some later point in time. Otherwise, looks fine.


diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index 6b10573..acd2a6c 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -19,7 +19,7 @@ static int (*inet_rcv_compat)(struct sk_buff *skb, struct 
nlmsghdr *nlh);
  static DEFINE_MUTEX(sock_diag_table_mutex);
  static struct workqueue_struct *broadcast_wq;

-static u64 sock_gen_cookie(struct sock *sk)
+u64 sock_gen_cookie(struct sock *sk)
  {
while (1) {
u64 res = atomic64_read(>sk_cookie);





Re: [PATCH net-next v2 1/2] Add a helper function to get socket cookie in eBPF

2017-02-05 Thread Eric Dumazet
On Mon, 2017-02-06 at 12:01 +0900, Lorenzo Colitti wrote:
> On Mon, Feb 6, 2017 at 11:17 AM, Chenbo Feng
>  wrote:
> > +BPF_CALL_1(bpf_get_socket_cookie, struct sk_buff *, skb)
> > +{
> > +   return skb->sk ? sock_gen_cookie(skb->sk) : 0;
> > +}
> > +
> 
> Does this code need to increment the socket refcount, or call
> ACCESS_ONCE to get skb->sk? The socket filter codepath should be safe,
> but if this function is called in xt_ebpf, could it race with
> something that sets skb->sk to null?

I do not see how this could possibly happen.

READ_ONCE() would not prevent the 'old' sk from disappearing anyway.





Re: [PATCH net-next v2 1/2] Add a helper function to get socket cookie in eBPF

2017-02-05 Thread Lorenzo Colitti
On Mon, Feb 6, 2017 at 11:17 AM, Chenbo Feng
 wrote:
> +BPF_CALL_1(bpf_get_socket_cookie, struct sk_buff *, skb)
> +{
> +   return skb->sk ? sock_gen_cookie(skb->sk) : 0;
> +}
> +

Does this code need to increment the socket refcount, or call
ACCESS_ONCE to get skb->sk? The socket filter codepath should be safe,
but if this function is called in xt_ebpf, could it race with
something that sets skb->sk to null?


Re: [PATCH net-next v2 1/2] Add a helper function to get socket cookie in eBPF

2017-02-05 Thread Eric Dumazet
On Sun, 2017-02-05 at 18:17 -0800, Chenbo Feng wrote:
> From: Chenbo Feng 
> 
> Retrieve the socket cookie generated by sock_gen_cookie() from a sk_buff
> with a known socket. Generates a new cookie if one was not yet set.If
> the socket pointer inside sk_buff is NULL, 0 is returned. The helper
> function coud be useful in monitoring per socket networking traffic
> statistics and provide a unique socket identifier per namespace.
> 
> Signed-off-by: Chenbo Feng 
> ---

Acked-by: Eric Dumazet 




[PATCH net-next v2 1/2] Add a helper function to get socket cookie in eBPF

2017-02-05 Thread Chenbo Feng
From: Chenbo Feng 

Retrieve the socket cookie generated by sock_gen_cookie() from a sk_buff
with a known socket. Generates a new cookie if one was not yet set.If
the socket pointer inside sk_buff is NULL, 0 is returned. The helper
function coud be useful in monitoring per socket networking traffic
statistics and provide a unique socket identifier per namespace.

Signed-off-by: Chenbo Feng 
---
 include/linux/sock_diag.h |  1 +
 include/uapi/linux/bpf.h  |  9 -
 net/core/filter.c | 15 +++
 net/core/sock_diag.c  |  2 +-
 4 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h
index a0596ca0..a2f8109 100644
--- a/include/linux/sock_diag.h
+++ b/include/linux/sock_diag.h
@@ -24,6 +24,7 @@ void sock_diag_unregister(const struct sock_diag_handler *h);
 void sock_diag_register_inet_compat(int (*fn)(struct sk_buff *skb, struct 
nlmsghdr *nlh));
 void sock_diag_unregister_inet_compat(int (*fn)(struct sk_buff *skb, struct 
nlmsghdr *nlh));
 
+u64 sock_gen_cookie(struct sock *sk);
 int sock_diag_check_cookie(struct sock *sk, const __u32 *cookie);
 void sock_diag_save_cookie(struct sock *sk, __u32 *cookie);
 
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index e07fd5a..6923d21 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -449,6 +449,12 @@ union bpf_attr {
  * Return:
  *   > 0 length of the string including the trailing NUL on success
  *   < 0 error
+ *
+ * u64 bpf_bpf_get_socket_cookie(skb)
+ * Get the cookie for the socket stored inside sk_buff.
+ * @skb: pointer to skb
+ * Return: 8 Bytes non-decreasing number on success or 0 if the socket
+ * field is missing inside sk_buff
  */
 #define __BPF_FUNC_MAPPER(FN)  \
FN(unspec), \
@@ -496,7 +502,8 @@ union bpf_attr {
FN(get_numa_node_id),   \
FN(skb_change_head),\
FN(xdp_adjust_head),\
-   FN(probe_read_str),
+   FN(probe_read_str), \
+   FN(get_socket_cookie),
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
  * function eBPF program intends to call
diff --git a/net/core/filter.c b/net/core/filter.c
index 0b753cb..632fb91 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -2599,6 +2600,18 @@ static const struct bpf_func_proto 
bpf_xdp_event_output_proto = {
.arg5_type  = ARG_CONST_SIZE,
 };
 
+BPF_CALL_1(bpf_get_socket_cookie, struct sk_buff *, skb)
+{
+   return skb->sk ? sock_gen_cookie(skb->sk) : 0;
+}
+
+static const struct bpf_func_proto bpf_get_socket_cookie_proto = {
+   .func   = bpf_get_socket_cookie,
+   .gpl_only   = false,
+   .ret_type   = RET_INTEGER,
+   .arg1_type  = ARG_PTR_TO_CTX,
+};
+
 static const struct bpf_func_proto *
 bpf_base_func_proto(enum bpf_func_id func_id)
 {
@@ -2622,6 +2635,8 @@ bpf_base_func_proto(enum bpf_func_id func_id)
case BPF_FUNC_trace_printk:
if (capable(CAP_SYS_ADMIN))
return bpf_get_trace_printk_proto();
+   case BPF_FUNC_get_socket_cookie:
+   return _get_socket_cookie_proto;
default:
return NULL;
}
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
index 6b10573..acd2a6c 100644
--- a/net/core/sock_diag.c
+++ b/net/core/sock_diag.c
@@ -19,7 +19,7 @@ static int (*inet_rcv_compat)(struct sk_buff *skb, struct 
nlmsghdr *nlh);
 static DEFINE_MUTEX(sock_diag_table_mutex);
 static struct workqueue_struct *broadcast_wq;
 
-static u64 sock_gen_cookie(struct sock *sk)
+u64 sock_gen_cookie(struct sock *sk)
 {
while (1) {
u64 res = atomic64_read(>sk_cookie);
-- 
2.7.4