kern/100579: Multicast data structure corruption in ipv6 stack

Tom Parker freebsd at wiresncode.com
Wed Jul 19 21:00:32 UTC 2006


>Number:         100579
>Category:       kern
>Synopsis:       Multicast data structure corruption in ipv6 stack
>Confidential:   no
>Severity:       non-critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul 19 21:00:30 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Tom Parker
>Release:        N/A
>Organization:
>Environment:
Using ported version of 4.4 code.  Code inspection reveals problem seems to be present in current releases.
>Description:
When an interface is removed in6_ifdetach calls in6_pcbpurgeif0 which calls in6_delmulti.  This call path frees, but does not remove the in6_multi structure from sockets that have listened to it.  Upon IPV6_LEAVE_GROUP freed memory is accessed in ip6_setmoptions because the in6_multi is still present in the im6o_memberships list in the pcb.

Here is my posting to freebsd-net.

Hi,

New to the list here, but fairly familiar with the innards of (at
least an older) version of the fbsd networking code. I'm fortunate in
my ability to run purify on a simulated instance of our ported version
of the networking code.  Purify has picked up a problem that I'm a bit
mystified as how it can be fixed.  It is present in current versions
also, I'm interested in any comments people have (I think ours is 4.4
vintage, but it is hard to tell).

As far as I can tell, in most calling paths when in6_delmulti() is
called, it is done after the in6_multi_mship structure has been
removed from the im6o_memberships list in the relevant PCB.  This
applies to in6_ifdetach(), in6_pcbpurgeif0, ip6_setmoptions()  etc.
However in in6_purgeaddr() in6_delmulti is called straight off.  I'm
not sure if we've violated some usage convention, but purify is
telling me this causes access violations when we then leave the same
group using setsockopt().  in6_purgeaddr is called when we remove the
address from the interface.

This should be possible in a real kernel.  Add a multicast address to
an interface, open a socket and listen to the address, then remove the
address from the interface.

Am I missing something here or is this a nasty problem in both the
kernel and our stack port?

Thanks,
Tom
>How-To-Repeat:
I am seeing this in a ported version of the code, I am not sure how to reproduce in the kernel but I can see no reason why this path might not be hit with a removable interface.
>Fix:
Reference counting for in6_multi is proxied to ifmultiaddr. in6m_refcount in in6_multi is unused.  Proper independant reference counting is needed for in6_multi so that it can persist if referenced by a socket after ifmultiaddr is destroyed.
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list