Skip to content

Commit d8647b7

Browse files
klassertdavem330
authored andcommitted
xfrm: Add user interface for esn and big anti-replay windows
This patch adds a netlink based user interface to configure esn and big anti-replay windows. The new netlink attribute XFRMA_REPLAY_ESN_VAL is used to configure the new implementation. If the XFRM_STATE_ESN flag is set, we use esn and support for big anti-replay windows for the configured state. If this flag is not set we use the new implementation with 32 bit sequence numbers. A big anti-replay window can be configured in this case anyway. Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 2cd0846 commit d8647b7

File tree

2 files changed

+87
-14
lines changed

2 files changed

+87
-14
lines changed

net/xfrm/xfrm_state.c

+2
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
356356
kfree(x->calg);
357357
kfree(x->encap);
358358
kfree(x->coaddr);
359+
kfree(x->replay_esn);
360+
kfree(x->preplay_esn);
359361
if (x->inner_mode)
360362
xfrm_put_mode(x->inner_mode);
361363
if (x->inner_mode_iaf)

net/xfrm/xfrm_user.c

+85-14
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,19 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs)
119119
return 0;
120120
}
121121

122+
static inline int verify_replay(struct xfrm_usersa_info *p,
123+
struct nlattr **attrs)
124+
{
125+
struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
126+
127+
if (!rt)
128+
return 0;
129+
130+
if (p->replay_window != 0)
131+
return -EINVAL;
132+
133+
return 0;
134+
}
122135

123136
static int verify_newsa_info(struct xfrm_usersa_info *p,
124137
struct nlattr **attrs)
@@ -214,6 +227,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
214227
goto out;
215228
if ((err = verify_sec_ctx_len(attrs)))
216229
goto out;
230+
if ((err = verify_replay(p, attrs)))
231+
goto out;
217232

218233
err = -EINVAL;
219234
switch (p->mode) {
@@ -345,6 +360,33 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props,
345360
return 0;
346361
}
347362

363+
static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn,
364+
struct xfrm_replay_state_esn **preplay_esn,
365+
struct nlattr *rta)
366+
{
367+
struct xfrm_replay_state_esn *p, *pp, *up;
368+
369+
if (!rta)
370+
return 0;
371+
372+
up = nla_data(rta);
373+
374+
p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
375+
if (!p)
376+
return -ENOMEM;
377+
378+
pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
379+
if (!pp) {
380+
kfree(p);
381+
return -ENOMEM;
382+
}
383+
384+
*replay_esn = p;
385+
*preplay_esn = pp;
386+
387+
return 0;
388+
}
389+
348390
static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx)
349391
{
350392
int len = 0;
@@ -380,10 +422,20 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
380422
static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs)
381423
{
382424
struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
425+
struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
383426
struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
384427
struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
385428
struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
386429

430+
if (re) {
431+
struct xfrm_replay_state_esn *replay_esn;
432+
replay_esn = nla_data(re);
433+
memcpy(x->replay_esn, replay_esn,
434+
xfrm_replay_state_esn_len(replay_esn));
435+
memcpy(x->preplay_esn, replay_esn,
436+
xfrm_replay_state_esn_len(replay_esn));
437+
}
438+
387439
if (rp) {
388440
struct xfrm_replay_state *replay;
389441
replay = nla_data(rp);
@@ -467,13 +519,14 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
467519
security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX])))
468520
goto error;
469521

522+
if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn,
523+
attrs[XFRMA_REPLAY_ESN_VAL])))
524+
goto error;
525+
470526
x->km.seq = p->seq;
471527
x->replay_maxdiff = net->xfrm.sysctl_aevent_rseqth;
472528
/* sysctl_xfrm_aevent_etime is in 100ms units */
473529
x->replay_maxage = (net->xfrm.sysctl_aevent_etime*HZ)/XFRM_AE_ETH_M;
474-
x->preplay.bitmap = 0;
475-
x->preplay.seq = x->replay.seq+x->replay_maxdiff;
476-
x->preplay.oseq = x->replay.oseq +x->replay_maxdiff;
477530

478531
if ((err = xfrm_init_replay(x)))
479532
goto error;
@@ -709,6 +762,10 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
709762
if (xfrm_mark_put(skb, &x->mark))
710763
goto nla_put_failure;
711764

765+
if (x->replay_esn)
766+
NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL,
767+
xfrm_replay_state_esn_len(x->replay_esn), x->replay_esn);
768+
712769
if (x->security && copy_sec_ctx(x->security, skb) < 0)
713770
goto nla_put_failure;
714771

@@ -1578,10 +1635,14 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
15781635
return 0;
15791636
}
15801637

1581-
static inline size_t xfrm_aevent_msgsize(void)
1638+
static inline size_t xfrm_aevent_msgsize(struct xfrm_state *x)
15821639
{
1640+
size_t replay_size = x->replay_esn ?
1641+
xfrm_replay_state_esn_len(x->replay_esn) :
1642+
sizeof(struct xfrm_replay_state);
1643+
15831644
return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id))
1584-
+ nla_total_size(sizeof(struct xfrm_replay_state))
1645+
+ nla_total_size(replay_size)
15851646
+ nla_total_size(sizeof(struct xfrm_lifetime_cur))
15861647
+ nla_total_size(sizeof(struct xfrm_mark))
15871648
+ nla_total_size(4) /* XFRM_AE_RTHR */
@@ -1606,7 +1667,13 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct
16061667
id->reqid = x->props.reqid;
16071668
id->flags = c->data.aevent;
16081669

1609-
NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay);
1670+
if (x->replay_esn)
1671+
NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL,
1672+
xfrm_replay_state_esn_len(x->replay_esn),
1673+
x->replay_esn);
1674+
else
1675+
NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay);
1676+
16101677
NLA_PUT(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft);
16111678

16121679
if (id->flags & XFRM_AE_RTHR)
@@ -1639,16 +1706,16 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
16391706
struct xfrm_aevent_id *p = nlmsg_data(nlh);
16401707
struct xfrm_usersa_id *id = &p->sa_id;
16411708

1642-
r_skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC);
1643-
if (r_skb == NULL)
1644-
return -ENOMEM;
1645-
16461709
mark = xfrm_mark_get(attrs, &m);
16471710

16481711
x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family);
1649-
if (x == NULL) {
1650-
kfree_skb(r_skb);
1712+
if (x == NULL)
16511713
return -ESRCH;
1714+
1715+
r_skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
1716+
if (r_skb == NULL) {
1717+
xfrm_state_put(x);
1718+
return -ENOMEM;
16521719
}
16531720

16541721
/*
@@ -1680,9 +1747,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
16801747
struct xfrm_mark m;
16811748
struct xfrm_aevent_id *p = nlmsg_data(nlh);
16821749
struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
1750+
struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
16831751
struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
16841752

1685-
if (!lt && !rp)
1753+
if (!lt && !rp && !re)
16861754
return err;
16871755

16881756
/* pedantic mode - thou shalt sayeth replaceth */
@@ -2147,6 +2215,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
21472215
[XFRMA_KMADDRESS] = { .len = sizeof(struct xfrm_user_kmaddress) },
21482216
[XFRMA_MARK] = { .len = sizeof(struct xfrm_mark) },
21492217
[XFRMA_TFCPAD] = { .type = NLA_U32 },
2218+
[XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) },
21502219
};
21512220

21522221
static struct xfrm_link {
@@ -2274,7 +2343,7 @@ static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event
22742343
struct net *net = xs_net(x);
22752344
struct sk_buff *skb;
22762345

2277-
skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC);
2346+
skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
22782347
if (skb == NULL)
22792348
return -ENOMEM;
22802349

@@ -2328,6 +2397,8 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x)
23282397
l += nla_total_size(sizeof(*x->encap));
23292398
if (x->tfcpad)
23302399
l += nla_total_size(sizeof(x->tfcpad));
2400+
if (x->replay_esn)
2401+
l += nla_total_size(xfrm_replay_state_esn_len(x->replay_esn));
23312402
if (x->security)
23322403
l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) +
23332404
x->security->ctx_len);

0 commit comments

Comments
 (0)