Following up on Mark's query where ip6_output was called without
softnet_lock via a callchain of:
ip6_output()
mld_sendpkt()
mld_start_listening()
in6_addmulti()
in6_joingroup()
in6_update_ifa1()
in6_update_ifa()
in6_control1()
in6_control()
udp6_usrreq_wrapper()
compat_ifioctl()
ifioctl()
soo_ioctl()
sys_ioctl()
sy_call()
syscall()
I looked at where softnet_lock is and isn't acquired in the kernel. I
think this is a simple case of mld_start_listening failing to acquire
the lock.
So I'd suggest just acquiring/releasing at start/end of
mld_{start,stop}_listening, as shown below. However,
mld_start_listening can call mld_sendpkt, which acquires softnet_lock.
And, in6_addmulti does splsoftnet, but doesn't acquire softnet_lock.
From the mutex man page, it seems that it's not acceptable to enter a
mutex that one already holds.
It's also not clear to me why the kernel lock is involved.
wrong patch that will mutex_enter an already held mutex:
--- mld6.c.~1.55.~ 2011-11-21 16:32:25.000000000 -0500
+++ mld6.c 2013-06-17 13:34:43.000000000 -0400
@@ -271,6 +271,9 @@ mld_start_listening(struct in6_multi *in
{
struct in6_addr all_in6;
+ mutex_enter(softnet_lock);
+ KERNEL_LOCK(1, NULL);
+
/*
* RFC2710 page 10:
* The node never sends a Report or Done for the link-scope all-nodes
@@ -296,6 +299,9 @@ mld_start_listening(struct in6_multi *in
mld_starttimer(in6m);
}
+
+ KERNEL_UNLOCK_ONE(NULL);
+ mutex_exit(softnet_lock);
}
static void
@@ -303,15 +309,18 @@ mld_stop_listening(struct in6_multi *in6
{
struct in6_addr allnode, allrouter;
+ mutex_enter(softnet_lock);
+ KERNEL_LOCK(1, NULL);
+
allnode = in6addr_linklocal_allnodes;
if (in6_setscope(&allnode, in6m->in6m_ifp, NULL)) {
/* XXX: this should not happen! */
- return;
+ goto out;
}
allrouter = in6addr_linklocal_allrouters;
if (in6_setscope(&allrouter, in6m->in6m_ifp, NULL)) {
/* XXX impossible */
- return;
+ goto out;
}
if (in6m->in6m_state == MLD_IREPORTEDLAST &&
@@ -320,6 +329,10 @@ mld_stop_listening(struct in6_multi *in6
IPV6_ADDR_SCOPE_INTFACELOCAL) {
mld_sendpkt(in6m, MLD_LISTENER_DONE, &allrouter);
}
+
+ out:
+ KERNEL_UNLOCK_ONE(NULL);
+ mutex_exit(softnet_lock);
}
void
Attachment:
pgp2_sJH9_Dqj.pgp
Description: PGP signature