Skip to content

Commit 1e424d0

Browse files
author
Paolo Abeni
committed
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/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 6e62807 + 6889cd2 commit 1e424d0

File tree

7 files changed

+103
-71
lines changed

7 files changed

+103
-71
lines changed

include/net/netns/xfrm.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ struct netns_xfrm {
5151
struct hlist_head *policy_byidx;
5252
unsigned int policy_idx_hmask;
5353
unsigned int idx_generator;
54-
struct hlist_head policy_inexact[XFRM_POLICY_MAX];
5554
struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX];
5655
unsigned int policy_count[XFRM_POLICY_MAX * 2];
5756
struct work_struct policy_hash_work;

include/net/xfrm.h

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -349,20 +349,25 @@ struct xfrm_if_cb {
349349
void xfrm_if_register_cb(const struct xfrm_if_cb *ifcb);
350350
void xfrm_if_unregister_cb(void);
351351

352+
struct xfrm_dst_lookup_params {
353+
struct net *net;
354+
int tos;
355+
int oif;
356+
xfrm_address_t *saddr;
357+
xfrm_address_t *daddr;
358+
u32 mark;
359+
__u8 ipproto;
360+
union flowi_uli uli;
361+
};
362+
352363
struct net_device;
353364
struct xfrm_type;
354365
struct xfrm_dst;
355366
struct xfrm_policy_afinfo {
356367
struct dst_ops *dst_ops;
357-
struct dst_entry *(*dst_lookup)(struct net *net,
358-
int tos, int oif,
359-
const xfrm_address_t *saddr,
360-
const xfrm_address_t *daddr,
361-
u32 mark);
362-
int (*get_saddr)(struct net *net, int oif,
363-
xfrm_address_t *saddr,
364-
xfrm_address_t *daddr,
365-
u32 mark);
368+
struct dst_entry *(*dst_lookup)(const struct xfrm_dst_lookup_params *params);
369+
int (*get_saddr)(xfrm_address_t *saddr,
370+
const struct xfrm_dst_lookup_params *params);
366371
int (*fill_dst)(struct xfrm_dst *xdst,
367372
struct net_device *dev,
368373
const struct flowi *fl);
@@ -1764,10 +1769,7 @@ static inline int xfrm_user_policy(struct sock *sk, int optname,
17641769
}
17651770
#endif
17661771

1767-
struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
1768-
const xfrm_address_t *saddr,
1769-
const xfrm_address_t *daddr,
1770-
int family, u32 mark);
1772+
struct dst_entry *__xfrm_dst_lookup(int family, const struct xfrm_dst_lookup_params *params);
17711773

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

net/ipv4/xfrm4_policy.c

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,47 +17,43 @@
1717
#include <net/ip.h>
1818
#include <net/l3mdev.h>
1919

20-
static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
21-
int tos, int oif,
22-
const xfrm_address_t *saddr,
23-
const xfrm_address_t *daddr,
24-
u32 mark)
20+
static struct dst_entry *__xfrm4_dst_lookup(struct flowi4 *fl4,
21+
const struct xfrm_dst_lookup_params *params)
2522
{
2623
struct rtable *rt;
2724

2825
memset(fl4, 0, sizeof(*fl4));
29-
fl4->daddr = daddr->a4;
30-
fl4->flowi4_tos = tos;
31-
fl4->flowi4_l3mdev = l3mdev_master_ifindex_by_index(net, oif);
32-
fl4->flowi4_mark = mark;
33-
if (saddr)
34-
fl4->saddr = saddr->a4;
35-
36-
rt = __ip_route_output_key(net, fl4);
26+
fl4->daddr = params->daddr->a4;
27+
fl4->flowi4_tos = params->tos;
28+
fl4->flowi4_l3mdev = l3mdev_master_ifindex_by_index(params->net,
29+
params->oif);
30+
fl4->flowi4_mark = params->mark;
31+
if (params->saddr)
32+
fl4->saddr = params->saddr->a4;
33+
fl4->flowi4_proto = params->ipproto;
34+
fl4->uli = params->uli;
35+
36+
rt = __ip_route_output_key(params->net, fl4);
3737
if (!IS_ERR(rt))
3838
return &rt->dst;
3939

4040
return ERR_CAST(rt);
4141
}
4242

43-
static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, int oif,
44-
const xfrm_address_t *saddr,
45-
const xfrm_address_t *daddr,
46-
u32 mark)
43+
static struct dst_entry *xfrm4_dst_lookup(const struct xfrm_dst_lookup_params *params)
4744
{
4845
struct flowi4 fl4;
4946

50-
return __xfrm4_dst_lookup(net, &fl4, tos, oif, saddr, daddr, mark);
47+
return __xfrm4_dst_lookup(&fl4, params);
5148
}
5249

53-
static int xfrm4_get_saddr(struct net *net, int oif,
54-
xfrm_address_t *saddr, xfrm_address_t *daddr,
55-
u32 mark)
50+
static int xfrm4_get_saddr(xfrm_address_t *saddr,
51+
const struct xfrm_dst_lookup_params *params)
5652
{
5753
struct dst_entry *dst;
5854
struct flowi4 fl4;
5955

60-
dst = __xfrm4_dst_lookup(net, &fl4, 0, oif, NULL, daddr, mark);
56+
dst = __xfrm4_dst_lookup(&fl4, params);
6157
if (IS_ERR(dst))
6258
return -EHOSTUNREACH;
6359

net/ipv6/xfrm6_policy.c

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,24 @@
2323
#include <net/ip6_route.h>
2424
#include <net/l3mdev.h>
2525

26-
static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
27-
const xfrm_address_t *saddr,
28-
const xfrm_address_t *daddr,
29-
u32 mark)
26+
static struct dst_entry *xfrm6_dst_lookup(const struct xfrm_dst_lookup_params *params)
3027
{
3128
struct flowi6 fl6;
3229
struct dst_entry *dst;
3330
int err;
3431

3532
memset(&fl6, 0, sizeof(fl6));
36-
fl6.flowi6_l3mdev = l3mdev_master_ifindex_by_index(net, oif);
37-
fl6.flowi6_mark = mark;
38-
memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
39-
if (saddr)
40-
memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));
33+
fl6.flowi6_l3mdev = l3mdev_master_ifindex_by_index(params->net,
34+
params->oif);
35+
fl6.flowi6_mark = params->mark;
36+
memcpy(&fl6.daddr, params->daddr, sizeof(fl6.daddr));
37+
if (params->saddr)
38+
memcpy(&fl6.saddr, params->saddr, sizeof(fl6.saddr));
4139

42-
dst = ip6_route_output(net, NULL, &fl6);
40+
fl6.flowi4_proto = params->ipproto;
41+
fl6.uli = params->uli;
42+
43+
dst = ip6_route_output(params->net, NULL, &fl6);
4344

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

53-
static int xfrm6_get_saddr(struct net *net, int oif,
54-
xfrm_address_t *saddr, xfrm_address_t *daddr,
55-
u32 mark)
54+
static int xfrm6_get_saddr(xfrm_address_t *saddr,
55+
const struct xfrm_dst_lookup_params *params)
5656
{
5757
struct dst_entry *dst;
5858
struct net_device *dev;
5959
struct inet6_dev *idev;
6060

61-
dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr, mark);
61+
dst = xfrm6_dst_lookup(params);
6262
if (IS_ERR(dst))
6363
return -EHOSTUNREACH;
6464

@@ -68,7 +68,8 @@ static int xfrm6_get_saddr(struct net *net, int oif,
6868
return -EHOSTUNREACH;
6969
}
7070
dev = idev->dev;
71-
ipv6_dev_get_saddr(dev_net(dev), dev, &daddr->in6, 0, &saddr->in6);
71+
ipv6_dev_get_saddr(dev_net(dev), dev, &params->daddr->in6, 0,
72+
&saddr->in6);
7273
dst_release(dst);
7374
return 0;
7475
}

net/xfrm/xfrm_device.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
269269

270270
dev = dev_get_by_index(net, xuo->ifindex);
271271
if (!dev) {
272+
struct xfrm_dst_lookup_params params;
273+
272274
if (!(xuo->flags & XFRM_OFFLOAD_INBOUND)) {
273275
saddr = &x->props.saddr;
274276
daddr = &x->id.daddr;
@@ -277,9 +279,12 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
277279
daddr = &x->props.saddr;
278280
}
279281

280-
dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr,
281-
x->props.family,
282-
xfrm_smark_get(0, x));
282+
memset(&params, 0, sizeof(params));
283+
params.net = net;
284+
params.saddr = saddr;
285+
params.daddr = daddr;
286+
params.mark = xfrm_smark_get(0, x);
287+
dst = __xfrm_dst_lookup(x->props.family, &params);
283288
if (IS_ERR(dst))
284289
return (is_packet_offload) ? -EINVAL : 0;
285290

net/xfrm/xfrm_policy.c

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -270,10 +270,8 @@ static const struct xfrm_if_cb *xfrm_if_get_cb(void)
270270
return rcu_dereference(xfrm_if_cb);
271271
}
272272

273-
struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
274-
const xfrm_address_t *saddr,
275-
const xfrm_address_t *daddr,
276-
int family, u32 mark)
273+
struct dst_entry *__xfrm_dst_lookup(int family,
274+
const struct xfrm_dst_lookup_params *params)
277275
{
278276
const struct xfrm_policy_afinfo *afinfo;
279277
struct dst_entry *dst;
@@ -282,7 +280,7 @@ struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
282280
if (unlikely(afinfo == NULL))
283281
return ERR_PTR(-EAFNOSUPPORT);
284282

285-
dst = afinfo->dst_lookup(net, tos, oif, saddr, daddr, mark);
283+
dst = afinfo->dst_lookup(params);
286284

287285
rcu_read_unlock();
288286

@@ -296,6 +294,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x,
296294
xfrm_address_t *prev_daddr,
297295
int family, u32 mark)
298296
{
297+
struct xfrm_dst_lookup_params params;
299298
struct net *net = xs_net(x);
300299
xfrm_address_t *saddr = &x->props.saddr;
301300
xfrm_address_t *daddr = &x->id.daddr;
@@ -310,7 +309,29 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x,
310309
daddr = x->coaddr;
311310
}
312311

313-
dst = __xfrm_dst_lookup(net, tos, oif, saddr, daddr, family, mark);
312+
params.net = net;
313+
params.saddr = saddr;
314+
params.daddr = daddr;
315+
params.tos = tos;
316+
params.oif = oif;
317+
params.mark = mark;
318+
params.ipproto = x->id.proto;
319+
if (x->encap) {
320+
switch (x->encap->encap_type) {
321+
case UDP_ENCAP_ESPINUDP:
322+
params.ipproto = IPPROTO_UDP;
323+
params.uli.ports.sport = x->encap->encap_sport;
324+
params.uli.ports.dport = x->encap->encap_dport;
325+
break;
326+
case TCP_ENCAP_ESPINTCP:
327+
params.ipproto = IPPROTO_TCP;
328+
params.uli.ports.sport = x->encap->encap_sport;
329+
params.uli.ports.dport = x->encap->encap_dport;
330+
break;
331+
}
332+
}
333+
334+
dst = __xfrm_dst_lookup(family, &params);
314335

315336
if (!IS_ERR(dst)) {
316337
if (prev_saddr != saddr)
@@ -2432,15 +2453,15 @@ int __xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk)
24322453
}
24332454

24342455
static int
2435-
xfrm_get_saddr(struct net *net, int oif, xfrm_address_t *local,
2436-
xfrm_address_t *remote, unsigned short family, u32 mark)
2456+
xfrm_get_saddr(unsigned short family, xfrm_address_t *saddr,
2457+
const struct xfrm_dst_lookup_params *params)
24372458
{
24382459
int err;
24392460
const struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
24402461

24412462
if (unlikely(afinfo == NULL))
24422463
return -EINVAL;
2443-
err = afinfo->get_saddr(net, oif, local, remote, mark);
2464+
err = afinfo->get_saddr(saddr, params);
24442465
rcu_read_unlock();
24452466
return err;
24462467
}
@@ -2469,9 +2490,14 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl,
24692490
remote = &tmpl->id.daddr;
24702491
local = &tmpl->saddr;
24712492
if (xfrm_addr_any(local, tmpl->encap_family)) {
2472-
error = xfrm_get_saddr(net, fl->flowi_oif,
2473-
&tmp, remote,
2474-
tmpl->encap_family, 0);
2493+
struct xfrm_dst_lookup_params params;
2494+
2495+
memset(&params, 0, sizeof(params));
2496+
params.net = net;
2497+
params.oif = fl->flowi_oif;
2498+
params.daddr = remote;
2499+
error = xfrm_get_saddr(tmpl->encap_family, &tmp,
2500+
&params);
24752501
if (error)
24762502
goto fail;
24772503
local = &tmp;
@@ -4180,7 +4206,6 @@ static int __net_init xfrm_policy_init(struct net *net)
41804206

41814207
net->xfrm.policy_count[dir] = 0;
41824208
net->xfrm.policy_count[XFRM_POLICY_MAX + dir] = 0;
4183-
INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]);
41844209

41854210
htab = &net->xfrm.policy_bydst[dir];
41864211
htab->table = xfrm_hash_alloc(sz);
@@ -4234,8 +4259,6 @@ static void xfrm_policy_fini(struct net *net)
42344259
for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
42354260
struct xfrm_policy_hash *htab;
42364261

4237-
WARN_ON(!hlist_empty(&net->xfrm.policy_inexact[dir]));
4238-
42394262
htab = &net->xfrm.policy_bydst[dir];
42404263
sz = (htab->hmask + 1) * sizeof(struct hlist_head);
42414264
WARN_ON(!hlist_empty(htab->table));

net/xfrm/xfrm_user.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
201201
{
202202
int err;
203203
u8 sa_dir = attrs[XFRMA_SA_DIR] ? nla_get_u8(attrs[XFRMA_SA_DIR]) : 0;
204+
u16 family = p->sel.family;
204205

205206
err = -EINVAL;
206207
switch (p->family) {
@@ -221,7 +222,10 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
221222
goto out;
222223
}
223224

224-
switch (p->sel.family) {
225+
if (!family && !(p->flags & XFRM_STATE_AF_UNSPEC))
226+
family = p->family;
227+
228+
switch (family) {
225229
case AF_UNSPEC:
226230
break;
227231

@@ -1098,7 +1102,9 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb)
10981102
if (!nla)
10991103
return -EMSGSIZE;
11001104
ap = nla_data(nla);
1101-
memcpy(ap, auth, sizeof(struct xfrm_algo_auth));
1105+
strscpy_pad(ap->alg_name, auth->alg_name, sizeof(ap->alg_name));
1106+
ap->alg_key_len = auth->alg_key_len;
1107+
ap->alg_trunc_len = auth->alg_trunc_len;
11021108
if (redact_secret && auth->alg_key_len)
11031109
memset(ap->alg_key, 0, (auth->alg_key_len + 7) / 8);
11041110
else

0 commit comments

Comments
 (0)