All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net 1/2] net: tun: avoid disabling NAPI twice
@ 2022-06-29 18:19 Jakub Kicinski
  2022-06-29 18:19 ` [PATCH net 2/2] selftest: tun: add test for NAPI dismantle Jakub Kicinski
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jakub Kicinski @ 2022-06-29 18:19 UTC (permalink / raw)
  To: edumazet; +Cc: netdev, davem, pabeni, Jakub Kicinski, syzbot, Petar Penkov

Eric reports that syzbot made short work out of my speculative
fix. Indeed when queue gets detached its tfile->tun remains,
so we would try to stop NAPI twice with a detach(), close()
sequence.

Alternative fix would be to move tun_napi_disable() to
tun_detach_all() and let the NAPI run after the queue
has been detached.

Fixes: a8fc8cb5692a ("net: tun: stop NAPI when detaching queues")
Reported-by: syzbot <syzkaller@googlegroups.com>
Reported-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
Cc: Petar Penkov <ppenkov@aviatrix.com>
---
CC: ppenkov@aviatrix.com
---
 drivers/net/tun.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index e2eb35887394..259b2b84b2b3 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -640,7 +640,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
 	tun = rtnl_dereference(tfile->tun);
 
 	if (tun && clean) {
-		tun_napi_disable(tfile);
+		if (!tfile->detached)
+			tun_napi_disable(tfile);
 		tun_napi_del(tfile);
 	}
 
-- 
2.36.1


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

* [PATCH net 2/2] selftest: tun: add test for NAPI dismantle
  2022-06-29 18:19 [PATCH net 1/2] net: tun: avoid disabling NAPI twice Jakub Kicinski
@ 2022-06-29 18:19 ` Jakub Kicinski
  2022-06-30 10:27 ` [PATCH net 1/2] net: tun: avoid disabling NAPI twice Eric Dumazet
  2022-06-30 18:50 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: Jakub Kicinski @ 2022-06-29 18:19 UTC (permalink / raw)
  To: edumazet; +Cc: netdev, davem, pabeni, Jakub Kicinski, shuah, linux-kselftest

Being lazy does not pay, add the test for various
ordering of tun queue close / detach / destroy.

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
CC: shuah@kernel.org
CC: linux-kselftest@vger.kernel.org
---
 tools/testing/selftests/net/Makefile |   2 +-
 tools/testing/selftests/net/tun.c    | 162 +++++++++++++++++++++++++++
 2 files changed, 163 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/net/tun.c

diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 7ea54af55490..ddad703ace34 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -54,7 +54,7 @@ TEST_GEN_FILES += ipsec
 TEST_GEN_FILES += ioam6_parser
 TEST_GEN_FILES += gro
 TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
-TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls
+TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls tun
 TEST_GEN_FILES += toeplitz
 TEST_GEN_FILES += cmsg_sender
 TEST_GEN_FILES += stress_reuseport_listen
diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/net/tun.c
new file mode 100644
index 000000000000..fa83918b62d1
--- /dev/null
+++ b/tools/testing/selftests/net/tun.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include "../kselftest_harness.h"
+
+static int tun_attach(int fd, char *dev)
+{
+	struct ifreq ifr;
+
+	memset(&ifr, 0, sizeof(ifr));
+	strcpy(ifr.ifr_name, dev);
+	ifr.ifr_flags = IFF_ATTACH_QUEUE;
+
+	return ioctl(fd, TUNSETQUEUE, (void *) &ifr);
+}
+
+static int tun_detach(int fd, char *dev)
+{
+	struct ifreq ifr;
+
+	memset(&ifr, 0, sizeof(ifr));
+	strcpy(ifr.ifr_name, dev);
+	ifr.ifr_flags = IFF_DETACH_QUEUE;
+
+	return ioctl(fd, TUNSETQUEUE, (void *) &ifr);
+}
+
+static int tun_alloc(char *dev)
+{
+	struct ifreq ifr;
+	int fd, err;
+
+	fd = open("/dev/net/tun", O_RDWR);
+	if (fd < 0) {
+		fprintf(stderr, "can't open tun: %s\n", strerror(errno));
+		return fd;
+	}
+
+	memset(&ifr, 0, sizeof(ifr));
+	strcpy(ifr.ifr_name, dev);
+	ifr.ifr_flags = IFF_TAP | IFF_NAPI | IFF_MULTI_QUEUE;
+
+	err = ioctl(fd, TUNSETIFF, (void *) &ifr);
+	if (err < 0) {
+		fprintf(stderr, "can't TUNSETIFF: %s\n", strerror(errno));
+		close(fd);
+		return err;
+	}
+	strcpy(dev, ifr.ifr_name);
+	return fd;
+}
+
+static int tun_delete(char *dev)
+{
+	struct {
+		struct nlmsghdr  nh;
+		struct ifinfomsg ifm;
+		unsigned char    data[64];
+	} req;
+	struct rtattr *rta;
+	int ret, rtnl;
+
+	rtnl = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
+	if (rtnl < 0) {
+		fprintf(stderr, "can't open rtnl: %s\n", strerror(errno));
+		return 1;
+	}
+
+	memset(&req, 0, sizeof(req));
+	req.nh.nlmsg_len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.ifm)));
+	req.nh.nlmsg_flags = NLM_F_REQUEST;
+	req.nh.nlmsg_type = RTM_DELLINK;
+
+	req.ifm.ifi_family = AF_UNSPEC;
+
+	rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nh.nlmsg_len));
+	rta->rta_type = IFLA_IFNAME;
+	rta->rta_len = RTA_LENGTH(IFNAMSIZ);
+	req.nh.nlmsg_len += rta->rta_len;
+	memcpy(RTA_DATA(rta), dev, IFNAMSIZ);
+
+	ret = send(rtnl, &req, req.nh.nlmsg_len, 0);
+	if (ret < 0)
+		fprintf(stderr, "can't send: %s\n", strerror(errno));
+	ret = (unsigned int)ret != req.nh.nlmsg_len;
+
+	close(rtnl);
+	return ret;
+}
+
+FIXTURE(tun)
+{
+	char ifname[IFNAMSIZ];
+	int fd, fd2;
+};
+
+FIXTURE_SETUP(tun)
+{
+	memset(self->ifname, 0, sizeof(self->ifname));
+
+	self->fd = tun_alloc(self->ifname);
+	ASSERT_GE(self->fd, 0);
+
+	self->fd2 = tun_alloc(self->ifname);
+	ASSERT_GE(self->fd2, 0);
+}
+
+FIXTURE_TEARDOWN(tun)
+{
+	if (self->fd >= 0)
+		close(self->fd);
+	if (self->fd2 >= 0)
+		close(self->fd2);
+}
+
+TEST_F(tun, delete_detach_close) {
+	EXPECT_EQ(tun_delete(self->ifname), 0);
+	EXPECT_EQ(tun_detach(self->fd, self->ifname), -1);
+	EXPECT_EQ(errno, 22);
+}
+
+TEST_F(tun, detach_delete_close) {
+	EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
+	EXPECT_EQ(tun_delete(self->ifname), 0);
+}
+
+TEST_F(tun, detach_close_delete) {
+	EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
+	close(self->fd);
+	self->fd = -1;
+	EXPECT_EQ(tun_delete(self->ifname), 0);
+}
+
+TEST_F(tun, reattach_delete_close) {
+	EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
+	EXPECT_EQ(tun_attach(self->fd, self->ifname), 0);
+	EXPECT_EQ(tun_delete(self->ifname), 0);
+}
+
+TEST_F(tun, reattach_close_delete) {
+	EXPECT_EQ(tun_detach(self->fd, self->ifname), 0);
+	EXPECT_EQ(tun_attach(self->fd, self->ifname), 0);
+	close(self->fd);
+	self->fd = -1;
+	EXPECT_EQ(tun_delete(self->ifname), 0);
+}
+
+TEST_HARNESS_MAIN
-- 
2.36.1


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

* Re: [PATCH net 1/2] net: tun: avoid disabling NAPI twice
  2022-06-29 18:19 [PATCH net 1/2] net: tun: avoid disabling NAPI twice Jakub Kicinski
  2022-06-29 18:19 ` [PATCH net 2/2] selftest: tun: add test for NAPI dismantle Jakub Kicinski
@ 2022-06-30 10:27 ` Eric Dumazet
  2022-06-30 18:50 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: Eric Dumazet @ 2022-06-30 10:27 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: netdev, David Miller, Paolo Abeni, syzbot, Petar Penkov

On Wed, Jun 29, 2022 at 8:19 PM Jakub Kicinski <kuba@kernel.org> wrote:
>
> Eric reports that syzbot made short work out of my speculative
> fix. Indeed when queue gets detached its tfile->tun remains,
> so we would try to stop NAPI twice with a detach(), close()
> sequence.
>
> Alternative fix would be to move tun_napi_disable() to
> tun_detach_all() and let the NAPI run after the queue
> has been detached.
>
> Fixes: a8fc8cb5692a ("net: tun: stop NAPI when detaching queues")

Reviewed-by: Eric Dumazet <edumazet@google.com>

> Reported-by: syzbot <syzkaller@googlegroups.com>
> Reported-by: Eric Dumazet <edumazet@google.com>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
> Cc: Petar Penkov <ppenkov@aviatrix.com>
> ---
> CC: ppenkov@aviatrix.com
> ---
>  drivers/net/tun.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index e2eb35887394..259b2b84b2b3 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
> @@ -640,7 +640,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
>         tun = rtnl_dereference(tfile->tun);
>
>         if (tun && clean) {
> -               tun_napi_disable(tfile);
> +               if (!tfile->detached)
> +                       tun_napi_disable(tfile);
>                 tun_napi_del(tfile);
>         }
>
> --
> 2.36.1
>

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

* Re: [PATCH net 1/2] net: tun: avoid disabling NAPI twice
  2022-06-29 18:19 [PATCH net 1/2] net: tun: avoid disabling NAPI twice Jakub Kicinski
  2022-06-29 18:19 ` [PATCH net 2/2] selftest: tun: add test for NAPI dismantle Jakub Kicinski
  2022-06-30 10:27 ` [PATCH net 1/2] net: tun: avoid disabling NAPI twice Eric Dumazet
@ 2022-06-30 18:50 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2022-06-30 18:50 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: edumazet, netdev, davem, pabeni, syzkaller, ppenkov

Hello:

This series was applied to netdev/net.git (master)
by Jakub Kicinski <kuba@kernel.org>:

On Wed, 29 Jun 2022 11:19:10 -0700 you wrote:
> Eric reports that syzbot made short work out of my speculative
> fix. Indeed when queue gets detached its tfile->tun remains,
> so we would try to stop NAPI twice with a detach(), close()
> sequence.
> 
> Alternative fix would be to move tun_napi_disable() to
> tun_detach_all() and let the NAPI run after the queue
> has been detached.
> 
> [...]

Here is the summary with links:
  - [net,1/2] net: tun: avoid disabling NAPI twice
    https://git.kernel.org/netdev/net/c/ff1fa2081d17
  - [net,2/2] selftest: tun: add test for NAPI dismantle
    https://git.kernel.org/netdev/net/c/839b92fede7b

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



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

end of thread, other threads:[~2022-06-30 18:50 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-29 18:19 [PATCH net 1/2] net: tun: avoid disabling NAPI twice Jakub Kicinski
2022-06-29 18:19 ` [PATCH net 2/2] selftest: tun: add test for NAPI dismantle Jakub Kicinski
2022-06-30 10:27 ` [PATCH net 1/2] net: tun: avoid disabling NAPI twice Eric Dumazet
2022-06-30 18:50 ` patchwork-bot+netdevbpf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.