public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC][PATCH 0/7]: Fix for unsafe notifier chain
@ 2005-11-19  2:19 Chandra Seetharaman
  0 siblings, 0 replies; 8+ messages in thread
From: Chandra Seetharaman @ 2005-11-19  2:19 UTC (permalink / raw)
  To: linux-kernel
  Cc: lse-tech, paulmck, kaos, Alan Stern, greg, Douglas_Warzecha,
	Abhay_Salunke, achim_leubner, dmp

In 2.6.14, notifier chains are unsafe. notifier_call_chain() walks through
the list of a call chain without any protection.

Alan Stern <stern@rowland.harvard.edu> brought the issue and suggested a fix
in lkml on Oct 24 2005:
	http://marc.theaimsgroup.com/?l=linux-kernel&m=113018709002036&w=2

There was a lot of discussion on that thread regarding the issue, and
following were the conclusions about the requirements of the notifier
call mechanism:

	- The chain list has to be protected in all the places where the
	  list is accessed.
	- We need a new notifier_head data structure to encompass the head 
	  of the notifier chain and a semaphore that protects the list.
	- There should be two types of call chains: one that is called in 
	  a process context and another that is called in atomic/interrupt
	  context.
	- No lock should be acquired in notifier_call_chain() for an
	  atomic-type chain.
	- notifier_chain_register() and notifier_chain_unregister() should
	  be called only from process context.
	- notifier_chain_unregister() should _not_ be called from a
	  callout routine.

I posted an RFC that meets the above listed requirements last Friday:
	- http://marc.theaimsgroup.com/?l=linux-kernel&m=113175279131346&w=2
	
Paul McKenney provided some suggestions w.r.t RCU usage. This patchset fixes
the issues he raised.  Keith Owens posted some changes to the diechain for
various architectures; his changes are included here.

This is posted as an RFC as we want to get a green signal from the owners of
the files that our classification of chains as ATOMIC or BLOCKING is ok.
Please comment.

This patchset has 7 patches:

1 of 7: Changes the definition of the heads. Same as what was posted last
	Friday with changes w.r.t Paul's comments.
2 of 7:	Changes that affected only the notifier_head definition.
3 of 7: Changes in which we removed some protection (it's no longer needed
	as the basic infrastructure itself provides the protection).
4 of 7: changes for diechain for different architectures.
5 of 7: changes removing calls to notifier_unregister in the callout.
6 of 7: changes to dcdbas.c (requires special handling).
7 of 7: changes to make usb_notify to use the notify chain infrastructure
	instead of its own.

----------------------------------------

Here are the list of chains and their classification:

BLOCKING:
+++++++++
arch/powerpc/platforms/pseries/reconfig.c:	pSeries_reconfig_chain
arch/s390/kernel/process.c:		idle_chain
drivers/base/memory.c:			memory_chain
drivers/cpufreq/cpufreq.c:		cpufreq_policy_notifier_list
drivers/cpufreq/cpufreq.c:		cpufreq_transition_notifier_list
drivers/macintosh/adb.c:		adb_client_list
drivers/macintosh/via-pmu.c:		sleep_notifier_list
drivers/macintosh/via-pmu68k.c:		sleep_notifier_list
drivers/macintosh/windfarm_core.c:	wf_client_list
drivers/usb/core/notify.c:		usb_notifier_list
drivers/video/fbmem.c:			fb_notifier_list
kernel/cpu.c:				cpu_chain
kernel/module.c:			module_notify_list
kernel/profile.c:			munmap_notifier
kernel/profile.c:			task_exit_notifier
kernel/sys.c:				reboot_notifier_list
net/core/dev.c:				netdev_chain
net/decnet/dn_dev.c:			dnaddr_chain
net/ipv4/devinet.c:			inetaddr_chain

ATOMIC:
+++++++
arch/i386/kernel/traps.c:		i386die_chain
arch/ia64/kernel/traps.c:		ia64die_chain
arch/powerpc/kernel/traps.c:		powerpc_die_chain
arch/sparc64/kernel/traps.c:		sparc64die_chain
arch/x86_64/kernel/traps.c:		die_chain
drivers/char/ipmi/ipmi_si_intf.c:	xaction_notifier_list
kernel/panic.c:				panic_notifier_list
kernel/profile.c:			task_free_notifier
net/bluetooth/hci_core.c:		hci_notifier
net/ipv4/netfilter/ip_conntrack_core.c:	ip_conntrack_chain
net/ipv4/netfilter/ip_conntrack_core.c:	ip_conntrack_expect_chain
net/ipv6/addrconf.c:			inet6addr_chain
net/netfilter/nf_conntrack_core.c:	nf_conntrack_chain
nen/netfilter/nf_conntrack_core.c:	nf_conntrack_expect_chain
net/netlink/af_netlink.c:		netlink_chain


-- 

----------------------------------------------------------------------
    Chandra Seetharaman               | Be careful what you choose....
              - sekharan@us.ibm.com   |      .......you may get it.
----------------------------------------------------------------------



^ permalink raw reply	[flat|nested] 8+ messages in thread
* Re: [RFC][PATCH 0/7]: Fix for unsafe notifier chain
@ 2005-12-07 20:12 Alan Stern
  2005-12-07 23:36 ` Andrew Morton
  0 siblings, 1 reply; 8+ messages in thread
From: Alan Stern @ 2005-12-07 20:12 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Chandra Seetharaman, Andi Kleen, Kernel development list

Andrew:

I wasn't on the CC: list for parts of this conversation, so I'm a little 
behind-hand.  But Chandra is off on vacation now, and he asked me to 
continue pursuing this.

On November 27, 2005, Andrew Morton wrote:

> This all looks exotically complex.
> 
> > ...
> > 
> > Here are the details:
> > In 2.6.14, notifier chains are unsafe. notifier_call_chain() walks through
> > the list of a call chain without any protection.

...

> - You don't state _why_ a callback cannot call
>   notifier_chain_unregister().  I assume that's because of the use of
>   write_lock() locking?

Yes, that's part of it.

>   We could do this with a new callback function return code and do it in
>   the core, or just change the code so it is permitted.

I don't think that could be made to work.  The new unregister routine
guarantees that when it returns, the callout is not running on any
processor and will not be invoked.  Clearly this guarantee is necessary
when unregistering a callout that's part of a module about to be unloaded.  
Equally clearly, the guarantee cannot be met when a callout tries to
unregister itself.

On the other hand, this is a very minor issue.  We identified only two
callout routines that want to unregister themselves, both on the reboot
notifier chain.  It's simple to work around the self-unregistration, and
one of the patches in our series (5 of 7) did just that.  That patch alone
is harmless, and in fact it could be accepted independently of the rest of
our changes.

> - You don't explain why RCU has been introduced into this subsystem. 
>   Seems overkillish, or was it done as a way to solve the correctness
>   problems?

[Chandra may have explained this already; if so please forgive the
repetition.]  At least one notifier chain is invoked inside an NMI
handler, so normal locking can't be used with it.  RCU seems like an ideal
way to handle such cases.

The RCU overhead in our patches is really very small.  It amounts to a 
preempt_disable in notifier_call_chain, together with a few memory 
barriers and a call to synchronize_rcu in notifier_unregister.

The memory barriers are necessary even without RCU; they are the same as 
the ones Andi put in his proposed patch.  So the only noticeable overhead 
is in the unregister routine, which runs very infrequently.  (Andi's patch 
explicitly ignores the problems raised by unregistration.)

> - Overall take on the patches: the problem here is that notifier chains
>   try to provide their own locking.  Each time we design a container which
>   does that, we screw it up and we regret it.
> 
>   Please consider removing all locking from the notifer chains and moving
>   it into the callers.

That's a good point.  Would you accept a compromise solution?

A high percentage of the existing notifier chains are of the blocking sort
(the callouts are allowed to sleep).  They are well served by a simple
rw-semaphore, as in our patch.  It seems foolish to force the duplication
of this locking code in all the places that would need it.

Likewise, the atomic-type chains (where the callouts must run in an atomic 
context) are generally well served by the RCU mechanism, especially in 
cases where callouts are never unregistered.

So I propose that, in addition to those two types of chains, we define a
third type: raw notifiers.  These will be implemented with no protection
at all.  No rw-semaphore, no spinlock, no RCU, no need to avoid
self-unregistration, nothing -- all protection will be up to the users.  
In other words, just what you asked for.

This gives us the best of both worlds.  The common cases can benefit from
the centralized locking and protection, while anyone who has special needs
can easily provide for them.

If you think this would be okay, I'll rewrite the notifier patch to 
include the raw type.

Alan Stern


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2005-12-13 23:37 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-19  2:19 [RFC][PATCH 0/7]: Fix for unsafe notifier chain Chandra Seetharaman
  -- strict thread matches above, loose matches on Subject: below --
2005-12-07 20:12 Alan Stern
2005-12-07 23:36 ` Andrew Morton
2005-12-08 19:53   ` Alan Stern
2005-12-13  5:02     ` Keith Owens
2005-12-13 15:06       ` Alan Stern
2005-12-13 23:36         ` Andrew Morton
2005-12-09  4:50   ` Keith Owens

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox