Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0fb031f0 authored by David S. Miller's avatar David S. Miller
Browse files


Steffen Klassert says:

====================
1) Initialize the satype field in key_notify_policy_flush(),
   this was left uninitialized. From Nicolas Dichtel.

2) The sequence number difference for replay notifications
   was misscalculated on ESN sequence number wrap. We need
   a separate replay notify function for esn.

3) Fix an off by one in the esn replay notify function.
   From Mathias Krause.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 24f11a5c 799ef90c
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -2693,6 +2693,7 @@ static int key_notify_policy_flush(const struct km_event *c)
	hdr->sadb_msg_pid = c->portid;
	hdr->sadb_msg_pid = c->portid;
	hdr->sadb_msg_version = PF_KEY_V2;
	hdr->sadb_msg_version = PF_KEY_V2;
	hdr->sadb_msg_errno = (uint8_t) 0;
	hdr->sadb_msg_errno = (uint8_t) 0;
	hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
	hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
	hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
	pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
	pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
	return 0;
	return 0;
+65 −1
Original line number Original line Diff line number Diff line
@@ -334,6 +334,70 @@ static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
		x->xflags &= ~XFRM_TIME_DEFER;
		x->xflags &= ~XFRM_TIME_DEFER;
}
}


static void xfrm_replay_notify_esn(struct xfrm_state *x, int event)
{
	u32 seq_diff, oseq_diff;
	struct km_event c;
	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
	struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn;

	/* we send notify messages in case
	 *  1. we updated on of the sequence numbers, and the seqno difference
	 *     is at least x->replay_maxdiff, in this case we also update the
	 *     timeout of our timer function
	 *  2. if x->replay_maxage has elapsed since last update,
	 *     and there were changes
	 *
	 *  The state structure must be locked!
	 */

	switch (event) {
	case XFRM_REPLAY_UPDATE:
		if (!x->replay_maxdiff)
			break;

		if (replay_esn->seq_hi == preplay_esn->seq_hi)
			seq_diff = replay_esn->seq - preplay_esn->seq;
		else
			seq_diff = ~preplay_esn->seq + replay_esn->seq + 1;

		if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
			oseq_diff = replay_esn->oseq - preplay_esn->oseq;
		else
			oseq_diff = ~preplay_esn->oseq + replay_esn->oseq + 1;

		if (seq_diff < x->replay_maxdiff &&
		    oseq_diff < x->replay_maxdiff) {

			if (x->xflags & XFRM_TIME_DEFER)
				event = XFRM_REPLAY_TIMEOUT;
			else
				return;
		}

		break;

	case XFRM_REPLAY_TIMEOUT:
		if (memcmp(x->replay_esn, x->preplay_esn,
			   xfrm_replay_state_esn_len(replay_esn)) == 0) {
			x->xflags |= XFRM_TIME_DEFER;
			return;
		}

		break;
	}

	memcpy(x->preplay_esn, x->replay_esn,
	       xfrm_replay_state_esn_len(replay_esn));
	c.event = XFRM_MSG_NEWAE;
	c.data.aevent = event;
	km_state_notify(x, &c);

	if (x->replay_maxage &&
	    !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
		x->xflags &= ~XFRM_TIME_DEFER;
}

static int xfrm_replay_overflow_esn(struct xfrm_state *x, struct sk_buff *skb)
static int xfrm_replay_overflow_esn(struct xfrm_state *x, struct sk_buff *skb)
{
{
	int err = 0;
	int err = 0;
@@ -510,7 +574,7 @@ static struct xfrm_replay xfrm_replay_esn = {
	.advance	= xfrm_replay_advance_esn,
	.advance	= xfrm_replay_advance_esn,
	.check		= xfrm_replay_check_esn,
	.check		= xfrm_replay_check_esn,
	.recheck	= xfrm_replay_recheck_esn,
	.recheck	= xfrm_replay_recheck_esn,
	.notify		= xfrm_replay_notify_bmp,
	.notify		= xfrm_replay_notify_esn,
	.overflow	= xfrm_replay_overflow_esn,
	.overflow	= xfrm_replay_overflow_esn,
};
};