@@ -119,6 +119,19 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs)
119
119
return 0 ;
120
120
}
121
121
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
+ }
122
135
123
136
static int verify_newsa_info (struct xfrm_usersa_info * p ,
124
137
struct nlattr * * attrs )
@@ -214,6 +227,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
214
227
goto out ;
215
228
if ((err = verify_sec_ctx_len (attrs )))
216
229
goto out ;
230
+ if ((err = verify_replay (p , attrs )))
231
+ goto out ;
217
232
218
233
err = - EINVAL ;
219
234
switch (p -> mode ) {
@@ -345,6 +360,33 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props,
345
360
return 0 ;
346
361
}
347
362
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
+
348
390
static inline int xfrm_user_sec_ctx_size (struct xfrm_sec_ctx * xfrm_ctx )
349
391
{
350
392
int len = 0 ;
@@ -380,10 +422,20 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
380
422
static void xfrm_update_ae_params (struct xfrm_state * x , struct nlattr * * attrs )
381
423
{
382
424
struct nlattr * rp = attrs [XFRMA_REPLAY_VAL ];
425
+ struct nlattr * re = attrs [XFRMA_REPLAY_ESN_VAL ];
383
426
struct nlattr * lt = attrs [XFRMA_LTIME_VAL ];
384
427
struct nlattr * et = attrs [XFRMA_ETIMER_THRESH ];
385
428
struct nlattr * rt = attrs [XFRMA_REPLAY_THRESH ];
386
429
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
+
387
439
if (rp ) {
388
440
struct xfrm_replay_state * replay ;
389
441
replay = nla_data (rp );
@@ -467,13 +519,14 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
467
519
security_xfrm_state_alloc (x , nla_data (attrs [XFRMA_SEC_CTX ])))
468
520
goto error ;
469
521
522
+ if ((err = xfrm_alloc_replay_state_esn (& x -> replay_esn , & x -> preplay_esn ,
523
+ attrs [XFRMA_REPLAY_ESN_VAL ])))
524
+ goto error ;
525
+
470
526
x -> km .seq = p -> seq ;
471
527
x -> replay_maxdiff = net -> xfrm .sysctl_aevent_rseqth ;
472
528
/* sysctl_xfrm_aevent_etime is in 100ms units */
473
529
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 ;
477
530
478
531
if ((err = xfrm_init_replay (x )))
479
532
goto error ;
@@ -709,6 +762,10 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
709
762
if (xfrm_mark_put (skb , & x -> mark ))
710
763
goto nla_put_failure ;
711
764
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
+
712
769
if (x -> security && copy_sec_ctx (x -> security , skb ) < 0 )
713
770
goto nla_put_failure ;
714
771
@@ -1578,10 +1635,14 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
1578
1635
return 0 ;
1579
1636
}
1580
1637
1581
- static inline size_t xfrm_aevent_msgsize (void )
1638
+ static inline size_t xfrm_aevent_msgsize (struct xfrm_state * x )
1582
1639
{
1640
+ size_t replay_size = x -> replay_esn ?
1641
+ xfrm_replay_state_esn_len (x -> replay_esn ) :
1642
+ sizeof (struct xfrm_replay_state );
1643
+
1583
1644
return NLMSG_ALIGN (sizeof (struct xfrm_aevent_id ))
1584
- + nla_total_size (sizeof ( struct xfrm_replay_state ) )
1645
+ + nla_total_size (replay_size )
1585
1646
+ nla_total_size (sizeof (struct xfrm_lifetime_cur ))
1586
1647
+ nla_total_size (sizeof (struct xfrm_mark ))
1587
1648
+ 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
1606
1667
id -> reqid = x -> props .reqid ;
1607
1668
id -> flags = c -> data .aevent ;
1608
1669
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
+
1610
1677
NLA_PUT (skb , XFRMA_LTIME_VAL , sizeof (x -> curlft ), & x -> curlft );
1611
1678
1612
1679
if (id -> flags & XFRM_AE_RTHR )
@@ -1639,16 +1706,16 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1639
1706
struct xfrm_aevent_id * p = nlmsg_data (nlh );
1640
1707
struct xfrm_usersa_id * id = & p -> sa_id ;
1641
1708
1642
- r_skb = nlmsg_new (xfrm_aevent_msgsize (), GFP_ATOMIC );
1643
- if (r_skb == NULL )
1644
- return - ENOMEM ;
1645
-
1646
1709
mark = xfrm_mark_get (attrs , & m );
1647
1710
1648
1711
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 )
1651
1713
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 ;
1652
1719
}
1653
1720
1654
1721
/*
@@ -1680,9 +1747,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
1680
1747
struct xfrm_mark m ;
1681
1748
struct xfrm_aevent_id * p = nlmsg_data (nlh );
1682
1749
struct nlattr * rp = attrs [XFRMA_REPLAY_VAL ];
1750
+ struct nlattr * re = attrs [XFRMA_REPLAY_ESN_VAL ];
1683
1751
struct nlattr * lt = attrs [XFRMA_LTIME_VAL ];
1684
1752
1685
- if (!lt && !rp )
1753
+ if (!lt && !rp && ! re )
1686
1754
return err ;
1687
1755
1688
1756
/* pedantic mode - thou shalt sayeth replaceth */
@@ -2147,6 +2215,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
2147
2215
[XFRMA_KMADDRESS ] = { .len = sizeof (struct xfrm_user_kmaddress ) },
2148
2216
[XFRMA_MARK ] = { .len = sizeof (struct xfrm_mark ) },
2149
2217
[XFRMA_TFCPAD ] = { .type = NLA_U32 },
2218
+ [XFRMA_REPLAY_ESN_VAL ] = { .len = sizeof (struct xfrm_replay_state_esn ) },
2150
2219
};
2151
2220
2152
2221
static struct xfrm_link {
@@ -2274,7 +2343,7 @@ static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event
2274
2343
struct net * net = xs_net (x );
2275
2344
struct sk_buff * skb ;
2276
2345
2277
- skb = nlmsg_new (xfrm_aevent_msgsize (), GFP_ATOMIC );
2346
+ skb = nlmsg_new (xfrm_aevent_msgsize (x ), GFP_ATOMIC );
2278
2347
if (skb == NULL )
2279
2348
return - ENOMEM ;
2280
2349
@@ -2328,6 +2397,8 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x)
2328
2397
l += nla_total_size (sizeof (* x -> encap ));
2329
2398
if (x -> tfcpad )
2330
2399
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 ));
2331
2402
if (x -> security )
2332
2403
l += nla_total_size (sizeof (struct xfrm_user_sec_ctx ) +
2333
2404
x -> security -> ctx_len );
0 commit comments