| From 1a6a0951fc009f6d9fe8ebea2d2417d80d54097b Mon Sep 17 00:00:00 2001 |
| From: Fernando Fernandez Mancera <ffmancera@riseup.net> |
| Date: Mon, 21 Jan 2019 12:53:21 +0100 |
| Subject: netfilter: nfnetlink_osf: add missing fmatch check |
| |
| From: Fernando Fernandez Mancera <ffmancera@riseup.net> |
| |
| commit 1a6a0951fc009f6d9fe8ebea2d2417d80d54097b upstream. |
| |
| When we check the tcp options of a packet and it doesn't match the current |
| fingerprint, the tcp packet option pointer must be restored to its initial |
| value in order to do the proper tcp options check for the next fingerprint. |
| |
| Here we can see an example. |
| Assumming the following fingerprint base with two lines: |
| |
| S10:64:1:60:M*,S,T,N,W6: Linux:3.0::Linux 3.0 |
| S20:64:1:60:M*,S,T,N,W7: Linux:4.19:arch:Linux 4.1 |
| |
| Where TCP options are the last field in the OS signature, all of them overlap |
| except by the last one, ie. 'W6' versus 'W7'. |
| |
| In case a packet for Linux 4.19 kicks in, the osf finds no matching because the |
| TCP options pointer is updated after checking for the TCP options in the first |
| line. |
| |
| Therefore, reset pointer back to where it should be. |
| |
| Fixes: 11eeef41d5f6 ("netfilter: passive OS fingerprint xtables match") |
| Signed-off-by: Fernando Fernandez Mancera <ffmancera@riseup.net> |
| Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| net/netfilter/nfnetlink_osf.c | 4 ++++ |
| 1 file changed, 4 insertions(+) |
| |
| --- a/net/netfilter/nfnetlink_osf.c |
| +++ b/net/netfilter/nfnetlink_osf.c |
| @@ -66,6 +66,7 @@ static bool nf_osf_match_one(const struc |
| int ttl_check, |
| struct nf_osf_hdr_ctx *ctx) |
| { |
| + const __u8 *optpinit = ctx->optp; |
| unsigned int check_WSS = 0; |
| int fmatch = FMATCH_WRONG; |
| int foptsize, optnum; |
| @@ -155,6 +156,9 @@ static bool nf_osf_match_one(const struc |
| } |
| } |
| |
| + if (fmatch != FMATCH_OK) |
| + ctx->optp = optpinit; |
| + |
| return fmatch == FMATCH_OK; |
| } |
| |