xfrm_replay.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * xfrm_replay.c - xfrm replay detection, derived from xfrm_state.c.
  3. */
  4. #include <net/xfrm.h>
  5. static void xfrm_replay_notify(struct xfrm_state *x, int event)
  6. {
  7. struct km_event c;
  8. /* we send notify messages in case
  9. * 1. we updated on of the sequence numbers, and the seqno difference
  10. * is at least x->replay_maxdiff, in this case we also update the
  11. * timeout of our timer function
  12. * 2. if x->replay_maxage has elapsed since last update,
  13. * and there were changes
  14. *
  15. * The state structure must be locked!
  16. */
  17. switch (event) {
  18. case XFRM_REPLAY_UPDATE:
  19. if (x->replay_maxdiff &&
  20. (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
  21. (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
  22. if (x->xflags & XFRM_TIME_DEFER)
  23. event = XFRM_REPLAY_TIMEOUT;
  24. else
  25. return;
  26. }
  27. break;
  28. case XFRM_REPLAY_TIMEOUT:
  29. if (memcmp(&x->replay, &x->preplay,
  30. sizeof(struct xfrm_replay_state)) == 0) {
  31. x->xflags |= XFRM_TIME_DEFER;
  32. return;
  33. }
  34. break;
  35. }
  36. memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));
  37. c.event = XFRM_MSG_NEWAE;
  38. c.data.aevent = event;
  39. km_state_notify(x, &c);
  40. if (x->replay_maxage &&
  41. !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
  42. x->xflags &= ~XFRM_TIME_DEFER;
  43. }
  44. static int xfrm_replay_overflow(struct xfrm_state *x, struct sk_buff *skb)
  45. {
  46. int err = 0;
  47. struct net *net = xs_net(x);
  48. if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
  49. XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq;
  50. if (unlikely(x->replay.oseq == 0)) {
  51. x->replay.oseq--;
  52. xfrm_audit_state_replay_overflow(x, skb);
  53. err = -EOVERFLOW;
  54. return err;
  55. }
  56. if (xfrm_aevent_is_on(net))
  57. x->repl->notify(x, XFRM_REPLAY_UPDATE);
  58. }
  59. return err;
  60. }
  61. static int xfrm_replay_check(struct xfrm_state *x,
  62. struct sk_buff *skb, __be32 net_seq)
  63. {
  64. u32 diff;
  65. u32 seq = ntohl(net_seq);
  66. if (unlikely(seq == 0))
  67. goto err;
  68. if (likely(seq > x->replay.seq))
  69. return 0;
  70. diff = x->replay.seq - seq;
  71. if (diff >= min_t(unsigned int, x->props.replay_window,
  72. sizeof(x->replay.bitmap) * 8)) {
  73. x->stats.replay_window++;
  74. goto err;
  75. }
  76. if (x->replay.bitmap & (1U << diff)) {
  77. x->stats.replay++;
  78. goto err;
  79. }
  80. return 0;
  81. err:
  82. xfrm_audit_state_replay(x, skb, net_seq);
  83. return -EINVAL;
  84. }
  85. static void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)
  86. {
  87. u32 diff;
  88. u32 seq = ntohl(net_seq);
  89. if (!x->props.replay_window)
  90. return;
  91. if (seq > x->replay.seq) {
  92. diff = seq - x->replay.seq;
  93. if (diff < x->props.replay_window)
  94. x->replay.bitmap = ((x->replay.bitmap) << diff) | 1;
  95. else
  96. x->replay.bitmap = 1;
  97. x->replay.seq = seq;
  98. } else {
  99. diff = x->replay.seq - seq;
  100. x->replay.bitmap |= (1U << diff);
  101. }
  102. if (xfrm_aevent_is_on(xs_net(x)))
  103. xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
  104. }
  105. static struct xfrm_replay xfrm_replay_legacy = {
  106. .advance = xfrm_replay_advance,
  107. .check = xfrm_replay_check,
  108. .notify = xfrm_replay_notify,
  109. .overflow = xfrm_replay_overflow,
  110. };
  111. int xfrm_init_replay(struct xfrm_state *x)
  112. {
  113. x->repl = &xfrm_replay_legacy;
  114. return 0;
  115. }
  116. EXPORT_SYMBOL(xfrm_init_replay);