提交 8e9b29cc 编写于 作者: D David S. Miller

Merge branch 'ppp_mppe_desync'

Sylvain Rochet says:

====================
ppp: mppe: fixes MPPE desync on links which don't guarantee packet ordering

I am currently having an issue with PPP over L2TP (UDP) and MPPE in
stateless mode (default mode), UDP does not guarantee packet ordering so
we might get out of order packet. MPPE needs to be continuously synched
so we should drop late UDP packet.

I added a printk on the number of time we rekeyed in MPPE decompressor,
this is what we currently have if we receive a slightly out of order UDP
packet:

[1731001.049206] mppe_decompress[1]: ccount 1559
[1731001.049216] mppe_decompress[1]: rekeyed 1 times

[1731001.049228] mppe_decompress[1]: ccount 1560
[1731001.049232] mppe_decompress[1]: rekeyed 1 times

[1731001.050170] mppe_decompress[1]: ccount 1562
[1731001.050182] mppe_decompress[1]: rekeyed 2 times

[1731001.050191] mppe_decompress[1]: ccount 1561
[1731001.062576] mppe_decompress[1]: rekeyed 4095 times
                                             ^^^^
This is obviously wrong, we missed packet 1561 and we already rekeyed 2
times for 1562 we previously received, we can't recover the decryption
key we need for 1561, we should drop it instead of rekeying 4095 times.

This patch series drop any packet with are not within the 4096/2 forward
window.
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
...@@ -478,7 +478,6 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, ...@@ -478,7 +478,6 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
struct blkcipher_desc desc = { .tfm = state->arc4 }; struct blkcipher_desc desc = { .tfm = state->arc4 };
unsigned ccount; unsigned ccount;
int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED; int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED;
int sanity = 0;
struct scatterlist sg_in[1], sg_out[1]; struct scatterlist sg_in[1], sg_out[1];
if (isize <= PPP_HDRLEN + MPPE_OVHD) { if (isize <= PPP_HDRLEN + MPPE_OVHD) {
...@@ -514,31 +513,19 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, ...@@ -514,31 +513,19 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
"mppe_decompress[%d]: ENCRYPTED bit not set!\n", "mppe_decompress[%d]: ENCRYPTED bit not set!\n",
state->unit); state->unit);
state->sanity_errors += 100; state->sanity_errors += 100;
sanity = 1; goto sanity_error;
} }
if (!state->stateful && !flushed) { if (!state->stateful && !flushed) {
printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in " printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in "
"stateless mode!\n", state->unit); "stateless mode!\n", state->unit);
state->sanity_errors += 100; state->sanity_errors += 100;
sanity = 1; goto sanity_error;
} }
if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) { if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) {
printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on " printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on "
"flag packet!\n", state->unit); "flag packet!\n", state->unit);
state->sanity_errors += 100; state->sanity_errors += 100;
sanity = 1; goto sanity_error;
}
if (sanity) {
if (state->sanity_errors < SANITY_MAX)
return DECOMP_ERROR;
else
/*
* Take LCP down if the peer is sending too many bogons.
* We don't want to do this for a single or just a few
* instances since it could just be due to packet corruption.
*/
return DECOMP_FATALERROR;
} }
/* /*
...@@ -546,6 +533,13 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, ...@@ -546,6 +533,13 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
*/ */
if (!state->stateful) { if (!state->stateful) {
/* Discard late packet */
if ((ccount - state->ccount) % MPPE_CCOUNT_SPACE
> MPPE_CCOUNT_SPACE / 2) {
state->sanity_errors++;
goto sanity_error;
}
/* RFC 3078, sec 8.1. Rekey for every packet. */ /* RFC 3078, sec 8.1. Rekey for every packet. */
while (state->ccount != ccount) { while (state->ccount != ccount) {
mppe_rekey(state, 0); mppe_rekey(state, 0);
...@@ -649,6 +643,16 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, ...@@ -649,6 +643,16 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf,
state->sanity_errors >>= 1; state->sanity_errors >>= 1;
return osize; return osize;
sanity_error:
if (state->sanity_errors < SANITY_MAX)
return DECOMP_ERROR;
else
/* Take LCP down if the peer is sending too many bogons.
* We don't want to do this for a single or just a few
* instances since it could just be due to packet corruption.
*/
return DECOMP_FATALERROR;
} }
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册