Blame SOURCES/0015-conf-Terminate-on-EMFILE-or-ENFILE-on-sockets-for-po.patch

f07426
From 1df417752faf52f17d8ec14578ffde89ced32772 Mon Sep 17 00:00:00 2001
f07426
From: Stefano Brivio <sbrivio@redhat.com>
f07426
Date: Wed, 8 Mar 2023 13:21:19 +0100
f07426
Subject: [PATCH 15/20] conf: Terminate on EMFILE or ENFILE on sockets for port
f07426
 mapping
f07426
f07426
In general, we don't terminate or report failures if we fail to bind
f07426
to some ports out of a given port range specifier, to allow users to
f07426
conveniently specify big port ranges (or "all") without having to
f07426
care about ports that might already be in use.
f07426
f07426
However, running out of the open file descriptors quota is a
f07426
different story: we can't do what the user requested in a very
f07426
substantial way.
f07426
f07426
For example, if the user specifies '-t all' and we can only bind
f07426
1024 sockets, the behaviour is rather unexpected.
f07426
f07426
Fail whenever socket creation returns -ENFILE or -EMFILE.
f07426
f07426
Link: https://bugs.passt.top/show_bug.cgi?id=27
f07426
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
f07426
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
f07426
(cherry picked from commit bb2b67cb3549ea2509f5b7b88790e08d2e362351)
f07426
---
f07426
 conf.c | 36 +++++++++++++++++++++++++++++-------
f07426
 1 file changed, 29 insertions(+), 7 deletions(-)
f07426
f07426
diff --git a/conf.c b/conf.c
f07426
index 37f25d6..7f25a22 100644
f07426
--- a/conf.c
f07426
+++ b/conf.c
f07426
@@ -182,6 +182,7 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg,
f07426
 	bool exclude_only = true, bound_one = false;
f07426
 	uint8_t exclude[PORT_BITMAP_SIZE] = { 0 };
f07426
 	sa_family_t af = AF_UNSPEC;
f07426
+	int ret;
f07426
 
f07426
 	if (!strcmp(optarg, "none")) {
f07426
 		if (fwd->mode)
f07426
@@ -216,11 +217,18 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg,
f07426
 
f07426
 		for (i = 0; i < PORT_EPHEMERAL_MIN; i++) {
f07426
 			if (optname == 't') {
f07426
-				if (!tcp_sock_init(c, AF_UNSPEC, NULL, NULL, i))
f07426
+				ret = tcp_sock_init(c, AF_UNSPEC, NULL, NULL,
f07426
+						    i);
f07426
+				if (ret == -ENFILE || ret == -EMFILE)
f07426
+					goto enfile;
f07426
+				if (!ret)
f07426
 					bound_one = true;
f07426
 			} else if (optname == 'u') {
f07426
-				if (!udp_sock_init(c, 0, AF_UNSPEC, NULL, NULL,
f07426
-						   i))
f07426
+				ret = udp_sock_init(c, 0, AF_UNSPEC, NULL, NULL,
f07426
+						    i);
f07426
+				if (ret == -ENFILE || ret == -EMFILE)
f07426
+					goto enfile;
f07426
+				if (!ret)
f07426
 					bound_one = true;
f07426
 			}
f07426
 		}
f07426
@@ -301,10 +309,16 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg,
f07426
 			bitmap_set(fwd->map, i);
f07426
 
f07426
 			if (optname == 't') {
f07426
-				if (!tcp_sock_init(c, af, addr, ifname, i))
f07426
+				ret = tcp_sock_init(c, af, addr, ifname, i);
f07426
+				if (ret == -ENFILE || ret == -EMFILE)
f07426
+					goto enfile;
f07426
+				if (!ret)
f07426
 					bound_one = true;
f07426
 			} else if (optname == 'u') {
f07426
-				if (!udp_sock_init(c, 0, af, addr, ifname, i))
f07426
+				ret = udp_sock_init(c, 0, af, addr, ifname, i);
f07426
+				if (ret == -ENFILE || ret == -EMFILE)
f07426
+					goto enfile;
f07426
+				if (!ret)
f07426
 					bound_one = true;
f07426
 			} else {
f07426
 				/* No way to check in advance for -T and -U */
f07426
@@ -356,10 +370,16 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg,
f07426
 			fwd->delta[i] = mapped_range.first - orig_range.first;
f07426
 
f07426
 			if (optname == 't') {
f07426
-				if (!tcp_sock_init(c, af, addr, ifname, i))
f07426
+				ret = tcp_sock_init(c, af, addr, ifname, i);
f07426
+				if (ret == -ENFILE || ret == -EMFILE)
f07426
+					goto enfile;
f07426
+				if (!ret)
f07426
 					bound_one = true;
f07426
 			} else if (optname == 'u') {
f07426
-				if (!udp_sock_init(c, 0, af, addr, ifname, i))
f07426
+				ret = udp_sock_init(c, 0, af, addr, ifname, i);
f07426
+				if (ret == -ENFILE || ret == -EMFILE)
f07426
+					goto enfile;
f07426
+				if (!ret)
f07426
 					bound_one = true;
f07426
 			} else {
f07426
 				/* No way to check in advance for -T and -U */
f07426
@@ -372,6 +392,8 @@ static void conf_ports(const struct ctx *c, char optname, const char *optarg,
f07426
 		goto bind_fail;
f07426
 
f07426
 	return;
f07426
+enfile:
f07426
+	die("Can't open enough sockets for port specifier: %s", optarg);
f07426
 bad:
f07426
 	die("Invalid port specifier %s", optarg);
f07426
 overlap:
f07426
-- 
f07426
2.39.2
f07426