Commit a206bcb3b02025b23137f3228109d72e0f835c05

Authored by Pablo Neira Ayuso
1 parent 71ffe9c77d

netfilter: xt_TCPOPTSTRIP: fix possible off by one access

Fix a possible off by one access since optlen()
touches opt[offset+1] unsafely when i == tcp_hdrlen(skb) - 1.

This patch replaces tcp_hdrlen() by the local variable tcp_hdrlen
that stores the TCP header length, to save some cycles.

Reported-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

Showing 1 changed file with 6 additions and 4 deletions Side-by-side Diff

net/netfilter/xt_TCPOPTSTRIP.c
... ... @@ -38,7 +38,7 @@
38 38 struct tcphdr *tcph;
39 39 u_int16_t n, o;
40 40 u_int8_t *opt;
41   - int len;
  41 + int len, tcp_hdrlen;
42 42  
43 43 /* This is a fragment, no TCP header is available */
44 44 if (par->fragoff != 0)
... ... @@ -52,7 +52,9 @@
52 52 return NF_DROP;
53 53  
54 54 tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
55   - if (tcph->doff * 4 > len)
  55 + tcp_hdrlen = tcph->doff * 4;
  56 +
  57 + if (len < tcp_hdrlen)
56 58 return NF_DROP;
57 59  
58 60 opt = (u_int8_t *)tcph;
59 61  
... ... @@ -61,10 +63,10 @@
61 63 * Walk through all TCP options - if we find some option to remove,
62 64 * set all octets to %TCPOPT_NOP and adjust checksum.
63 65 */
64   - for (i = sizeof(struct tcphdr); i < tcp_hdrlen(skb); i += optl) {
  66 + for (i = sizeof(struct tcphdr); i < tcp_hdrlen - 1; i += optl) {
65 67 optl = optlen(opt, i);
66 68  
67   - if (i + optl > tcp_hdrlen(skb))
  69 + if (i + optl > tcp_hdrlen)
68 70 break;
69 71  
70 72 if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i]))