Subject: Re: ip_nat MSS clamping
To: Andrey Petrov <petrov@netbsd.org>
From: Martin Husemann <martin@duskware.de>
List: tech-net
Date: 06/03/2002 20:40:28
> This is quite dangerous construction for any platform with strict
> alignment.
True.
Index: ip_nat.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet/ip_nat.c,v
retrieving revision 1.48
diff -c -u -r1.48 ip_nat.c
--- ip_nat.c 2002/05/02 17:13:29 1.48
+++ ip_nat.c 2002/06/03 18:37:24
@@ -1147,34 +1147,45 @@
fr_info_t *fin;
u_short *csump;
{
- uint8_t *cp;
+ uint8_t *cp, *ep;
uint32_t opt, mss, sumd;
+ uint16_t netmss;
int hlen;
+ int advance;
hlen = tcp->th_off << 2;
if (hlen > sizeof(*tcp)) {
cp = (uint8_t *)tcp + sizeof(*tcp);
+ ep = cp + hlen;
- while (hlen > 0) {
- opt = *cp++;
- switch(opt) {
- case TCPOPT_MAXSEG:
- ++cp;
- mss = (uint32_t)ntohs(*(short *)cp);
+ while (cp < ep) {
+ opt = cp[0];
+ if (opt == TCPOPT_EOL)
+ break;
+ if (opt == TCPOPT_NOP) {
+ cp++;
+ continue;
+ }
+
+ if (&cp[1] > ep)
+ break;
+ advance = cp[1];
+ if (&cp[advance] > ep)
+ break;
+ if (opt == TCPOPT_MAXSEG) {
+ if (advance != 4)
+ break;
+ memcpy(&netmss, &cp[2], 2);
+ mss = (uint32_t)ntohs(netmss);
if (mss > maxmss) {
- *(short *)cp = htons((short)(maxmss));
+ netmss = htons((short)(maxmss));
+ memcpy(&cp[2], &netmss, 2);
CALC_SUMD(mss, maxmss, sumd);
fix_outcksum(fin, csump, sumd);
}
- hlen = 0;
break;
- case TCPOPT_EOL:
- case TCPOPT_NOP:
- hlen--;
- default:
- hlen -= *cp;
- cp += *cp - 2;
}
+ cp += advance;
}
}
}