|
|
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 |
|