Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 26 Dec 2021 19:07:06 +0000
From:      Jessica Clarke <jrtc27@freebsd.org>
To:        Gleb Smirnoff <glebius@FreeBSD.org>
Cc:        "src-committers@freebsd.org" <src-committers@FreeBSD.org>, "dev-commits-src-all@freebsd.org" <dev-commits-src-all@FreeBSD.org>, "dev-commits-src-main@freebsd.org" <dev-commits-src-main@FreeBSD.org>
Subject:   Re: git: eb8dcdeac22d - main - jail: network epoch protection for IP address lists
Message-ID:  <04FFE80E-388E-4028-A6D8-FE6F725C1B5B@freebsd.org>
In-Reply-To: <202112261846.1BQIkYd8075256@gitrepo.freebsd.org>
References:  <202112261846.1BQIkYd8075256@gitrepo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On 26 Dec 2021, at 18:46, Gleb Smirnoff <glebius@FreeBSD.org> wrote:
>=20
> The branch main has been updated by glebius:
>=20
> URL: =
https://cgit.FreeBSD.org/src/commit/?id=3Deb8dcdeac22daadbf07be81d7338e14e=
c4cc7d7f
>=20
> commit eb8dcdeac22daadbf07be81d7338e14ec4cc7d7f
> Author:     Gleb Smirnoff <glebius@FreeBSD.org>
> AuthorDate: 2021-12-26 18:45:50 +0000
> Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
> CommitDate: 2021-12-26 18:45:50 +0000
>=20
>    jail: network epoch protection for IP address lists
>=20
>    Now struct prison has two pointers (IPv4 and IPv6) of struct
>    prison_ip type.  Each points into epoch context, address count
>    and variable size array of addresses.  These structures are
>    freed with network epoch deferred free and are not edited in
>    place, instead a new structure is allocated and set.
>=20
>    While here, the change also generalizes a lot (but not enough)
>    of IPv4 and IPv6 processing. E.g. address family agnostic helpers
>    for kern_jail_set() are provided, that reduce v4-v6 copy-paste.
>=20
>    The fast-path prison_check_ip[46]_locked() is also generalized
>    into prison_ip_check() that can be executed with network epoch
>    protection only.
>=20
>    Reviewed by:            jamie
>    Differential revision:  https://reviews.freebsd.org/D33339
> ---
> sys/kern/kern_jail.c    | 770 =
+++++++++++++++++++++++++++++++-----------------
> sys/netinet/in.c        |   2 +
> sys/netinet/in_jail.c   | 139 ++-------
> sys/netinet6/in6_jail.c | 133 ++-------
> sys/sys/jail.h          |  25 +-
> 5 files changed, 572 insertions(+), 497 deletions(-)
>=20
> diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
> index e505e9bf1276..f1c81d8813bd 100644
> --- a/sys/kern/kern_jail.c
> +++ b/sys/kern/kern_jail.c
> @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
> #include <sys/osd.h>
> #include <sys/priv.h>
> #include <sys/proc.h>
> +#include <sys/epoch.h>
> #include <sys/taskqueue.h>
> #include <sys/fcntl.h>
> #include <sys/jail.h>
> @@ -531,15 +532,407 @@ sys_jail_set(struct thread *td, struct =
jail_set_args *uap)
> 	return (error);
> }
>=20
> +#if defined(INET) || defined(INET6)
> +typedef int prison_addr_cmp_t(const void *, const void *);
> +typedef bool prison_addr_valid_t(const void *);
> +static const struct pr_family {
> +	size_t			size;
> +	prison_addr_cmp_t	*cmp;
> +	prison_addr_valid_t	*valid;
> +	int			ip_flag;
> +} pr_families[PR_FAMILY_MAX] =3D {
> +#ifdef INET
> +	[PR_INET] =3D {
> +		.size =3D sizeof(struct in_addr),
> +		.cmp =3D prison_qcmp_v4,
> +		.valid =3D prison_valid_v4,
> +		.ip_flag =3D PR_IP4_USER,
> +	 },
> +#endif
> +#ifdef INET6
> +	[PR_INET6] =3D {
> +		.size =3D sizeof(struct in6_addr),
> +		.cmp =3D prison_qcmp_v6,
> +		.valid =3D prison_valid_v6,
> +		.ip_flag =3D PR_IP6_USER,
> +	},
> +#endif
> +};
> +
> +/*
> + * Network address lists (pr_addrs) allocation for jails.  The =
addresses
> + * are accessed locklessly by the network stack, thus need to be =
protected by
> + * the network epoch.
> + */
> +struct prison_ip {
> +	struct epoch_context ctx;
> +	uint32_t	ips;
> +#ifdef FUTURE_C
> +	union {
> +		struct in_addr pr_ip4[];
> +		struct in6_addr pr_ip6[];
> +	};
> +#else /* No future C :( */
> +#define	PR_IP(pip, i)	((const char *)((pip) + 1) + =
pr_families[af].size * (i))
> +#define	PR_IPD(pip, i)	((char *)((pip) + 1) + =
pr_families[af].size * (i))
> +#endif
> +};

You can make this work with a prison_ip base and prison_ipv[46] derived
structs.

As it stands this is quite gross, you=E2=80=99re assuming things about
alignment, and don=E2=80=99t even have a flexible char[] at the end to
represent the extra data.

Jess




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?04FFE80E-388E-4028-A6D8-FE6F725C1B5B>