Commit a206bcb3b02025b23137f3228109d72e0f835c05
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])) |