From: ebiederm@xmission.com (Eric W. Biederman)
To: Boris Sukholitko <boris.sukholitko@broadcom.com>
Cc: linux-fsdevel@vger.kernel.org,
Luis Chamberlain <mcgrof@kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
keescook@chromium.org, yzaikin@google.com
Subject: Re: [PATCH] get_subdir: do not drop new subdir if returning it
Date: Mon, 01 Jun 2020 10:01:18 -0500 [thread overview]
Message-ID: <871rmyn83l.fsf@x220.int.ebiederm.org> (raw)
In-Reply-To: <20200531112444.GA25164@noodle> (Boris Sukholitko's message of "Sun, 31 May 2020 14:24:44 +0300")
Boris Sukholitko <boris.sukholitko@broadcom.com> writes:
> In testing of our kernel (based on 4.19, tainted, sorry!) on our aarch64 based hardware
> we've come upon the following oops (lightly edited to omit irrelevant
> details):
I don't doubt you are seeing problems.
I need to refresh my knowledge of that code to know for certain but I am
not yet convinced this is the problem.
I don't see any reason that the assertion your code makes would
necessarily be a problem.
Why can't a directory only have a single entry?
I am not saying you are wrong. Just that I have not looked enough to
verify there is an invariant being violated there.
A very confusiong part of this situation is the fact he code has been
stable for quite a while. I would have suspected someone's fuzzer to
trigger problems on something other than aarch64. Especially if
registering and unregistering a network device is enough to cause this.
As that can be performed as non-root.
Eric
> The crash is in the call to count_subheaders(header->ctl_table_arg).
>
> Although the header (being in x19 == 0xffffffc01f0d6030) looks like a
> normal kernel pointer, ctl_table_arg (x0 == 0x0000000000007a12) looks
> invalid.
>
> Trying to find the issue, we've started tracing header allocation being
> done by kzalloc in __register_sysctl_table and header freeing being done
> in drop_sysctl_table.
>
> Then we've noticed headers being freed which where not allocated before.
> The faulty freeing was done on parent->header at the end of
> drop_sysctl_table.
>
> The invariant on __register_sysctl_table seems to be that non-empty
> parent dir should have its header.nreg > 1. By failing this invariant
> (see WARN_ON hunk in the patch) we've come upon the conclusion that
> something is fishy with nreg counting.
>
> The root cause seems to be dropping new subdir in get_subdir function.
> Here are the new subdir adventures leading to the invariant failure
> above:
>
> 1. new subdir comes to being with nreg == 1
> 2. the nreg is being incremented in the found clause, nreg == 2
> 3. nreg is being decremented by the if (new) drop, nreg == 1
> 4. coming out of get_subdir, insert_header increments nreg: nreg == 2
> 5. nreg is being decremented at the end of __register_sysctl_table
>
> The fix seems to be avoiding step 3 if new subdir is the one being
> returned. The patch does this and also adds warning for the nreg
> invariant.
> ---
> fs/proc/proc_sysctl.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> index b6f5d459b087..12fa5803dcb3 100644
> --- a/fs/proc/proc_sysctl.c
> +++ b/fs/proc/proc_sysctl.c
> @@ -1010,7 +1010,7 @@ static struct ctl_dir *get_subdir(struct ctl_dir *dir,
> namelen, namelen, name, PTR_ERR(subdir));
> }
> drop_sysctl_table(&dir->header);
> - if (new)
> + if (new && new != subdir)
> drop_sysctl_table(&new->header);
> spin_unlock(&sysctl_lock);
> return subdir;
> @@ -1334,6 +1334,7 @@ struct ctl_table_header *__register_sysctl_table(
> goto fail_put_dir_locked;
>
> drop_sysctl_table(&dir->header);
> + WARN_ON(dir->header.nreg < 2);
> spin_unlock(&sysctl_lock);
>
> return header;
prev parent reply other threads:[~2020-06-01 15:05 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-31 11:24 [PATCH] get_subdir: do not drop new subdir if returning it Boris Sukholitko
2020-06-01 15:01 ` Eric W. Biederman [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=871rmyn83l.fsf@x220.int.ebiederm.org \
--to=ebiederm@xmission.com \
--cc=akpm@linux-foundation.org \
--cc=boris.sukholitko@broadcom.com \
--cc=keescook@chromium.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=mcgrof@kernel.org \
--cc=yzaikin@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.