* [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 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).