Hi, this is feed back from USAGI Project.
1. Ensure to send paramter problem for fragment.
2. Fix router-alert option format.
3. Do not overrun while parsing tlv options.
[MEMO] bFIX_2_4_0-20010111 -> tFIX_2_4_0-20010111_20010111
Index: net/ipv6/icmp.c
===================================================================
RCS file: /cvsroot/usagi/kernel/linux24/net/ipv6/icmp.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.2.2
diff -u -r1.1.1.2 -r1.1.1.2.2.2
--- net/ipv6/icmp.c 2001/01/05 05:39:31 1.1.1.2
+++ net/ipv6/icmp.c 2001/01/11 00:17:49 1.1.1.2.2.2
@@ -23,6 +23,8 @@
* Andi Kleen : exception handling
* Andi Kleen add rate limits. never reply to a icmp.
* add more length checks and other fixes.
+ * yoshfuji : ensure to sent parameter problem for
+ * fragments.
*/
#define __NO_VERSION__
@@ -191,9 +193,14 @@
* for sender.
*
* --ANK (980726)
+ *
+ * Note: We MUST send Parameter Problem even if it is not for the first
+ * fragment. See RFC2460.
+ *
+ * --yoshfuji (2001/01/05)
*/
-static int is_ineligible(struct ipv6hdr *hdr, int len)
+static int is_ineligible(int type, struct ipv6hdr *hdr, int len)
{
u8 *ptr;
__u8 nexthdr = hdr->nexthdr;
@@ -208,7 +215,7 @@
struct icmp6hdr *ihdr = (struct icmp6hdr *)ptr;
return (ptr - (u8*)hdr) > len || !(ihdr->icmp6_type & 0x80);
}
- return nexthdr == NEXTHDR_FRAGMENT;
+ return nexthdr == NEXTHDR_FRAGMENT && type != ICMPV6_PARAMPROB;
}
int sysctl_icmpv6_time = 1*HZ;
@@ -341,7 +348,7 @@
/*
* Never answer to a ICMP packet.
*/
- if (is_ineligible(hdr, (u8*)skb->tail - (u8*)hdr)) {
+ if (is_ineligible(type, hdr, (u8*)skb->tail - (u8*)hdr)) {
if (net_ratelimit())
printk(KERN_DEBUG "icmpv6_send: no reply to icmp
error/fragment\n");
return;
Index: net/ipv6/mcast.c
===================================================================
RCS file: /cvsroot/usagi/kernel/linux24/net/ipv6/mcast.c,v
retrieving revision 1.1.1.5
retrieving revision 1.1.1.5.2.2
diff -u -r1.1.1.5 -r1.1.1.5.2.2
--- net/ipv6/mcast.c 2000/10/05 13:40:35 1.1.1.5
+++ net/ipv6/mcast.c 2001/01/11 00:17:49 1.1.1.5.2.2
@@ -15,6 +15,11 @@
* 2 of the License, or (at your option) any later version.
*/
+/* Changes:
+ *
+ * yoshfuji : fix format of router-alert option
+ */
+
#define __NO_VERSION__
#include <linux/config.h>
#include <linux/module.h>
@@ -491,7 +496,7 @@
struct in6_addr all_routers;
int err, len, payload_len, full_len;
u8 ra[8] = { IPPROTO_ICMPV6, 0,
- IPV6_TLV_ROUTERALERT, 0, 0, 0,
+ IPV6_TLV_ROUTERALERT, 2, 0, 0,
IPV6_TLV_PADN, 0 };
snd_addr = addr;
Index: net/ipv6/exthdrs.c
===================================================================
RCS file: /cvsroot/usagi/kernel/linux24/net/ipv6/exthdrs.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.10.1
diff -u -r1.1.1.1 -r1.1.1.1.10.1
--- net/ipv6/exthdrs.c 2000/08/25 02:29:26 1.1.1.1
+++ net/ipv6/exthdrs.c 2001/01/11 00:33:05 1.1.1.1.10.1
@@ -15,6 +15,11 @@
* 2 of the License, or (at your option) any later version.
*/
+/* Changes:
+ * yoshfuji : ensure not to overrun while parsing
+ * tlv options.
+ */
+
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
@@ -104,6 +109,7 @@
struct tlvtype_proc *curr;
u8 *ptr = skb->h.raw;
int len = ((ptr[1]+1)<<3) - 2;
+ int optlen;
ptr += 2;
@@ -113,19 +119,31 @@
}
while (len > 0) {
- int optlen = ptr[1]+2;
-
switch (ptr[0]) {
case IPV6_TLV_PAD0:
optlen = 1;
break;
case IPV6_TLV_PADN:
+ if (len < 2)
+ goto bad;
+ optlen = ptr[1]+2;
+ if (len < optlen)
+ goto bad;
break;
- default: /* Other TLV code so scan list */
+ default:
+ /* Other TLV code so scan list */
+ if (len < 2)
+ goto bad;
+ optlen = ptr[1]+2;
+ if (len < optlen)
+ goto bad;
for (curr=procs; curr->type >= 0; curr++) {
if (curr->type == ptr[0]) {
+ /* type specific length/alignment
+ checks will be perfomed in the
+ func(). */
if (curr->func(skb, ptr) == 0)
return 0;
break;
@@ -142,6 +160,7 @@
}
if (len == 0)
return 1;
+bad:
kfree_skb(skb);
return 0;
}
--
Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@xxxxxxxxxxxxxx>
PGP5i FP: F731 6599 5EB2 BBA7 1515 1323 1806 A96F 5700 6B25
|