Compare commits

...

No commits in common. "c9-beta" and "c9" have entirely different histories.
c9-beta ... c9

23 changed files with 1735 additions and 98 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/passt-b86afe3559c0bd3d24bc6fed7c60466cf141224c.tar.xz
SOURCES/passt-4ddbcb9c0c555838b123c018a9ebc9b7e14a87e5.tar.xz

View File

@ -1 +1 @@
833dc4cee84bf49eb54354f5da5ae07748ce2969 SOURCES/passt-b86afe3559c0bd3d24bc6fed7c60466cf141224c.tar.xz
f0d7edae2c421217fd15a72ce7b552656ce4ed16 SOURCES/passt-4ddbcb9c0c555838b123c018a9ebc9b7e14a87e5.tar.xz

View File

@ -1,52 +0,0 @@
From 6977619743bbc602a865f79562b59a80921d6063 Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Mon, 21 Aug 2023 17:52:28 +0200
Subject: [PATCH] selinux: Drop user_namespace create allow rules
Those are incompatible with current el9 kernels. I introduced them
upstream with commit 62059058cf24 ("selinux: Fix user namespace
creation after breaking kernel change"), in turn as a result of
kernel commit ed5d44d42c95 ("selinux: Implement userns_create hook"),
but on current el9 kernels (which lack the hook) they result in
failures such as:
Failed to resolve allow statement at /var/lib/selinux/targeted/tmp/modules/200/passt/cil:103
Failed to resolve AST
/usr/sbin/semodule: Failed!
Failed to resolve allow statement at /var/lib/selinux/targeted/tmp/modules/200/pasta/cil:104
Failed to resolve AST
/usr/sbin/semodule: Failed!
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
---
contrib/selinux/passt.te | 1 -
contrib/selinux/pasta.te | 1 -
2 files changed, 2 deletions(-)
diff --git a/contrib/selinux/passt.te b/contrib/selinux/passt.te
index facc2d1..de10f45 100644
--- a/contrib/selinux/passt.te
+++ b/contrib/selinux/passt.te
@@ -93,7 +93,6 @@ allow syslogd_t self:cap_userns sys_ptrace;
allow passt_t self:process setcap;
allow passt_t self:capability { sys_tty_config setpcap net_bind_service setuid setgid};
allow passt_t self:cap_userns { setpcap sys_admin sys_ptrace };
-allow passt_t self:user_namespace create;
allow passt_t passwd_file_t:file read_file_perms;
sssd_search_lib(passt_t)
diff --git a/contrib/selinux/pasta.te b/contrib/selinux/pasta.te
index ed70c5f..3226e37 100644
--- a/contrib/selinux/pasta.te
+++ b/contrib/selinux/pasta.te
@@ -113,7 +113,6 @@ init_daemon_domain(pasta_t, pasta_exec_t)
allow pasta_t self:capability { setpcap net_bind_service sys_tty_config dac_read_search net_admin sys_resource setuid setgid };
allow pasta_t self:cap_userns { setpcap sys_admin sys_ptrace net_admin net_bind_service };
-allow pasta_t self:user_namespace create;
allow pasta_t passwd_file_t:file read_file_perms;
sssd_search_lib(pasta_t)
--
2.39.2

View File

@ -0,0 +1,47 @@
From 0dfc25b917f7e94ac56ea4285a5d394305787b06 Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Thu, 23 Feb 2023 12:21:29 +0000
Subject: [PATCH 01/20] udp: Actually use host resolver to forward DNS queries
Instead of the address of the first resolver we advertise to
the guest or namespace.
This was one of the intentions behind commit 3a2afde87dd1 ("conf,
udp: Drop mostly duplicated dns_send arrays, rename related fields"),
but I forgot to implement this part. In practice, they are usually
the same thing, unless /etc/resolv.conf points to a loopback address.
Fixes: 3a2afde87dd1 ("conf, udp: Drop mostly duplicated dns_send arrays, rename related fields")
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Tested-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit ddf7097a718095e879428667f2d56ec7d4f027e5)
---
udp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/udp.c b/udp.c
index c913d27..1d65559 100644
--- a/udp.c
+++ b/udp.c
@@ -867,7 +867,7 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
} else if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr,
&c->ip4.dns_match) &&
ntohs(s_in.sin_port) == 53) {
- s_in.sin_addr = c->ip4.dns[0];
+ s_in.sin_addr = c->ip4.dns_host;
}
} else {
s_in6 = (struct sockaddr_in6) {
@@ -890,7 +890,7 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
s_in6.sin6_addr = c->ip6.addr_seen;
} else if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.dns_match) &&
ntohs(s_in6.sin6_port) == 53) {
- s_in6.sin6_addr = c->ip6.dns[0];
+ s_in6.sin6_addr = c->ip6.dns_host;
} else if (IN6_IS_ADDR_LINKLOCAL(&s_in6.sin6_addr)) {
bind_addr = &c->ip6.addr_ll;
}
--
2.39.2

View File

@ -0,0 +1,129 @@
From bf19154051b6c920f702c8394cd6821bb00f531a Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Thu, 23 Feb 2023 13:32:30 +0000
Subject: [PATCH 02/20] conf: Split add_dns{4,6}() out of get_dns()
The logic handling which resolvers we add, and whether to add them,
is getting rather cramped in get_dns(): split it into separate
functions.
No functional changes intended.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Tested-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit 8ca907a3f0a095691cdaf56ad610fd802df88146)
---
conf.c | 86 ++++++++++++++++++++++++++++++++++------------------------
1 file changed, 51 insertions(+), 35 deletions(-)
diff --git a/conf.c b/conf.c
index 4dc0660..ed25e35 100644
--- a/conf.c
+++ b/conf.c
@@ -382,6 +382,53 @@ bind_fail:
die("Failed to bind any port for '-%c %s', exiting", optname, optarg);
}
+/**
+ * add_dns4() - Possibly add the IPv4 address of a DNS resolver to configuration
+ * @c: Execution context
+ * @addr: Address found in /etc/resolv.conf
+ * @conf: Pointer to reference of current entry in array of IPv4 resolvers
+ */
+static void add_dns4(struct ctx *c, struct in_addr *addr, struct in_addr **conf)
+{
+ /* Guest or container can only access local addresses via redirect */
+ if (IN4_IS_ADDR_LOOPBACK(addr)) {
+ if (!c->no_map_gw) {
+ **conf = c->ip4.gw;
+ (*conf)++;
+ }
+ } else {
+ **conf = *addr;
+ (*conf)++;
+ }
+
+ if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_host))
+ c->ip4.dns_host = *addr;
+}
+
+/**
+ * add_dns6() - Possibly add the IPv6 address of a DNS resolver to configuration
+ * @c: Execution context
+ * @addr: Address found in /etc/resolv.conf
+ * @conf: Pointer to reference of current entry in array of IPv6 resolvers
+ */
+static void add_dns6(struct ctx *c,
+ struct in6_addr *addr, struct in6_addr **conf)
+{
+ /* Guest or container can only access local addresses via redirect */
+ if (IN6_IS_ADDR_LOOPBACK(addr)) {
+ if (!c->no_map_gw) {
+ memcpy(*conf, &c->ip6.gw, sizeof(**conf));
+ (*conf)++;
+ }
+ } else {
+ memcpy(*conf, addr, sizeof(**conf));
+ (*conf)++;
+ }
+
+ if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_host))
+ c->ip6.dns_host = *addr;
+}
+
/**
* get_dns() - Get nameserver addresses from local /etc/resolv.conf
* @c: Execution context
@@ -420,44 +467,13 @@ static void get_dns(struct ctx *c)
if (!dns4_set &&
dns4 - &c->ip4.dns[0] < ARRAY_SIZE(c->ip4.dns) - 1
- && inet_pton(AF_INET, p + 1, &dns4_tmp)) {
- /* Guest or container can only access local
- * addresses via local redirect
- */
- if (IN4_IS_ADDR_LOOPBACK(&dns4_tmp)) {
- if (!c->no_map_gw) {
- *dns4 = c->ip4.gw;
- dns4++;
- }
- } else {
- *dns4 = dns4_tmp;
- dns4++;
- }
-
- if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_host))
- c->ip4.dns_host = dns4_tmp;
- }
+ && inet_pton(AF_INET, p + 1, &dns4_tmp))
+ add_dns4(c, &dns4_tmp, &dns4);
if (!dns6_set &&
dns6 - &c->ip6.dns[0] < ARRAY_SIZE(c->ip6.dns) - 1
- && inet_pton(AF_INET6, p + 1, &dns6_tmp)) {
- /* Guest or container can only access local
- * addresses via local redirect
- */
- if (IN6_IS_ADDR_LOOPBACK(&dns6_tmp)) {
- if (!c->no_map_gw) {
- memcpy(dns6, &c->ip6.gw,
- sizeof(*dns6));
- dns6++;
- }
- } else {
- memcpy(dns6, &dns6_tmp, sizeof(*dns6));
- dns6++;
- }
-
- if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_host))
- c->ip6.dns_host = dns6_tmp;
- }
+ && inet_pton(AF_INET6, p + 1, &dns6_tmp))
+ add_dns6(c, &dns6_tmp, &dns6);
} else if (!dnss_set && strstr(line, "search ") == line &&
s == c->dns_search) {
end = strpbrk(line, "\n");
--
2.39.2

View File

@ -0,0 +1,119 @@
From ae0004f591d816f1b6e78c57c3d9530098f123b0 Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Thu, 23 Feb 2023 16:41:47 +0000
Subject: [PATCH 03/20] conf, udp: Allow any loopback address to be used as
resolver
Andrea reports that with a Fedora 37 guest running on a Fedora 37
host, both using systemd-resolved, with passt connecting them,
running with default options, DNS queries don't work.
systemd-resolved on the host is reachable only at the loopback
address 127.0.0.53.
We advertise the default gateway address to the guest as resolver,
because our local address is of course unreachable from there, which
means we see DNS queries directed to the default gateway, and we
redirect them to 127.0.0.1. However, systemd-resolved doesn't answer
on 127.0.0.1.
To fix this, set @dns_match to the address of the default gateway,
unless a different resolver address is explicitly configured, so that
we know we explicitly have to map DNS queries, in this case, to the
address of the local resolver.
This means that in udp_tap_handler() we need to check, first, if
the destination address of packets matches @dns_match: even if it's
the address of the local gateway, we want to map that to a specific
address, which isn't necessarily 127.0.0.1.
Do the same for IPv6 for consistency, even though IPv6 defines a
single loopback address.
Reported-by: Andrea Bolognani <abologna@redhat.com>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Tested-by: Andrea Bolognani <abologna@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit bad252687271c0255f6a077f19cbc19aa0427f8d)
---
conf.c | 6 ++++++
udp.c | 20 ++++++++++----------
2 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/conf.c b/conf.c
index ed25e35..37f25d6 100644
--- a/conf.c
+++ b/conf.c
@@ -395,6 +395,9 @@ static void add_dns4(struct ctx *c, struct in_addr *addr, struct in_addr **conf)
if (!c->no_map_gw) {
**conf = c->ip4.gw;
(*conf)++;
+
+ if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns_match))
+ c->ip4.dns_match = c->ip4.gw;
}
} else {
**conf = *addr;
@@ -419,6 +422,9 @@ static void add_dns6(struct ctx *c,
if (!c->no_map_gw) {
memcpy(*conf, &c->ip6.gw, sizeof(**conf));
(*conf)++;
+
+ if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns_match))
+ memcpy(&c->ip6.dns_match, addr, sizeof(*addr));
}
} else {
memcpy(*conf, addr, sizeof(**conf));
diff --git a/udp.c b/udp.c
index 1d65559..20a9ea0 100644
--- a/udp.c
+++ b/udp.c
@@ -857,17 +857,16 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
udp_tap_map[V4][src].ts = now->tv_sec;
- if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.gw) &&
- !c->no_map_gw) {
+ if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.dns_match) &&
+ ntohs(s_in.sin_port) == 53) {
+ s_in.sin_addr = c->ip4.dns_host;
+ } else if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr, &c->ip4.gw) &&
+ !c->no_map_gw) {
if (!(udp_tap_map[V4][dst].flags & PORT_LOCAL) ||
(udp_tap_map[V4][dst].flags & PORT_LOOPBACK))
s_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
else
s_in.sin_addr = c->ip4.addr_seen;
- } else if (IN4_ARE_ADDR_EQUAL(&s_in.sin_addr,
- &c->ip4.dns_match) &&
- ntohs(s_in.sin_port) == 53) {
- s_in.sin_addr = c->ip4.dns_host;
}
} else {
s_in6 = (struct sockaddr_in6) {
@@ -880,7 +879,11 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
sa = (struct sockaddr *)&s_in6;
sl = sizeof(s_in6);
- if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.gw) && !c->no_map_gw) {
+ if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.dns_match) &&
+ ntohs(s_in6.sin6_port) == 53) {
+ s_in6.sin6_addr = c->ip6.dns_host;
+ } else if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.gw) &&
+ !c->no_map_gw) {
if (!(udp_tap_map[V6][dst].flags & PORT_LOCAL) ||
(udp_tap_map[V6][dst].flags & PORT_LOOPBACK))
s_in6.sin6_addr = in6addr_loopback;
@@ -888,9 +891,6 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
s_in6.sin6_addr = c->ip6.addr;
else
s_in6.sin6_addr = c->ip6.addr_seen;
- } else if (IN6_ARE_ADDR_EQUAL(addr, &c->ip6.dns_match) &&
- ntohs(s_in6.sin6_port) == 53) {
- s_in6.sin6_addr = c->ip6.dns_host;
} else if (IN6_IS_ADDR_LINKLOCAL(&s_in6.sin6_addr)) {
bind_addr = &c->ip6.addr_ll;
}
--
2.39.2

View File

@ -0,0 +1,130 @@
From 850bb9c15d39dcbefb0849955f4f09382f587c20 Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Mon, 27 Feb 2023 02:45:42 +0100
Subject: [PATCH 04/20] tcp, tcp_splice: Get rid of false positive CWE-394
Coverity warning from fls()
We use the return value of fls() as array index for debug strings.
While fls() can return -1 (if no bit is set), Coverity Scan doesn't
see that we're first checking the return value of another fls() call
with the same bitmask, before using it.
Call fls() once, store its return value, check it, and use the stored
value as array index.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit 5474bc5485d814acae19961f9a9cd4b541722a5e)
---
tcp.c | 12 ++++++++----
tcp_splice.c | 24 ++++++++++++++++--------
2 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/tcp.c b/tcp.c
index 803c2c4..c62fe44 100644
--- a/tcp.c
+++ b/tcp.c
@@ -743,15 +743,19 @@ static void conn_flag_do(const struct ctx *c, struct tcp_tap_conn *conn,
unsigned long flag)
{
if (flag & (flag - 1)) {
+ int flag_index = fls(~flag);
+
if (!(conn->flags & ~flag))
return;
conn->flags &= flag;
- if (fls(~flag) >= 0) {
+ if (flag_index >= 0) {
debug("TCP: index %li: %s dropped", CONN_IDX(conn),
- tcp_flag_str[fls(~flag)]);
+ tcp_flag_str[flag_index]);
}
} else {
+ int flag_index = fls(~flag);
+
if (conn->flags & flag) {
/* Special case: setting ACK_FROM_TAP_DUE on a
* connection where it's already set is used to
@@ -766,9 +770,9 @@ static void conn_flag_do(const struct ctx *c, struct tcp_tap_conn *conn,
}
conn->flags |= flag;
- if (fls(flag) >= 0) {
+ if (flag_index >= 0) {
debug("TCP: index %li: %s", CONN_IDX(conn),
- tcp_flag_str[fls(flag)]);
+ tcp_flag_str[flag_index]);
}
}
diff --git a/tcp_splice.c b/tcp_splice.c
index 84f855e..67af46b 100644
--- a/tcp_splice.c
+++ b/tcp_splice.c
@@ -127,22 +127,26 @@ static void conn_flag_do(const struct ctx *c, struct tcp_splice_conn *conn,
unsigned long flag)
{
if (flag & (flag - 1)) {
+ int flag_index = fls(~flag);
+
if (!(conn->flags & ~flag))
return;
conn->flags &= flag;
- if (fls(~flag) >= 0) {
+ if (flag_index >= 0) {
debug("TCP (spliced): index %li: %s dropped", CONN_IDX(conn),
- tcp_splice_flag_str[fls(~flag)]);
+ tcp_splice_flag_str[flag_index]);
}
} else {
+ int flag_index = fls(flag);
+
if (conn->flags & flag)
return;
conn->flags |= flag;
- if (fls(flag) >= 0) {
+ if (flag_index >= 0) {
debug("TCP (spliced): index %li: %s", CONN_IDX(conn),
- tcp_splice_flag_str[fls(flag)]);
+ tcp_splice_flag_str[flag_index]);
}
}
@@ -207,22 +211,26 @@ static void conn_event_do(const struct ctx *c, struct tcp_splice_conn *conn,
unsigned long event)
{
if (event & (event - 1)) {
+ int flag_index = fls(~event);
+
if (!(conn->events & ~event))
return;
conn->events &= event;
- if (fls(~event) >= 0) {
+ if (flag_index >= 0) {
debug("TCP (spliced): index %li, ~%s", CONN_IDX(conn),
- tcp_splice_event_str[fls(~event)]);
+ tcp_splice_event_str[flag_index]);
}
} else {
+ int flag_index = fls(event);
+
if (conn->events & event)
return;
conn->events |= event;
- if (fls(event) >= 0) {
+ if (flag_index >= 0) {
debug("TCP (spliced): index %li, %s", CONN_IDX(conn),
- tcp_splice_event_str[fls(event)]);
+ tcp_splice_event_str[flag_index]);
}
}
--
2.39.2

View File

@ -0,0 +1,39 @@
From 65d8d329620973319b577e9a1b0ffad528a4df1f Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Mon, 27 Feb 2023 03:05:26 +0100
Subject: [PATCH 05/20] tcp: Avoid false (but convoluted) positive Coverity
CWE-476 warning
If there are no TCP options in the header, tcp_tap_handler() will
pass the corresponding pointer, fetched via packet_get(), as NULL to
tcp_conn_from_sock_finish(), which in turn indirectly calls
tcp_opt_get().
If there are no options, tcp_opt_get() will stop right away because
the option length is indicated as zero. However, if the logic is
complicated enough to follow for static checkers, adding an explicit
check against NULL in tcp_opt_get() is probably a good idea.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit a1d5537741679c117b4c1a9b736ea2540a976eee)
---
tcp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tcp.c b/tcp.c
index c62fe44..a811b5e 100644
--- a/tcp.c
+++ b/tcp.c
@@ -1114,7 +1114,7 @@ static int tcp_opt_get(const char *opts, size_t len, uint8_t type_find,
{
uint8_t type, optlen;
- if (!len)
+ if (!opts || !len)
return -1;
for (; len >= 2; opts += optlen, len -= optlen) {
--
2.39.2

View File

@ -0,0 +1,35 @@
From cd950e6b7f85f4f8f80284ba79a027dee57bfa61 Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Mon, 27 Feb 2023 03:13:31 +0100
Subject: [PATCH 06/20] tcp: Avoid (theoretical) resource leak (CWE-772)
Coverity warning
If tcp_timer_ctl() gets a socket number greater than SOCKET_MAX
(2 ^ 24), we return error but we don't close the socket. This is a
rather formal issue given that, at least on Linux, socket numbers are
monotonic and we're in general not allowed to open so many sockets.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit 4f523c3276741781346478328f863e60f30cba8e)
---
tcp.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tcp.c b/tcp.c
index a811b5e..fe6e458 100644
--- a/tcp.c
+++ b/tcp.c
@@ -702,6 +702,9 @@ static void tcp_timer_ctl(const struct ctx *c, struct tcp_tap_conn *conn)
fd = timerfd_create(CLOCK_MONOTONIC, 0);
if (fd == -1 || fd > SOCKET_MAX) {
debug("TCP: failed to get timer: %s", strerror(errno));
+ if (fd > -1)
+ close(fd);
+ conn->timer = -1;
return;
}
conn->timer = fd;
--
2.39.2

View File

@ -0,0 +1,84 @@
From 44d35498a98da3d3234b0084033f6dcd6450e22b Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Mon, 27 Feb 2023 03:30:01 +0100
Subject: [PATCH 07/20] Fix definitions of SOCKET_MAX, TCP_MAX_CONNS
...and, given that I keep getting this wrong, add a convenience
macro, MAX_FROM_BITS().
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit 26a0e4d6ee17fa174a401d8e8d9a4c189f11f258)
---
passt.h | 4 ++--
tcp.h | 4 ++--
tcp_conn.h | 2 +-
util.h | 2 ++
4 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/passt.h b/passt.h
index 3d7e567..e0383eb 100644
--- a/passt.h
+++ b/passt.h
@@ -42,7 +42,7 @@ union epoll_ref;
/**
* union epoll_ref - Breakdown of reference for epoll socket bookkeeping
* @proto: IP protocol number
- * @s: Socket number (implies 2^24 limit on number of descriptors)
+ * @s: Socket number (implies 2^24-1 limit on number of descriptors)
* @tcp: TCP-specific reference part
* @udp: UDP-specific reference part
* @icmp: ICMP-specific reference part
@@ -53,7 +53,7 @@ union epoll_ref {
struct {
int32_t proto:8,
#define SOCKET_REF_BITS 24
-#define SOCKET_MAX (1 << SOCKET_REF_BITS)
+#define SOCKET_MAX MAX_FROM_BITS(SOCKET_REF_BITS)
s:SOCKET_REF_BITS;
union {
union tcp_epoll_ref tcp;
diff --git a/tcp.h b/tcp.h
index 5527c5b..36e5391 100644
--- a/tcp.h
+++ b/tcp.h
@@ -8,8 +8,8 @@
#define TCP_TIMER_INTERVAL 1000 /* ms */
-#define TCP_CONN_INDEX_BITS 17 /* 128k */
-#define TCP_MAX_CONNS (1 << TCP_CONN_INDEX_BITS)
+#define TCP_CONN_INDEX_BITS 17 /* 128k - 1 */
+#define TCP_MAX_CONNS MAX_FROM_BITS(TCP_CONN_INDEX_BITS)
struct ctx;
diff --git a/tcp_conn.h b/tcp_conn.h
index a499f34..c22632b 100644
--- a/tcp_conn.h
+++ b/tcp_conn.h
@@ -54,7 +54,7 @@ struct tcp_tap_conn {
#define TCP_RETRANS_BITS 3
unsigned int retrans :TCP_RETRANS_BITS;
-#define TCP_MAX_RETRANS ((1U << TCP_RETRANS_BITS) - 1)
+#define TCP_MAX_RETRANS MAX_FROM_BITS(TCP_RETRANS_BITS)
#define TCP_WS_BITS 4 /* RFC 7323 */
#define TCP_WS_MAX 14
diff --git a/util.h b/util.h
index 6303c17..570094c 100644
--- a/util.h
+++ b/util.h
@@ -40,6 +40,8 @@
#define ROUND_DOWN(x, y) ((x) & ~((y) - 1))
#define ROUND_UP(x, y) (((x) + (y) - 1) & ~((y) - 1))
+#define MAX_FROM_BITS(n) ((int)((1U << (n)) - 1))
+
#define BIT(n) (1UL << (n))
#define BITMAP_BIT(n) (BIT((n) % (sizeof(long) * 8)))
#define BITMAP_WORD(n) (n / (sizeof(long) * 8))
--
2.39.2

View File

@ -0,0 +1,44 @@
From 8d631f17e11d6c9f1c01eb0dc1cb104ac45e63ac Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Mon, 27 Feb 2023 03:44:25 +0100
Subject: [PATCH 08/20] doc/demo: Fix and suppress ShellCheck warnings
ShellCheck reports (SC2034) that __qemu_arch is not used. Use it,
and silence the resulting SC2086 warning as we want word splitting on
options we pass with it.
While at it, silence SC2317 warnings for commands in cleanup() that
appear to be unreachable: cleanup() is only called as trap.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit fb05a713789fd9c20d0432f023ce26f3c5b94251)
---
doc/demo.sh | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/doc/demo.sh b/doc/demo.sh
index ed71ffb..5b05ddf 100755
--- a/doc/demo.sh
+++ b/doc/demo.sh
@@ -110,6 +110,7 @@ next() {
}
# cleanup() - Terminate pasta and passt, clean up, restore TTY settings
+# shellcheck disable=SC2317
cleanup() {
[ -f "${DEMO_DIR}/pasta.pid" ] && kill "$(cat "${DEMO_DIR}/pasta.pid")"
[ -f "${DEMO_DIR}/passt.pid" ] && kill "$(cat "${DEMO_DIR}/passt.pid")"
@@ -223,7 +224,8 @@ into_ns() {
echo "Use ^C to terminate it."
next
- cmd qrap 5 qemu-system-x86_64 -M pc,accel=kvm:tcg \
+ # shellcheck disable=SC2086
+ cmd qrap 5 ${__qemu_arch} \
-smp "$(nproc)" -m 1024 \
-nographic -serial stdio -nodefaults -no-reboot -vga none \
-initrd "${DEMO_DIR}/demo.img" \
--
2.39.2

View File

@ -0,0 +1,29 @@
From bbeecf78cf598f24bd2f1434dfbb3fad7b549f59 Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Mon, 6 Mar 2023 22:48:21 +0000
Subject: [PATCH 09/20] contrib/selinux: Drop duplicate init_daemon_domain()
rule
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Tested-by: Laine Stump <laine@redhat.com>
Reviewed-by: Laine Stump <laine@redhat.com>
(cherry picked from commit 009af75e450aae1d4e9e031a9e42a0e74ce1adf7)
---
contrib/selinux/passt.te | 1 -
1 file changed, 1 deletion(-)
diff --git a/contrib/selinux/passt.te b/contrib/selinux/passt.te
index 7fa4fb9..593b346 100644
--- a/contrib/selinux/passt.te
+++ b/contrib/selinux/passt.te
@@ -57,7 +57,6 @@ type passt_t;
domain_type(passt_t);
type passt_exec_t;
files_type(passt_exec_t);
-init_daemon_domain(passt_t, passt_exec_t)
type passt_log_t;
logging_log_file(passt_log_t);
type passt_etc_t;
--
2.39.2

View File

@ -0,0 +1,33 @@
From 2fcc8f2b519facb139df5e412379f991d8322bf4 Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Mon, 6 Mar 2023 22:49:39 +0000
Subject: [PATCH 10/20] contrib/selinux: Let passt write to stdout and stderr
when it starts
Otherwise, it's unusable as stand-alone tool, or in foreground mode,
and it's also impossible to get output from --help or --version,
because for SELinux it's just a daemon.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Tested-by: Laine Stump <laine@redhat.com>
Reviewed-by: Laine Stump <laine@redhat.com>
(cherry picked from commit 41bc669866b9e408d8d4966ee06e01784949b98d)
---
contrib/selinux/passt.te | 1 +
1 file changed, 1 insertion(+)
diff --git a/contrib/selinux/passt.te b/contrib/selinux/passt.te
index 593b346..6cd61f1 100644
--- a/contrib/selinux/passt.te
+++ b/contrib/selinux/passt.te
@@ -72,6 +72,7 @@ type_transition unconfined_t passt_exec_t : process passt_t;
allow unconfined_t passt_t : process transition ;
init_daemon_domain(passt_t, passt_exec_t)
+term_use_all_inherited_terms(passt_t)
allow passt_t bin_t:file { execute execute_no_trans map };
allow passt_t user_home_dir_t:dir { search add_name write };
--
2.39.2

View File

@ -0,0 +1,78 @@
From 8cb64a237ed6183c492dea04da7c8d3ca064a155 Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Mon, 6 Mar 2023 23:05:36 +0000
Subject: [PATCH 11/20] contrib/selinux: Allow binding and connecting to all
UDP and TCP ports
Laine reports that with a simple:
<portForward proto='tcp'>
<range start='2022' to='22'/>
</portForward>
in libvirt's domain XML, passt won't start as it fails to bind
arbitrary ports. That was actually the intention behind passt_port_t:
the user or system administrator should have explicitly configured
allowed ports on a given machine. But it's probably not realistic, so
just allow any port to be bound and forwarded.
Also fix up some missing operations on sockets.
Reported-by: Laine Stump <laine@redhat.com>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Tested-by: Laine Stump <laine@redhat.com>
Reviewed-by: Laine Stump <laine@redhat.com>
(cherry picked from commit de9b0cb5fee2ea00ed7e7877ef9be8c446bca134)
---
contrib/selinux/passt.te | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/contrib/selinux/passt.te b/contrib/selinux/passt.te
index 6cd61f1..438155d 100644
--- a/contrib/selinux/passt.te
+++ b/contrib/selinux/passt.te
@@ -62,9 +62,6 @@ logging_log_file(passt_log_t);
type passt_etc_t;
files_config_file(passt_etc_t);
-type passt_port_t;
-typeattribute passt_port_t port_type;
-
role unconfined_r types passt_t;
allow passt_t passt_exec_t : file { ioctl read getattr lock execute execute_no_trans entrypoint open } ;
@@ -100,16 +97,22 @@ allow passt_t net_conf_t:lnk_file read;
allow passt_t tmp_t:sock_file { create unlink write };
allow passt_t self:netlink_route_socket { bind create nlmsg_read read write setopt };
-allow passt_t self:tcp_socket create_stream_socket_perms;
-corenet_tcp_sendrecv_generic_node(passt_t)
-corenet_tcp_bind_generic_node(passt_t)
-allow passt_t passt_port_t:tcp_socket { name_bind name_connect };
-allow passt_t http_port_t:tcp_socket { name_bind name_connect };
-allow passt_t self:udp_socket create_stream_socket_perms;
-corenet_udp_sendrecv_generic_node(passt_t)
-corenet_udp_bind_generic_node(passt_t)
-allow passt_t passt_port_t:udp_socket { name_bind };
+corenet_tcp_bind_all_nodes(passt_t)
+corenet_udp_bind_all_nodes(passt_t)
+
+corenet_tcp_bind_all_ports(passt_t)
+corenet_udp_bind_all_ports(passt_t)
+
+corenet_tcp_connect_all_ports(passt_t)
+
+corenet_tcp_sendrecv_all_ports(passt_t)
+corenet_udp_sendrecv_all_ports(passt_t)
+
allow passt_t node_t:icmp_socket { name_bind node_bind };
+allow passt_t port_t:icmp_socket name_bind;
+
+allow passt_t self:tcp_socket { create getopt setopt connect bind listen accept shutdown read write };
+allow passt_t self:udp_socket { create getopt setopt connect bind read write };
allow passt_t self:icmp_socket { bind create setopt read write };
allow passt_t user_tmp_t:dir { add_name write };
--
2.39.2

View File

@ -0,0 +1,65 @@
From 7c01aa69bcd52197af708b9e08ce3067624288ef Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Mon, 6 Mar 2023 23:19:18 +0000
Subject: [PATCH 12/20] contrib/selinux: Let interface users set paths for log,
PID, socket files
Even libvirt itself will configure passt to write log, PID and socket
files to different locations depending on whether the domain is
started as root (/var/log/libvirt/...) or as a regular user
(/var/log/<PID>/libvirt/...), and user_tmp_t would only cover the
latter.
Create interfaces for log and PID files, so that callers can specify
different file contexts for those, and modify the interface for the
UNIX socket file to allow different paths as well.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Tested-by: Laine Stump <laine@redhat.com>
Reviewed-by: Laine Stump <laine@redhat.com>
(cherry picked from commit d361fe6e809bdf3539d764cfa5058f46ce51bcbf)
---
contrib/selinux/passt.if | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/contrib/selinux/passt.if b/contrib/selinux/passt.if
index 893395b..6a6105c 100644
--- a/contrib/selinux/passt.if
+++ b/contrib/selinux/passt.if
@@ -30,8 +30,32 @@ interface(`passt_socket',`
type passt_t;
')
- allow $1 user_tmp_t:sock_file write;
+ allow $1 $2:sock_file write;
allow $1 passt_t:unix_stream_socket connectto;
+
+ allow passt_t $2:sock_file { create read write unlink };
+')
+
+interface(`passt_logfile',`
+ gen_require(`
+ type passt_t;
+ ')
+
+ logging_log_file($1);
+ allow passt_t $1:dir { search write add_name };
+ allow passt_t $1:file { create open read write };
+')
+
+interface(`passt_pidfile',`
+ gen_require(`
+ type passt_t;
+ ')
+
+ allow $1 $2:file { open read unlink };
+
+ files_pid_file($2);
+ allow passt_t $2:dir { search write add_name };
+ allow passt_t $2:file { create open write };
')
interface(`passt_kill',`
--
2.39.2

View File

@ -0,0 +1,243 @@
From 812d24c91aecff78369f32f6593045f24d578d38 Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Wed, 8 Mar 2023 12:14:29 +0100
Subject: [PATCH 13/20] tcp, udp, util: Pass socket creation errors all the way
up
...starting from sock_l4(), pass negative error (errno) codes instead
of -1. They will only be used in two commits from now, no functional
changes intended here.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit 73992c42cea0df56f6ba0a3bef0f4a939f26ebad)
---
tcp.c | 22 ++++++++++++----------
udp.c | 18 +++++++++---------
util.c | 31 ++++++++++++++++++-------------
3 files changed, 39 insertions(+), 32 deletions(-)
diff --git a/tcp.c b/tcp.c
index fe6e458..482c2f9 100644
--- a/tcp.c
+++ b/tcp.c
@@ -2891,7 +2891,7 @@ void tcp_sock_handler(struct ctx *c, union epoll_ref ref, uint32_t events,
* @addr: Pointer to address for binding, NULL if not configured
* @ifname: Name of interface to bind to, NULL if not configured
*
- * Return: fd for the new listening socket, or -1 on failure
+ * Return: fd for the new listening socket, negative error code on failure
*/
static int tcp_sock_init_af(const struct ctx *c, int af, in_port_t port,
const struct in_addr *addr, const char *ifname)
@@ -2904,13 +2904,13 @@ static int tcp_sock_init_af(const struct ctx *c, int af, in_port_t port,
if (c->tcp.fwd_in.mode == FWD_AUTO) {
if (af == AF_INET || af == AF_UNSPEC)
- tcp_sock_init_ext[port][V4] = s;
+ tcp_sock_init_ext[port][V4] = s < 0 ? -1 : s;
if (af == AF_INET6 || af == AF_UNSPEC)
- tcp_sock_init_ext[port][V6] = s;
+ tcp_sock_init_ext[port][V6] = s < 0 ? -1 : s;
}
if (s < 0)
- return -1;
+ return s;
tcp_sock_set_bufsize(c, s);
return s;
@@ -2924,12 +2924,12 @@ static int tcp_sock_init_af(const struct ctx *c, int af, in_port_t port,
* @ifname: Name of interface to bind to, NULL if not configured
* @port: Port, host order
*
- * Return: 0 on (partial) success, -1 on (complete) failure
+ * Return: 0 on (partial) success, negative error code on (complete) failure
*/
int tcp_sock_init(const struct ctx *c, sa_family_t af, const void *addr,
const char *ifname, in_port_t port)
{
- int ret = 0;
+ int ret = 0, af_ret;
if (af == AF_UNSPEC && c->ifi4 && c->ifi6)
/* Attempt to get a dual stack socket */
@@ -2938,13 +2938,15 @@ int tcp_sock_init(const struct ctx *c, sa_family_t af, const void *addr,
/* Otherwise create a socket per IP version */
if ((af == AF_INET || af == AF_UNSPEC) && c->ifi4) {
- if (tcp_sock_init_af(c, AF_INET, port, addr, ifname) < 0)
- ret = -1;
+ af_ret = tcp_sock_init_af(c, AF_INET, port, addr, ifname);
+ if (af_ret < 0)
+ ret = af_ret;
}
if ((af == AF_INET6 || af == AF_UNSPEC) && c->ifi6) {
- if (tcp_sock_init_af(c, AF_INET6, port, addr, ifname) < 0)
- ret = -1;
+ af_ret = tcp_sock_init_af(c, AF_INET6, port, addr, ifname);
+ if (af_ret < 0)
+ ret = af_ret;
}
return ret;
diff --git a/udp.c b/udp.c
index 20a9ea0..9a43835 100644
--- a/udp.c
+++ b/udp.c
@@ -956,7 +956,7 @@ int udp_tap_handler(struct ctx *c, int af, const void *addr,
* @ifname: Name of interface to bind to, NULL if not configured
* @port: Port, host order
*
- * Return: 0 on (partial) success, -1 on (complete) failure
+ * Return: 0 on (partial) success, negative error code on (complete) failure
*/
int udp_sock_init(const struct ctx *c, int ns, sa_family_t af,
const void *addr, const char *ifname, in_port_t port)
@@ -981,19 +981,19 @@ int udp_sock_init(const struct ctx *c, int ns, sa_family_t af,
s = sock_l4(c, AF_INET, IPPROTO_UDP, addr, ifname,
port, uref.u32);
- udp_tap_map[V4][uref.udp.port].sock = s;
- udp_splice_init[V4][port].sock = s;
+ udp_tap_map[V4][uref.udp.port].sock = s < 0 ? -1 : s;
+ udp_splice_init[V4][port].sock = s < 0 ? -1 : s;
} else {
struct in_addr loopback = { htonl(INADDR_LOOPBACK) };
uref.udp.ns = true;
s = sock_l4(c, AF_INET, IPPROTO_UDP, &loopback,
ifname, port, uref.u32);
- udp_splice_ns[V4][port].sock = s;
+ udp_splice_ns[V4][port].sock = s < 0 ? -1 : s;
}
if (s < 0)
- ret = -1;
+ ret = s;
}
if ((af == AF_INET6 || af == AF_UNSPEC) && c->ifi6) {
@@ -1005,18 +1005,18 @@ int udp_sock_init(const struct ctx *c, int ns, sa_family_t af,
s = sock_l4(c, AF_INET6, IPPROTO_UDP, addr, ifname,
port, uref.u32);
- udp_tap_map[V6][uref.udp.port].sock = s;
- udp_splice_init[V6][port].sock = s;
+ udp_tap_map[V6][uref.udp.port].sock = s < 0 ? -1 : s;
+ udp_splice_init[V6][port].sock = s < 0 ? -1 : s;
} else {
uref.udp.ns = true;
s = sock_l4(c, AF_INET6, IPPROTO_UDP, &in6addr_loopback,
ifname, port, uref.u32);
- udp_splice_ns[V6][port].sock = s;
+ udp_splice_ns[V6][port].sock = s < 0 ? -1 : s;
}
if (s < 0)
- ret = -1;
+ ret = s;
}
return ret;
diff --git a/util.c b/util.c
index c5ee1c0..13f8fab 100644
--- a/util.c
+++ b/util.c
@@ -95,7 +95,7 @@ found:
* @port: Port, host order
* @data: epoll reference portion for protocol handlers
*
- * Return: newly created socket, -1 on error
+ * Return: newly created socket, negative error code on failure
*/
int sock_l4(const struct ctx *c, int af, uint8_t proto,
const void *bind_addr, const char *ifname, uint16_t port,
@@ -114,16 +114,16 @@ int sock_l4(const struct ctx *c, int af, uint8_t proto,
};
const struct sockaddr *sa;
bool dual_stack = false;
+ int fd, sl, y = 1, ret;
struct epoll_event ev;
- int fd, sl, y = 1;
if (proto != IPPROTO_TCP && proto != IPPROTO_UDP &&
proto != IPPROTO_ICMP && proto != IPPROTO_ICMPV6)
- return -1; /* Not implemented. */
+ return -EPFNOSUPPORT; /* Not implemented. */
if (af == AF_UNSPEC) {
if (!DUAL_STACK_SOCKETS || bind_addr)
- return -1;
+ return -EINVAL;
dual_stack = true;
af = AF_INET6;
}
@@ -133,14 +133,15 @@ int sock_l4(const struct ctx *c, int af, uint8_t proto,
else
fd = socket(af, SOCK_DGRAM | SOCK_NONBLOCK, proto);
+ ret = -errno;
if (fd < 0) {
- warn("L4 socket: %s", strerror(errno));
- return -1;
+ warn("L4 socket: %s", strerror(-ret));
+ return ret;
}
if (fd > SOCKET_MAX) {
close(fd);
- return -1;
+ return -EBADF;
}
ref.r.s = fd;
@@ -185,10 +186,11 @@ int sock_l4(const struct ctx *c, int af, uint8_t proto,
*/
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
ifname, strlen(ifname))) {
+ ret = -errno;
warn("Can't bind socket for %s port %u to %s, closing",
ip_proto_str[proto], port, ifname);
close(fd);
- return -1;
+ return ret;
}
}
@@ -199,22 +201,25 @@ int sock_l4(const struct ctx *c, int af, uint8_t proto,
* broken SELinux policy, see icmp_tap_handler().
*/
if (proto != IPPROTO_ICMP && proto != IPPROTO_ICMPV6) {
+ ret = -errno;
close(fd);
- return -1;
+ return ret;
}
}
if (proto == IPPROTO_TCP && listen(fd, 128) < 0) {
- warn("TCP socket listen: %s", strerror(errno));
+ ret = -errno;
+ warn("TCP socket listen: %s", strerror(-ret));
close(fd);
- return -1;
+ return ret;
}
ev.events = EPOLLIN;
ev.data.u64 = ref.u64;
if (epoll_ctl(c->epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
- warn("L4 epoll_ctl: %s", strerror(errno));
- return -1;
+ ret = -errno;
+ warn("L4 epoll_ctl: %s", strerror(-ret));
+ return ret;
}
return fd;
--
2.39.2

View File

@ -0,0 +1,139 @@
From 8f71f17cc087fc80f1cbe9b71852b95916a9afbc Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Wed, 8 Mar 2023 12:38:39 +0100
Subject: [PATCH 14/20] tcp, udp: Fix partial success return codes in
{tcp,udp}_sock_init()
The comments say we should return 0 on partial success, and an error
code on complete failure. Rationale: if the user configures a port
forwarding, and we succeed to bind that port for IPv4 or IPv6 only,
that might actually be what the user intended.
Adjust the two functions to reflect the comments.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit 5aea2f88ab5f63f01885109a4afb1271607fc06b)
---
tcp.c | 21 +++++++++------------
udp.c | 30 ++++++++++++++----------------
2 files changed, 23 insertions(+), 28 deletions(-)
diff --git a/tcp.c b/tcp.c
index 482c2f9..001fa50 100644
--- a/tcp.c
+++ b/tcp.c
@@ -2929,7 +2929,7 @@ static int tcp_sock_init_af(const struct ctx *c, int af, in_port_t port,
int tcp_sock_init(const struct ctx *c, sa_family_t af, const void *addr,
const char *ifname, in_port_t port)
{
- int ret = 0, af_ret;
+ int r4 = SOCKET_MAX + 1, r6 = SOCKET_MAX + 1;
if (af == AF_UNSPEC && c->ifi4 && c->ifi6)
/* Attempt to get a dual stack socket */
@@ -2937,19 +2937,16 @@ int tcp_sock_init(const struct ctx *c, sa_family_t af, const void *addr,
return 0;
/* Otherwise create a socket per IP version */
- if ((af == AF_INET || af == AF_UNSPEC) && c->ifi4) {
- af_ret = tcp_sock_init_af(c, AF_INET, port, addr, ifname);
- if (af_ret < 0)
- ret = af_ret;
- }
+ if ((af == AF_INET || af == AF_UNSPEC) && c->ifi4)
+ r4 = tcp_sock_init_af(c, AF_INET, port, addr, ifname);
- if ((af == AF_INET6 || af == AF_UNSPEC) && c->ifi6) {
- af_ret = tcp_sock_init_af(c, AF_INET6, port, addr, ifname);
- if (af_ret < 0)
- ret = af_ret;
- }
+ if ((af == AF_INET6 || af == AF_UNSPEC) && c->ifi6)
+ r6 = tcp_sock_init_af(c, AF_INET6, port, addr, ifname);
- return ret;
+ if (IN_INTERVAL(0, SOCKET_MAX, r4) || IN_INTERVAL(0, SOCKET_MAX, r6))
+ return 0;
+
+ return r4 < 0 ? r4 : r6;
}
/**
diff --git a/udp.c b/udp.c
index 9a43835..20ee0f2 100644
--- a/udp.c
+++ b/udp.c
@@ -962,7 +962,7 @@ int udp_sock_init(const struct ctx *c, int ns, sa_family_t af,
const void *addr, const char *ifname, in_port_t port)
{
union udp_epoll_ref uref = { .u32 = 0 };
- int s, ret = 0;
+ int s, r4 = SOCKET_MAX + 1, r6 = SOCKET_MAX + 1;
if (ns) {
uref.udp.port = (in_port_t)(port +
@@ -978,8 +978,8 @@ int udp_sock_init(const struct ctx *c, int ns, sa_family_t af,
uref.udp.orig = true;
if (!ns) {
- s = sock_l4(c, AF_INET, IPPROTO_UDP, addr, ifname,
- port, uref.u32);
+ r4 = s = sock_l4(c, AF_INET, IPPROTO_UDP, addr,
+ ifname, port, uref.u32);
udp_tap_map[V4][uref.udp.port].sock = s < 0 ? -1 : s;
udp_splice_init[V4][port].sock = s < 0 ? -1 : s;
@@ -987,13 +987,10 @@ int udp_sock_init(const struct ctx *c, int ns, sa_family_t af,
struct in_addr loopback = { htonl(INADDR_LOOPBACK) };
uref.udp.ns = true;
- s = sock_l4(c, AF_INET, IPPROTO_UDP, &loopback,
- ifname, port, uref.u32);
+ r4 = s = sock_l4(c, AF_INET, IPPROTO_UDP, &loopback,
+ ifname, port, uref.u32);
udp_splice_ns[V4][port].sock = s < 0 ? -1 : s;
}
-
- if (s < 0)
- ret = s;
}
if ((af == AF_INET6 || af == AF_UNSPEC) && c->ifi6) {
@@ -1002,24 +999,25 @@ int udp_sock_init(const struct ctx *c, int ns, sa_family_t af,
uref.udp.orig = true;
if (!ns) {
- s = sock_l4(c, AF_INET6, IPPROTO_UDP, addr, ifname,
- port, uref.u32);
+ r6 = s = sock_l4(c, AF_INET6, IPPROTO_UDP, addr,
+ ifname, port, uref.u32);
udp_tap_map[V6][uref.udp.port].sock = s < 0 ? -1 : s;
udp_splice_init[V6][port].sock = s < 0 ? -1 : s;
} else {
uref.udp.ns = true;
- s = sock_l4(c, AF_INET6, IPPROTO_UDP, &in6addr_loopback,
- ifname, port, uref.u32);
+ r6 = s = sock_l4(c, AF_INET6, IPPROTO_UDP,
+ &in6addr_loopback,
+ ifname, port, uref.u32);
udp_splice_ns[V6][port].sock = s < 0 ? -1 : s;
}
-
- if (s < 0)
- ret = s;
}
- return ret;
+ if (IN_INTERVAL(0, SOCKET_MAX, r4) || IN_INTERVAL(0, SOCKET_MAX, r6))
+ return 0;
+
+ return r4 < 0 ? r4 : r6;
}
/**
--
2.39.2

View File

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

View File

@ -0,0 +1,129 @@
From 96bf75e8ebffe06d33b5dee20c44e16ce53ea663 Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Wed, 8 Mar 2023 18:07:42 +0100
Subject: [PATCH 16/20] tcp: Clamp MSS value when queueing data to tap, also
for pasta
Tom reports that a pattern of repated ~1 MiB chunks downloads over
NNTP over TLS, on Podman 4.4 using pasta as network back-end, results
in pasta taking one full CPU thread after a while, and the download
never succeeds.
On that setup, we end up re-sending the same frame over and over,
with a consistent 65 534 bytes size, and never get an
acknowledgement from the tap-side client. This only happens for the
default MTU value (65 520 bytes) or for values that are slightly
smaller than that (down to 64 499 bytes).
We hit this condition because the MSS value we use in
tcp_data_from_sock(), only in pasta mode, is simply clamped to
USHRT_MAX, and not to the actual size of the buffers we pre-cooked
for sending, which is a bit less than that.
It looks like we got away with it until commit 0fb7b2b9080a ("tap:
Use different io vector bases depending on tap type") fixed the
setting of iov_len.
Luckily, since it's pasta, we're queueing up to two frames at a time,
so the worst that can happen is a badly segmented TCP stream: we
always have some space at the tail of the buffer.
Clamp the MSS value to the appropriate maximum given by struct
tcp{4,6}_buf_data_t, no matter if we're running in pasta or passt
mode.
While at it, fix the comments to those structs to reflect the current
struct size. This is not really relevant for any further calculation
or consideration, but it's convenient to know while debugging this
kind of issues.
Thanks to Tom for reporting the issue in a very detailed way and for
providing a test setup.
Reported-by: Tom Mombourquette <tom@devnode.com>
Link: https://github.com/containers/podman/issues/17703
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
(cherry picked from commit d7272f1df89c099a7e98ae43d1ef9b936c7e46f7)
---
tcp.c | 23 +++++++++--------------
1 file changed, 9 insertions(+), 14 deletions(-)
diff --git a/tcp.c b/tcp.c
index 001fa50..1355b0e 100644
--- a/tcp.c
+++ b/tcp.c
@@ -460,7 +460,7 @@ static struct tcp4_l2_buf_t {
struct iphdr iph; /* 44 28 */
struct tcphdr th; /* 64 48 */
uint8_t data[MSS4]; /* 84 68 */
- /* 65541 65525 */
+ /* 65536 65532 */
#ifdef __AVX2__
} __attribute__ ((packed, aligned(32)))
#else
@@ -488,7 +488,7 @@ struct tcp6_l2_buf_t {
struct ipv6hdr ip6h; /* 32 20 */
struct tcphdr th; /* 72 60 */
uint8_t data[MSS6]; /* 92 80 */
- /* 65639 65627 */
+ /* 65536 65532 */
#ifdef __AVX2__
} __attribute__ ((packed, aligned(32)))
#else
@@ -1913,15 +1913,13 @@ int tcp_conn_new_sock(const struct ctx *c, sa_family_t af)
/**
* tcp_conn_tap_mss() - Get MSS value advertised by tap/guest
- * @c: Execution context
* @conn: Connection pointer
* @opts: Pointer to start of TCP options
* @optlen: Bytes in options: caller MUST ensure available length
*
* Return: clamped MSS value
*/
-static uint16_t tcp_conn_tap_mss(const struct ctx *c,
- const struct tcp_tap_conn *conn,
+static uint16_t tcp_conn_tap_mss(const struct tcp_tap_conn *conn,
const char *opts, size_t optlen)
{
unsigned int mss;
@@ -1932,13 +1930,10 @@ static uint16_t tcp_conn_tap_mss(const struct ctx *c,
else
mss = ret;
- /* Don't upset qemu */
- if (c->mode == MODE_PASST) {
- if (CONN_V4(conn))
- mss = MIN(MSS4, mss);
- else
- mss = MIN(MSS6, mss);
- }
+ if (CONN_V4(conn))
+ mss = MIN(MSS4, mss);
+ else
+ mss = MIN(MSS6, mss);
return MIN(mss, USHRT_MAX);
}
@@ -2007,7 +2002,7 @@ static void tcp_conn_from_tap(struct ctx *c, int af, const void *addr,
conn->wnd_to_tap = WINDOW_DEFAULT;
- mss = tcp_conn_tap_mss(c, conn, opts, optlen);
+ mss = tcp_conn_tap_mss(conn, opts, optlen);
if (setsockopt(s, SOL_TCP, TCP_MAXSEG, &mss, sizeof(mss)))
trace("TCP: failed to set TCP_MAXSEG on socket %i", s);
MSS_SET(conn, mss);
@@ -2469,7 +2464,7 @@ static void tcp_conn_from_sock_finish(struct ctx *c, struct tcp_tap_conn *conn,
if (!(conn->wnd_from_tap >>= conn->ws_from_tap))
conn->wnd_from_tap = 1;
- MSS_SET(conn, tcp_conn_tap_mss(c, conn, opts, optlen));
+ MSS_SET(conn, tcp_conn_tap_mss(conn, opts, optlen));
conn->seq_init_from_tap = ntohl(th->seq) + 1;
conn->seq_from_tap = conn->seq_init_from_tap;
--
2.39.2

View File

@ -0,0 +1,98 @@
From def7d05a8babf5ea227f688f1f3a8bce286f97a3 Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Fri, 10 Mar 2023 14:53:14 +0000
Subject: [PATCH 17/20] contrib/selinux: Drop "example" from headers: this is
the actual policy
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
(cherry picked from commit 9f35cf0b11891e9dfb12eeb5d52f728881f84967)
---
contrib/selinux/passt.fc | 2 +-
contrib/selinux/passt.if | 2 +-
contrib/selinux/passt.te | 2 +-
contrib/selinux/pasta.fc | 2 +-
contrib/selinux/pasta.if | 2 +-
contrib/selinux/pasta.te | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/contrib/selinux/passt.fc b/contrib/selinux/passt.fc
index 286c868..88e388e 100644
--- a/contrib/selinux/passt.fc
+++ b/contrib/selinux/passt.fc
@@ -3,7 +3,7 @@
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
-# contrib/selinux/passt.fc - SELinux profile example: File Context for passt
+# contrib/selinux/passt.fc - SELinux profile: File Context for passt
#
# Copyright (c) 2022 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
diff --git a/contrib/selinux/passt.if b/contrib/selinux/passt.if
index 6a6105c..a79a8ec 100644
--- a/contrib/selinux/passt.if
+++ b/contrib/selinux/passt.if
@@ -3,7 +3,7 @@
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
-# contrib/selinux/passt.if - SELinux profile example: Interface File for passt
+# contrib/selinux/passt.if - SELinux profile: Interface File for passt
#
# Copyright (c) 2022 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
diff --git a/contrib/selinux/passt.te b/contrib/selinux/passt.te
index 438155d..590ad40 100644
--- a/contrib/selinux/passt.te
+++ b/contrib/selinux/passt.te
@@ -3,7 +3,7 @@
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
-# contrib/selinux/passt.te - SELinux profile example: Type Enforcement for passt
+# contrib/selinux/passt.te - SELinux profile: Type Enforcement for passt
#
# Copyright (c) 2022 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
diff --git a/contrib/selinux/pasta.fc b/contrib/selinux/pasta.fc
index f8fa0fa..e72b4ac 100644
--- a/contrib/selinux/pasta.fc
+++ b/contrib/selinux/pasta.fc
@@ -3,7 +3,7 @@
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
-# contrib/selinux/pasta.fc - SELinux profile example: File Context for pasta
+# contrib/selinux/pasta.fc - SELinux profile: File Context for pasta
#
# Copyright (c) 2022 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
diff --git a/contrib/selinux/pasta.if b/contrib/selinux/pasta.if
index a42bfcd..149045a 100644
--- a/contrib/selinux/pasta.if
+++ b/contrib/selinux/pasta.if
@@ -3,7 +3,7 @@
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
-# contrib/selinux/pasta.if - SELinux profile example: Interface File for pasta
+# contrib/selinux/pasta.if - SELinux profile: Interface File for pasta
#
# Copyright (c) 2022 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
diff --git a/contrib/selinux/pasta.te b/contrib/selinux/pasta.te
index 8986c0c..7856019 100644
--- a/contrib/selinux/pasta.te
+++ b/contrib/selinux/pasta.te
@@ -3,7 +3,7 @@
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
-# contrib/selinux/pasta.te - SELinux profile example: Type Enforcement for pasta
+# contrib/selinux/pasta.te - SELinux profile: Type Enforcement for pasta
#
# Copyright (c) 2022 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
--
2.39.2

View File

@ -0,0 +1,34 @@
From 6b5f382f342ad4a0a46e30b5ba165713768e363a Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Fri, 10 Mar 2023 14:53:37 +0000
Subject: [PATCH 18/20] contrib/selinux: Drop unused passt_read_data()
interface
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
(cherry picked from commit dcdc50fc2251339d6e929f708fad114e61b60627)
---
contrib/selinux/passt.if | 8 --------
1 file changed, 8 deletions(-)
diff --git a/contrib/selinux/passt.if b/contrib/selinux/passt.if
index a79a8ec..3e37c5b 100644
--- a/contrib/selinux/passt.if
+++ b/contrib/selinux/passt.if
@@ -8,14 +8,6 @@
# Copyright (c) 2022 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
-interface(`passt_read_data',`
- gen_require(`
- type passt_data_t;
- ')
- allow $1 passt_t:dir { search add_name };
- allow $1 passt_t:file { open read getattr };
-')
-
interface(`passt_domtrans',`
gen_require(`
type passt_t, passt_exec_t;
--
2.39.2

View File

@ -0,0 +1,120 @@
From 80978901354b17cf3460d5d4451b48b59a9204ae Mon Sep 17 00:00:00 2001
From: Stefano Brivio <sbrivio@redhat.com>
Date: Fri, 10 Mar 2023 17:00:31 +0000
Subject: [PATCH 19/20] contrib/selinux: Split interfaces into smaller bits
...to fit accepted Fedora practices.
Link: https://github.com/fedora-selinux/selinux-policy/pull/1613
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
(cherry picked from commit 93105ea06619d4c199f8140f4b75ae359757dc6d)
---
contrib/selinux/passt.if | 71 ++++++++++++++++++++++++++++++++++------
1 file changed, 61 insertions(+), 10 deletions(-)
diff --git a/contrib/selinux/passt.if b/contrib/selinux/passt.if
index 3e37c5b..f7560a7 100644
--- a/contrib/selinux/passt.if
+++ b/contrib/selinux/passt.if
@@ -17,37 +17,88 @@ interface(`passt_domtrans',`
domtrans_pattern($1, passt_exec_t, passt_t)
')
-interface(`passt_socket',`
+interface(`passt_socket_dir',`
+ gen_require(`
+ type passt_t;
+ ')
+
+ allow passt_t $1:dir add_entry_dir_perms;
+')
+
+interface(`passt_socket_create',`
+ gen_require(`
+ type passt_t;
+ ')
+
+ allow passt_t $1:sock_file create;
+')
+
+interface(`passt_socket_use',`
gen_require(`
type passt_t;
')
- allow $1 $2:sock_file write;
allow $1 passt_t:unix_stream_socket connectto;
+ allow $1 $2:sock_file { read write };
+ allow passt_t $2:sock_file { read write };
+')
+
+interface(`passt_socket_delete',`
+ gen_require(`
+ type passt_t;
+ ')
+
+ allow $1 $2:sock_file unlink;
+')
+
+interface(`passt_logfile_dir',`
+ gen_require(`
+ type passt_t;
+ ')
- allow passt_t $2:sock_file { create read write unlink };
+ allow passt_t $1:dir add_entry_dir_perms;
')
-interface(`passt_logfile',`
+interface(`passt_logfile_use',`
gen_require(`
type passt_t;
')
logging_log_file($1);
- allow passt_t $1:dir { search write add_name };
allow passt_t $1:file { create open read write };
')
-interface(`passt_pidfile',`
+interface(`passt_pidfile_dir',`
+ gen_require(`
+ type passt_t;
+ ')
+
+ allow passt_t $1:dir add_entry_dir_perms;
+')
+
+interface(`passt_pidfile_write',`
+ gen_require(`
+ type passt_t;
+ ')
+
+ files_pid_file($1);
+ allow passt_t $1:file { create open write };
+')
+
+interface(`passt_pidfile_read',`
gen_require(`
type passt_t;
')
- allow $1 $2:file { open read unlink };
+ allow $1 $2:file { open read };
+')
+
+interface(`passt_pidfile_delete',`
+ gen_require(`
+ type passt_t;
+ ')
- files_pid_file($2);
- allow passt_t $2:dir { search write add_name };
- allow passt_t $2:file { create open write };
+ allow $1 $2:file unlink;
')
interface(`passt_kill',`
--
2.39.2

View File

@ -7,22 +7,40 @@
# Copyright (c) 2022 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
%global git_hash b86afe3559c0bd3d24bc6fed7c60466cf141224c
%global git_hash 4ddbcb9c0c555838b123c018a9ebc9b7e14a87e5
%global selinuxtype targeted
Name: passt
Version: 0^20231204.gb86afe3
Release: 1%{?dist}
Version: 0^20230222.g4ddbcb9
Release: 4%{?dist}
Summary: User-mode networking daemons for virtual machines and namespaces
License: GPLv2+ and BSD
License: AGPLv3+ and BSD
Group: System Environment/Daemons
URL: https://passt.top/
Source: https://passt.top/passt/snapshot/passt-%{git_hash}.tar.xz
Patch1: 0001-selinux-Drop-user_namespace-create-allow-rules.patch
Patch1: 0001-udp-Actually-use-host-resolver-to-forward-DNS-querie.patch
Patch2: 0002-conf-Split-add_dns-4-6-out-of-get_dns.patch
Patch3: 0003-conf-udp-Allow-any-loopback-address-to-be-used-as-re.patch
Patch4: 0004-tcp-tcp_splice-Get-rid-of-false-positive-CWE-394-Cov.patch
Patch5: 0005-tcp-Avoid-false-but-convoluted-positive-Coverity-CWE.patch
Patch6: 0006-tcp-Avoid-theoretical-resource-leak-CWE-772-Coverity.patch
Patch7: 0007-Fix-definitions-of-SOCKET_MAX-TCP_MAX_CONNS.patch
Patch8: 0008-doc-demo-Fix-and-suppress-ShellCheck-warnings.patch
Patch9: 0009-contrib-selinux-Drop-duplicate-init_daemon_domain-ru.patch
Patch10: 0010-contrib-selinux-Let-passt-write-to-stdout-and-stderr.patch
Patch11: 0011-contrib-selinux-Allow-binding-and-connecting-to-all-.patch
Patch12: 0012-contrib-selinux-Let-interface-users-set-paths-for-lo.patch
Patch13: 0013-tcp-udp-util-Pass-socket-creation-errors-all-the-way.patch
Patch14: 0014-tcp-udp-Fix-partial-success-return-codes-in-tcp-udp-.patch
Patch15: 0015-conf-Terminate-on-EMFILE-or-ENFILE-on-sockets-for-po.patch
Patch16: 0016-tcp-Clamp-MSS-value-when-queueing-data-to-tap-also-f.patch
Patch17: 0017-contrib-selinux-Drop-example-from-headers-this-is-th.patch
Patch18: 0018-contrib-selinux-Drop-unused-passt_read_data-interfac.patch
Patch19: 0019-contrib-selinux-Split-interfaces-into-smaller-bits.patch
BuildRequires: gcc, make, git, checkpolicy, selinux-policy-devel
Requires: (%{name}-selinux = %{version}-%{release} if selinux-policy-%{selinuxtype})
Requires: (%{name}-selinux = %{version}-%{release} if selinux-policy-%{selinuxtype})
%description
passt implements a translation layer between a Layer-2 network interface and
@ -53,30 +71,13 @@ This package adds SELinux enforcement to passt(1) and pasta(1).
%build
%set_build_flags
# The Makefile creates symbolic links for pasta, but we need actual copies for
# SELinux file contexts to work as intended. Same with pasta.avx2 if present.
# Build twice, changing the version string, to avoid duplicate Build-IDs.
%make_build VERSION="%{version}-%{release}.%{_arch}-pasta"
mv -f passt pasta
%ifarch x86_64
mv -f passt.avx2 pasta.avx2
%make_build passt passt.avx2 VERSION="%{version}-%{release}.%{_arch}"
%else
%make_build passt VERSION="%{version}-%{release}.%{_arch}"
%endif
%make_build VERSION="%{version}-%{release}.%{_arch}"
%install
# Already built (not as symbolic links), see above
touch pasta
%ifarch x86_64
touch pasta.avx2
%endif
%make_install DESTDIR=%{buildroot} prefix=%{_prefix} bindir=%{_bindir} mandir=%{_mandir} docdir=%{_docdir}/%{name}
%ifarch x86_64
ln -sr %{buildroot}%{_mandir}/man1/passt.1 %{buildroot}%{_mandir}/man1/passt.avx2.1
ln -sr %{buildroot}%{_mandir}/man1/pasta.1 %{buildroot}%{_mandir}/man1/pasta.avx2.1
install -p -m 755 %{buildroot}%{_bindir}/passt.avx2 %{buildroot}%{_bindir}/pasta.avx2
%endif
pushd contrib/selinux
@ -103,7 +104,7 @@ fi
%selinux_relabel_post -s %{selinuxtype}
%files
%license LICENSES/{GPL-2.0-or-later.txt,BSD-3-Clause.txt}
%license LICENSES/{AGPL-3.0-or-later.txt,BSD-3-Clause.txt}
%dir %{_docdir}/%{name}
%doc %{_docdir}/%{name}/README.md
%doc %{_docdir}/%{name}/demo.sh
@ -126,25 +127,6 @@ fi
%{_datadir}/selinux/packages/%{selinuxtype}/pasta.pp
%changelog
* Fri Dec 15 2023 Stefano Brivio <sbrivio@redhat.com> - 0^20231204.gb86afe3-1
- Resolves: RHEL-19590
* Tue Aug 22 2023 Stefano Brivio <sbrivio@redhat.com> - 0^20230818.g0af928e-4
- Switch to copies instead of links for pasta: previous workaround unreliable
- Resolves: RHELPLAN-155811
* Tue Aug 22 2023 Stefano Brivio <sbrivio@redhat.com> - 0^20230818.g0af928e-3
- Explicit restorecon in scriptlet as rpm(8) mix up contexts with hard links
- Resolves: RHELPLAN-155811
* Mon Aug 21 2023 Stefano Brivio <sbrivio@redhat.com> - 0^20230818.g0af928e-2
- Drop user_namespace create allow rule, incompatible with current el9 kernel
- Resolves: RHELPLAN-155811
* Sat Aug 19 2023 Stefano Brivio <sbrivio@redhat.com> - 0^20230818.g0af928e-1
- Rebase from Fedora 39
- Resolves: RHELPLAN-155811
* Sun Jun 11 2023 Stefano Brivio <sbrivio@redhat.com> - 0^20230222.g4ddbcb9-4
- Drop (pointless) patches 20, 21, 22, actually apply changes to the spec file!
- Refresh SELinux labels in scriptlets, require -selinux package (rhbz#2183089)