Commit 1e424d08 authored by Paolo Abeni's avatar Paolo Abeni
Browse files
Steffen Klassert says:

====================
pull request (net): ipsec 2024-10-22

1) Fix routing behavior that relies on L4 information
   for xfrm encapsulated packets.
   From Eyal Birger.

2) Remove leftovers of pernet policy_inexact lists.
   From Florian Westphal.

3) Validate new SA's prefixlen when the selector family is
   not set from userspace.
   From Sabrina Dubroca.

4) Fix a kernel-infoleak when dumping an auth algorithm.
   From Petr Vaganov.

Please pull or let me know if there are problems.

ipsec-2024-10-22

* tag 'ipsec-2024-10-22' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec:
  xfrm: fix one more kernel-infoleak in algo dumping
  xfrm: validate new SA's prefixlen using SA family when sel.family is unset
  xfrm: policy: remove last remnants of pernet inexact list
  xfrm: respect ip protocols rules criteria when performing dst lookups
  xfrm: extract dst lookup parameters into a struct
====================

Link: https://patch.msgid.link/20241022092226.654370-1-steffen.klassert@secunet.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 6e62807c 6889cd2a
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -51,7 +51,6 @@ struct netns_xfrm {
	struct hlist_head	*policy_byidx;
	unsigned int		policy_idx_hmask;
	unsigned int		idx_generator;
	struct hlist_head	policy_inexact[XFRM_POLICY_MAX];
	struct xfrm_policy_hash	policy_bydst[XFRM_POLICY_MAX];
	unsigned int		policy_count[XFRM_POLICY_MAX * 2];
	struct work_struct	policy_hash_work;
+15 −13
Original line number Diff line number Diff line
@@ -349,20 +349,25 @@ struct xfrm_if_cb {
void xfrm_if_register_cb(const struct xfrm_if_cb *ifcb);
void xfrm_if_unregister_cb(void);

struct xfrm_dst_lookup_params {
	struct net *net;
	int tos;
	int oif;
	xfrm_address_t *saddr;
	xfrm_address_t *daddr;
	u32 mark;
	__u8 ipproto;
	union flowi_uli uli;
};

struct net_device;
struct xfrm_type;
struct xfrm_dst;
struct xfrm_policy_afinfo {
	struct dst_ops		*dst_ops;
	struct dst_entry	*(*dst_lookup)(struct net *net,
					       int tos, int oif,
					       const xfrm_address_t *saddr,
					       const xfrm_address_t *daddr,
					       u32 mark);
	int			(*get_saddr)(struct net *net, int oif,
					     xfrm_address_t *saddr,
					     xfrm_address_t *daddr,
					     u32 mark);
	struct dst_entry	*(*dst_lookup)(const struct xfrm_dst_lookup_params *params);
	int			(*get_saddr)(xfrm_address_t *saddr,
					     const struct xfrm_dst_lookup_params *params);
	int			(*fill_dst)(struct xfrm_dst *xdst,
					    struct net_device *dev,
					    const struct flowi *fl);
@@ -1764,10 +1769,7 @@ static inline int xfrm_user_policy(struct sock *sk, int optname,
}
#endif

struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
				    const xfrm_address_t *saddr,
				    const xfrm_address_t *daddr,
				    int family, u32 mark);
struct dst_entry *__xfrm_dst_lookup(int family, const struct xfrm_dst_lookup_params *params);

struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp);

+18 −22
Original line number Diff line number Diff line
@@ -17,47 +17,43 @@
#include <net/ip.h>
#include <net/l3mdev.h>

static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
					    int tos, int oif,
					    const xfrm_address_t *saddr,
					    const xfrm_address_t *daddr,
					    u32 mark)
static struct dst_entry *__xfrm4_dst_lookup(struct flowi4 *fl4,
					    const struct xfrm_dst_lookup_params *params)
{
	struct rtable *rt;

	memset(fl4, 0, sizeof(*fl4));
	fl4->daddr = daddr->a4;
	fl4->flowi4_tos = tos;
	fl4->flowi4_l3mdev = l3mdev_master_ifindex_by_index(net, oif);
	fl4->flowi4_mark = mark;
	if (saddr)
		fl4->saddr = saddr->a4;

	rt = __ip_route_output_key(net, fl4);
	fl4->daddr = params->daddr->a4;
	fl4->flowi4_tos = params->tos;
	fl4->flowi4_l3mdev = l3mdev_master_ifindex_by_index(params->net,
							    params->oif);
	fl4->flowi4_mark = params->mark;
	if (params->saddr)
		fl4->saddr = params->saddr->a4;
	fl4->flowi4_proto = params->ipproto;
	fl4->uli = params->uli;

	rt = __ip_route_output_key(params->net, fl4);
	if (!IS_ERR(rt))
		return &rt->dst;

	return ERR_CAST(rt);
}

static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, int oif,
					  const xfrm_address_t *saddr,
					  const xfrm_address_t *daddr,
					  u32 mark)
static struct dst_entry *xfrm4_dst_lookup(const struct xfrm_dst_lookup_params *params)
{
	struct flowi4 fl4;

	return __xfrm4_dst_lookup(net, &fl4, tos, oif, saddr, daddr, mark);
	return __xfrm4_dst_lookup(&fl4, params);
}

static int xfrm4_get_saddr(struct net *net, int oif,
			   xfrm_address_t *saddr, xfrm_address_t *daddr,
			   u32 mark)
static int xfrm4_get_saddr(xfrm_address_t *saddr,
			   const struct xfrm_dst_lookup_params *params)
{
	struct dst_entry *dst;
	struct flowi4 fl4;

	dst = __xfrm4_dst_lookup(net, &fl4, 0, oif, NULL, daddr, mark);
	dst = __xfrm4_dst_lookup(&fl4, params);
	if (IS_ERR(dst))
		return -EHOSTUNREACH;

+16 −15
Original line number Diff line number Diff line
@@ -23,23 +23,24 @@
#include <net/ip6_route.h>
#include <net/l3mdev.h>

static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
					  const xfrm_address_t *saddr,
					  const xfrm_address_t *daddr,
					  u32 mark)
static struct dst_entry *xfrm6_dst_lookup(const struct xfrm_dst_lookup_params *params)
{
	struct flowi6 fl6;
	struct dst_entry *dst;
	int err;

	memset(&fl6, 0, sizeof(fl6));
	fl6.flowi6_l3mdev = l3mdev_master_ifindex_by_index(net, oif);
	fl6.flowi6_mark = mark;
	memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
	if (saddr)
		memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));
	fl6.flowi6_l3mdev = l3mdev_master_ifindex_by_index(params->net,
							   params->oif);
	fl6.flowi6_mark = params->mark;
	memcpy(&fl6.daddr, params->daddr, sizeof(fl6.daddr));
	if (params->saddr)
		memcpy(&fl6.saddr, params->saddr, sizeof(fl6.saddr));

	dst = ip6_route_output(net, NULL, &fl6);
	fl6.flowi4_proto = params->ipproto;
	fl6.uli = params->uli;

	dst = ip6_route_output(params->net, NULL, &fl6);

	err = dst->error;
	if (dst->error) {
@@ -50,15 +51,14 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
	return dst;
}

static int xfrm6_get_saddr(struct net *net, int oif,
			   xfrm_address_t *saddr, xfrm_address_t *daddr,
			   u32 mark)
static int xfrm6_get_saddr(xfrm_address_t *saddr,
			   const struct xfrm_dst_lookup_params *params)
{
	struct dst_entry *dst;
	struct net_device *dev;
	struct inet6_dev *idev;

	dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr, mark);
	dst = xfrm6_dst_lookup(params);
	if (IS_ERR(dst))
		return -EHOSTUNREACH;

@@ -68,7 +68,8 @@ static int xfrm6_get_saddr(struct net *net, int oif,
		return -EHOSTUNREACH;
	}
	dev = idev->dev;
	ipv6_dev_get_saddr(dev_net(dev), dev, &daddr->in6, 0, &saddr->in6);
	ipv6_dev_get_saddr(dev_net(dev), dev, &params->daddr->in6, 0,
			   &saddr->in6);
	dst_release(dst);
	return 0;
}
+8 −3
Original line number Diff line number Diff line
@@ -269,6 +269,8 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,

	dev = dev_get_by_index(net, xuo->ifindex);
	if (!dev) {
		struct xfrm_dst_lookup_params params;

		if (!(xuo->flags & XFRM_OFFLOAD_INBOUND)) {
			saddr = &x->props.saddr;
			daddr = &x->id.daddr;
@@ -277,9 +279,12 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
			daddr = &x->props.saddr;
		}

		dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr,
					x->props.family,
					xfrm_smark_get(0, x));
		memset(&params, 0, sizeof(params));
		params.net = net;
		params.saddr = saddr;
		params.daddr = daddr;
		params.mark = xfrm_smark_get(0, x);
		dst = __xfrm_dst_lookup(x->props.family, &params);
		if (IS_ERR(dst))
			return (is_packet_offload) ? -EINVAL : 0;

Loading