linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
@ 2019-07-10  3:09 Xiaoming Ni
  2019-07-10  5:49 ` Vasily Averin
  2019-07-10  5:56 ` Greg KH
  0 siblings, 2 replies; 15+ messages in thread
From: Xiaoming Ni @ 2019-07-10  3:09 UTC (permalink / raw)
  To: adobriyan, akpm, anna.schumaker, arjan, bfields, chuck.lever,
	davem, gregkh, jlayton, luto, mingo, Nadia.Derbey, paulmck,
	semen.protsenko, stable, stern, tglx, torvalds, trond.myklebust,
	viresh.kumar, vvs
  Cc: alex.huangjianhui, dylix.dailei, nixiaoming, linux-kernel,
	linux-nfs, netdev

Registering the same notifier to a hook repeatedly can cause the hook
list to form a ring or lose other members of the list.

case1: An infinite loop in notifier_chain_register() can cause soft lockup
        atomic_notifier_chain_register(&test_notifier_list, &test1);
        atomic_notifier_chain_register(&test_notifier_list, &test1);
        atomic_notifier_chain_register(&test_notifier_list, &test2);

case2: An infinite loop in notifier_chain_register() can cause soft lockup
        atomic_notifier_chain_register(&test_notifier_list, &test1);
        atomic_notifier_chain_register(&test_notifier_list, &test1);
        atomic_notifier_call_chain(&test_notifier_list, 0, NULL);

case3: lose other hook test2
        atomic_notifier_chain_register(&test_notifier_list, &test1);
        atomic_notifier_chain_register(&test_notifier_list, &test2);
        atomic_notifier_chain_register(&test_notifier_list, &test1);

case4: Unregister returns 0, but the hook is still in the linked list,
        and it is not really registered. If you call notifier_call_chain
        after ko is unloaded, it will trigger oops. if the system is
       	configured with softlockup_panic and the same hook is repeatedly
       	registered on the panic_notifier_list, it will cause a loop panic.

so. need add a check in in notifier_chain_register() to avoid duplicate
registration

v1:
* use notifier_chain_cond_register replace notifier_chain_register

v2:
* Add a check in notifier_chain_register() to avoid duplicate registration
* remove notifier_chain_cond_register() to avoid duplicate code 
* remove blocking_notifier_chain_cond_register() to avoid duplicate code

v3:
* Add a cover letter.

Xiaoming Ni (3):
  kernel/notifier.c: avoid duplicate registration
  kernel/notifier.c: remove notifier_chain_cond_register()
  kernel/notifier.c: remove blocking_notifier_chain_cond_register()

 include/linux/notifier.h |  4 ----
 kernel/notifier.c        | 41 +++--------------------------------------
 net/sunrpc/rpc_pipe.c    |  2 +-
 3 files changed, 4 insertions(+), 43 deletions(-)

-- 
1.8.5.6


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

* Re: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-10  3:09 [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration Xiaoming Ni
@ 2019-07-10  5:49 ` Vasily Averin
  2019-07-11  1:55   ` Nixiaoming
  2019-07-10  5:56 ` Greg KH
  1 sibling, 1 reply; 15+ messages in thread
From: Vasily Averin @ 2019-07-10  5:49 UTC (permalink / raw)
  To: Xiaoming Ni, adobriyan, akpm, anna.schumaker, arjan, bfields,
	chuck.lever, davem, gregkh, jlayton, luto, mingo, Nadia.Derbey,
	paulmck, semen.protsenko, stable, stern, tglx, torvalds,
	trond.myklebust, viresh.kumar
  Cc: alex.huangjianhui, dylix.dailei, linux-kernel, linux-nfs, netdev

On 7/10/19 6:09 AM, Xiaoming Ni wrote:
> Registering the same notifier to a hook repeatedly can cause the hook
> list to form a ring or lose other members of the list.

I think is not enough to _prevent_ 2nd register attempt,
it's enough to detect just attempt and generate warning to mark host in bad state.

Unexpected 2nd register of the same hook most likely will lead to 2nd unregister,
and it can lead to host crash in any time: 
you can unregister notifier on first attempt it can be too early, it can be still in use.
on the other hand you can never call 2nd unregister at all.

Unfortunately I do not see any ways to handle such cases properly,
and it seems for me your patches does not resolve this problem.

Am I missed something probably?
 
> case1: An infinite loop in notifier_chain_register() can cause soft lockup
>         atomic_notifier_chain_register(&test_notifier_list, &test1);
>         atomic_notifier_chain_register(&test_notifier_list, &test1);
>         atomic_notifier_chain_register(&test_notifier_list, &test2);
> 
> case2: An infinite loop in notifier_chain_register() can cause soft lockup
>         atomic_notifier_chain_register(&test_notifier_list, &test1);
>         atomic_notifier_chain_register(&test_notifier_list, &test1);
>         atomic_notifier_call_chain(&test_notifier_list, 0, NULL);
> 
> case3: lose other hook test2
>         atomic_notifier_chain_register(&test_notifier_list, &test1);
>         atomic_notifier_chain_register(&test_notifier_list, &test2);
>         atomic_notifier_chain_register(&test_notifier_list, &test1);
> 
> case4: Unregister returns 0, but the hook is still in the linked list,
>         and it is not really registered. If you call notifier_call_chain
>         after ko is unloaded, it will trigger oops. if the system is
>        	configured with softlockup_panic and the same hook is repeatedly
>        	registered on the panic_notifier_list, it will cause a loop panic.
> 
> so. need add a check in in notifier_chain_register() to avoid duplicate
> registration
> 
> v1:
> * use notifier_chain_cond_register replace notifier_chain_register
> 
> v2:
> * Add a check in notifier_chain_register() to avoid duplicate registration
> * remove notifier_chain_cond_register() to avoid duplicate code 
> * remove blocking_notifier_chain_cond_register() to avoid duplicate code
> 
> v3:
> * Add a cover letter.
> 
> Xiaoming Ni (3):
>   kernel/notifier.c: avoid duplicate registration
>   kernel/notifier.c: remove notifier_chain_cond_register()
>   kernel/notifier.c: remove blocking_notifier_chain_cond_register()
> 
>  include/linux/notifier.h |  4 ----
>  kernel/notifier.c        | 41 +++--------------------------------------
>  net/sunrpc/rpc_pipe.c    |  2 +-
>  3 files changed, 4 insertions(+), 43 deletions(-)
> 

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

* Re: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-10  3:09 [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration Xiaoming Ni
  2019-07-10  5:49 ` Vasily Averin
@ 2019-07-10  5:56 ` Greg KH
  2019-07-11  1:32   ` Nixiaoming
  1 sibling, 1 reply; 15+ messages in thread
From: Greg KH @ 2019-07-10  5:56 UTC (permalink / raw)
  To: Xiaoming Ni
  Cc: adobriyan, akpm, anna.schumaker, arjan, bfields, chuck.lever,
	davem, jlayton, luto, mingo, Nadia.Derbey, paulmck,
	semen.protsenko, stable, stern, tglx, torvalds, trond.myklebust,
	viresh.kumar, vvs, alex.huangjianhui, dylix.dailei, linux-kernel,
	linux-nfs, netdev

On Wed, Jul 10, 2019 at 11:09:07AM +0800, Xiaoming Ni wrote:
> Registering the same notifier to a hook repeatedly can cause the hook
> list to form a ring or lose other members of the list.

Then don't do that :)

Is there any in-kernel users that do do this?  If so, please just fix
them.

thanks,

greg k-h

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

* RE: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-10  5:56 ` Greg KH
@ 2019-07-11  1:32   ` Nixiaoming
  0 siblings, 0 replies; 15+ messages in thread
From: Nixiaoming @ 2019-07-11  1:32 UTC (permalink / raw)
  To: Greg KH
  Cc: adobriyan, akpm, anna.schumaker, arjan, bfields, chuck.lever,
	davem, jlayton, luto, mingo, Nadia.Derbey, paulmck,
	semen.protsenko, stable, stern, tglx, torvalds, trond.myklebust,
	viresh.kumar, vvs, Huangjianhui (Alex),
	Dailei, linux-kernel, linux-nfs, netdev

On Wed, July 10, 2019 1:56 PM Greg KH wrote:
>On Wed, Jul 10, 2019 at 11:09:07AM +0800, Xiaoming Ni wrote:
>> Registering the same notifier to a hook repeatedly can cause the hook
>> list to form a ring or lose other members of the list.
>
>Then don't do that :)
>

Duplicate registration is checked and exited in notifier_chain_cond_register()

Duplicate registration was checked in notifier_chain_register() but only 
the alarm was triggered without exiting. added by commit 831246570d34692e 
("kernel/notifier.c: double register detection")

This patch is similar to commit 8312465 and notifier_chain_cond_register(),
 with actual prevention for such behaviour,  which I think is necessary to 
 avoid the formation of a linked list ring.

>Is there any in-kernel users that do do this?  If so, please just fix
>them.
>
Notifier_chain_register() is not a hotspot path.
Adding a check here can make the kernel more stable.

Thanks

Xiaoming Ni


>thanks,
>
>greg k-h
>

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

* RE: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-10  5:49 ` Vasily Averin
@ 2019-07-11  1:55   ` Nixiaoming
  2019-07-11 13:57     ` Vasily Averin
  0 siblings, 1 reply; 15+ messages in thread
From: Nixiaoming @ 2019-07-11  1:55 UTC (permalink / raw)
  To: Vasily Averin, adobriyan, akpm, anna.schumaker, arjan, bfields,
	chuck.lever, davem, gregkh, jlayton, luto, mingo, Nadia.Derbey,
	paulmck, semen.protsenko, stable, stern, tglx, torvalds,
	trond.myklebust, viresh.kumar
  Cc: Huangjianhui (Alex), Dailei, linux-kernel, linux-nfs, netdev

On Wed, July 10, 2019 1:49 PM Vasily Averin wrote:
>On 7/10/19 6:09 AM, Xiaoming Ni wrote:
>> Registering the same notifier to a hook repeatedly can cause the hook
>> list to form a ring or lose other members of the list.
>
>I think is not enough to _prevent_ 2nd register attempt,
>it's enough to detect just attempt and generate warning to mark host in bad state.
>

Duplicate registration is prevented in my patch, not just "mark host in bad state"

Duplicate registration is checked and exited in notifier_chain_cond_register()

Duplicate registration was checked in notifier_chain_register() but only 
the alarm was triggered without exiting. added by commit 831246570d34692e 
("kernel/notifier.c: double register detection")

My patch is like a combination of 831246570d34692e and notifier_chain_cond_register(),
 which triggers an alarm and exits when a duplicate registration is detected.

>Unexpected 2nd register of the same hook most likely will lead to 2nd unregister,
>and it can lead to host crash in any time: 
>you can unregister notifier on first attempt it can be too early, it can be still in use.
>on the other hand you can never call 2nd unregister at all.

Since the member was not added to the linked list at the time of the second registration, 
no linked list ring was formed. 
The member is released on the first unregistration and -ENOENT on the second unregistration.
After patching, the fault has been alleviated

It may be more helpful to return an error code when someone tries to register the same
notification program a second time.
But I noticed that notifier_chain_cond_register() returns 0 when duplicate registration 
is detected. At the same time, in all the existing export function comments of notify,
"Currently always returns zero"

I am a bit confused: which is better?

>
>Unfortunately I do not see any ways to handle such cases properly,
>and it seems for me your patches does not resolve this problem.
>
>Am I missed something probably?
> 
>> case1: An infinite loop in notifier_chain_register() can cause soft lockup
>>         atomic_notifier_chain_register(&test_notifier_list, &test1);
>>         atomic_notifier_chain_register(&test_notifier_list, &test1);
>>         atomic_notifier_chain_register(&test_notifier_list, &test2);

Thanks

Xiaoming Ni

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

* Re: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-11  1:55   ` Nixiaoming
@ 2019-07-11 13:57     ` Vasily Averin
  2019-07-12 13:11       ` Xiaoming Ni
  0 siblings, 1 reply; 15+ messages in thread
From: Vasily Averin @ 2019-07-11 13:57 UTC (permalink / raw)
  To: Nixiaoming, adobriyan, akpm, anna.schumaker, arjan, bfields,
	chuck.lever, davem, gregkh, jlayton, luto, mingo, Nadia.Derbey,
	paulmck, semen.protsenko, stable, stern, tglx, torvalds,
	trond.myklebust, viresh.kumar
  Cc: Huangjianhui (Alex), Dailei, linux-kernel, linux-nfs, netdev

On 7/11/19 4:55 AM, Nixiaoming wrote:
> On Wed, July 10, 2019 1:49 PM Vasily Averin wrote:
>> On 7/10/19 6:09 AM, Xiaoming Ni wrote:
>>> Registering the same notifier to a hook repeatedly can cause the hook
>>> list to form a ring or lose other members of the list.
>>
>> I think is not enough to _prevent_ 2nd register attempt,
>> it's enough to detect just attempt and generate warning to mark host in bad state.
>>
> 
> Duplicate registration is prevented in my patch, not just "mark host in bad state"
> 
> Duplicate registration is checked and exited in notifier_chain_cond_register()
> 
> Duplicate registration was checked in notifier_chain_register() but only 
> the alarm was triggered without exiting. added by commit 831246570d34692e 
> ("kernel/notifier.c: double register detection")
> 
> My patch is like a combination of 831246570d34692e and notifier_chain_cond_register(),
>  which triggers an alarm and exits when a duplicate registration is detected.
> 
>> Unexpected 2nd register of the same hook most likely will lead to 2nd unregister,
>> and it can lead to host crash in any time: 
>> you can unregister notifier on first attempt it can be too early, it can be still in use.
>> on the other hand you can never call 2nd unregister at all.
> 
> Since the member was not added to the linked list at the time of the second registration, 
> no linked list ring was formed. 
> The member is released on the first unregistration and -ENOENT on the second unregistration.
> After patching, the fault has been alleviated

You are wrong here.
2nd notifier's registration is a pure bug, this should never happen.
If you know the way to reproduce this situation -- you need to fix it. 

2nd registration can happen in 2 cases:
1) missed rollback, when someone forget to call unregister after successfull registration, 
and then tried to call register again. It can lead to crash for example when according module will be unloaded.
2) some subsystem is registered twice, for example from  different namespaces.
in this case unregister called during sybsystem cleanup in first namespace will incorrectly remove notifier used 
in second namespace, it also can lead to unexpacted behaviour.

> It may be more helpful to return an error code when someone tries to register the same
> notification program a second time.

You are wrong again here, it is senseless.
If you have detected 2nd register -- your node is already in bad state.

> But I noticed that notifier_chain_cond_register() returns 0 when duplicate registration 
> is detected. At the same time, in all the existing export function comments of notify,
> "Currently always returns zero"
> 
> I am a bit confused: which is better?
> 
>>
>> Unfortunately I do not see any ways to handle such cases properly,
>> and it seems for me your patches does not resolve this problem.
>>
>> Am I missed something probably?
>>
>>> case1: An infinite loop in notifier_chain_register() can cause soft lockup
>>>         atomic_notifier_chain_register(&test_notifier_list, &test1);
>>>         atomic_notifier_chain_register(&test_notifier_list, &test1);
>>>         atomic_notifier_chain_register(&test_notifier_list, &test2);
> 
> Thanks
> 
> Xiaoming Ni
> 

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

* Re: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-11 13:57     ` Vasily Averin
@ 2019-07-12 13:11       ` Xiaoming Ni
  2019-07-12 14:07         ` gregkh
  0 siblings, 1 reply; 15+ messages in thread
From: Xiaoming Ni @ 2019-07-12 13:11 UTC (permalink / raw)
  To: Vasily Averin, adobriyan, akpm, anna.schumaker, arjan, bfields,
	chuck.lever, davem, gregkh, jlayton, luto, mingo, Nadia.Derbey,
	paulmck, semen.protsenko, stable, stern, tglx, torvalds,
	trond.myklebust, viresh.kumar
  Cc: Huangjianhui (Alex), Dailei, linux-kernel, linux-nfs, netdev

On 2019/7/11 21:57, Vasily Averin wrote:
> On 7/11/19 4:55 AM, Nixiaoming wrote:
>> On Wed, July 10, 2019 1:49 PM Vasily Averin wrote:
>>> On 7/10/19 6:09 AM, Xiaoming Ni wrote:
>>>> Registering the same notifier to a hook repeatedly can cause the hook
>>>> list to form a ring or lose other members of the list.
>>>
>>> I think is not enough to _prevent_ 2nd register attempt,
>>> it's enough to detect just attempt and generate warning to mark host in bad state.
>>>
>>
>> Duplicate registration is prevented in my patch, not just "mark host in bad state"
>>
>> Duplicate registration is checked and exited in notifier_chain_cond_register()
>>
>> Duplicate registration was checked in notifier_chain_register() but only 
>> the alarm was triggered without exiting. added by commit 831246570d34692e 
>> ("kernel/notifier.c: double register detection")
>>
>> My patch is like a combination of 831246570d34692e and notifier_chain_cond_register(),
>>  which triggers an alarm and exits when a duplicate registration is detected.
>>
>>> Unexpected 2nd register of the same hook most likely will lead to 2nd unregister,
>>> and it can lead to host crash in any time: 
>>> you can unregister notifier on first attempt it can be too early, it can be still in use.
>>> on the other hand you can never call 2nd unregister at all.
>>
>> Since the member was not added to the linked list at the time of the second registration, 
>> no linked list ring was formed. 
>> The member is released on the first unregistration and -ENOENT on the second unregistration.
>> After patching, the fault has been alleviated
> 
> You are wrong here.
> 2nd notifier's registration is a pure bug, this should never happen.
> If you know the way to reproduce this situation -- you need to fix it. 
> 
> 2nd registration can happen in 2 cases:
> 1) missed rollback, when someone forget to call unregister after successfull registration, 
> and then tried to call register again. It can lead to crash for example when according module will be unloaded.
> 2) some subsystem is registered twice, for example from  different namespaces.
> in this case unregister called during sybsystem cleanup in first namespace will incorrectly remove notifier used 
> in second namespace, it also can lead to unexpacted behaviour.
> 
So in these two cases, is it more reasonable to trigger BUG() directly when checking for duplicate registration ?
But why does current notifier_chain_register() just trigger WARN() without exiting ?
notifier_chain_cond_register() direct exit without triggering WARN() ?

Thanks

Xiaoming Ni

>> It may be more helpful to return an error code when someone tries to register the same
>> notification program a second time.
> 
> You are wrong again here, it is senseless.
> If you have detected 2nd register -- your node is already in bad state.
> 
>> But I noticed that notifier_chain_cond_register() returns 0 when duplicate registration 
>> is detected. At the same time, in all the existing export function comments of notify,
>> "Currently always returns zero"
>>
>> I am a bit confused: which is better?
>>
>>>
>>> Unfortunately I do not see any ways to handle such cases properly,
>>> and it seems for me your patches does not resolve this problem.
>>>
>>> Am I missed something probably?
>>>
>>>> case1: An infinite loop in notifier_chain_register() can cause soft lockup
>>>>         atomic_notifier_chain_register(&test_notifier_list, &test1);
>>>>         atomic_notifier_chain_register(&test_notifier_list, &test1);
>>>>         atomic_notifier_chain_register(&test_notifier_list, &test2);
>>
>> Thanks
>>
>> Xiaoming Ni
>>
> 
> .
> 


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

* Re: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-12 13:11       ` Xiaoming Ni
@ 2019-07-12 14:07         ` gregkh
  2019-07-14  2:45           ` Xiaoming Ni
  0 siblings, 1 reply; 15+ messages in thread
From: gregkh @ 2019-07-12 14:07 UTC (permalink / raw)
  To: Xiaoming Ni
  Cc: Vasily Averin, adobriyan, akpm, anna.schumaker, arjan, bfields,
	chuck.lever, davem, jlayton, luto, mingo, Nadia.Derbey, paulmck,
	semen.protsenko, stable, stern, tglx, torvalds, trond.myklebust,
	viresh.kumar, Huangjianhui (Alex),
	Dailei, linux-kernel, linux-nfs, netdev

On Fri, Jul 12, 2019 at 09:11:57PM +0800, Xiaoming Ni wrote:
> On 2019/7/11 21:57, Vasily Averin wrote:
> > On 7/11/19 4:55 AM, Nixiaoming wrote:
> >> On Wed, July 10, 2019 1:49 PM Vasily Averin wrote:
> >>> On 7/10/19 6:09 AM, Xiaoming Ni wrote:
> >>>> Registering the same notifier to a hook repeatedly can cause the hook
> >>>> list to form a ring or lose other members of the list.
> >>>
> >>> I think is not enough to _prevent_ 2nd register attempt,
> >>> it's enough to detect just attempt and generate warning to mark host in bad state.
> >>>
> >>
> >> Duplicate registration is prevented in my patch, not just "mark host in bad state"
> >>
> >> Duplicate registration is checked and exited in notifier_chain_cond_register()
> >>
> >> Duplicate registration was checked in notifier_chain_register() but only 
> >> the alarm was triggered without exiting. added by commit 831246570d34692e 
> >> ("kernel/notifier.c: double register detection")
> >>
> >> My patch is like a combination of 831246570d34692e and notifier_chain_cond_register(),
> >>  which triggers an alarm and exits when a duplicate registration is detected.
> >>
> >>> Unexpected 2nd register of the same hook most likely will lead to 2nd unregister,
> >>> and it can lead to host crash in any time: 
> >>> you can unregister notifier on first attempt it can be too early, it can be still in use.
> >>> on the other hand you can never call 2nd unregister at all.
> >>
> >> Since the member was not added to the linked list at the time of the second registration, 
> >> no linked list ring was formed. 
> >> The member is released on the first unregistration and -ENOENT on the second unregistration.
> >> After patching, the fault has been alleviated
> > 
> > You are wrong here.
> > 2nd notifier's registration is a pure bug, this should never happen.
> > If you know the way to reproduce this situation -- you need to fix it. 
> > 
> > 2nd registration can happen in 2 cases:
> > 1) missed rollback, when someone forget to call unregister after successfull registration, 
> > and then tried to call register again. It can lead to crash for example when according module will be unloaded.
> > 2) some subsystem is registered twice, for example from  different namespaces.
> > in this case unregister called during sybsystem cleanup in first namespace will incorrectly remove notifier used 
> > in second namespace, it also can lead to unexpacted behaviour.
> > 
> So in these two cases, is it more reasonable to trigger BUG() directly when checking for duplicate registration ?
> But why does current notifier_chain_register() just trigger WARN() without exiting ?
> notifier_chain_cond_register() direct exit without triggering WARN() ?

It should recover from this, if it can be detected.  The main point is
that not all apis have to be this "robust" when used within the kernel
as we do allow for the callers to know what they are doing :)

If this does not cause any additional problems or slow downs, it's
probably fine to add.

thanks,

greg k-h

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

* Re: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-12 14:07         ` gregkh
@ 2019-07-14  2:45           ` Xiaoming Ni
  2019-07-15  5:38             ` Vasily Averin
  0 siblings, 1 reply; 15+ messages in thread
From: Xiaoming Ni @ 2019-07-14  2:45 UTC (permalink / raw)
  To: gregkh
  Cc: Vasily Averin, adobriyan, akpm, anna.schumaker, arjan, bfields,
	chuck.lever, davem, jlayton, luto, mingo, Nadia.Derbey, paulmck,
	semen.protsenko, stable, stern, tglx, torvalds, trond.myklebust,
	viresh.kumar, Huangjianhui (Alex),
	Dailei, linux-kernel, linux-nfs, netdev

On 2019/7/12 22:07, gregkh@linuxfoundation.org wrote:
> On Fri, Jul 12, 2019 at 09:11:57PM +0800, Xiaoming Ni wrote:
>> On 2019/7/11 21:57, Vasily Averin wrote:
>>> On 7/11/19 4:55 AM, Nixiaoming wrote:
>>>> On Wed, July 10, 2019 1:49 PM Vasily Averin wrote:
>>>>> On 7/10/19 6:09 AM, Xiaoming Ni wrote:
>>>>>> Registering the same notifier to a hook repeatedly can cause the hook
>>>>>> list to form a ring or lose other members of the list.
>>>>>
>>>>> I think is not enough to _prevent_ 2nd register attempt,
>>>>> it's enough to detect just attempt and generate warning to mark host in bad state.
>>>>>
>>>>
>>>> Duplicate registration is prevented in my patch, not just "mark host in bad state"
>>>>
>>>> Duplicate registration is checked and exited in notifier_chain_cond_register()
>>>>
>>>> Duplicate registration was checked in notifier_chain_register() but only 
>>>> the alarm was triggered without exiting. added by commit 831246570d34692e 
>>>> ("kernel/notifier.c: double register detection")
>>>>
>>>> My patch is like a combination of 831246570d34692e and notifier_chain_cond_register(),
>>>>  which triggers an alarm and exits when a duplicate registration is detected.
>>>>
>>>>> Unexpected 2nd register of the same hook most likely will lead to 2nd unregister,
>>>>> and it can lead to host crash in any time: 
>>>>> you can unregister notifier on first attempt it can be too early, it can be still in use.
>>>>> on the other hand you can never call 2nd unregister at all.
>>>>
>>>> Since the member was not added to the linked list at the time of the second registration, 
>>>> no linked list ring was formed. 
>>>> The member is released on the first unregistration and -ENOENT on the second unregistration.
>>>> After patching, the fault has been alleviated
>>>
>>> You are wrong here.
>>> 2nd notifier's registration is a pure bug, this should never happen.
>>> If you know the way to reproduce this situation -- you need to fix it. 
>>>
>>> 2nd registration can happen in 2 cases:
>>> 1) missed rollback, when someone forget to call unregister after successfull registration, 
>>> and then tried to call register again. It can lead to crash for example when according module will be unloaded.
>>> 2) some subsystem is registered twice, for example from  different namespaces.
>>> in this case unregister called during sybsystem cleanup in first namespace will incorrectly remove notifier used 
>>> in second namespace, it also can lead to unexpacted behaviour.
>>>
>> So in these two cases, is it more reasonable to trigger BUG() directly when checking for duplicate registration ?
>> But why does current notifier_chain_register() just trigger WARN() without exiting ?
>> notifier_chain_cond_register() direct exit without triggering WARN() ?
> 
> It should recover from this, if it can be detected.  The main point is
> that not all apis have to be this "robust" when used within the kernel
> as we do allow for the callers to know what they are doing :)
> 
In the notifier_chain_register(), the condition ( (*nl) == n) is the same registration of the same hook.
 We can intercept this situation and avoid forming a linked list ring to make the API more rob

> If this does not cause any additional problems or slow downs, it's
> probably fine to add.
> 
Notifier_chain_register() is not a system hotspot function.
At the same time, there is already a WARN_ONCE judgment. There is no new judgment in the new patch.
It only changes the processing under the condition of (*nl) == n, which will not cause performance problems.
At the same time, avoiding the formation of a link ring can make the system more robust.

> thanks,
> 
> greg k-h
> 
> .
> 
Thanks

Xiaoming Ni



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

* Re: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-14  2:45           ` Xiaoming Ni
@ 2019-07-15  5:38             ` Vasily Averin
  2019-07-16  2:00               ` Xiaoming Ni
  0 siblings, 1 reply; 15+ messages in thread
From: Vasily Averin @ 2019-07-15  5:38 UTC (permalink / raw)
  To: Xiaoming Ni, gregkh
  Cc: adobriyan, akpm, anna.schumaker, arjan, bfields, chuck.lever,
	davem, jlayton, luto, mingo, Nadia.Derbey, paulmck,
	semen.protsenko, stable, stern, tglx, torvalds, trond.myklebust,
	viresh.kumar, Huangjianhui (Alex),
	Dailei, linux-kernel, linux-nfs, netdev

On 7/14/19 5:45 AM, Xiaoming Ni wrote:
> On 2019/7/12 22:07, gregkh@linuxfoundation.org wrote:
>> On Fri, Jul 12, 2019 at 09:11:57PM +0800, Xiaoming Ni wrote:
>>> On 2019/7/11 21:57, Vasily Averin wrote:
>>>> On 7/11/19 4:55 AM, Nixiaoming wrote:
>>>>> On Wed, July 10, 2019 1:49 PM Vasily Averin wrote:
>>>>>> On 7/10/19 6:09 AM, Xiaoming Ni wrote:
>>>>>>> Registering the same notifier to a hook repeatedly can cause the hook
>>>>>>> list to form a ring or lose other members of the list.
>>>>>>
>>>>>> I think is not enough to _prevent_ 2nd register attempt,
>>>>>> it's enough to detect just attempt and generate warning to mark host in bad state.
>>>>>>
>>>>>
>>>>> Duplicate registration is prevented in my patch, not just "mark host in bad state"
>>>>>
>>>>> Duplicate registration is checked and exited in notifier_chain_cond_register()
>>>>>
>>>>> Duplicate registration was checked in notifier_chain_register() but only 
>>>>> the alarm was triggered without exiting. added by commit 831246570d34692e 
>>>>> ("kernel/notifier.c: double register detection")
>>>>>
>>>>> My patch is like a combination of 831246570d34692e and notifier_chain_cond_register(),
>>>>>  which triggers an alarm and exits when a duplicate registration is detected.
>>>>>
>>>>>> Unexpected 2nd register of the same hook most likely will lead to 2nd unregister,
>>>>>> and it can lead to host crash in any time: 
>>>>>> you can unregister notifier on first attempt it can be too early, it can be still in use.
>>>>>> on the other hand you can never call 2nd unregister at all.
>>>>>
>>>>> Since the member was not added to the linked list at the time of the second registration, 
>>>>> no linked list ring was formed. 
>>>>> The member is released on the first unregistration and -ENOENT on the second unregistration.
>>>>> After patching, the fault has been alleviated
>>>>
>>>> You are wrong here.
>>>> 2nd notifier's registration is a pure bug, this should never happen.
>>>> If you know the way to reproduce this situation -- you need to fix it. 
>>>>
>>>> 2nd registration can happen in 2 cases:
>>>> 1) missed rollback, when someone forget to call unregister after successfull registration, 
>>>> and then tried to call register again. It can lead to crash for example when according module will be unloaded.
>>>> 2) some subsystem is registered twice, for example from  different namespaces.
>>>> in this case unregister called during sybsystem cleanup in first namespace will incorrectly remove notifier used 
>>>> in second namespace, it also can lead to unexpacted behaviour.
>>>>
>>> So in these two cases, is it more reasonable to trigger BUG() directly when checking for duplicate registration ?
>>> But why does current notifier_chain_register() just trigger WARN() without exiting ?
>>> notifier_chain_cond_register() direct exit without triggering WARN() ?
>>
>> It should recover from this, if it can be detected.  The main point is
>> that not all apis have to be this "robust" when used within the kernel
>> as we do allow for the callers to know what they are doing :)
>>
> In the notifier_chain_register(), the condition ( (*nl) == n) is the same registration of the same hook.
>  We can intercept this situation and avoid forming a linked list ring to make the API more rob

Once again -- yes, you CAN prevent list corruption, but you CANNOT recover the host and return it back to safe state.
If double register event was detected -- it means you have bug in kernel.

Yes, you can add BUG here and crash the host immediately, but I prefer to use warning in such situations.

>> If this does not cause any additional problems or slow downs, it's
>> probably fine to add.
>>
> Notifier_chain_register() is not a system hotspot function.
> At the same time, there is already a WARN_ONCE judgment. There is no new judgment in the new patch.
> It only changes the processing under the condition of (*nl) == n, which will not cause performance problems.
> At the same time, avoiding the formation of a link ring can make the system more robust.

I disagree, 
yes, node will have correct list, but anyway node will work wrong and can crash the host in any time.

>> thanks,
>>
>> greg k-h
>>
>> .
>>
> Thanks
> 
> Xiaoming Ni
> 
> 
> 

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

* Re: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-15  5:38             ` Vasily Averin
@ 2019-07-16  2:00               ` Xiaoming Ni
  2019-07-16 10:20                 ` Vasily Averin
  0 siblings, 1 reply; 15+ messages in thread
From: Xiaoming Ni @ 2019-07-16  2:00 UTC (permalink / raw)
  To: Vasily Averin, gregkh
  Cc: adobriyan, akpm, anna.schumaker, arjan, bfields, chuck.lever,
	davem, jlayton, luto, mingo, Nadia.Derbey, paulmck,
	semen.protsenko, stable, stern, tglx, torvalds, trond.myklebust,
	viresh.kumar, Huangjianhui (Alex),
	Dailei, linux-kernel, linux-nfs, netdev

On 2019/7/15 13:38, Vasily Averin wrote:
> On 7/14/19 5:45 AM, Xiaoming Ni wrote:
>> On 2019/7/12 22:07, gregkh@linuxfoundation.org wrote:
>>> On Fri, Jul 12, 2019 at 09:11:57PM +0800, Xiaoming Ni wrote:
>>>> On 2019/7/11 21:57, Vasily Averin wrote:
>>>>> On 7/11/19 4:55 AM, Nixiaoming wrote:
>>>>>> On Wed, July 10, 2019 1:49 PM Vasily Averin wrote:
>>>>>>> On 7/10/19 6:09 AM, Xiaoming Ni wrote:
>>>>>>>> Registering the same notifier to a hook repeatedly can cause the hook
>>>>>>>> list to form a ring or lose other members of the list.
>>>>>>>
>>>>>>> I think is not enough to _prevent_ 2nd register attempt,
>>>>>>> it's enough to detect just attempt and generate warning to mark host in bad state.
>>>>>>>
>>>>>>
>>>>>> Duplicate registration is prevented in my patch, not just "mark host in bad state"
>>>>>>
>>>>>> Duplicate registration is checked and exited in notifier_chain_cond_register()
>>>>>>
>>>>>> Duplicate registration was checked in notifier_chain_register() but only 
>>>>>> the alarm was triggered without exiting. added by commit 831246570d34692e 
>>>>>> ("kernel/notifier.c: double register detection")
>>>>>>
>>>>>> My patch is like a combination of 831246570d34692e and notifier_chain_cond_register(),
>>>>>>  which triggers an alarm and exits when a duplicate registration is detected.
>>>>>>
>>>>>>> Unexpected 2nd register of the same hook most likely will lead to 2nd unregister,
>>>>>>> and it can lead to host crash in any time: 
>>>>>>> you can unregister notifier on first attempt it can be too early, it can be still in use.
>>>>>>> on the other hand you can never call 2nd unregister at all.
>>>>>>
>>>>>> Since the member was not added to the linked list at the time of the second registration, 
>>>>>> no linked list ring was formed. 
>>>>>> The member is released on the first unregistration and -ENOENT on the second unregistration.
>>>>>> After patching, the fault has been alleviated
>>>>>
>>>>> You are wrong here.
>>>>> 2nd notifier's registration is a pure bug, this should never happen.
>>>>> If you know the way to reproduce this situation -- you need to fix it. 
>>>>>
>>>>> 2nd registration can happen in 2 cases:
>>>>> 1) missed rollback, when someone forget to call unregister after successfull registration, 
>>>>> and then tried to call register again. It can lead to crash for example when according module will be unloaded.
>>>>> 2) some subsystem is registered twice, for example from  different namespaces.
>>>>> in this case unregister called during sybsystem cleanup in first namespace will incorrectly remove notifier used 
>>>>> in second namespace, it also can lead to unexpacted behaviour.
>>>>>
>>>> So in these two cases, is it more reasonable to trigger BUG() directly when checking for duplicate registration ?
>>>> But why does current notifier_chain_register() just trigger WARN() without exiting ?
>>>> notifier_chain_cond_register() direct exit without triggering WARN() ?
>>>
>>> It should recover from this, if it can be detected.  The main point is
>>> that not all apis have to be this "robust" when used within the kernel
>>> as we do allow for the callers to know what they are doing :)
>>>
>> In the notifier_chain_register(), the condition ( (*nl) == n) is the same registration of the same hook.
>>  We can intercept this situation and avoid forming a linked list ring to make the API more rob
> 
> Once again -- yes, you CAN prevent list corruption, but you CANNOT recover the host and return it back to safe state.
> If double register event was detected -- it means you have bug in kernel.
> 
> Yes, you can add BUG here and crash the host immediately, but I prefer to use warning in such situations.
> 
>>> If this does not cause any additional problems or slow downs, it's
>>> probably fine to add.
>>>
>> Notifier_chain_register() is not a system hotspot function.
>> At the same time, there is already a WARN_ONCE judgment. There is no new judgment in the new patch.
>> It only changes the processing under the condition of (*nl) == n, which will not cause performance problems.
>> At the same time, avoiding the formation of a link ring can make the system more robust.
> 
> I disagree, 
> yes, node will have correct list, but anyway node will work wrong and can crash the host in any time.

Sorry, my description is not accurate.

My patch feature does not prevent users from repeatedly registering hooks.
But avoiding the chain ring caused by the user repeatedly registering the hook

There are no modules for duplicate registration hooks in the current system.
But considering that not all modules are in the kernel source tree,
In order to improve the robustness of the kernel API, we should avoid the linked list ring caused by repeated registration.
Or in order to improve the efficiency of problem location, when the duplicate registration is checked, the system crashes directly.

On the other hand, the difference between notifier_chain_register() and notifier_chain_cond_register() for duplicate registrations is confusing:
Blocking the formation of the linked list ring in notifier_chain_cond_register()
There is no interception of the linked list ring in notifier_chain_register(), just an alarm.
Give me the illusion: Isn't notifier_chain_register() allowed to create a linked list ring?

Thanks

xiaoming Ni




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

* Re: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-16  2:00               ` Xiaoming Ni
@ 2019-07-16 10:20                 ` Vasily Averin
  2019-07-16 14:07                   ` Xiaoming Ni
  0 siblings, 1 reply; 15+ messages in thread
From: Vasily Averin @ 2019-07-16 10:20 UTC (permalink / raw)
  To: Xiaoming Ni, gregkh
  Cc: adobriyan, akpm, anna.schumaker, arjan, bfields, chuck.lever,
	davem, jlayton, luto, mingo, Nadia.Derbey, paulmck,
	semen.protsenko, stable, stern, tglx, torvalds, trond.myklebust,
	viresh.kumar, Huangjianhui (Alex),
	Dailei, linux-kernel, linux-nfs, netdev

On 7/16/19 5:00 AM, Xiaoming Ni wrote:
> On 2019/7/15 13:38, Vasily Averin wrote:
>> On 7/14/19 5:45 AM, Xiaoming Ni wrote:
>>> On 2019/7/12 22:07, gregkh@linuxfoundation.org wrote:
>>>> On Fri, Jul 12, 2019 at 09:11:57PM +0800, Xiaoming Ni wrote:
>>>>> On 2019/7/11 21:57, Vasily Averin wrote:
>>>>>> On 7/11/19 4:55 AM, Nixiaoming wrote:
>>>>>>> On Wed, July 10, 2019 1:49 PM Vasily Averin wrote:
>>>>>>>> On 7/10/19 6:09 AM, Xiaoming Ni wrote:
>>>>>>>>> Registering the same notifier to a hook repeatedly can cause the hook
>>>>>>>>> list to form a ring or lose other members of the list.
>>>>>>>>
>>>>>>>> I think is not enough to _prevent_ 2nd register attempt,
>>>>>>>> it's enough to detect just attempt and generate warning to mark host in bad state.
>>>>>>>>
>>>>>>>
>>>>>>> Duplicate registration is prevented in my patch, not just "mark host in bad state"
>>>>>>>
>>>>>>> Duplicate registration is checked and exited in notifier_chain_cond_register()
>>>>>>>
>>>>>>> Duplicate registration was checked in notifier_chain_register() but only 
>>>>>>> the alarm was triggered without exiting. added by commit 831246570d34692e 
>>>>>>> ("kernel/notifier.c: double register detection")
>>>>>>>
>>>>>>> My patch is like a combination of 831246570d34692e and notifier_chain_cond_register(),
>>>>>>>  which triggers an alarm and exits when a duplicate registration is detected.
>>>>>>>
>>>>>>>> Unexpected 2nd register of the same hook most likely will lead to 2nd unregister,
>>>>>>>> and it can lead to host crash in any time: 
>>>>>>>> you can unregister notifier on first attempt it can be too early, it can be still in use.
>>>>>>>> on the other hand you can never call 2nd unregister at all.
>>>>>>>
>>>>>>> Since the member was not added to the linked list at the time of the second registration, 
>>>>>>> no linked list ring was formed. 
>>>>>>> The member is released on the first unregistration and -ENOENT on the second unregistration.
>>>>>>> After patching, the fault has been alleviated
>>>>>>
>>>>>> You are wrong here.
>>>>>> 2nd notifier's registration is a pure bug, this should never happen.
>>>>>> If you know the way to reproduce this situation -- you need to fix it. 
>>>>>>
>>>>>> 2nd registration can happen in 2 cases:
>>>>>> 1) missed rollback, when someone forget to call unregister after successfull registration, 
>>>>>> and then tried to call register again. It can lead to crash for example when according module will be unloaded.
>>>>>> 2) some subsystem is registered twice, for example from  different namespaces.
>>>>>> in this case unregister called during sybsystem cleanup in first namespace will incorrectly remove notifier used 
>>>>>> in second namespace, it also can lead to unexpacted behaviour.
>>>>>>
>>>>> So in these two cases, is it more reasonable to trigger BUG() directly when checking for duplicate registration ?
>>>>> But why does current notifier_chain_register() just trigger WARN() without exiting ?
>>>>> notifier_chain_cond_register() direct exit without triggering WARN() ?
>>>>
>>>> It should recover from this, if it can be detected.  The main point is
>>>> that not all apis have to be this "robust" when used within the kernel
>>>> as we do allow for the callers to know what they are doing :)
>>>>
>>> In the notifier_chain_register(), the condition ( (*nl) == n) is the same registration of the same hook.
>>>  We can intercept this situation and avoid forming a linked list ring to make the API more rob
>>
>> Once again -- yes, you CAN prevent list corruption, but you CANNOT recover the host and return it back to safe state.
>> If double register event was detected -- it means you have bug in kernel.
>>
>> Yes, you can add BUG here and crash the host immediately, but I prefer to use warning in such situations.
>>
>>>> If this does not cause any additional problems or slow downs, it's
>>>> probably fine to add.
>>>>
>>> Notifier_chain_register() is not a system hotspot function.
>>> At the same time, there is already a WARN_ONCE judgment. There is no new judgment in the new patch.
>>> It only changes the processing under the condition of (*nl) == n, which will not cause performance problems.
>>> At the same time, avoiding the formation of a link ring can make the system more robust.
>>
>> I disagree, 
>> yes, node will have correct list, but anyway node will work wrong and can crash the host in any time.
> 
> Sorry, my description is not accurate.
> 
> My patch feature does not prevent users from repeatedly registering hooks.
> But avoiding the chain ring caused by the user repeatedly registering the hook
> 
> There are no modules for duplicate registration hooks in the current system.
> But considering that not all modules are in the kernel source tree,
> In order to improve the robustness of the kernel API, we should avoid the linked list ring caused by repeated registration.
> Or in order to improve the efficiency of problem location, when the duplicate registration is checked, the system crashes directly.

Detect of duplicate registration means an unrecoverable error,
from this point of view it makes sense to replace WARN_ONCE by BUG_ON.
 
> On the other hand, the difference between notifier_chain_register() and notifier_chain_cond_register() for duplicate registrations is confusing:
> Blocking the formation of the linked list ring in notifier_chain_cond_register()
> There is no interception of the linked list ring in notifier_chain_register(), just an alarm.
> Give me the illusion: Isn't notifier_chain_register() allowed to create a linked list ring?

I'm not sure that I understood your question correctly but will try to answer.
As far as I see all callers of notifier_chain_cond_register checks return value, expect possible failure and handle it somehow.
On the other hand callers of notifier_chain_register() in many cases do not check return value and always expect success.
The goal of original WARN_ONCE -- to detect possible misuse of notifiers and it seems for me it correctly handles this task.


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

* Re: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-16 10:20                 ` Vasily Averin
@ 2019-07-16 14:07                   ` Xiaoming Ni
  2019-07-17 11:15                     ` Vasily Averin
  0 siblings, 1 reply; 15+ messages in thread
From: Xiaoming Ni @ 2019-07-16 14:07 UTC (permalink / raw)
  To: Vasily Averin, gregkh
  Cc: adobriyan, akpm, anna.schumaker, arjan, bfields, chuck.lever,
	davem, jlayton, luto, mingo, Nadia.Derbey, paulmck,
	semen.protsenko, stable, stern, tglx, torvalds, trond.myklebust,
	viresh.kumar, Huangjianhui (Alex),
	Dailei, linux-kernel, linux-nfs, netdev



On 2019/7/16 18:20, Vasily Averin wrote:
> On 7/16/19 5:00 AM, Xiaoming Ni wrote:
>> On 2019/7/15 13:38, Vasily Averin wrote:
>>> On 7/14/19 5:45 AM, Xiaoming Ni wrote:
>>>> On 2019/7/12 22:07, gregkh@linuxfoundation.org wrote:
>>>>> On Fri, Jul 12, 2019 at 09:11:57PM +0800, Xiaoming Ni wrote:
>>>>>> On 2019/7/11 21:57, Vasily Averin wrote:
>>>>>>> On 7/11/19 4:55 AM, Nixiaoming wrote:
>>>>>>>> On Wed, July 10, 2019 1:49 PM Vasily Averin wrote:
>>>>>>>>> On 7/10/19 6:09 AM, Xiaoming Ni wrote:
>>>>>>>>>> Registering the same notifier to a hook repeatedly can cause the hook
>>>>>>>>>> list to form a ring or lose other members of the list.
>>>>>>>>>
>>>>>>>>> I think is not enough to _prevent_ 2nd register attempt,
>>>>>>>>> it's enough to detect just attempt and generate warning to mark host in bad state.
>>>>>>>>>
>>>>>>>>
>>>>>>>> Duplicate registration is prevented in my patch, not just "mark host in bad state"
>>>>>>>>
>>>>>>>> Duplicate registration is checked and exited in notifier_chain_cond_register()
>>>>>>>>
>>>>>>>> Duplicate registration was checked in notifier_chain_register() but only 
>>>>>>>> the alarm was triggered without exiting. added by commit 831246570d34692e 
>>>>>>>> ("kernel/notifier.c: double register detection")
>>>>>>>>
>>>>>>>> My patch is like a combination of 831246570d34692e and notifier_chain_cond_register(),
>>>>>>>>  which triggers an alarm and exits when a duplicate registration is detected.
>>>>>>>>
>>>>>>>>> Unexpected 2nd register of the same hook most likely will lead to 2nd unregister,
>>>>>>>>> and it can lead to host crash in any time: 
>>>>>>>>> you can unregister notifier on first attempt it can be too early, it can be still in use.
>>>>>>>>> on the other hand you can never call 2nd unregister at all.
>>>>>>>>
>>>>>>>> Since the member was not added to the linked list at the time of the second registration, 
>>>>>>>> no linked list ring was formed. 
>>>>>>>> The member is released on the first unregistration and -ENOENT on the second unregistration.
>>>>>>>> After patching, the fault has been alleviated
>>>>>>>
>>>>>>> You are wrong here.
>>>>>>> 2nd notifier's registration is a pure bug, this should never happen.
>>>>>>> If you know the way to reproduce this situation -- you need to fix it. 
>>>>>>>
>>>>>>> 2nd registration can happen in 2 cases:
>>>>>>> 1) missed rollback, when someone forget to call unregister after successfull registration, 
>>>>>>> and then tried to call register again. It can lead to crash for example when according module will be unloaded.
>>>>>>> 2) some subsystem is registered twice, for example from  different namespaces.
>>>>>>> in this case unregister called during sybsystem cleanup in first namespace will incorrectly remove notifier used 
>>>>>>> in second namespace, it also can lead to unexpacted behaviour.
>>>>>>>
>>>>>> So in these two cases, is it more reasonable to trigger BUG() directly when checking for duplicate registration ?
>>>>>> But why does current notifier_chain_register() just trigger WARN() without exiting ?
>>>>>> notifier_chain_cond_register() direct exit without triggering WARN() ?
>>>>>
>>>>> It should recover from this, if it can be detected.  The main point is
>>>>> that not all apis have to be this "robust" when used within the kernel
>>>>> as we do allow for the callers to know what they are doing :)
>>>>>
>>>> In the notifier_chain_register(), the condition ( (*nl) == n) is the same registration of the same hook.
>>>>  We can intercept this situation and avoid forming a linked list ring to make the API more rob
>>>
>>> Once again -- yes, you CAN prevent list corruption, but you CANNOT recover the host and return it back to safe state.
>>> If double register event was detected -- it means you have bug in kernel.
>>>
>>> Yes, you can add BUG here and crash the host immediately, but I prefer to use warning in such situations.
>>>
>>>>> If this does not cause any additional problems or slow downs, it's
>>>>> probably fine to add.
>>>>>
>>>> Notifier_chain_register() is not a system hotspot function.
>>>> At the same time, there is already a WARN_ONCE judgment. There is no new judgment in the new patch.
>>>> It only changes the processing under the condition of (*nl) == n, which will not cause performance problems.
>>>> At the same time, avoiding the formation of a link ring can make the system more robust.
>>>
>>> I disagree, 
>>> yes, node will have correct list, but anyway node will work wrong and can crash the host in any time.
>>
>> Sorry, my description is not accurate.
>>
>> My patch feature does not prevent users from repeatedly registering hooks.
>> But avoiding the chain ring caused by the user repeatedly registering the hook
>>
>> There are no modules for duplicate registration hooks in the current system.
>> But considering that not all modules are in the kernel source tree,
>> In order to improve the robustness of the kernel API, we should avoid the linked list ring caused by repeated registration.
>> Or in order to improve the efficiency of problem location, when the duplicate registration is checked, the system crashes directly.
> 
> Detect of duplicate registration means an unrecoverable error,
> from this point of view it makes sense to replace WARN_ONCE by BUG_ON.
>  
>> On the other hand, the difference between notifier_chain_register() and notifier_chain_cond_register() for duplicate registrations is confusing:
>> Blocking the formation of the linked list ring in notifier_chain_cond_register()
>> There is no interception of the linked list ring in notifier_chain_register(), just an alarm.
>> Give me the illusion: Isn't notifier_chain_register() allowed to create a linked list ring?
> 
> I'm not sure that I understood your question correctly but will try to answer.
> As far as I see all callers of notifier_chain_cond_register checks return value, expect possible failure and handle it somehow.
> On the other hand callers of notifier_chain_register() in many cases do not check return value and always expect success.
> The goal of original WARN_ONCE -- to detect possible misuse of notifiers and it seems for me it correctly handles this task.
>
Notifier_chain_cond_register() has only one return value: 0
At the same time, it is only called by blocking_notifier_chain_cond_register().
In the function comment of blocking_notifier_chain_cond_register there is " Currently always returns zero."
Therefore, the user cannot check whether the hook has duplicate registration or other errors by checking the return value.

If the interceptor list ring is added to notifier_chain_register(), notifier_chain_register()
 And notifier_chain_cond_register() becomes redundant code, we can delete one of them

> 
> .
> 


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

* Re: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-16 14:07                   ` Xiaoming Ni
@ 2019-07-17 11:15                     ` Vasily Averin
  2019-09-10  3:57                       ` Xiaoming Ni
  0 siblings, 1 reply; 15+ messages in thread
From: Vasily Averin @ 2019-07-17 11:15 UTC (permalink / raw)
  To: Xiaoming Ni, gregkh
  Cc: adobriyan, akpm, anna.schumaker, arjan, bfields, chuck.lever,
	davem, jlayton, luto, mingo, Nadia.Derbey, paulmck,
	semen.protsenko, stable, stern, tglx, torvalds, trond.myklebust,
	viresh.kumar, Huangjianhui (Alex),
	Dailei, linux-kernel, linux-nfs, netdev

On 7/16/19 5:07 PM, Xiaoming Ni wrote:
> On 2019/7/16 18:20, Vasily Averin wrote:
>> On 7/16/19 5:00 AM, Xiaoming Ni wrote:
>>> On 2019/7/15 13:38, Vasily Averin wrote:
>>>> On 7/14/19 5:45 AM, Xiaoming Ni wrote:
>>>>> On 2019/7/12 22:07, gregkh@linuxfoundation.org wrote:
>>>>>> On Fri, Jul 12, 2019 at 09:11:57PM +0800, Xiaoming Ni wrote:
>>>>>>> On 2019/7/11 21:57, Vasily Averin wrote:
>>>>>>>> On 7/11/19 4:55 AM, Nixiaoming wrote:
>>>>>>>>> On Wed, July 10, 2019 1:49 PM Vasily Averin wrote:
>>>>>>>>>> On 7/10/19 6:09 AM, Xiaoming Ni wrote:
>>>>>>>>>>> Registering the same notifier to a hook repeatedly can cause the hook
>>>>>>>>>>> list to form a ring or lose other members of the list.
>>>>>>>>>>
>>>>>>>>>> I think is not enough to _prevent_ 2nd register attempt,
>>>>>>>>>> it's enough to detect just attempt and generate warning to mark host in bad state.
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Duplicate registration is prevented in my patch, not just "mark host in bad state"
>>>>>>>>>
>>>>>>>>> Duplicate registration is checked and exited in notifier_chain_cond_register()
>>>>>>>>>
>>>>>>>>> Duplicate registration was checked in notifier_chain_register() but only 
>>>>>>>>> the alarm was triggered without exiting. added by commit 831246570d34692e 
>>>>>>>>> ("kernel/notifier.c: double register detection")
>>>>>>>>>
>>>>>>>>> My patch is like a combination of 831246570d34692e and notifier_chain_cond_register(),
>>>>>>>>>  which triggers an alarm and exits when a duplicate registration is detected.
>>>>>>>>>
>>>>>>>>>> Unexpected 2nd register of the same hook most likely will lead to 2nd unregister,
>>>>>>>>>> and it can lead to host crash in any time: 
>>>>>>>>>> you can unregister notifier on first attempt it can be too early, it can be still in use.
>>>>>>>>>> on the other hand you can never call 2nd unregister at all.
>>>>>>>>>
>>>>>>>>> Since the member was not added to the linked list at the time of the second registration, 
>>>>>>>>> no linked list ring was formed. 
>>>>>>>>> The member is released on the first unregistration and -ENOENT on the second unregistration.
>>>>>>>>> After patching, the fault has been alleviated
>>>>>>>>
>>>>>>>> You are wrong here.
>>>>>>>> 2nd notifier's registration is a pure bug, this should never happen.
>>>>>>>> If you know the way to reproduce this situation -- you need to fix it. 
>>>>>>>>
>>>>>>>> 2nd registration can happen in 2 cases:
>>>>>>>> 1) missed rollback, when someone forget to call unregister after successfull registration, 
>>>>>>>> and then tried to call register again. It can lead to crash for example when according module will be unloaded.
>>>>>>>> 2) some subsystem is registered twice, for example from  different namespaces.
>>>>>>>> in this case unregister called during sybsystem cleanup in first namespace will incorrectly remove notifier used 
>>>>>>>> in second namespace, it also can lead to unexpacted behaviour.
>>>>>>>>
>>>>>>> So in these two cases, is it more reasonable to trigger BUG() directly when checking for duplicate registration ?
>>>>>>> But why does current notifier_chain_register() just trigger WARN() without exiting ?
>>>>>>> notifier_chain_cond_register() direct exit without triggering WARN() ?
>>>>>>
>>>>>> It should recover from this, if it can be detected.  The main point is
>>>>>> that not all apis have to be this "robust" when used within the kernel
>>>>>> as we do allow for the callers to know what they are doing :)
>>>>>>
>>>>> In the notifier_chain_register(), the condition ( (*nl) == n) is the same registration of the same hook.
>>>>>  We can intercept this situation and avoid forming a linked list ring to make the API more rob
>>>>
>>>> Once again -- yes, you CAN prevent list corruption, but you CANNOT recover the host and return it back to safe state.
>>>> If double register event was detected -- it means you have bug in kernel.
>>>>
>>>> Yes, you can add BUG here and crash the host immediately, but I prefer to use warning in such situations.
>>>>
>>>>>> If this does not cause any additional problems or slow downs, it's
>>>>>> probably fine to add.
>>>>>>
>>>>> Notifier_chain_register() is not a system hotspot function.
>>>>> At the same time, there is already a WARN_ONCE judgment. There is no new judgment in the new patch.
>>>>> It only changes the processing under the condition of (*nl) == n, which will not cause performance problems.
>>>>> At the same time, avoiding the formation of a link ring can make the system more robust.
>>>>
>>>> I disagree, 
>>>> yes, node will have correct list, but anyway node will work wrong and can crash the host in any time.
>>>
>>> Sorry, my description is not accurate.
>>>
>>> My patch feature does not prevent users from repeatedly registering hooks.
>>> But avoiding the chain ring caused by the user repeatedly registering the hook
>>>
>>> There are no modules for duplicate registration hooks in the current system.
>>> But considering that not all modules are in the kernel source tree,
>>> In order to improve the robustness of the kernel API, we should avoid the linked list ring caused by repeated registration.
>>> Or in order to improve the efficiency of problem location, when the duplicate registration is checked, the system crashes directly.
>>
>> Detect of duplicate registration means an unrecoverable error,
>> from this point of view it makes sense to replace WARN_ONCE by BUG_ON.
>>  
>>> On the other hand, the difference between notifier_chain_register() and notifier_chain_cond_register() for duplicate registrations is confusing:
>>> Blocking the formation of the linked list ring in notifier_chain_cond_register()
>>> There is no interception of the linked list ring in notifier_chain_register(), just an alarm.
>>> Give me the illusion: Isn't notifier_chain_register() allowed to create a linked list ring?
>>
>> I'm not sure that I understood your question correctly but will try to answer.
>> As far as I see all callers of notifier_chain_cond_register checks return value, expect possible failure and handle it somehow.
>> On the other hand callers of notifier_chain_register() in many cases do not check return value and always expect success.
>> The goal of original WARN_ONCE -- to detect possible misuse of notifiers and it seems for me it correctly handles this task.
>>
> Notifier_chain_cond_register() has only one return value: 0

It looks wrong for me.

> At the same time, it is only called by blocking_notifier_chain_cond_register().
> In the function comment of blocking_notifier_chain_cond_register there is " Currently always returns zero."
> Therefore, the user cannot check whether the hook has duplicate registration or other errors by checking the return value.

I think notifier_chain_cond_register can be changed to return error.
It is safe now, all its in-tree callers checks return value and can properly react on such error.

On the other hand, in all cases notifier_chain_cond_register are  __init functions, 
they are called once only and double registration seems is impossible here:
even if some old notifier was lost and was not properly unregistered, 
new one will have another address.
And even if these addresses was equal -- it is critical error 
and I prefer to generate warning instead of silent failure of module load.

> If the interceptor list ring is added to notifier_chain_register(), notifier_chain_register()
>  And notifier_chain_cond_register() becomes redundant code, we can delete one of them

Yes, I'm agree, at present there are no difference between
notifier_chain_cond_register() and notifier_chain_register()

Question is -- how to improve it.
You propose to remove notifier_chain_cond_register() by some way.
Another option is return an error, for some abstract callers who expect possible double registration.

Frankly speaking I prefer second one,
however because of kernel do not have any such callers right now seems you are right, 
and we can delete notifier_chain_cond_register().

So let me finally accept your patch-set.

Thank you,
	Vasily Averin

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

* Re: [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration
  2019-07-17 11:15                     ` Vasily Averin
@ 2019-09-10  3:57                       ` Xiaoming Ni
  0 siblings, 0 replies; 15+ messages in thread
From: Xiaoming Ni @ 2019-09-10  3:57 UTC (permalink / raw)
  To: Vasily Averin, gregkh
  Cc: adobriyan, akpm, anna.schumaker, arjan, bfields, chuck.lever,
	davem, jlayton, luto, mingo, Nadia.Derbey, paulmck,
	semen.protsenko, stable, stern, tglx, torvalds, trond.myklebust,
	viresh.kumar, Huangjianhui (Alex),
	Dailei, linux-kernel, linux-nfs, netdev


On 2019/7/17 19:15, Vasily Averin wrote:
> On 7/16/19 5:07 PM, Xiaoming Ni wrote:
>> On 2019/7/16 18:20, Vasily Averin wrote:
>>> On 7/16/19 5:00 AM, Xiaoming Ni wrote:
>>>> On 2019/7/15 13:38, Vasily Averin wrote:
>>>>> On 7/14/19 5:45 AM, Xiaoming Ni wrote:
>>>>>> On 2019/7/12 22:07, gregkh@linuxfoundation.org wrote:
>>>>>>> On Fri, Jul 12, 2019 at 09:11:57PM +0800, Xiaoming Ni wrote:
>>>>>>>> On 2019/7/11 21:57, Vasily Averin wrote:
>>>>>>>>> On 7/11/19 4:55 AM, Nixiaoming wrote:
>>>>>>>>>> On Wed, July 10, 2019 1:49 PM Vasily Averin wrote:
>>>>>>>>>>> On 7/10/19 6:09 AM, Xiaoming Ni wrote:
....
...
>>>>>>>> So in these two cases, is it more reasonable to trigger BUG() directly when checking for duplicate registration ?
>>>>>>>> But why does current notifier_chain_register() just trigger WARN() without exiting ?
>>>>>>>> notifier_chain_cond_register() direct exit without triggering WARN() ?
>>>>>>>
>>>>>>> It should recover from this, if it can be detected.  The main point is
>>>>>>> that not all apis have to be this "robust" when used within the kernel
>>>>>>> as we do allow for the callers to know what they are doing :)
>>>>>>>
>>>>>> In the notifier_chain_register(), the condition ( (*nl) == n) is the same registration of the same hook.
>>>>>>  We can intercept this situation and avoid forming a linked list ring to make the API more rob
...
...

> Yes, I'm agree, at present there are no difference between
> notifier_chain_cond_register() and notifier_chain_register()
> 
> Question is -- how to improve it.
> You propose to remove notifier_chain_cond_register() by some way.
> Another option is return an error, for some abstract callers who expect possible double registration.
> 
> Frankly speaking I prefer second one,
> however because of kernel do not have any such callers right now seems you are right, 
> and we can delete notifier_chain_cond_register().
> 
> So let me finally accept your patch-set.
> 
> Thank you,
> 	Vasily Averin
> 
> .
>

Dear Greg Kroah-Hartman
is there any other opinion on this patch set?
can you pick this series?

thanks
	Xiaoming Ni


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

end of thread, other threads:[~2019-09-10  3:58 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-10  3:09 [PATCH v3 0/3] kernel/notifier.c: avoid duplicate registration Xiaoming Ni
2019-07-10  5:49 ` Vasily Averin
2019-07-11  1:55   ` Nixiaoming
2019-07-11 13:57     ` Vasily Averin
2019-07-12 13:11       ` Xiaoming Ni
2019-07-12 14:07         ` gregkh
2019-07-14  2:45           ` Xiaoming Ni
2019-07-15  5:38             ` Vasily Averin
2019-07-16  2:00               ` Xiaoming Ni
2019-07-16 10:20                 ` Vasily Averin
2019-07-16 14:07                   ` Xiaoming Ni
2019-07-17 11:15                     ` Vasily Averin
2019-09-10  3:57                       ` Xiaoming Ni
2019-07-10  5:56 ` Greg KH
2019-07-11  1:32   ` Nixiaoming

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).