ipsec-2024-10-22
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH7ZpcWbFyOOp6OJbrB3Eaf9PW7cFAmcXbBEACgkQrB3Eaf9P W7e0hQ//XiBdyhArA8kYIgsCylrOr+y/uCErnIhzUTqo20uE3dMPvzQHwY1GIgiU HYXKg49WLVxSuFtLRu32qCr0G+muU1UI5OL58IQuQ+TxKzj0hnV4BqAx+rNYhaFb JxJhgAcQQu7VCL7/qgqGsQnhq/hhg29Rfqa1VTEZ4RthEMahPDbwyibjyOfqwSgm fCPIl2FTkB7E0PZnwZJGxmaOJXS7g/djb+CPmBI6zxLQHG5VXY/UGNyObUvTLD9K gV+N0u0ieyDTxpvpgh6HMAFSkORLS/PIUCAX0SZEW48+7DLbBeKMMYwegtxxJZ3D 3zaWi8uKGh5rjOslQbU4ZlpxJr7yvIV6RhGJhOPDYz5Es4EXHU7c0tZ/pma46eb0 2PJxQyTHW4O9fbybQvl0w9fUQlhjKMbv/TygJgpOIk9YUr2y8Yxc8yhmWi+669ly e7PEi/33lqJI44gisu0BMresxJcPA3eFWje+Dzw/7N/tlLJzbWt3psRqB9u/JwVH LD0YvXraZYvaRNzeGUfbXTrvmouhLcl15zAE8RFJBTgGJbpILviJ9NfUMOIO7Yor BBKEWlylCm/4x5iOdVb17gFCi7uERiahbxNg3+hltAQuMvEdrhhWXp1N7esTRvkf D1o0qR5C2k2jyc9LQNqfiGWDEOgTCt1DCdhpo2F/EtF5kSerp6s= =Ai21 -----END PGP SIGNATURE----- Merge tag 'ipsec-2024-10-22' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec 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: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
1e424d08d3
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
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(net, fl4);
|
||||
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;
|
||||
|
||||
|
@ -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, ¶ms->daddr->in6, 0,
|
||||
&saddr->in6);
|
||||
dst_release(dst);
|
||||
return 0;
|
||||
}
|
||||
|
@ -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(¶ms, 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, ¶ms);
|
||||
if (IS_ERR(dst))
|
||||
return (is_packet_offload) ? -EINVAL : 0;
|
||||
|
||||
|
@ -270,10 +270,8 @@ static const struct xfrm_if_cb *xfrm_if_get_cb(void)
|
||||
return rcu_dereference(xfrm_if_cb);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
const struct xfrm_policy_afinfo *afinfo;
|
||||
struct dst_entry *dst;
|
||||
@ -282,7 +280,7 @@ struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
|
||||
if (unlikely(afinfo == NULL))
|
||||
return ERR_PTR(-EAFNOSUPPORT);
|
||||
|
||||
dst = afinfo->dst_lookup(net, tos, oif, saddr, daddr, mark);
|
||||
dst = afinfo->dst_lookup(params);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
@ -296,6 +294,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x,
|
||||
xfrm_address_t *prev_daddr,
|
||||
int family, u32 mark)
|
||||
{
|
||||
struct xfrm_dst_lookup_params params;
|
||||
struct net *net = xs_net(x);
|
||||
xfrm_address_t *saddr = &x->props.saddr;
|
||||
xfrm_address_t *daddr = &x->id.daddr;
|
||||
@ -310,7 +309,29 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x,
|
||||
daddr = x->coaddr;
|
||||
}
|
||||
|
||||
dst = __xfrm_dst_lookup(net, tos, oif, saddr, daddr, family, mark);
|
||||
params.net = net;
|
||||
params.saddr = saddr;
|
||||
params.daddr = daddr;
|
||||
params.tos = tos;
|
||||
params.oif = oif;
|
||||
params.mark = mark;
|
||||
params.ipproto = x->id.proto;
|
||||
if (x->encap) {
|
||||
switch (x->encap->encap_type) {
|
||||
case UDP_ENCAP_ESPINUDP:
|
||||
params.ipproto = IPPROTO_UDP;
|
||||
params.uli.ports.sport = x->encap->encap_sport;
|
||||
params.uli.ports.dport = x->encap->encap_dport;
|
||||
break;
|
||||
case TCP_ENCAP_ESPINTCP:
|
||||
params.ipproto = IPPROTO_TCP;
|
||||
params.uli.ports.sport = x->encap->encap_sport;
|
||||
params.uli.ports.dport = x->encap->encap_dport;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dst = __xfrm_dst_lookup(family, ¶ms);
|
||||
|
||||
if (!IS_ERR(dst)) {
|
||||
if (prev_saddr != saddr)
|
||||
@ -2432,15 +2453,15 @@ int __xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk)
|
||||
}
|
||||
|
||||
static int
|
||||
xfrm_get_saddr(struct net *net, int oif, xfrm_address_t *local,
|
||||
xfrm_address_t *remote, unsigned short family, u32 mark)
|
||||
xfrm_get_saddr(unsigned short family, xfrm_address_t *saddr,
|
||||
const struct xfrm_dst_lookup_params *params)
|
||||
{
|
||||
int err;
|
||||
const struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
|
||||
|
||||
if (unlikely(afinfo == NULL))
|
||||
return -EINVAL;
|
||||
err = afinfo->get_saddr(net, oif, local, remote, mark);
|
||||
err = afinfo->get_saddr(saddr, params);
|
||||
rcu_read_unlock();
|
||||
return err;
|
||||
}
|
||||
@ -2469,9 +2490,14 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl,
|
||||
remote = &tmpl->id.daddr;
|
||||
local = &tmpl->saddr;
|
||||
if (xfrm_addr_any(local, tmpl->encap_family)) {
|
||||
error = xfrm_get_saddr(net, fl->flowi_oif,
|
||||
&tmp, remote,
|
||||
tmpl->encap_family, 0);
|
||||
struct xfrm_dst_lookup_params params;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.net = net;
|
||||
params.oif = fl->flowi_oif;
|
||||
params.daddr = remote;
|
||||
error = xfrm_get_saddr(tmpl->encap_family, &tmp,
|
||||
¶ms);
|
||||
if (error)
|
||||
goto fail;
|
||||
local = &tmp;
|
||||
@ -4180,7 +4206,6 @@ static int __net_init xfrm_policy_init(struct net *net)
|
||||
|
||||
net->xfrm.policy_count[dir] = 0;
|
||||
net->xfrm.policy_count[XFRM_POLICY_MAX + dir] = 0;
|
||||
INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]);
|
||||
|
||||
htab = &net->xfrm.policy_bydst[dir];
|
||||
htab->table = xfrm_hash_alloc(sz);
|
||||
@ -4234,8 +4259,6 @@ static void xfrm_policy_fini(struct net *net)
|
||||
for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
|
||||
struct xfrm_policy_hash *htab;
|
||||
|
||||
WARN_ON(!hlist_empty(&net->xfrm.policy_inexact[dir]));
|
||||
|
||||
htab = &net->xfrm.policy_bydst[dir];
|
||||
sz = (htab->hmask + 1) * sizeof(struct hlist_head);
|
||||
WARN_ON(!hlist_empty(htab->table));
|
||||
|
@ -201,6 +201,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
|
||||
{
|
||||
int err;
|
||||
u8 sa_dir = attrs[XFRMA_SA_DIR] ? nla_get_u8(attrs[XFRMA_SA_DIR]) : 0;
|
||||
u16 family = p->sel.family;
|
||||
|
||||
err = -EINVAL;
|
||||
switch (p->family) {
|
||||
@ -221,7 +222,10 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (p->sel.family) {
|
||||
if (!family && !(p->flags & XFRM_STATE_AF_UNSPEC))
|
||||
family = p->family;
|
||||
|
||||
switch (family) {
|
||||
case AF_UNSPEC:
|
||||
break;
|
||||
|
||||
@ -1098,7 +1102,9 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb)
|
||||
if (!nla)
|
||||
return -EMSGSIZE;
|
||||
ap = nla_data(nla);
|
||||
memcpy(ap, auth, sizeof(struct xfrm_algo_auth));
|
||||
strscpy_pad(ap->alg_name, auth->alg_name, sizeof(ap->alg_name));
|
||||
ap->alg_key_len = auth->alg_key_len;
|
||||
ap->alg_trunc_len = auth->alg_trunc_len;
|
||||
if (redact_secret && auth->alg_key_len)
|
||||
memset(ap->alg_key, 0, (auth->alg_key_len + 7) / 8);
|
||||
else
|
||||
|
Loading…
Reference in New Issue
Block a user