* [PATCH] fs: Handle register_shrinker failure
@ 2017-03-24 7:55 Nikolay Borisov
2017-04-06 19:21 ` Goldwyn Rodrigues
2017-04-28 4:30 ` Al Viro
0 siblings, 2 replies; 5+ messages in thread
From: Nikolay Borisov @ 2017-03-24 7:55 UTC (permalink / raw)
To: dvyukov; +Cc: viro, linux-fsdevel, linux-kernel, syzkaller, Nikolay Borisov
register_shrinker allocates dynamic memory and thus is susceptible to failures
under low-memory situation. Currently,get_userns ignores the return value of
register_shrinker, potentially exposing not fully initialised object. This
can lead to a NULL-ptr deref everytime shrinker->nr_deferred is referenced.
Fix this by failing to register the filesystem in case there is not enough
memory to fully construct the shrinker object.
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
---
fs/super.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/fs/super.c b/fs/super.c
index b8b6a086c03b..964b18447c92 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -518,7 +518,19 @@ struct super_block *sget_userns(struct file_system_type *type,
hlist_add_head(&s->s_instances, &type->fs_supers);
spin_unlock(&sb_lock);
get_filesystem(type);
- register_shrinker(&s->s_shrink);
+ err = register_shrinker(&s->s_shrink);
+ if (err) {
+ spin_lock(&sb_lock);
+ list_del(&s->s_list);
+ hlist_del(&s->s_instances);
+ spin_unlock(&sb_lock);
+
+ up_write(&s->s_umount);
+ destroy_super(s);
+ put_filesystem(type);
+ return ERR_PTR(err);
+ }
+
return s;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH] fs: Handle register_shrinker failure
2017-03-23 14:14 fs: GPF in deactivate_locked_super Dmitry Vyukov
@ 2017-03-24 7:57 ` Nikolay Borisov
0 siblings, 0 replies; 5+ messages in thread
From: Nikolay Borisov @ 2017-03-24 7:57 UTC (permalink / raw)
To: dvyukov; +Cc: viro, linux-fsdevel, linux-kernel, syzkaller, Nikolay Borisov
register_shrinker allocates dynamic memory and thus is susceptible to failures
under low-memory situation. Currently,get_userns ignores the return value of
register_shrinker, potentially exposing not fully initialised object. This
can lead to a NULL-ptr deref everytime shrinker->nr_deferred is referenced.
Fix this by failing to register the filesystem in case there is not enough
memory to fully construct the shrinker object.
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
---
fs/super.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/fs/super.c b/fs/super.c
index b8b6a086c03b..964b18447c92 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -518,7 +518,19 @@ struct super_block *sget_userns(struct file_system_type *type,
hlist_add_head(&s->s_instances, &type->fs_supers);
spin_unlock(&sb_lock);
get_filesystem(type);
- register_shrinker(&s->s_shrink);
+ err = register_shrinker(&s->s_shrink);
+ if (err) {
+ spin_lock(&sb_lock);
+ list_del(&s->s_list);
+ hlist_del(&s->s_instances);
+ spin_unlock(&sb_lock);
+
+ up_write(&s->s_umount);
+ destroy_super(s);
+ put_filesystem(type);
+ return ERR_PTR(err);
+ }
+
return s;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] fs: Handle register_shrinker failure
2017-03-24 7:55 [PATCH] fs: Handle register_shrinker failure Nikolay Borisov
@ 2017-04-06 19:21 ` Goldwyn Rodrigues
2017-04-28 4:30 ` Al Viro
1 sibling, 0 replies; 5+ messages in thread
From: Goldwyn Rodrigues @ 2017-04-06 19:21 UTC (permalink / raw)
To: Nikolay Borisov, dvyukov; +Cc: viro, linux-fsdevel, linux-kernel, syzkaller
On 03/24/2017 02:55 AM, Nikolay Borisov wrote:
> register_shrinker allocates dynamic memory and thus is susceptible to failures
> under low-memory situation. Currently,get_userns ignores the return value of
> register_shrinker, potentially exposing not fully initialised object. This
> can lead to a NULL-ptr deref everytime shrinker->nr_deferred is referenced.
>
> Fix this by failing to register the filesystem in case there is not enough
> memory to fully construct the shrinker object.
>
> Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Looks good, though the situation seems rare.
Reviewed-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
> ---
> fs/super.c | 14 +++++++++++++-
> 1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/fs/super.c b/fs/super.c
> index b8b6a086c03b..964b18447c92 100644
> --- a/fs/super.c
> +++ b/fs/super.c
> @@ -518,7 +518,19 @@ struct super_block *sget_userns(struct file_system_type *type,
> hlist_add_head(&s->s_instances, &type->fs_supers);
> spin_unlock(&sb_lock);
> get_filesystem(type);
> - register_shrinker(&s->s_shrink);
> + err = register_shrinker(&s->s_shrink);
> + if (err) {
> + spin_lock(&sb_lock);
> + list_del(&s->s_list);
> + hlist_del(&s->s_instances);
> + spin_unlock(&sb_lock);
> +
> + up_write(&s->s_umount);
> + destroy_super(s);
> + put_filesystem(type);
> + return ERR_PTR(err);
> + }
> +
> return s;
> }
>
>
--
Goldwyn
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fs: Handle register_shrinker failure
2017-03-24 7:55 [PATCH] fs: Handle register_shrinker failure Nikolay Borisov
2017-04-06 19:21 ` Goldwyn Rodrigues
@ 2017-04-28 4:30 ` Al Viro
2017-04-28 5:34 ` Al Viro
1 sibling, 1 reply; 5+ messages in thread
From: Al Viro @ 2017-04-28 4:30 UTC (permalink / raw)
To: Nikolay Borisov; +Cc: dvyukov, linux-fsdevel, linux-kernel, syzkaller
On Fri, Mar 24, 2017 at 09:55:40AM +0200, Nikolay Borisov wrote:
> register_shrinker allocates dynamic memory and thus is susceptible to failures
> under low-memory situation. Currently,get_userns ignores the return value of
> register_shrinker, potentially exposing not fully initialised object. This
> can lead to a NULL-ptr deref everytime shrinker->nr_deferred is referenced.
>
> Fix this by failing to register the filesystem in case there is not enough
> memory to fully construct the shrinker object.
>
> Signed-off-by: Nikolay Borisov <nborisov@suse.com>
> ---
> fs/super.c | 14 +++++++++++++-
> 1 file changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/fs/super.c b/fs/super.c
> index b8b6a086c03b..964b18447c92 100644
> --- a/fs/super.c
> +++ b/fs/super.c
> @@ -518,7 +518,19 @@ struct super_block *sget_userns(struct file_system_type *type,
> hlist_add_head(&s->s_instances, &type->fs_supers);
> spin_unlock(&sb_lock);
> get_filesystem(type);
> - register_shrinker(&s->s_shrink);
> + err = register_shrinker(&s->s_shrink);
> + if (err) {
> + spin_lock(&sb_lock);
> + list_del(&s->s_list);
> + hlist_del(&s->s_instances);
> + spin_unlock(&sb_lock);
> +
> + up_write(&s->s_umount);
> + destroy_super(s);
> + put_filesystem(type);
> + return ERR_PTR(err);
I really don't like that. Your "remove it from all lists and pray that
nobody has picked a reference of any kind" at the very least needs a careful
written proof of correctness. AFAICS, somebody might've found it on the
list and attempted to grab ->s_umount (grab_super() from another thread
calling sget()). Then they'd block until your up_write() in there and
bugger the system up trying to play with ->s_umount in the object you've
freed.
NAK. Yes, the bug is real, but this is not a solution.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fs: Handle register_shrinker failure
2017-04-28 4:30 ` Al Viro
@ 2017-04-28 5:34 ` Al Viro
0 siblings, 0 replies; 5+ messages in thread
From: Al Viro @ 2017-04-28 5:34 UTC (permalink / raw)
To: Nikolay Borisov
Cc: dvyukov, linux-fsdevel, linux-kernel, syzkaller, Dave Chinner
On Fri, Apr 28, 2017 at 05:30:46AM +0100, Al Viro wrote:
> I really don't like that. Your "remove it from all lists and pray that
> nobody has picked a reference of any kind" at the very least needs a careful
> written proof of correctness. AFAICS, somebody might've found it on the
> list and attempted to grab ->s_umount (grab_super() from another thread
> calling sget()). Then they'd block until your up_write() in there and
> bugger the system up trying to play with ->s_umount in the object you've
> freed.
>
> NAK. Yes, the bug is real, but this is not a solution.
Why do we register it that early, anyway? super_cache_scan() won't do
anything until we are done with setting the sucker up and dropped ->s_umount.
How about we initialize ->s_shrink.list in alloc_super(), have
deactivate_locked_super() call unregister_shrinker() only if list_empty(...)
and have mount_fs() do
error = register_shrinker(&sb->s_shrink);
if (error)
goto out_sb;
sb->s_flags |= MS_BORN;
error = security_sb_kern_mount(sb, flags, secdata);
if (error)
goto out_sb;
Folks? Am I missing something subtle here?
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2017-04-28 5:34 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-03-24 7:55 [PATCH] fs: Handle register_shrinker failure Nikolay Borisov
2017-04-06 19:21 ` Goldwyn Rodrigues
2017-04-28 4:30 ` Al Viro
2017-04-28 5:34 ` Al Viro
-- strict thread matches above, loose matches on Subject: below --
2017-03-23 14:14 fs: GPF in deactivate_locked_super Dmitry Vyukov
2017-03-24 7:57 ` [PATCH] fs: Handle register_shrinker failure Nikolay Borisov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.