From: Dave Martin <Dave.Martin@arm.com>
To: Julien Grall <julien.grall@arm.com>
Cc: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>,
Catalin Marinas <catalin.marinas@arm.com>,
linux-kernel@vger.kernel.org,
Masayoshi Mizuma <msys.mizuma@gmail.com>,
Will Deacon <will@kernel.org>,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v2] arm64/sve: Fix wrong free for task->thread.sve_state
Date: Mon, 30 Sep 2019 14:02:46 +0100 [thread overview]
Message-ID: <20190930130244.GT27757@arm.com> (raw)
In-Reply-To: <b3dba44e-216c-f060-be8e-1c44bdc61576@arm.com>
On Mon, Sep 30, 2019 at 01:23:18PM +0100, Julien Grall wrote:
> Hi,
>
> On 27/09/2019 16:39, Masayoshi Mizuma wrote:
> >From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
> >
> >The system which has SVE feature crashed because of
> >the memory pointed by task->thread.sve_state was destroyed
> >by someone.
> >
> >That is because sve_state is freed while the forking the
> >child process. The child process has the pointer of sve_state
> >which is same as the parent's because the child's task_struct
> >is copied from the parent's one. If the copy_process()
> >fails as an error on somewhere, for example, copy_creds(),
> >then the sve_state is freed even if the parent is alive.
> >The flow is as follows.
> >
> >copy_process
> > p = dup_task_struct
> > => arch_dup_task_struct
> > *dst = *src; // copy the entire region.
> >:
> > retval = copy_creds
> > if (retval < 0)
> > goto bad_fork_free;
> >:
> >bad_fork_free:
> >...
> > delayed_free_task(p);
> > => free_task
> > => arch_release_task_struct
> > => fpsimd_release_task
> > => __sve_free
> > => kfree(task->thread.sve_state);
> > // free the parent's sve_state
> >
> >Move child's sve_state = NULL and clearing TIF_SVE flag
> >to arch_dup_task_struct() so that the child doesn't free the
> >parent's one.
> >
> >Cc: stable@vger.kernel.org
> >Fixes: bc0ee4760364 ("arm64/sve: Core task context handling")
>
> Looking at the log, it looks like THREAD_INFO_IN_TASK was selected before
> the bc0ee4760364. So it should be fine to backport for all the Linux tree
> contain this commit.
>
> >Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
> >Reported-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
> >Suggested-by: Dave Martin <Dave.Martin@arm.com>
>
> I have tested the patch and can confirm that double-free disappeared after
> the patch is applied:
>
> Tested-by: Julien Grall <julien.grall@arm.com>
Good to have that confirmed -- thanks for verifying.
[...]
> >---
> > arch/arm64/kernel/process.c | 21 ++++-----------------
> > 1 file changed, 4 insertions(+), 17 deletions(-)
> >
> >diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> >index f674f28df..6937f5935 100644
> >--- a/arch/arm64/kernel/process.c
> >+++ b/arch/arm64/kernel/process.c
> >@@ -323,22 +323,16 @@ void arch_release_task_struct(struct task_struct *tsk)
> > fpsimd_release_task(tsk);
> > }
> >-/*
> >- * src and dst may temporarily have aliased sve_state after task_struct
> >- * is copied. We cannot fix this properly here, because src may have
> >- * live SVE state and dst's thread_info may not exist yet, so tweaking
> >- * either src's or dst's TIF_SVE is not safe.
> >- *
> >- * The unaliasing is done in copy_thread() instead. This works because
> >- * dst is not schedulable or traceable until both of these functions
> >- * have been called.
> >- */
>
> It would be good to explain in the commit message why tweaking "dst" in
> arch_dup_task_struct() is fine.
>
> From my understanding, Arm64 used to have thread_info on the stack. So it
> would not be possible to clear TIF_SVE until the stack is initialized.
>
> Now that the thread_info is part of the task, it should be valid to modify
> the flag from arch_dup_task_struct().
>
> Note that technically, TIF_SVE does not need to be cleared from
> arch_dup_task_struct(). It could also be done from copy_thread(). But it is
> easier to keep the both changes together.
>
> > int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
> > {
> > if (current->mm)
> > fpsimd_preserve_current_state();
> > *dst = *src;
Ack, some more explanation would be a good idea here.
Maybe the following comments are sufficient?
/* We rely on the above assingment to initialise dst's thread_flags: */
> >+ BUILD_BUG_ON(!IS_ENABLED(CONFIG_THREAD_INFO_IN_TASK));
>
and
/*
* Detach src's sve_state (if any) from dst so that it does not
* get erroneously used or freed prematurely. dst's sve_state
* will be allocated on demand later on if dst uses SVE.
* For consistency, also clear TIF_SVE here: this could be done
* later in copy_process(), but to avoid tripping up future
* maintainers it is best not to leave TIF_SVE and sve_state in
* an inconsistent state, even temporarily.
*/
> >+ dst->thread.sve_state = NULL;
> >+ clear_tsk_thread_flag(dst, TIF_SVE);
(TIF_SVE should not usually be set in the first place of course, since
we are in a fork() or clone() syscall in src. This may not be true if
a task is created using kernel_thread() while running in the context of
some user task that entered the kernel due to a trap or syscall --
though probably nobody should be doing that.)
[...]
Cheers
---DavE
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
WARNING: multiple messages have this Message-ID (diff)
From: Dave Martin <Dave.Martin@arm.com>
To: Julien Grall <julien.grall@arm.com>
Cc: Masayoshi Mizuma <msys.mizuma@gmail.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
linux-arm-kernel@lists.infradead.org,
Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] arm64/sve: Fix wrong free for task->thread.sve_state
Date: Mon, 30 Sep 2019 14:02:46 +0100 [thread overview]
Message-ID: <20190930130244.GT27757@arm.com> (raw)
In-Reply-To: <b3dba44e-216c-f060-be8e-1c44bdc61576@arm.com>
On Mon, Sep 30, 2019 at 01:23:18PM +0100, Julien Grall wrote:
> Hi,
>
> On 27/09/2019 16:39, Masayoshi Mizuma wrote:
> >From: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
> >
> >The system which has SVE feature crashed because of
> >the memory pointed by task->thread.sve_state was destroyed
> >by someone.
> >
> >That is because sve_state is freed while the forking the
> >child process. The child process has the pointer of sve_state
> >which is same as the parent's because the child's task_struct
> >is copied from the parent's one. If the copy_process()
> >fails as an error on somewhere, for example, copy_creds(),
> >then the sve_state is freed even if the parent is alive.
> >The flow is as follows.
> >
> >copy_process
> > p = dup_task_struct
> > => arch_dup_task_struct
> > *dst = *src; // copy the entire region.
> >:
> > retval = copy_creds
> > if (retval < 0)
> > goto bad_fork_free;
> >:
> >bad_fork_free:
> >...
> > delayed_free_task(p);
> > => free_task
> > => arch_release_task_struct
> > => fpsimd_release_task
> > => __sve_free
> > => kfree(task->thread.sve_state);
> > // free the parent's sve_state
> >
> >Move child's sve_state = NULL and clearing TIF_SVE flag
> >to arch_dup_task_struct() so that the child doesn't free the
> >parent's one.
> >
> >Cc: stable@vger.kernel.org
> >Fixes: bc0ee4760364 ("arm64/sve: Core task context handling")
>
> Looking at the log, it looks like THREAD_INFO_IN_TASK was selected before
> the bc0ee4760364. So it should be fine to backport for all the Linux tree
> contain this commit.
>
> >Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
> >Reported-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
> >Suggested-by: Dave Martin <Dave.Martin@arm.com>
>
> I have tested the patch and can confirm that double-free disappeared after
> the patch is applied:
>
> Tested-by: Julien Grall <julien.grall@arm.com>
Good to have that confirmed -- thanks for verifying.
[...]
> >---
> > arch/arm64/kernel/process.c | 21 ++++-----------------
> > 1 file changed, 4 insertions(+), 17 deletions(-)
> >
> >diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> >index f674f28df..6937f5935 100644
> >--- a/arch/arm64/kernel/process.c
> >+++ b/arch/arm64/kernel/process.c
> >@@ -323,22 +323,16 @@ void arch_release_task_struct(struct task_struct *tsk)
> > fpsimd_release_task(tsk);
> > }
> >-/*
> >- * src and dst may temporarily have aliased sve_state after task_struct
> >- * is copied. We cannot fix this properly here, because src may have
> >- * live SVE state and dst's thread_info may not exist yet, so tweaking
> >- * either src's or dst's TIF_SVE is not safe.
> >- *
> >- * The unaliasing is done in copy_thread() instead. This works because
> >- * dst is not schedulable or traceable until both of these functions
> >- * have been called.
> >- */
>
> It would be good to explain in the commit message why tweaking "dst" in
> arch_dup_task_struct() is fine.
>
> From my understanding, Arm64 used to have thread_info on the stack. So it
> would not be possible to clear TIF_SVE until the stack is initialized.
>
> Now that the thread_info is part of the task, it should be valid to modify
> the flag from arch_dup_task_struct().
>
> Note that technically, TIF_SVE does not need to be cleared from
> arch_dup_task_struct(). It could also be done from copy_thread(). But it is
> easier to keep the both changes together.
>
> > int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
> > {
> > if (current->mm)
> > fpsimd_preserve_current_state();
> > *dst = *src;
Ack, some more explanation would be a good idea here.
Maybe the following comments are sufficient?
/* We rely on the above assingment to initialise dst's thread_flags: */
> >+ BUILD_BUG_ON(!IS_ENABLED(CONFIG_THREAD_INFO_IN_TASK));
>
and
/*
* Detach src's sve_state (if any) from dst so that it does not
* get erroneously used or freed prematurely. dst's sve_state
* will be allocated on demand later on if dst uses SVE.
* For consistency, also clear TIF_SVE here: this could be done
* later in copy_process(), but to avoid tripping up future
* maintainers it is best not to leave TIF_SVE and sve_state in
* an inconsistent state, even temporarily.
*/
> >+ dst->thread.sve_state = NULL;
> >+ clear_tsk_thread_flag(dst, TIF_SVE);
(TIF_SVE should not usually be set in the first place of course, since
we are in a fork() or clone() syscall in src. This may not be true if
a task is created using kernel_thread() while running in the context of
some user task that entered the kernel due to a trap or syscall --
though probably nobody should be doing that.)
[...]
Cheers
---DavE
next prev parent reply other threads:[~2019-09-30 13:03 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-27 15:39 [PATCH v2] arm64/sve: Fix wrong free for task->thread.sve_state Masayoshi Mizuma
2019-09-27 15:39 ` Masayoshi Mizuma
2019-09-27 16:15 ` Dave Martin
2019-09-27 16:15 ` Dave Martin
2019-09-27 19:56 ` Julien Grall
2019-09-27 19:56 ` Julien Grall
2019-09-30 12:23 ` Julien Grall
2019-09-30 12:23 ` Julien Grall
2019-09-30 13:02 ` Dave Martin [this message]
2019-09-30 13:02 ` Dave Martin
2019-09-30 14:29 ` Masayoshi Mizuma
2019-09-30 14:29 ` Masayoshi Mizuma
2019-09-30 15:34 ` Dave Martin
2019-09-30 15:34 ` Dave Martin
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=20190930130244.GT27757@arm.com \
--to=dave.martin@arm.com \
--cc=catalin.marinas@arm.com \
--cc=julien.grall@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=m.mizuma@jp.fujitsu.com \
--cc=msys.mizuma@gmail.com \
--cc=will@kernel.org \
/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.