Netdev List
 help / color / mirror / Atom feed
* [PATCH bpf-next v5 2/3] bpf: btf: add btf print functionality
From: Okash Khawaja @ 2018-07-12  3:08 UTC (permalink / raw)
  To: Daniel Borkmann, Martin KaFai Lau, Alexei Starovoitov,
	Yonghong Song, Quentin Monnet, Jakub Kicinski, David S. Miller
  Cc: netdev, kernel-team, linux-kernel
In-Reply-To: <20180712030803.875913594@fb.com>

[-- Attachment #1: 02-add-btf-dump-map.patch --]
[-- Type: text/plain, Size: 9540 bytes --]

This consumes functionality exported in the previous patch. It does the
main job of printing with BTF data. This is used in the following patch
to provide a more readable output of a map's dump. It relies on
json_writer to do json printing. Below is sample output where map keys
are ints and values are of type struct A:

typedef int int_type;
enum E {
        E0,
        E1,
};

struct B {
        int x;
        int y;
};

struct A {
        int m;
        unsigned long long n;
        char o;
        int p[8];
        int q[4][8];
        enum E r;
        void *s;
        struct B t;
        const int u;
        int_type v;
        unsigned int w1: 3;
        unsigned int w2: 3;
};

$ sudo bpftool map dump id 14
[{
        "key": 0,
        "value": {
            "m": 1,
            "n": 2,
            "o": "c",
            "p": [15,16,17,18,15,16,17,18
            ],
            "q": [[25,26,27,28,25,26,27,28
                ],[35,36,37,38,35,36,37,38
                ],[45,46,47,48,45,46,47,48
                ],[55,56,57,58,55,56,57,58
                ]
            ],
            "r": 1,
            "s": 0x7ffd80531cf8,
            "t": {
                "x": 5,
                "y": 10
            },
            "u": 100,
            "v": 20,
            "w1": 0x7,
            "w2": 0x3
        }
    }
]

This patch uses json's {} and [] to imply struct/union and array. More
explicit information can be added later. For example, a command line
option can be introduced to print whether a key or value is struct
or union, name of a struct etc. This will however come at the expense
of duplicating info when, for example, printing an array of structs.
enums are printed as ints without their names.

Signed-off-by: Okash Khawaja <osk@fb.com>

---
 tools/bpf/bpftool/btf_dumper.c |  251 +++++++++++++++++++++++++++++++++++++++++
 tools/bpf/bpftool/main.h       |   15 ++
 2 files changed, 266 insertions(+)

--- /dev/null
+++ b/tools/bpf/bpftool/btf_dumper.c
@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018 Facebook */
+
+#include <ctype.h>
+#include <stdio.h> /* for (FILE *) used by json_writer */
+#include <string.h>
+#include <asm/byteorder.h>
+#include <linux/bitops.h>
+#include <linux/btf.h>
+#include <linux/err.h>
+
+#include "btf.h"
+#include "json_writer.h"
+#include "main.h"
+
+#define BITS_PER_BYTE_MASK (BITS_PER_BYTE - 1)
+#define BITS_PER_BYTE_MASKED(bits) ((bits) & BITS_PER_BYTE_MASK)
+#define BITS_ROUNDDOWN_BYTES(bits) ((bits) >> 3)
+#define BITS_ROUNDUP_BYTES(bits) \
+	(BITS_ROUNDDOWN_BYTES(bits) + !!BITS_PER_BYTE_MASKED(bits))
+
+static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id,
+			      __u8 bit_offset, const void *data);
+
+static void btf_dumper_ptr(const void *data, json_writer_t *jw,
+			   bool is_plain_text)
+{
+	if (is_plain_text)
+		jsonw_printf(jw, "%p", *(unsigned long *)data);
+	else
+		jsonw_printf(jw, "%u", *(unsigned long *)data);
+}
+
+static int btf_dumper_modifier(const struct btf_dumper *d, __u32 type_id,
+			       const void *data)
+{
+	int actual_type_id;
+
+	actual_type_id = btf__resolve_type(d->btf, type_id);
+	if (actual_type_id < 0)
+		return actual_type_id;
+
+	return btf_dumper_do_type(d, actual_type_id, 0, data);
+}
+
+static void btf_dumper_enum(const void *data, json_writer_t *jw)
+{
+	jsonw_printf(jw, "%d", *(int *)data);
+}
+
+static int btf_dumper_array(const struct btf_dumper *d, __u32 type_id,
+			    const void *data)
+{
+	const struct btf_type *t = btf__type_by_id(d->btf, type_id);
+	struct btf_array *arr = (struct btf_array *)(t + 1);
+	long long elem_size;
+	int ret = 0;
+	__u32 i;
+
+	elem_size = btf__resolve_size(d->btf, arr->type);
+	if (elem_size < 0)
+		return elem_size;
+
+	jsonw_start_array(d->jw);
+	for (i = 0; i < arr->nelems; i++) {
+		ret = btf_dumper_do_type(d, arr->type, 0,
+					 data + i * elem_size);
+		if (ret)
+			break;
+	}
+
+	jsonw_end_array(d->jw);
+	return ret;
+}
+
+static void btf_dumper_int_bits(__u32 int_type, __u8 bit_offset,
+				const void *data, json_writer_t *jw,
+				bool is_plain_text)
+{
+	int left_shift_bits, right_shift_bits;
+	int nr_bits = BTF_INT_BITS(int_type);
+	int total_bits_offset;
+	int bytes_to_copy;
+	int bits_to_copy;
+	__u64 print_num;
+
+	total_bits_offset = bit_offset + BTF_INT_OFFSET(int_type);
+	data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
+	bit_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
+	bits_to_copy = bit_offset + nr_bits;
+	bytes_to_copy = BITS_ROUNDUP_BYTES(bits_to_copy);
+
+	print_num = 0;
+	memcpy(&print_num, data, bytes_to_copy);
+#if defined(__BIG_ENDIAN_BITFIELD)
+	left_shift_bits = bit_offset;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	left_shift_bits = 64 - bits_to_copy;
+#else
+#error neither big nor little endian
+#endif
+	right_shift_bits = 64 - nr_bits;
+
+	print_num <<= left_shift_bits;
+	print_num >>= right_shift_bits;
+	if (is_plain_text)
+		jsonw_printf(jw, "0x%llx", print_num);
+	else
+		jsonw_printf(jw, "%llu", print_num);
+}
+
+static int btf_dumper_int(const struct btf_type *t, __u8 bit_offset,
+			  const void *data, json_writer_t *jw,
+			  bool is_plain_text)
+{
+	__u32 *int_type;
+	__u32 nr_bits;
+
+	int_type = (__u32 *)(t + 1);
+	nr_bits = BTF_INT_BITS(*int_type);
+	/* if this is bit field */
+	if (bit_offset || BTF_INT_OFFSET(*int_type) ||
+	    BITS_PER_BYTE_MASKED(nr_bits)) {
+		btf_dumper_int_bits(*int_type, bit_offset, data, jw,
+				    is_plain_text);
+		return 0;
+	}
+
+	switch (BTF_INT_ENCODING(*int_type)) {
+	case 0:
+		if (BTF_INT_BITS(*int_type) == 64)
+			jsonw_printf(jw, "%lu", *(__u64 *)data);
+		else if (BTF_INT_BITS(*int_type) == 32)
+			jsonw_printf(jw, "%u", *(__u32 *)data);
+		else if (BTF_INT_BITS(*int_type) == 16)
+			jsonw_printf(jw, "%hu", *(__u16 *)data);
+		else if (BTF_INT_BITS(*int_type) == 8)
+			jsonw_printf(jw, "%hhu", *(__u8 *)data);
+		else
+			btf_dumper_int_bits(*int_type, bit_offset, data, jw,
+					    is_plain_text);
+		break;
+	case BTF_INT_SIGNED:
+		if (BTF_INT_BITS(*int_type) == 64)
+			jsonw_printf(jw, "%ld", *(long long *)data);
+		else if (BTF_INT_BITS(*int_type) == 32)
+			jsonw_printf(jw, "%d", *(int *)data);
+		else if (BTF_INT_BITS(*int_type) == 16)
+			jsonw_printf(jw, "%hd", *(short *)data);
+		else if (BTF_INT_BITS(*int_type) == 8)
+			jsonw_printf(jw, "%hhd", *(char *)data);
+		else
+			btf_dumper_int_bits(*int_type, bit_offset, data, jw,
+					    is_plain_text);
+		break;
+	case BTF_INT_CHAR:
+		if (isprint(*(char *)data))
+			jsonw_printf(jw, "\"%c\"", *(char *)data);
+		else
+			if (is_plain_text)
+				jsonw_printf(jw, "0x%hhx", *(char *)data);
+			else
+				jsonw_printf(jw, "\"\\u00%02hhx\"",
+					     *(char *)data);
+		break;
+	case BTF_INT_BOOL:
+		jsonw_bool(jw, *(int *)data);
+		break;
+	default:
+		/* shouldn't happen */
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int btf_dumper_struct(const struct btf_dumper *d, __u32 type_id,
+			     const void *data)
+{
+	const struct btf_type *t;
+	struct btf_member *m;
+	const void *data_off;
+	int ret = 0;
+	int i, vlen;
+
+	t = btf__type_by_id(d->btf, type_id);
+	if (!t)
+		return -EINVAL;
+
+	vlen = BTF_INFO_VLEN(t->info);
+	jsonw_start_object(d->jw);
+	m = (struct btf_member *)(t + 1);
+
+	for (i = 0; i < vlen; i++) {
+		data_off = data + BITS_ROUNDDOWN_BYTES(m[i].offset);
+		jsonw_name(d->jw, btf__name_by_offset(d->btf, m[i].name_off));
+		ret = btf_dumper_do_type(d, m[i].type,
+					 BITS_PER_BYTE_MASKED(m[i].offset),
+					 data_off);
+		if (ret)
+			break;
+	}
+
+	jsonw_end_object(d->jw);
+
+	return ret;
+}
+
+static int btf_dumper_do_type(const struct btf_dumper *d, __u32 type_id,
+			      __u8 bit_offset, const void *data)
+{
+	const struct btf_type *t = btf__type_by_id(d->btf, type_id);
+
+	switch (BTF_INFO_KIND(t->info)) {
+	case BTF_KIND_INT:
+		return btf_dumper_int(t, bit_offset, data, d->jw,
+				     d->is_plain_text);
+	case BTF_KIND_STRUCT:
+	case BTF_KIND_UNION:
+		return btf_dumper_struct(d, type_id, data);
+	case BTF_KIND_ARRAY:
+		return btf_dumper_array(d, type_id, data);
+	case BTF_KIND_ENUM:
+		btf_dumper_enum(data, d->jw);
+		return 0;
+	case BTF_KIND_PTR:
+		btf_dumper_ptr(data, d->jw, d->is_plain_text);
+		return 0;
+	case BTF_KIND_UNKN:
+		jsonw_printf(d->jw, "(unknown)");
+		return 0;
+	case BTF_KIND_FWD:
+		/* map key or value can't be forward */
+		jsonw_printf(d->jw, "(fwd-kind-invalid)");
+		return -EINVAL;
+	case BTF_KIND_TYPEDEF:
+	case BTF_KIND_VOLATILE:
+	case BTF_KIND_CONST:
+	case BTF_KIND_RESTRICT:
+		return btf_dumper_modifier(d, type_id, data);
+	default:
+		jsonw_printf(d->jw, "(unsupported-kind");
+		return -EINVAL;
+	}
+}
+
+int btf_dumper_type(const struct btf_dumper *d, __u32 type_id,
+		    const void *data)
+{
+	return btf_dumper_do_type(d, type_id, 0, data);
+}
--- a/tools/bpf/bpftool/main.h
+++ b/tools/bpf/bpftool/main.h
@@ -131,4 +131,19 @@ unsigned int get_page_size(void);
 unsigned int get_possible_cpus(void);
 const char *ifindex_to_bfd_name_ns(__u32 ifindex, __u64 ns_dev, __u64 ns_ino);
 
+struct btf_dumper {
+	const struct btf *btf;
+	json_writer_t *jw;
+	bool is_plain_text;
+};
+
+/* btf_dumper_type - print data along with type information
+ * @d: an instance containing context for dumping types
+ * @type_id: index in btf->types array. this points to the type to be dumped
+ * @data: pointer the actual data, i.e. the values to be printed
+ *
+ * Returns zero on success and negative error code otherwise
+ */
+int btf_dumper_type(const struct btf_dumper *d, __u32 type_id,
+		    const void *data);
 #endif

^ permalink raw reply

* [PATCH bpf-next v5 0/3] bpf: btf: print bpftool map data with btf
From: Okash Khawaja @ 2018-07-12  3:08 UTC (permalink / raw)
  To: Daniel Borkmann, Martin KaFai Lau, Alexei Starovoitov,
	Yonghong Song, Quentin Monnet, Jakub Kicinski, David S. Miller
  Cc: netdev, kernel-team, linux-kernel

Hi,

Here are the changes from v4:

patch 2:

- sort headers in btf_dumper.c
- remove extra parentheses
- include asm/byteorder.h
- compile error when big and small endian bitfields macro undefined

Thanks,
Okash

^ permalink raw reply

* Re: [PATCH] net: convert gro_count to bitmask
From: David Miller @ 2018-07-12  2:49 UTC (permalink / raw)
  To: lirongqing; +Cc: netdev
In-Reply-To: <1531300553-21413-1-git-send-email-lirongqing@baidu.com>

From: Li RongQing <lirongqing@baidu.com>
Date: Wed, 11 Jul 2018 17:15:53 +0800

> +		clear_bit(index, &napi->gro_bitmask);

Please don't use atomics here, at least use __clear_bit().

This is why I did the operations by hand in my version of the patch.
Also, if you are going to preempt my patch, at least retain the
comment I added around the GRO_HASH_BUCKETS definitions which warns
the reader about the limit.

Thanks.

^ permalink raw reply

* Re: Bug report: epoll can fail to report EPOLLOUT when unix datagram socket peer is closed
From: Jason Baron @ 2018-07-12  2:46 UTC (permalink / raw)
  To: Ian Lance Taylor, netdev
In-Reply-To: <CAOyqgcXzie6xRSEfVvtSS=uSkEaBxP-LjCcUxXLoqCjbvTO4yg@mail.gmail.com>



On 06/26/2018 10:18 AM, Ian Lance Taylor wrote:
> I'm reporting what appears to be a bug in the Linux kernel's epoll
> support.  It seems that epoll appears to sometimes fail to report an
> EPOLLOUT event when the other side of an AF_UNIX/SOCK_DGRAM socket is
> closed.  This bug report started as a Go program reported at
> https://golang.org/issue/23604.  I've written a C program that
> demonstrates the same symptoms, at
> https://github.com/golang/go/issues/23604#issuecomment-398945027 .
> 
> The C program sets up an AF_UNIX/SOCK_DGRAM server and serveral
> identical clients, all running in non-blocking mode.  All the
> non-blocking sockets are added to epoll, using EPOLLET.  The server
> periodically closes and reopens its socket.  The clients look for
> ECONNREFUSED errors on their write calls, and close and reopen their
> sockets when they see one.
> 
> The clients will sometimes fill up their buffer and block with EAGAIN.
> At that point they expect the poller to return an EPOLLOUT event to
> tell them when they are ready to write again.  The expectation is that
> either the server will read data, freeing up buffer space, or will
> close the socket, which should cause the sending packets to be
> discarded, freeing up buffer space.  Generally the EPOLLOUT event
> happens.  But sometimes, the poller never returns such an event, and
> the client stalls.  In the test program this is reported as a client
> that waits more than 20 seconds to be told to continue.
> 
> A similar bug report was made, with few details, at
> https://stackoverflow.com/questions/38441059/edge-triggered-epoll-for-unix-domain-socket
> .
> 
> I've tested the program and seen the failure on kernel 4.9.0-6-amd64.
> A colleague has tested the program and seen the failure on
> 4.18.0-smp-DEV #3 SMP @1529531011 x86_64 GNU/Linux.
> 
> If there is a better way for me to report this, please let me know.
> 
> Thanks for your attention.
> 
> Ian
> 

Hi,

Thanks for the report and the test program. The patch below seems to
have cured the reproducer for me. But perhaps you can confirm?

Thanks,

-Jason


[PATCH] af_unix: ensure POLLOUT on remote close() for connected dgram socket

Applictions use ECONNREFUSED as returned from write() in order to
determine that a socket should be closed. When using connected dgram
unix sockets in a poll/write loop, this relies on POLLOUT being
signaled when the remote end closes. However, due to a race POLLOUT
can be missed when the remote closes:

          thread 1 (client)                   thread 2 (server)

connect() to server
write() returns -EAGAIN
unix_dgram_poll()
 -> unix_recvq_full() is true
                                       close()
                                        ->unix_release_sock()
                                         ->wake_up_interruptible_all()
unix_dgram_poll() (due to the
     wake_up_interruptible_all)
 -> unix_recvq_full() still is true
                                         ->free all skbs


Now thread 1 is stuck and will not receive anymore wakeups. In this
case, when thread 1 gets the -EAGAIN, it has not queued any skbs
otherwise the 'free all skbs' step would in fact cause a wakeup and
a POLLOUT return. So the race here is probably fairly rare because
it means there are no skbs that thread 1 queued and that thread 1
schedules before the 'free all skbs' step. Nevertheless, this has
been observed in the wild via syslog.

The proposed fix is to move the wake_up_interruptible_all() call
after the 'free all skbs' step.

Signed-off-by: Jason Baron <jbaron@akamai.com>
---
 net/unix/af_unix.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index e5473c0..de242cf 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -529,8 +529,6 @@ static void unix_release_sock(struct sock *sk, int
embrion)
 	sk->sk_state = TCP_CLOSE;
 	unix_state_unlock(sk);

-	wake_up_interruptible_all(&u->peer_wait);
-
 	skpair = unix_peer(sk);

 	if (skpair != NULL) {
@@ -560,6 +558,9 @@ static void unix_release_sock(struct sock *sk, int
embrion)
 		kfree_skb(skb);
 	}

+	/* after freeing skbs to make sure POLLOUT triggers */
+	wake_up_interruptible_all(&u->peer_wait);
+
 	if (path.dentry)
 		path_put(&path);

-- 
2.7.4

^ permalink raw reply related

* 答复: [PATCH] net: convert gro_count to bitmask
From: Li,Rongqing @ 2018-07-12  2:31 UTC (permalink / raw)
  To: Stefano Brivio; +Cc: netdev@vger.kernel.org, Eric Dumazet
In-Reply-To: <20180711125133.60528540@epycfail>



> -----邮件原件-----
> 发件人: Stefano Brivio [mailto:sbrivio@redhat.com]
> 发送时间: 2018年7月11日 18:52
> 收件人: Li,Rongqing <lirongqing@baidu.com>
> 抄送: netdev@vger.kernel.org; Eric Dumazet <edumazet@google.com>
> 主题: Re: [PATCH] net: convert gro_count to bitmask
> 
> On Wed, 11 Jul 2018 17:15:53 +0800
> Li RongQing <lirongqing@baidu.com> wrote:
> 
> > @@ -5380,6 +5382,12 @@ static enum gro_result dev_gro_receive(struct
> napi_struct *napi, struct sk_buff
> >  	if (grow > 0)
> >  		gro_pull_from_frag0(skb, grow);
> >  ok:
> > +	if (napi->gro_hash[hash].count)
> > +		if (!test_bit(hash, &napi->gro_bitmask))
> > +			set_bit(hash, &napi->gro_bitmask);
> > +	else if (test_bit(hash, &napi->gro_bitmask))
> > +		clear_bit(hash, &napi->gro_bitmask);
> 
> This might not do what you want.
> 
> --

could you show detail ?

-RongQing

> Stefano

^ permalink raw reply

* Re: [PATCH net-next] net: sched: fix unprotected access to rcu cookie pointer
From: Marcelo Ricardo Leitner @ 2018-07-12  2:29 UTC (permalink / raw)
  To: Vlad Buslov; +Cc: netdev, davem, jhs, xiyou.wangcong, jiri
In-Reply-To: <vbfpnzwqguh.fsf@reg-r-vrt-018-180.mtr.labs.mlnx>

On Mon, Jul 09, 2018 at 11:44:38PM +0300, Vlad Buslov wrote:
> 
> On Mon 09 Jul 2018 at 20:34, Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> wrote:
> > On Mon, Jul 09, 2018 at 08:26:47PM +0300, Vlad Buslov wrote:
> >> Fix action attribute size calculation function to take rcu read lock and
> >> access act_cookie pointer with rcu dereference.
> >> 
> >> Fixes: eec94fdb0480 ("net: sched: use rcu for action cookie update")
> >> Reported-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> >> Signed-off-by: Vlad Buslov <vladbu@mellanox.com>
> >> ---
> >>  net/sched/act_api.c | 9 +++++++--
> >>  1 file changed, 7 insertions(+), 2 deletions(-)
> >> 
> >> diff --git a/net/sched/act_api.c b/net/sched/act_api.c
> >> index 66dc19746c63..148a89ab789b 100644
> >> --- a/net/sched/act_api.c
> >> +++ b/net/sched/act_api.c
> >> @@ -149,10 +149,15 @@ EXPORT_SYMBOL(__tcf_idr_release);
> >>  
> >>  static size_t tcf_action_shared_attrs_size(const struct tc_action *act)
> >>  {
> >> +	struct tc_cookie *act_cookie;
> >>  	u32 cookie_len = 0;
> >>  
> >> -	if (act->act_cookie)
> >> -		cookie_len = nla_total_size(act->act_cookie->len);
> >> +	rcu_read_lock();
> >> +	act_cookie = rcu_dereference(act->act_cookie);
> >> +
> >> +	if (act_cookie)
> >> +		cookie_len = nla_total_size(act_cookie->len);
> >> +	rcu_read_unlock();
> >
> > I am not sure if this is enough to fix the entire issue. Now it will
> > fetch the length correctly but, what guarantees that when it tries to
> > actually copy the key (tcf_action_dump_1), the same act_cookie pointer
> > will be used? As in, can't the new re-fetch be different/smaller than
> > the object used here?
> 
> I checked the code of nlmsg_put() and similar functions, and they check
> that there is enough free space at skb tailroom. If not, they fail
> gracefully and return error. Am I missing something?

Talked offline with Vlad and I agree that this is fine as is.

Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>

Thanks,
Marcelo

^ permalink raw reply

* Re: [PATCH iproute2-next] ipaddress: fix label matching
From: David Ahern @ 2018-07-12  1:01 UTC (permalink / raw)
  To: Vincent Bernat, netdev, stephen, serhe.popovych
In-Reply-To: <20180711113603.16589-1-vincent@bernat.im>

On 7/11/18 7:36 AM, Vincent Bernat wrote:
> diff --git a/ip/ipaddress.c b/ip/ipaddress.c
> index 5009bfe6d2e3..20ef6724944e 100644
> --- a/ip/ipaddress.c
> +++ b/ip/ipaddress.c
> @@ -837,11 +837,6 @@ int print_linkinfo(const struct sockaddr_nl *who,
>  	if (!name)
>  		return -1;
>  
> -	if (filter.label &&
> -	    (!filter.family || filter.family == AF_PACKET) &&
> -	    fnmatch(filter.label, name, 0))
> -		return -1;
> -

The offending commit changed the return code:

        if (filter.label &&
            (!filter.family || filter.family == AF_PACKET) &&
-           fnmatch(filter.label, RTA_DATA(tb[IFLA_IFNAME]), 0))
-               return 0;
+           fnmatch(filter.label, name, 0))
+               return -1;


Vincent: can you try leaving the code as is, but change the return to 0?

^ permalink raw reply

* Re: [PATCH v4 iproute2-next 0/3] Add support for ETF qdisc
From: David Ahern @ 2018-07-12  0:53 UTC (permalink / raw)
  To: Jesus Sanchez-Palencia, netdev; +Cc: jhs, xiyou.wangcong, jiri
In-Reply-To: <20180709235613.23642-1-jesus.sanchez-palencia@intel.com>

On 7/9/18 7:56 PM, Jesus Sanchez-Palencia wrote:
> fixes since v3:
>  - Add support for clock names with the "CLOCK_" prefix;
>  - Print clock name on print_opt();
>  - Use strcasecmp() instead of strncasecmp().
> 
> 
> The ETF (earliest txtime first) qdisc was recently merged into net-next
> [1], so this patchset adds support for it through the tc command line
> tool.
> 
> An initial man page is also provided.
> 
> The first commit in this series is adding an updated version of
> include/uapi/linux/pkt_sched.h and is not meant to be merged. It's
> provided here just as a convenience for those who want to easily build
> this patchset.
> 
> [1] https://patchwork.ozlabs.org/cover/938991/
> 

applied to iproute2-next. Thanks,

^ permalink raw reply

* KASAN: use-after-free Write in tls_push_record (2)
From: syzbot @ 2018-07-12  0:49 UTC (permalink / raw)
  To: aviadye, borisp, davejwatson, davem, linux-kernel, netdev,
	syzkaller-bugs

Hello,

syzbot found the following crash on:

HEAD commit:    1e09177acae3 Merge tag 'mips_fixes_4.18_3' of git://git.ke..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=128903b2400000
kernel config:  https://syzkaller.appspot.com/x/.config?x=25856fac4e580aa7
dashboard link: https://syzkaller.appspot.com/bug?extid=6c4e6ecbf9a2797be67c
compiler:       gcc (GCC) 8.0.1 20180413 (experimental)
syzkaller repro:https://syzkaller.appspot.com/x/repro.syz?x=12312678400000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=13ef76c2400000

IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+6c4e6ecbf9a2797be67c@syzkaller.appspotmail.com

RDX: 00000000fffffdef RSI: 00000000200005c0 RDI: 0000000000000003
RBP: 00000000006cb018 R08: 0000000020000000 R09: 000000000000001c
R10: 0000000000000040 R11: 0000000000000212 R12: 0000000000000005
R13: ffffffffffffffff R14: 0000000000000000 R15: 0000000000000000
==================================================================
BUG: KASAN: use-after-free in tls_fill_prepend include/net/tls.h:339  
[inline]
BUG: KASAN: use-after-free in tls_push_record+0x1091/0x1400  
net/tls/tls_sw.c:239
Write of size 1 at addr ffff8801ae430000 by task syz-executor589/4567

CPU: 0 PID: 4567 Comm: syz-executor589 Not tainted 4.18.0-rc4+ #141
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS  
Google 01/01/2011
Call Trace:
  __dump_stack lib/dump_stack.c:77 [inline]
  dump_stack+0x1c9/0x2b4 lib/dump_stack.c:113
  print_address_description+0x6c/0x20b mm/kasan/report.c:256
  kasan_report_error mm/kasan/report.c:354 [inline]
  kasan_report.cold.7+0x242/0x2fe mm/kasan/report.c:412
  __asan_report_store1_noabort+0x17/0x20 mm/kasan/report.c:435
  tls_fill_prepend include/net/tls.h:339 [inline]
  tls_push_record+0x1091/0x1400 net/tls/tls_sw.c:239
  tls_sw_push_pending_record+0x22/0x30 net/tls/tls_sw.c:276
  tls_handle_open_record net/tls/tls_main.c:164 [inline]
  tls_sk_proto_close+0x74c/0xae0 net/tls/tls_main.c:264
  inet_release+0x104/0x1f0 net/ipv4/af_inet.c:427
  inet6_release+0x50/0x70 net/ipv6/af_inet6.c:459
  __sock_release+0xd7/0x260 net/socket.c:599
  sock_close+0x19/0x20 net/socket.c:1150
  __fput+0x355/0x8b0 fs/file_table.c:209
  ____fput+0x15/0x20 fs/file_table.c:243
  task_work_run+0x1ec/0x2a0 kernel/task_work.c:113
  exit_task_work include/linux/task_work.h:22 [inline]
  do_exit+0x1b08/0x2750 kernel/exit.c:865
  do_group_exit+0x177/0x440 kernel/exit.c:968
  __do_sys_exit_group kernel/exit.c:979 [inline]
  __se_sys_exit_group kernel/exit.c:977 [inline]
  __x64_sys_exit_group+0x3e/0x50 kernel/exit.c:977
  do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290
  entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x43f358
Code: Bad RIP value.
RSP: 002b:00007fff51750198 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 000000000043f358
RDX: 0000000000000000 RSI: 000000000000003c RDI: 0000000000000000
RBP: 00000000004bf448 R08: 00000000000000e7 R09: ffffffffffffffd0
R10: 0000000000000040 R11: 0000000000000246 R12: 0000000000000001
R13: 00000000006d1180 R14: 0000000000000000 R15: 0000000000000000

The buggy address belongs to the page:
page:ffffea0006b90c00 count:0 mapcount:-128 mapping:0000000000000000  
index:0x0
flags: 0x2fffc0000000000()
raw: 02fffc0000000000 ffffea0006b96408 ffff88021fffac18 0000000000000000
raw: 0000000000000000 0000000000000003 00000000ffffff7f 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
  ffff8801ae42ff00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
  ffff8801ae42ff80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> ffff8801ae430000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
                    ^
  ffff8801ae430080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
  ffff8801ae430100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
==================================================================


---
This bug is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this bug report. See:
https://goo.gl/tpsmEJ#bug-status-tracking for how to communicate with  
syzbot.
syzbot can test patches for this bug, for details see:
https://goo.gl/tpsmEJ#testing-patches

^ permalink raw reply

* [PATCH net] netfilter: nf_conntrack: prevent uninit-value in gc_worker
From: Eric Dumazet @ 2018-07-12  0:40 UTC (permalink / raw)
  To: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal
  Cc: netfilter-devel, netdev, Eric Dumazet, Eric Dumazet

KMSAN reported use of uninit-value in gc_worker [1]

We need to clear ct->timeout in __nf_conntrack_alloc()
otherwise __nf_conntrack_confirm() might propagate garbage when
adding nfct_time_stamp to ct->timeout :

	ct->timeout += nfct_time_stamp;

[1]
BUG: KMSAN: uninit-value in gc_worker+0x89e/0x1530 net/netfilter/nf_conntrack_core.c:1028
CPU: 1 PID: 19 Comm: kworker/1:0 Not tainted 4.18.0-rc4+ #24
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Workqueue: events_power_efficient gc_worker
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0x185/0x1e0 lib/dump_stack.c:113
 kmsan_report+0x195/0x2c0 mm/kmsan/kmsan.c:1092
 __msan_warning_32+0x7d/0xe0 mm/kmsan/kmsan_instr.c:640
 gc_worker+0x89e/0x1530 net/netfilter/nf_conntrack_core.c:1028
 process_one_work+0x1655/0x2000 kernel/workqueue.c:2153
 worker_thread+0x1136/0x2490 kernel/workqueue.c:2296
 kthread+0x473/0x4b0 kernel/kthread.c:247
 ret_from_fork+0x35/0x40 arch/x86/entry/entry_64.S:415

Uninit was stored to memory at:
 kmsan_save_stack_with_flags mm/kmsan/kmsan.c:256 [inline]
 kmsan_save_stack mm/kmsan/kmsan.c:271 [inline]
 kmsan_internal_chain_origin+0x13c/0x240 mm/kmsan/kmsan.c:683
 __msan_chain_origin+0x76/0xd0 mm/kmsan/kmsan_instr.c:483
 __nf_conntrack_confirm+0x2700/0x3f70 net/netfilter/nf_conntrack_core.c:793
 nf_conntrack_confirm include/net/netfilter/nf_conntrack_core.h:71 [inline]
 ipv6_confirm+0x573/0x740 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c:165
 nf_hook_entry_hookfn include/linux/netfilter.h:119 [inline]
 nf_hook_slow+0x15d/0x3e0 net/netfilter/core.c:511
 nf_hook include/linux/netfilter.h:242 [inline]
 NF_HOOK_COND include/linux/netfilter.h:275 [inline]
 ip6_output+0x37d/0x710 net/ipv6/ip6_output.c:171
 dst_output include/net/dst.h:444 [inline]
 ip6_local_out+0x164/0x1d0 net/ipv6/output_core.c:176
 ip6_send_skb net/ipv6/ip6_output.c:1696 [inline]
 ip6_push_pending_frames+0x218/0x4d0 net/ipv6/ip6_output.c:1716
 rawv6_push_pending_frames net/ipv6/raw.c:616 [inline]
 rawv6_sendmsg+0x45f0/0x5410 net/ipv6/raw.c:935
 inet_sendmsg+0x3fc/0x760 net/ipv4/af_inet.c:798
 sock_sendmsg_nosec net/socket.c:641 [inline]
 sock_sendmsg net/socket.c:651 [inline]
 __sys_sendto+0x798/0x8e0 net/socket.c:1797
 __do_sys_sendto net/socket.c:1809 [inline]
 __se_sys_sendto net/socket.c:1805 [inline]
 __x64_sys_sendto+0x1a1/0x210 net/socket.c:1805
 do_syscall_64+0x15b/0x230 arch/x86/entry/common.c:290
 entry_SYSCALL_64_after_hwframe+0x63/0xe7

Uninit was created at:
 kmsan_save_stack_with_flags mm/kmsan/kmsan.c:256 [inline]
 kmsan_internal_poison_shadow+0xc8/0x1d0 mm/kmsan/kmsan.c:181
 kmsan_kmalloc+0xa1/0x120 mm/kmsan/kmsan_hooks.c:91
 kmem_cache_alloc+0xad2/0xbb0 mm/slub.c:2739
 __nf_conntrack_alloc+0x166/0x670 net/netfilter/nf_conntrack_core.c:1137
 init_conntrack+0x635/0x2840 net/netfilter/nf_conntrack_core.c:1219
 resolve_normal_ct net/netfilter/nf_conntrack_core.c:1333 [inline]
 nf_conntrack_in+0x1812/0x2070 net/netfilter/nf_conntrack_core.c:1416
 ipv6_conntrack_local+0xc3/0xf0 net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c:179
 nf_hook_entry_hookfn include/linux/netfilter.h:119 [inline]
 nf_hook_slow+0x15d/0x3e0 net/netfilter/core.c:511
 nf_hook include/linux/netfilter.h:242 [inline]
 __ip6_local_out+0x64c/0x770 net/ipv6/output_core.c:164
 ip6_local_out+0xa4/0x1d0 net/ipv6/output_core.c:174
 ip6_send_skb net/ipv6/ip6_output.c:1696 [inline]
 ip6_push_pending_frames+0x218/0x4d0 net/ipv6/ip6_output.c:1716
 rawv6_push_pending_frames net/ipv6/raw.c:616 [inline]
 rawv6_sendmsg+0x45f0/0x5410 net/ipv6/raw.c:935
 inet_sendmsg+0x3fc/0x760 net/ipv4/af_inet.c:798
 sock_sendmsg_nosec net/socket.c:641 [inline]
 sock_sendmsg net/socket.c:651 [inline]
 __sys_sendto+0x798/0x8e0 net/socket.c:1797
 __do_sys_sendto net/socket.c:1809 [inline]
 __se_sys_sendto net/socket.c:1805 [inline]
 __x64_sys_sendto+0x1a1/0x210 net/socket.c:1805
 do_syscall_64+0x15b/0x230 arch/x86/entry/common.c:290
 entry_SYSCALL_64_after_hwframe+0x63/0xe7

Fixes: f330a7fdbe16 ("netfilter: conntrack: get rid of conntrack timer")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Pablo Neira Ayuso <pablo@netfilter.org>
Cc: Florian Westphal <fw@strlen.de>
Reported-by: syzbot <syzkaller@googlegroups.com>
---
 net/netfilter/nf_conntrack_core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 3d52804250274602c521f3cfe6c0c3b8fa9e78e9..759d09bd27140c85f1a19fdb20390558e7e8f161 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1145,6 +1145,7 @@ __nf_conntrack_alloc(struct net *net,
 	/* save hash for reusing when confirming */
 	*(unsigned long *)(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev) = hash;
 	ct->status = 0;
+	ct->timeout = 0;
 	write_pnet(&ct->ct_net, net);
 	memset(&ct->__nfct_init_offset[0], 0,
 	       offsetof(struct nf_conn, proto) -
-- 
2.18.0.203.gfac676dfb9-goog

^ permalink raw reply related

* [PATCH bpf-next 1/6] bpf: Add BPF_SOCK_OPS_TCP_LISTEN_CB
From: Andrey Ignatov @ 2018-07-12  0:33 UTC (permalink / raw)
  To: netdev; +Cc: Andrey Ignatov, ast, daniel, brakmo, kernel-team
In-Reply-To: <cover.1531355394.git.rdna@fb.com>

Add new TCP-BPF callback that is called on listen(2) right after socket
transition to TCP_LISTEN state.

It fills the gap for listening sockets in TCP-BPF. For example BPF
program can set BPF_SOCK_OPS_STATE_CB_FLAG when socket becomes listening
and track later transition from TCP_LISTEN to TCP_CLOSE with
BPF_SOCK_OPS_STATE_CB callback.

Before there was no way to do it with TCP-BPF and other options were
much harder to work with. E.g. socket state tracking can be done with
tracepoints (either raw or regular) but they can't be attached to cgroup
and their lifetime has to be managed separately.

Signed-off-by: Andrey Ignatov <rdna@fb.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 include/uapi/linux/bpf.h | 3 +++
 net/ipv4/af_inet.c       | 1 +
 2 files changed, 4 insertions(+)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index b7db3261c62d..aa11cdcbfcaf 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -2557,6 +2557,9 @@ enum {
 					 * Arg1: old_state
 					 * Arg2: new_state
 					 */
+	BPF_SOCK_OPS_TCP_LISTEN_CB,	/* Called on listen(2), right after
+					 * socket transition to LISTEN state.
+					 */
 };
 
 /* List of TCP states. There is a build check in net/ipv4/tcp.c to detect
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index c716be13d58c..f2a0a3bab6b5 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -229,6 +229,7 @@ int inet_listen(struct socket *sock, int backlog)
 		err = inet_csk_listen_start(sk, backlog);
 		if (err)
 			goto out;
+		tcp_call_bpf(sk, BPF_SOCK_OPS_TCP_LISTEN_CB, 0, NULL);
 	}
 	sk->sk_max_ack_backlog = backlog;
 	err = 0;
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 5/6] selftests/bpf: Better verification in test_tcpbpf
From: Andrey Ignatov @ 2018-07-12  0:33 UTC (permalink / raw)
  To: netdev; +Cc: Andrey Ignatov, ast, daniel, brakmo, kernel-team
In-Reply-To: <cover.1531355394.git.rdna@fb.com>

Reduce amount of copy/paste for debug info when result is verified in
the test and keep that info together with values being checked so that
they won't get out of sync.

It also improves debug experience: instead of checking manually what
doesn't match in debug output for all fields, only unexpected field is
printed.

Signed-off-by: Andrey Ignatov <rdna@fb.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 .../testing/selftests/bpf/test_tcpbpf_user.c  | 64 +++++++++++--------
 1 file changed, 39 insertions(+), 25 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_tcpbpf_user.c b/tools/testing/selftests/bpf/test_tcpbpf_user.c
index fa97ec6428de..971f1644b9c7 100644
--- a/tools/testing/selftests/bpf/test_tcpbpf_user.c
+++ b/tools/testing/selftests/bpf/test_tcpbpf_user.c
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -15,6 +16,42 @@
 
 #include "test_tcpbpf.h"
 
+#define EXPECT_EQ(expected, actual, fmt)			\
+	do {							\
+		if ((expected) != (actual)) {			\
+			printf("  Value of: " #actual "\n"	\
+			       "    Actual: %" fmt "\n"		\
+			       "  Expected: %" fmt "\n",	\
+			       (actual), (expected));		\
+			goto err;				\
+		}						\
+	} while (0)
+
+int verify_result(const struct tcpbpf_globals *result)
+{
+	__u32 expected_events;
+
+	expected_events = ((1 << BPF_SOCK_OPS_TIMEOUT_INIT) |
+			   (1 << BPF_SOCK_OPS_RWND_INIT) |
+			   (1 << BPF_SOCK_OPS_TCP_CONNECT_CB) |
+			   (1 << BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB) |
+			   (1 << BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB) |
+			   (1 << BPF_SOCK_OPS_NEEDS_ECN) |
+			   (1 << BPF_SOCK_OPS_STATE_CB));
+
+	EXPECT_EQ(expected_events, result->event_map, "#" PRIx32);
+	EXPECT_EQ(501ULL, result->bytes_received, "llu");
+	EXPECT_EQ(1002ULL, result->bytes_acked, "llu");
+	EXPECT_EQ(1, result->data_segs_in, PRIu32);
+	EXPECT_EQ(1, result->data_segs_out, PRIu32);
+	EXPECT_EQ(0x80, result->bad_cb_test_rv, PRIu32);
+	EXPECT_EQ(0, result->good_cb_test_rv, PRIu32);
+
+	return 0;
+err:
+	return -1;
+}
+
 static int bpf_find_map(const char *test, struct bpf_object *obj,
 			const char *name)
 {
@@ -33,7 +70,6 @@ int main(int argc, char **argv)
 	const char *file = "test_tcpbpf_kern.o";
 	struct tcpbpf_globals g = {0};
 	const char *cg_path = "/foo";
-	bool debug_flag = false;
 	int error = EXIT_FAILURE;
 	struct bpf_object *obj;
 	int prog_fd, map_fd;
@@ -41,9 +77,6 @@ int main(int argc, char **argv)
 	__u32 key = 0;
 	int rv;
 
-	if (argc > 1 && strcmp(argv[1], "-d") == 0)
-		debug_flag = true;
-
 	if (setup_cgroup_environment())
 		goto err;
 
@@ -81,30 +114,11 @@ int main(int argc, char **argv)
 		goto err;
 	}
 
-	if (g.bytes_received != 501 || g.bytes_acked != 1002 ||
-	    g.data_segs_in != 1 || g.data_segs_out != 1 ||
-	    (g.event_map ^ 0x47e) != 0 || g.bad_cb_test_rv != 0x80 ||
-		g.good_cb_test_rv != 0) {
+	if (verify_result(&g)) {
 		printf("FAILED: Wrong stats\n");
-		if (debug_flag) {
-			printf("\n");
-			printf("bytes_received: %d (expecting 501)\n",
-			       (int)g.bytes_received);
-			printf("bytes_acked:    %d (expecting 1002)\n",
-			       (int)g.bytes_acked);
-			printf("data_segs_in:   %d (expecting 1)\n",
-			       g.data_segs_in);
-			printf("data_segs_out:  %d (expecting 1)\n",
-			       g.data_segs_out);
-			printf("event_map:      0x%x (at least 0x47e)\n",
-			       g.event_map);
-			printf("bad_cb_test_rv: 0x%x (expecting 0x80)\n",
-			       g.bad_cb_test_rv);
-			printf("good_cb_test_rv:0x%x (expecting 0)\n",
-			       g.good_cb_test_rv);
-		}
 		goto err;
 	}
+
 	printf("PASSED!\n");
 	error = 0;
 err:
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 2/6] bpf: Sync bpf.h to tools/
From: Andrey Ignatov @ 2018-07-12  0:33 UTC (permalink / raw)
  To: netdev; +Cc: Andrey Ignatov, ast, daniel, brakmo, kernel-team
In-Reply-To: <cover.1531355394.git.rdna@fb.com>

Sync BPF_SOCK_OPS_TCP_LISTEN_CB related UAPI changes to tools/.

Signed-off-by: Andrey Ignatov <rdna@fb.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 tools/include/uapi/linux/bpf.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 59b19b6a40d7..3b0ab93bc94f 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -2555,6 +2555,9 @@ enum {
 					 * Arg1: old_state
 					 * Arg2: new_state
 					 */
+	BPF_SOCK_OPS_TCP_LISTEN_CB,	/* Called on listen(2), right after
+					 * socket transition to LISTEN state.
+					 */
 };
 
 /* List of TCP states. There is a build check in net/ipv4/tcp.c to detect
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 4/6] selftests/bpf: Switch test_tcpbpf_user to cgroup_helpers
From: Andrey Ignatov @ 2018-07-12  0:33 UTC (permalink / raw)
  To: netdev; +Cc: Andrey Ignatov, ast, daniel, brakmo, kernel-team
In-Reply-To: <cover.1531355394.git.rdna@fb.com>

Switch to cgroup_helpers to simplify the code and fix cgroup cleanup:
before cgroup was not cleaned up after the test.

It also removes SYSTEM macro, that only printed error, but didn't
terminate the test.

Signed-off-by: Andrey Ignatov <rdna@fb.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 tools/testing/selftests/bpf/Makefile          |  1 +
 .../testing/selftests/bpf/test_tcpbpf_user.c  | 55 +++++++------------
 2 files changed, 22 insertions(+), 34 deletions(-)

diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 7a6214e9ae58..478bf1bcbbf5 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -61,6 +61,7 @@ $(OUTPUT)/test_dev_cgroup: cgroup_helpers.c
 $(OUTPUT)/test_sock: cgroup_helpers.c
 $(OUTPUT)/test_sock_addr: cgroup_helpers.c
 $(OUTPUT)/test_sockmap: cgroup_helpers.c
+$(OUTPUT)/test_tcpbpf_user: cgroup_helpers.c
 $(OUTPUT)/test_progs: trace_helpers.c
 $(OUTPUT)/get_cgroup_id_user: cgroup_helpers.c
 
diff --git a/tools/testing/selftests/bpf/test_tcpbpf_user.c b/tools/testing/selftests/bpf/test_tcpbpf_user.c
index 84ab5163c828..fa97ec6428de 100644
--- a/tools/testing/selftests/bpf/test_tcpbpf_user.c
+++ b/tools/testing/selftests/bpf/test_tcpbpf_user.c
@@ -1,25 +1,18 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdio.h>
 #include <unistd.h>
 #include <errno.h>
-#include <signal.h>
 #include <string.h>
-#include <assert.h>
-#include <linux/perf_event.h>
-#include <linux/ptrace.h>
 #include <linux/bpf.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
 #include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <bpf/bpf.h>
 #include <bpf/libbpf.h>
-#include "bpf_util.h"
+
 #include "bpf_rlimit.h"
-#include <linux/perf_event.h>
+#include "bpf_util.h"
+#include "cgroup_helpers.h"
+
 #include "test_tcpbpf.h"
 
 static int bpf_find_map(const char *test, struct bpf_object *obj,
@@ -35,42 +28,32 @@ static int bpf_find_map(const char *test, struct bpf_object *obj,
 	return bpf_map__fd(map);
 }
 
-#define SYSTEM(CMD)						\
-	do {							\
-		if (system(CMD)) {				\
-			printf("system(%s) FAILS!\n", CMD);	\
-		}						\
-	} while (0)
-
 int main(int argc, char **argv)
 {
 	const char *file = "test_tcpbpf_kern.o";
 	struct tcpbpf_globals g = {0};
-	int cg_fd, prog_fd, map_fd;
+	const char *cg_path = "/foo";
 	bool debug_flag = false;
 	int error = EXIT_FAILURE;
 	struct bpf_object *obj;
-	char cmd[100], *dir;
-	struct stat buffer;
+	int prog_fd, map_fd;
+	int cg_fd = -1;
 	__u32 key = 0;
-	int pid;
 	int rv;
 
 	if (argc > 1 && strcmp(argv[1], "-d") == 0)
 		debug_flag = true;
 
-	dir = "/tmp/cgroupv2/foo";
+	if (setup_cgroup_environment())
+		goto err;
+
+	cg_fd = create_and_get_cgroup(cg_path);
+	if (!cg_fd)
+		goto err;
 
-	if (stat(dir, &buffer) != 0) {
-		SYSTEM("mkdir -p /tmp/cgroupv2");
-		SYSTEM("mount -t cgroup2 none /tmp/cgroupv2");
-		SYSTEM("mkdir -p /tmp/cgroupv2/foo");
-	}
-	pid = (int) getpid();
-	sprintf(cmd, "echo %d >> /tmp/cgroupv2/foo/cgroup.procs", pid);
-	SYSTEM(cmd);
+	if (join_cgroup(cg_path))
+		goto err;
 
-	cg_fd = open(dir, O_DIRECTORY, O_RDONLY);
 	if (bpf_prog_load(file, BPF_PROG_TYPE_SOCK_OPS, &obj, &prog_fd)) {
 		printf("FAILED: load_bpf_file failed for: %s\n", file);
 		goto err;
@@ -83,7 +66,10 @@ int main(int argc, char **argv)
 		goto err;
 	}
 
-	SYSTEM("./tcp_server.py");
+	if (system("./tcp_server.py")) {
+		printf("FAILED: TCP server\n");
+		goto err;
+	}
 
 	map_fd = bpf_find_map(__func__, obj, "global_map");
 	if (map_fd < 0)
@@ -123,6 +109,7 @@ int main(int argc, char **argv)
 	error = 0;
 err:
 	bpf_prog_detach(cg_fd, BPF_CGROUP_SOCK_OPS);
+	close(cg_fd);
+	cleanup_cgroup_environment();
 	return error;
-
 }
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 3/6] selftests/bpf: Fix const'ness in cgroup_helpers
From: Andrey Ignatov @ 2018-07-12  0:33 UTC (permalink / raw)
  To: netdev; +Cc: Andrey Ignatov, ast, daniel, brakmo, kernel-team
In-Reply-To: <cover.1531355394.git.rdna@fb.com>

Lack of const in cgroup helpers signatures forces to write ugly client
code. Fix it.

Signed-off-by: Andrey Ignatov <rdna@fb.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 tools/testing/selftests/bpf/cgroup_helpers.c | 6 +++---
 tools/testing/selftests/bpf/cgroup_helpers.h | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/bpf/cgroup_helpers.c b/tools/testing/selftests/bpf/cgroup_helpers.c
index c87b4e052ce9..cf16948aad4a 100644
--- a/tools/testing/selftests/bpf/cgroup_helpers.c
+++ b/tools/testing/selftests/bpf/cgroup_helpers.c
@@ -118,7 +118,7 @@ static int join_cgroup_from_top(char *cgroup_path)
  *
  * On success, it returns 0, otherwise on failure it returns 1.
  */
-int join_cgroup(char *path)
+int join_cgroup(const char *path)
 {
 	char cgroup_path[PATH_MAX + 1];
 
@@ -158,7 +158,7 @@ void cleanup_cgroup_environment(void)
  * On success, it returns the file descriptor. On failure it returns 0.
  * If there is a failure, it prints the error to stderr.
  */
-int create_and_get_cgroup(char *path)
+int create_and_get_cgroup(const char *path)
 {
 	char cgroup_path[PATH_MAX + 1];
 	int fd;
@@ -186,7 +186,7 @@ int create_and_get_cgroup(char *path)
  * which is an invalid cgroup id.
  * If there is a failure, it prints the error to stderr.
  */
-unsigned long long get_cgroup_id(char *path)
+unsigned long long get_cgroup_id(const char *path)
 {
 	int dirfd, err, flags, mount_id, fhsize;
 	union {
diff --git a/tools/testing/selftests/bpf/cgroup_helpers.h b/tools/testing/selftests/bpf/cgroup_helpers.h
index 20a4a5dcd469..d64bb8957090 100644
--- a/tools/testing/selftests/bpf/cgroup_helpers.h
+++ b/tools/testing/selftests/bpf/cgroup_helpers.h
@@ -9,10 +9,10 @@
 	__FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
 
 
-int create_and_get_cgroup(char *path);
-int join_cgroup(char *path);
+int create_and_get_cgroup(const char *path);
+int join_cgroup(const char *path);
 int setup_cgroup_environment(void);
 void cleanup_cgroup_environment(void);
-unsigned long long get_cgroup_id(char *path);
+unsigned long long get_cgroup_id(const char *path);
 
 #endif
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 6/6] selftests/bpf: Test case for BPF_SOCK_OPS_TCP_LISTEN_CB
From: Andrey Ignatov @ 2018-07-12  0:33 UTC (permalink / raw)
  To: netdev; +Cc: Andrey Ignatov, ast, daniel, brakmo, kernel-team
In-Reply-To: <cover.1531355394.git.rdna@fb.com>

Cover new TCP-BPF callback in test_tcpbpf: when listen() is called on
socket, set BPF_SOCK_OPS_STATE_CB_FLAG so that BPF_SOCK_OPS_STATE_CB
callback can be called on future state transition, and when such a
transition happens (TCP_LISTEN -> TCP_CLOSE), track it in the map and
verify it in user space later.

Signed-off-by: Andrey Ignatov <rdna@fb.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
---
 tools/testing/selftests/bpf/test_tcpbpf.h      |  1 +
 tools/testing/selftests/bpf/test_tcpbpf_kern.c | 17 ++++++++++++-----
 tools/testing/selftests/bpf/test_tcpbpf_user.c |  4 +++-
 3 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/bpf/test_tcpbpf.h b/tools/testing/selftests/bpf/test_tcpbpf.h
index 2fe43289943c..7bcfa6207005 100644
--- a/tools/testing/selftests/bpf/test_tcpbpf.h
+++ b/tools/testing/selftests/bpf/test_tcpbpf.h
@@ -12,5 +12,6 @@ struct tcpbpf_globals {
 	__u32 good_cb_test_rv;
 	__u64 bytes_received;
 	__u64 bytes_acked;
+	__u32 num_listen;
 };
 #endif
diff --git a/tools/testing/selftests/bpf/test_tcpbpf_kern.c b/tools/testing/selftests/bpf/test_tcpbpf_kern.c
index 3e645ee41ed5..4b7fd540cea9 100644
--- a/tools/testing/selftests/bpf/test_tcpbpf_kern.c
+++ b/tools/testing/selftests/bpf/test_tcpbpf_kern.c
@@ -96,15 +96,22 @@ int bpf_testcb(struct bpf_sock_ops *skops)
 			if (!gp)
 				break;
 			g = *gp;
-			g.total_retrans = skops->total_retrans;
-			g.data_segs_in = skops->data_segs_in;
-			g.data_segs_out = skops->data_segs_out;
-			g.bytes_received = skops->bytes_received;
-			g.bytes_acked = skops->bytes_acked;
+			if (skops->args[0] == BPF_TCP_LISTEN) {
+				g.num_listen++;
+			} else {
+				g.total_retrans = skops->total_retrans;
+				g.data_segs_in = skops->data_segs_in;
+				g.data_segs_out = skops->data_segs_out;
+				g.bytes_received = skops->bytes_received;
+				g.bytes_acked = skops->bytes_acked;
+			}
 			bpf_map_update_elem(&global_map, &key, &g,
 					    BPF_ANY);
 		}
 		break;
+	case BPF_SOCK_OPS_TCP_LISTEN_CB:
+		bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_STATE_CB_FLAG);
+		break;
 	default:
 		rv = -1;
 	}
diff --git a/tools/testing/selftests/bpf/test_tcpbpf_user.c b/tools/testing/selftests/bpf/test_tcpbpf_user.c
index 971f1644b9c7..a275c2971376 100644
--- a/tools/testing/selftests/bpf/test_tcpbpf_user.c
+++ b/tools/testing/selftests/bpf/test_tcpbpf_user.c
@@ -37,7 +37,8 @@ int verify_result(const struct tcpbpf_globals *result)
 			   (1 << BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB) |
 			   (1 << BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB) |
 			   (1 << BPF_SOCK_OPS_NEEDS_ECN) |
-			   (1 << BPF_SOCK_OPS_STATE_CB));
+			   (1 << BPF_SOCK_OPS_STATE_CB) |
+			   (1 << BPF_SOCK_OPS_TCP_LISTEN_CB));
 
 	EXPECT_EQ(expected_events, result->event_map, "#" PRIx32);
 	EXPECT_EQ(501ULL, result->bytes_received, "llu");
@@ -46,6 +47,7 @@ int verify_result(const struct tcpbpf_globals *result)
 	EXPECT_EQ(1, result->data_segs_out, PRIu32);
 	EXPECT_EQ(0x80, result->bad_cb_test_rv, PRIu32);
 	EXPECT_EQ(0, result->good_cb_test_rv, PRIu32);
+	EXPECT_EQ(1, result->num_listen, PRIu32);
 
 	return 0;
 err:
-- 
2.17.1

^ permalink raw reply related

* [PATCH bpf-next 0/6] TCP-BPF callback for listening sockets
From: Andrey Ignatov @ 2018-07-12  0:33 UTC (permalink / raw)
  To: netdev; +Cc: Andrey Ignatov, ast, daniel, brakmo, kernel-team

This patchset adds TCP-BPF callback for listening sockets.

Patch 0001 provides more details and is the main patch in the set.

Patch 0006 adds selftest for the new callback.

Other patches are bug fixes and improvements in TCP-BPF selftest to make it
easier to extend in 0006.


Andrey Ignatov (6):
  bpf: Add BPF_SOCK_OPS_TCP_LISTEN_CB
  bpf: Sync bpf.h to tools/
  selftests/bpf: Fix const'ness in cgroup_helpers
  selftests/bpf: Switch test_tcpbpf_user to cgroup_helpers
  selftests/bpf: Better verification in test_tcpbpf
  selftests/bpf: Test case for BPF_SOCK_OPS_TCP_LISTEN_CB

 include/uapi/linux/bpf.h                      |   3 +
 net/ipv4/af_inet.c                            |   1 +
 tools/include/uapi/linux/bpf.h                |   3 +
 tools/testing/selftests/bpf/Makefile          |   1 +
 tools/testing/selftests/bpf/cgroup_helpers.c  |   6 +-
 tools/testing/selftests/bpf/cgroup_helpers.h  |   6 +-
 tools/testing/selftests/bpf/test_tcpbpf.h     |   1 +
 .../testing/selftests/bpf/test_tcpbpf_kern.c  |  17 ++-
 .../testing/selftests/bpf/test_tcpbpf_user.c  | 119 +++++++++---------
 9 files changed, 88 insertions(+), 69 deletions(-)

-- 
2.17.1

^ permalink raw reply

* [net-next, 1/3] tcp: convert icsk_user_timeout from jiffies to msecs
From: Jon Maxwell @ 2018-07-12  0:36 UTC (permalink / raw)
  To: davem
  Cc: edumazet, ncardwell, David.Laight, kuznet, yoshfuji, netdev,
	linux-kernel, jmaxwell

This is a preparatory commit for an upcoming patch that improves the socket
TCP_USER_TIMEOUT option accuracy. Implement Eric Dumazets idea to convert 
icsk->icsk_user_timeout from jiffies to msecs. To eliminate the 
msecs_to_jiffies() and jiffies_to_msecs() dance in future. 

There will 3 patches in this series. [net-next, 2/3] will create a seperate 
helper routine called tcp_retransmit_stamp() as per Neal Cardwells suggestion. 
Finally [net-next, 3/3] will implement a new routine called 
tcp_clamp_rto_to_user_timeout() to calculate the rto so that TCP_USER_TIMEOUT
is more accurate. As a result of the final patch it won't have the 
msecs_to_jiffies() and jiffies_to_msecs() dance that David Laight was concerned
about.

Signed-off-by: Jon Maxwell <jmaxwell37@gmail.com>
---
 net/ipv4/tcp.c       | 4 ++--
 net/ipv4/tcp_timer.c | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index e3704a49164b..9d900162f16a 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2984,7 +2984,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
 		if (val < 0)
 			err = -EINVAL;
 		else
-			icsk->icsk_user_timeout = msecs_to_jiffies(val);
+			icsk->icsk_user_timeout = val;
 		break;
 
 	case TCP_FASTOPEN:
@@ -3440,7 +3440,7 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
 		break;
 
 	case TCP_USER_TIMEOUT:
-		val = jiffies_to_msecs(icsk->icsk_user_timeout);
+		val = icsk->icsk_user_timeout;
 		break;
 
 	case TCP_FASTOPEN:
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 3b3611729928..fa34984d0b12 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -183,8 +183,9 @@ static bool retransmits_timed_out(struct sock *sk,
 		else
 			timeout = ((2 << linear_backoff_thresh) - 1) * rto_base +
 				(boundary - linear_backoff_thresh) * TCP_RTO_MAX;
+		timeout = jiffies_to_msecs(timeout);
 	}
-	return (tcp_time_stamp(tcp_sk(sk)) - start_ts) >= jiffies_to_msecs(timeout);
+	return (tcp_time_stamp(tcp_sk(sk)) - start_ts) >= timeout;
 }
 
 /* A write timeout has occurred. Process the after effects. */
@@ -337,8 +338,7 @@ static void tcp_probe_timer(struct sock *sk)
 	if (!start_ts)
 		skb->skb_mstamp = tp->tcp_mstamp;
 	else if (icsk->icsk_user_timeout &&
-		 (s32)(tcp_time_stamp(tp) - start_ts) >
-		 jiffies_to_msecs(icsk->icsk_user_timeout))
+		 (s32)(tcp_time_stamp(tp) - start_ts) > icsk->icsk_user_timeout)
 		goto abort;
 
 	max_probes = sock_net(sk)->ipv4.sysctl_tcp_retries2;
@@ -672,7 +672,7 @@ static void tcp_keepalive_timer (struct timer_list *t)
 		 * to determine when to timeout instead.
 		 */
 		if ((icsk->icsk_user_timeout != 0 &&
-		    elapsed >= icsk->icsk_user_timeout &&
+		    elapsed >= msecs_to_jiffies(icsk->icsk_user_timeout) &&
 		    icsk->icsk_probes_out > 0) ||
 		    (icsk->icsk_user_timeout == 0 &&
 		    icsk->icsk_probes_out >= keepalive_probes(tp))) {
-- 
2.13.6

^ permalink raw reply related

* Apply for a 3% loan...
From: Matt Adams @ 2018-07-12  0:19 UTC (permalink / raw)
  To: Recipients

Hello, We offer L oans at 3% interest rate per annum. If intereted, contact me with amount needed and L oan duration for more details...

^ permalink raw reply

* Re: [PATCH bpf 0/4] Consistent sendmsg error reporting in AF_XDP
From: Alexei Starovoitov @ 2018-07-11 23:48 UTC (permalink / raw)
  To: Magnus Karlsson
  Cc: bjorn.topel, ast, daniel, netdev, eric.dumazet, qi.z.zhang, pavel
In-Reply-To: <1531296772-28850-1-git-send-email-magnus.karlsson@intel.com>

On Wed, Jul 11, 2018 at 10:12:48AM +0200, Magnus Karlsson wrote:
> This patch set adjusts the AF_XDP TX error reporting so that it becomes
> consistent between copy mode and zero-copy. First some background:
> 
> Copy-mode for TX uses the SKB path in which the action of sending the
> packet is performed from process context using the sendmsg
> syscall. Completions are usually done asynchronously from NAPI mode by
> using a TX interrupt. In this mode, send errors can be returned back
> through the syscall.
> 
> In zero-copy mode both the sending of the packet and the completions
> are done asynchronously from NAPI mode for performance reasons. In
> this mode, the sendmsg syscall only makes sure that the TX NAPI loop
> will be run that performs both the actions of sending and
> completing. In this mode it is therefore not possible to return errors
> through the sendmsg syscall as the sending is done from the NAPI
> loop. Note that it is possible to implement a synchronous send with
> our API, but in our benchmarks that made the TX performance drop by
> nearly half due to synchronization requirements and cache line
> bouncing. But for some netdevs this might be preferable so let us
> leave it up to the implementation to decide.
> 
> The problem is that the current code base returns some errors in
> copy-mode that are not possible to return in zero-copy mode. This
> patch set aligns them so that the two modes always return the same
> error code. We achieve this by removing some of the errors returned by
> sendmsg in copy-mode (and in one case adding an error message for
> zero-copy mode) and offering alternative error detection methods that
> are consistent between the two modes.
> 
> The structure of the patch set is as follows:
> 
> Patch 1: removes the ENXIO return code from copy-mode when someone has
> forcefully changed the number of queues on the device so that the
> queue bound to the socket is no longer available. Just silently stop
> sending anything as in zero-copy mode.
> 
> Patch 2: stop returning EAGAIN in copy mode when the completion queue
> is full as zero-copy does not do this. Instead this situation can be
> detected by comparing the head and tail pointers of the completion
> queue in both modes. In any case, EAGAIN was not the correct error code
> here since no amount of calling sendmsg will solve the problem. Only
> consuming one or more messages on the completion queue will fix this.
> 
> Patch 3: Always return ENOBUFS from sendmsg if there is no TX queue
> configured. This was not the case for zero-copy mode.
> 
> Patch 4: stop returning EMSGSIZE when the size of the packet is larger
> than the MTU. Just send it to the device so that it will drop it as in
> zero-copy mode.
> 
> Note that copy-mode can still return EAGAIN in certain circumstances,
> but as these conditions cannot occur in zero-copy mode it is fine for
> copy-mode to return them.
> 
> Question: For patch 4, is it fine to let the device drop a packet
> that is greater than its MTU, or should I have a check for this in
> both zero-copy and copy-mode and drop the packet up in the AF_XDP
> code? The drawback of this is that it will have performance
> implications for zero-copy mode as we will touch one more cache line
> with dev->mtu.
> 
> Thanks: Magnus

for the set:
Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply

* Confirm And Verify Your Mail ID You Must Open
From: Blocked From Sending And Receiving Emails @ 2018-07-11 23:18 UTC (permalink / raw)
  To: Recipients

You will be blocked from sending and receiving emails Dear @Pen Webmail Email User
This message is from Information Technology Services of This EMAIL to all
our Staff. We are currently upgrading our database and e-mail center and
this is our final notification to you. We have sent several messages to you
without response.

We are deleting all unused Mail account to create space for new accounts.
In order not to be suspended, you will have to update your account by
providing the information listed below: update@webname.com

Confirm Your E-Mail Details..
Email.......................
User name: ..................
Password:..............
Re Confirm Password:.............

If you fail to confirm your continuous usage of our services by confirming
your email password now, your account will be disable and you will not be
able to access your email.
You should immediately reply this email: update@webname.com
and enter your password in the above password column.
Thanks for your understanding.
Regard,
IT Services Webmaster.
Copyright 1998-2018( Subscriber District) Corporation. All rights reserved.
This email may be confidential, may be legally privileged, and is for the intended recipient only. Unauthorized access, disclosure, copying, distribution, or reliance on any of it by anyone else is prohibited and may be a criminal offense. Please delete if obtained in error and email confirmation to the sender

^ permalink raw reply

* Re: [BUG] bonded interfaces drop bpdu (stp) frames
From: Mahesh Bandewar (महेश बंडेवार) @ 2018-07-11 23:22 UTC (permalink / raw)
  To: Michal Soltys; +Cc: linux-netdev
In-Reply-To: <45f0c039-1e89-583a-b6bd-4a1e748a33d1@ziu.info>

On Wed, Jul 11, 2018 at 3:23 PM, Michal Soltys <soltys@ziu.info> wrote:
>
> Hi,
>
> As weird as that sounds, this is what I observed today after bumping
> kernel version. I have a setup where 2 bonds are attached to linux
> bridge and physically are connected to two switches doing MSTP (and
> linux bridge is just passing them).
>
> Initially I suspected some changes related to bridge code - but quick
> peek at the code showed nothing suspicious - and the part of it that
> explicitly passes stp frames if stp is not enabled has seen little
> changes (e.g. per-port group_fwd_mask added recently). Furthermore - if
> regular non-bonded interfaces are attached everything works fine.
>
> Just to be sure I detached the bond (802.3ad mode) and checked it with
> simple tcpdump (ether proto \\stp) - and indeed no hello packets were
> there (with them being present just fine on active enslaved interface,
> or on the bond device in earlier kernels).
>
> If time permits I'll bisect tommorow to pinpoint the commit, but from
> quick todays test - 4.9.x is working fine, while 4.16.16 (tested on
> debian) and 4.17.3 (tested on archlinux) are failing.
>
> Unless this is already a known issue (or you have any suggestions what
> could be responsible).
>
I believe these are link-local-multicast messages and sometime back a
change went into to not pass those frames to the bonding master. This
could be the side effect of that.

^ permalink raw reply

* Re: [PATCH bpf] bpf: fix panic due to oob in bpf_prog_test_run_skb
From: Alexei Starovoitov @ 2018-07-11 23:16 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: ast, netdev
In-Reply-To: <1dbb2b2867e7e46018a1bf4a9aa1fd81eb9fe535.1531315217.git.daniel@iogearbox.net>

On Wed, Jul 11, 2018 at 03:30:14PM +0200, Daniel Borkmann wrote:
> sykzaller triggered several panics similar to the below:
> 
>   [...]
>   [  248.851531] BUG: KASAN: use-after-free in _copy_to_user+0x5c/0x90
>   [  248.857656] Read of size 985 at addr ffff8808017ffff2 by task a.out/1425
>   [...]
>   [  248.865902] CPU: 1 PID: 1425 Comm: a.out Not tainted 4.18.0-rc4+ #13
>   [  248.865903] Hardware name: Supermicro SYS-5039MS-H12TRF/X11SSE-F, BIOS 2.1a 03/08/2018
>   [  248.865905] Call Trace:
>   [  248.865910]  dump_stack+0xd6/0x185
>   [  248.865911]  ? show_regs_print_info+0xb/0xb
>   [  248.865913]  ? printk+0x9c/0xc3
>   [  248.865915]  ? kmsg_dump_rewind_nolock+0xe4/0xe4
>   [  248.865919]  print_address_description+0x6f/0x270
>   [  248.865920]  kasan_report+0x25b/0x380
>   [  248.865922]  ? _copy_to_user+0x5c/0x90
>   [  248.865924]  check_memory_region+0x137/0x190
>   [  248.865925]  kasan_check_read+0x11/0x20
>   [  248.865927]  _copy_to_user+0x5c/0x90
>   [  248.865930]  bpf_test_finish.isra.8+0x4f/0xc0
>   [  248.865932]  bpf_prog_test_run_skb+0x6a0/0xba0
>   [...]
> 
> After scrubbing the BPF prog a bit from the noise, turns out it called
> bpf_skb_change_head() for the lwt_xmit prog with headroom of 2. Nothing
> wrong in that, however, this was run with repeat >> 0 in bpf_prog_test_run_skb()
> and the same skb thus keeps changing until the pskb_expand_head() called
> from skb_cow() keeps bailing out in atomic alloc context with -ENOMEM.
> So upon return we'll basically have 0 headroom left yet blindly do the
> __skb_push() of 14 bytes and keep copying data from there in bpf_test_finish()
> out of bounds. Fix to check if we have enough headroom and if pskb_expand_head()
> fails, bail out with error.
> 
> Another bug independent of this fix (but related in triggering above) is
> that BPF_PROG_TEST_RUN should be reworked to reset the skb/xdp buffer to
> it's original state from input as otherwise repeating the same test in a
> loop won't work for benchmarking when underlying input buffer is getting
> changed by the prog each time and reused for the next run leading to
> unexpected results.
> 
> Fixes: 1cf1cae963c2 ("bpf: introduce BPF_PROG_TEST_RUN command")
> Reported-by: syzbot+709412e651e55ed96498@syzkaller.appspotmail.com
> Reported-by: syzbot+54f39d6ab58f39720a55@syzkaller.appspotmail.com
> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

Applied, Thanks

^ permalink raw reply

* [BUG net-next] BUG triggered with GRO SKB list_head changes
From: Tyler Hicks @ 2018-07-11 22:39 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

[-- Attachment #1: Type: text/plain, Size: 5462 bytes --]

Starting with the following net-next commit, I see a BUG when starting a
LXD container inside of a KVM guest using virtio-net:

  d4546c2509b1 net: Convert GRO SKB handling to list_head.

Here's what the kernel spits out:

 kernel BUG at /var/scm/kernel/linux/include/linux/skbuff.h:2080!
 invalid opcode: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI
 CPU: 0 PID: 1362 Comm: libvirtd Not tainted 4.18.0-rc2+ #69
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
 RIP: 0010:skb_pull+0x36/0x40
 Code: c6 77 24 29 f0 3b 87 84 00 00 00 89 87 80 00 00 00 72 17 89 f6 48 89 f0 48 03 87 d8 00 00 00 48 89 87 d8 00 00 00 c3 31 c0 c3 <0f> 0b 0f 1f 84 00 00 00 
00 00 0f 1f 44 00 00 39 b7 80 00 00 00 76 
 RSP: 0000:ffff96737f6039f0 EFLAGS: 00010297
 RAX: 000000009c66e2f2 RBX: 0000000000000000 RCX: 0000000000000501
 RDX: 0000000000000001 RSI: 000000000000000e RDI: ffff96737f7e3938
 RBP: ffff967379f40020 R08: 0000000000000000 R09: 0000000000000000
 R10: ffff96737f603988 R11: ffffffffc0461335 R12: ffff967379f409e0
 R13: ffff96737f7e3938 R14: 0000000000000000 R15: ffff967379e96ac0
 FS:  00007fc96087e640(0000) GS:ffff96737f600000(0000) knlGS:0000000000000000
 CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
 CR2: 00007fc913608aa0 CR3: 000000005dacc001 CR4: 00000000001606f0
 Call Trace:
  <IRQ>
  br_dev_xmit+0xe1/0x3d0 [bridge]
  dev_hard_start_xmit+0xbc/0x3b0
  __dev_queue_xmit+0xb98/0xc30
  ip_finish_output2+0x3e5/0x670
  ? ip_output+0x7f/0x250
  ip_output+0x7f/0x250
  ? ip_fragment.constprop.5+0x80/0x80
  ip_forward+0x3e2/0x650
  ? ipv4_frags_init_net+0x130/0x130
  ip_rcv+0x2be/0x500
  ? ip_local_deliver_finish+0x3b0/0x3b0
  __netif_receive_skb_core+0x6a8/0xb30
  ? lock_acquire+0xab/0x200
  ? netif_receive_skb_internal+0x2a/0x380
  netif_receive_skb_internal+0x73/0x380
  ? napi_gro_complete+0xcf/0x1b0
  dev_gro_receive+0x374/0x730
  napi_gro_receive+0x4f/0x1d0
  receive_buf+0x4b6/0x1930 [virtio_net]
  ? detach_buf+0x69/0x120 [virtio_ring]
  virtnet_poll+0x122/0x2e0 [virtio_net]
  net_rx_action+0x207/0x450
  __do_softirq+0x149/0x4ea
  irq_exit+0xbf/0xd0
  do_IRQ+0x6c/0x130
  common_interrupt+0xf/0xf
  </IRQ>
 RIP: 0010:__radix_tree_lookup+0x28/0xe0
 Code: 00 00 53 49 89 ca 41 bb 40 00 00 00 4c 8b 47 50 4c 89 c0 83 e0 03 48 83 f8 01 0f 85 a8 00 00 00 4c 89 c0 48 83 e0 fe 0f b6 08 <4c> 89 d8 48 d3 e0 48 83 
e8 01 48 39 c6 76 11 e9 9f 00 00 00 4c 89 
 RSP: 0000:ffffae150048fcc0 EFLAGS: 00000282 ORIG_RAX: ffffffffffffffd9
 RAX: ffff96735d2ef908 RBX: 000000000000001f RCX: 0000000000000006
 RDX: 0000000000000000 RSI: 00000000000002e2 RDI: ffff96735d10b788
 RBP: 00000000000002e2 R08: ffff96735d2ef909 R09: 0000000000000000
 R10: 0000000000000000 R11: 0000000000000040 R12: 000000000000001f
 R13: ffffec01c15f3a80 R14: 000000000000001f R15: ffffae150048fd18
  __do_page_cache_readahead+0x11f/0x2e0
  filemap_fault+0x408/0x660
  ext4_filemap_fault+0x2f/0x40
  __do_fault+0x1f/0xd0
  __handle_mm_fault+0x915/0xfa0
  handle_mm_fault+0x1c2/0x390
  __do_page_fault+0x2f6/0x580
  ? async_page_fault+0x5/0x20
  async_page_fault+0x1b/0x20
 RIP: 0033:0x7fc913608aa0
 Code: Bad RIP value.
 RSP: 002b:00007ffcfa9c7f08 EFLAGS: 00010206
 RAX: 0000000000000000 RBX: 0000000000000003 RCX: 0000000000000080
 RDX: 0000000000000006 RSI: 00007fc913a74bf8 RDI: 00007fc913df9720
 RBP: 0000000000000001 R08: 000055df45795700 R09: 0000000000000000
 R10: 000055df4574c010 R11: 0000000000000001 R12: 00007ffcfa9c8c38
 R13: 00007ffcfa9c8c48 R14: 00007fc913dc3d70 R15: 000055df4578ab30
 Modules linked in: veth ebtable_filter ebtables ipt_MASQUERADE xt_CHECKSUM xt_comment xt_tcpudp iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack libcrc32c iptable_mangle iptable_filter bpfilter bridge stp llc fuse kvm_intel kvm irqbypass 9pnet_virtio 9pnet virtio_balloon ib_iser rdma_cm configfs iw_cm ib_cm ib_core iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi ip_tables x_tables virtio_net net_failover virtio_blk failover crc32_pclmul crc32c_intel pcbc aesni_intel aes_x86_64 crypto_simd cryptd glue_helper virtio_pci psmouse virtio_ring virtio

I'm not very familiar with the GRO or IP fragmentation code but I was
able to identify that this change "fixes" the issue:

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 7ccc601b55d9..a5cea572a7f1 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -666,6 +666,7 @@ struct sk_buff {
 			/* These two members must be first. */
 			struct sk_buff		*next;
 			struct sk_buff		*prev;
+			struct list_head	list;
 
 			union {
 				struct net_device	*dev;
@@ -678,7 +679,6 @@ struct sk_buff {
 			};
 		};
 		struct rb_node		rbnode; /* used in netem & tcp stack */
-		struct list_head	list;
 	};
 	struct sock		*sk;
 

That's not the correct fix, as we wouldn't want to waste space with two
list implementations always being around, but I think it shows that
perhaps there is something in the call stack attempting to use both the
list_head list and the ip_defrag_offset at the same time and
unintentionally trouncing over the other member in the union.

I wish I had a proper fix but I suspect that someone more familiar with
this code will spot the issue quickly. I didn't see anything incorrect
in the list manipulations in the offending commit so some deeper
knowledge of the network stack is needed.

Tyler

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply related

* [BUG] bonded interfaces drop bpdu (stp) frames
From: Michal Soltys @ 2018-07-11 22:23 UTC (permalink / raw)
  To: netdev

Hi,

As weird as that sounds, this is what I observed today after bumping
kernel version. I have a setup where 2 bonds are attached to linux
bridge and physically are connected to two switches doing MSTP (and
linux bridge is just passing them).

Initially I suspected some changes related to bridge code - but quick
peek at the code showed nothing suspicious - and the part of it that
explicitly passes stp frames if stp is not enabled has seen little
changes (e.g. per-port group_fwd_mask added recently). Furthermore - if
regular non-bonded interfaces are attached everything works fine.

Just to be sure I detached the bond (802.3ad mode) and checked it with
simple tcpdump (ether proto \\stp) - and indeed no hello packets were
there (with them being present just fine on active enslaved interface,
or on the bond device in earlier kernels).

If time permits I'll bisect tommorow to pinpoint the commit, but from
quick todays test - 4.9.x is working fine, while 4.16.16 (tested on
debian) and 4.17.3 (tested on archlinux) are failing.

Unless this is already a known issue (or you have any suggestions what
could be responsible).

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox