@@ -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
123136static 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+
348390static 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 *
380422static 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
21522221static 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