# ChangeSet # 2004/12/14 11:06:25-08:00 chrisw@osdl.org # [IPV4/IPV6]: IGMP source filter fixes # # When adding or deleting from the source list make sure to find matches # by comparing against the new source address, not the group address. # Also, check each addr in the list rather than just the first one. # And, finally, only delete from list when there's a match rather than # vice-versa. Drop the effort to keep list sorted, since it's not done # on full-state api and can create an sl_addr entry that the delta api # won't be able to delete. Without these fixes sl_count can be corrupted # which can allow for kernel memory corruption. # # Signed-off-by: Chris Wright # Signed-off-by: David S. Miller # diff -Nru a/net/ipv4/igmp.c b/net/ipv4/igmp.c --- a/net/ipv4/igmp.c 2004-12-20 11:32:15 -08:00 +++ b/net/ipv4/igmp.c 2004-12-20 11:32:15 -08:00 @@ -1778,12 +1778,12 @@ goto done; rv = !0; for (i=0; isl_count; i++) { - rv = memcmp(&psl->sl_addr, &mreqs->imr_multiaddr, + rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr, sizeof(__u32)); - if (rv >= 0) + if (rv == 0) break; } - if (!rv) /* source not found */ + if (rv) /* source not found */ goto done; /* update the interface filter */ @@ -1825,9 +1825,9 @@ } rv = 1; /* > 0 for insert logic below if sl_count is 0 */ for (i=0; isl_count; i++) { - rv = memcmp(&psl->sl_addr, &mreqs->imr_multiaddr, + rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr, sizeof(__u32)); - if (rv >= 0) + if (rv == 0) break; } if (rv == 0) /* address already there is an error */ diff -Nru a/net/ipv6/mcast.c b/net/ipv6/mcast.c --- a/net/ipv6/mcast.c 2004-12-20 11:32:15 -08:00 +++ b/net/ipv6/mcast.c 2004-12-20 11:32:15 -08:00 @@ -391,12 +391,12 @@ goto done; rv = !0; for (i=0; isl_count; i++) { - rv = memcmp(&psl->sl_addr, group, + rv = memcmp(&psl->sl_addr[i], source, sizeof(struct in6_addr)); - if (rv >= 0) + if (rv == 0) break; } - if (!rv) /* source not found */ + if (rv) /* source not found */ goto done; /* update the interface filter */ @@ -437,8 +437,8 @@ } rv = 1; /* > 0 for insert logic below if sl_count is 0 */ for (i=0; isl_count; i++) { - rv = memcmp(&psl->sl_addr, group, sizeof(struct in6_addr)); - if (rv >= 0) + rv = memcmp(&psl->sl_addr[i], source, sizeof(struct in6_addr)); + if (rv == 0) break; } if (rv == 0) /* address already there is an error */