From: David Gibson <david@gibson.dropbear.id.au>
To: Stefano Brivio <sbrivio@redhat.com>
Cc: passt-dev@passt.top
Subject: Re: Alas for CAP_NET_BIND_SERVICE
Date: Fri, 14 Oct 2022 13:56:37 +1100 [thread overview]
Message-ID: <Y0jP5dN1Z8ajBpRf@yekko> (raw)
In-Reply-To: <20221013125017.195769cf@elisabeth>
[-- Attachment #1: Type: text/plain, Size: 6503 bytes --]
On Thu, Oct 13, 2022 at 12:50:17PM +0200, Stefano Brivio wrote:
> On Wed, 12 Oct 2022 12:47:07 +0200
> Stefano Brivio <sbrivio@redhat.com> wrote:
>
> > [...]
> >
> > We currently need to process port configuration in a second step for
> > two reasons:
> >
> > - we might bind ports in the detached namespace (-T, -U)
> >
> > - one between IPv4 and IPv6 support could be administratively disabled
> > (operationally, who cares, we'll just fail to bind if that's the
> > case)
> >
> > ...but for init/host facing ports (now: "inbound"), we don't care about
> > the detached namespace, and we could simply call conf_ports() for -t
> > and -u in a second step after the main loop. Sure, if we continue like
> > this, we'll end up with O(n²) option handling, but right now it
> > doesn't look that bad to me.
> >
> > I would give it a shot after I'm done reviewing your patchset (it
> > should also look clearer after that) and re-spinning my recent ones,
> > unless you see something wrong with it.
>
> So, I have a draft (minus man page changes), a bit more involved than I
> wanted but still not adding much.
>
> It's based on your patchset, so I can't really test it with Podman
> because of that new issue I'm facing with filesystem-bound namespaces,
> but it passes our tests, and it works with low ports too.
>
> I would try to figure out that other issue before posting it properly,
> here it comes anyway:
Looks reasonable.
> diff --git a/conf.c b/conf.c
> index a22ef48..e1f42f1 100644
> --- a/conf.c
> +++ b/conf.c
> @@ -1530,6 +1530,11 @@ void conf(struct ctx *c, int argc, char **argv)
> }
> } while (name != -1);
>
> + if (v4_only && v6_only) {
> + err("Options ipv4-only and ipv6-only are mutually exclusive");
> + usage(argv[0]);
> + }
> +
> ret = conf_ugid(runas, &uid, &gid);
> if (ret)
> usage(argv[0]);
> @@ -1539,6 +1544,30 @@ void conf(struct ctx *c, int argc, char **argv)
> logfile, logsize);
> }
>
> + nl_sock_init(c, false);
> + if (!v6_only)
> + c->ifi4 = conf_ip4(ifi, &c->ip4, c->mac);
> + if (!v4_only)
> + c->ifi6 = conf_ip6(ifi, &c->ip6, c->mac);
> + if (!c->ifi4 && !c->ifi6) {
> + err("External interface not usable");
> + exit(EXIT_FAILURE);
> + }
> +
> + /* Inbound port options can be parsed now (after IPv4/IPv6 settings) */
> + optind = 1;
> + do {
> + struct port_fwd *fwd;
> +
> + name = getopt_long(argc, argv, optstring, options, NULL);
> +
> + if ((name == 't' && (fwd = &c->tcp.fwd_in)) ||
> + (name == 'u' && (fwd = &c->udp.fwd_in.f))) {
> + if (!optarg || conf_ports(c, name, optarg, fwd))
> + usage(argv[0]);
> + }
> + } while (name != -1);
> +
> if (c->mode == MODE_PASTA) {
> if (conf_pasta_ns(&netns_only, userns, netns,
> optind, argc, argv) < 0)
> @@ -1561,50 +1590,20 @@ void conf(struct ctx *c, int argc, char **argv)
> }
> }
>
> - if (nl_sock_init(c)) {
> - err("Failed to get netlink socket");
> - exit(EXIT_FAILURE);
> - }
> -
> - if (v4_only && v6_only) {
> - err("Options ipv4-only and ipv6-only are mutually exclusive");
> - usage(argv[0]);
> - }
> - if (!v6_only)
> - c->ifi4 = conf_ip4(ifi, &c->ip4, c->mac);
> - if (!v4_only)
> - c->ifi6 = conf_ip6(ifi, &c->ip6, c->mac);
> - if (!c->ifi4 && !c->ifi6) {
> - err("External interface not usable");
> - exit(EXIT_FAILURE);
> - }
> + if (c->mode == MODE_PASTA)
> + nl_sock_init(c, true);
>
> - /* Now we can process port configuration options */
> + /* ...and outbound port options now that namespaces are set up. */
> optind = 1;
> do {
> - struct port_fwd *fwd = NULL;
> + struct port_fwd *fwd;
>
> name = getopt_long(argc, argv, optstring, options, NULL);
> - switch (name) {
> - case 't':
> - case 'u':
> - case 'T':
> - case 'U':
> - if (name == 't')
> - fwd = &c->tcp.fwd_in;
> - else if (name == 'T')
> - fwd = &c->tcp.fwd_out;
> - else if (name == 'u')
> - fwd = &c->udp.fwd_in.f;
> - else if (name == 'U')
> - fwd = &c->udp.fwd_out.f;
>
> + if ((name == 'T' && (fwd = &c->tcp.fwd_out)) ||
> + (name == 'U' && (fwd = &c->udp.fwd_out.f))) {
> if (!optarg || conf_ports(c, name, optarg, fwd))
> usage(argv[0]);
> -
> - break;
> - default:
> - break;
> }
> } while (name != -1);
>
> diff --git a/netlink.c b/netlink.c
> index 6e5a96b..3ee4d42 100644
> --- a/netlink.c
> +++ b/netlink.c
> @@ -19,6 +19,7 @@
> #include <sys/types.h>
> #include <limits.h>
> #include <stdlib.h>
> +#include <stdbool.h>
> #include <stdint.h>
> #include <unistd.h>
> #include <arpa/inet.h>
> @@ -71,25 +72,28 @@ ns:
> }
>
> /**
> - * nl_sock_init() - Call nl_sock_init_do() and check for failures
> + * nl_sock_init() - Call nl_sock_init_do(), won't return on failure
> * @c: Execution context
> - *
> - * Return: -EIO if sockets couldn't be set up, 0 otherwise
> + * @ns: Get socket in namespace, not in init
> */
> -int nl_sock_init(const struct ctx *c)
> +void nl_sock_init(const struct ctx *c, bool ns)
> {
> - if (c->mode == MODE_PASTA) {
> + if (c->mode == MODE_PASTA && ns) {
> NS_CALL(nl_sock_init_do, c);
> if (nl_sock_ns == -1)
> - return -EIO;
> + goto fail;
> } else {
> nl_sock_init_do(NULL);
> }
>
> if (nl_sock == -1)
> - return -EIO;
> + goto fail;
>
> - return 0;
> + return;
> +
> +fail:
> + err("Failed to get netlink socket");
> + exit(EXIT_FAILURE);
> }
>
> /**
> diff --git a/netlink.h b/netlink.h
> index 5ce5037..3c991cc 100644
> --- a/netlink.h
> +++ b/netlink.h
> @@ -6,7 +6,7 @@
> #ifndef NETLINK_H
> #define NETLINK_H
>
> -int nl_sock_init(const struct ctx *c);
> +void nl_sock_init(const struct ctx *c, bool ns);
> unsigned int nl_get_ext_if(sa_family_t af);
> void nl_route(int ns, unsigned int ifi, sa_family_t af, void *gw);
> void nl_addr(int ns, unsigned int ifi, sa_family_t af,
> diff --git a/tap.c b/tap.c
> index 77e513c..8b6d9bc 100644
> --- a/tap.c
> +++ b/tap.c
> @@ -30,6 +30,7 @@
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <sys/uio.h>
> +#include <stdbool.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <netinet/ip.h>
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
prev parent reply other threads:[~2022-10-14 2:57 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-12 2:55 Alas for CAP_NET_BIND_SERVICE David Gibson
2022-10-12 5:54 ` Stefano Brivio
2022-10-12 9:31 ` David Gibson
2022-10-12 10:47 ` Stefano Brivio
2022-10-13 0:34 ` David Gibson
2022-10-13 4:54 ` Stefano Brivio
2022-10-13 5:15 ` Stefano Brivio
2022-10-14 2:54 ` David Gibson
2022-10-16 9:46 ` Stefano Brivio
2022-10-17 3:20 ` David Gibson
2022-10-13 10:50 ` Stefano Brivio
2022-10-14 2:56 ` David Gibson [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Y0jP5dN1Z8ajBpRf@yekko \
--to=david@gibson.dropbear.id.au \
--cc=passt-dev@passt.top \
--cc=sbrivio@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://passt.top/passt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).