From: Dave Hansen <dave.hansen@intel.com>
To: Linus Torvalds <torvalds@linux-foundation.org>,
Borislav Petkov <bp@suse.de>,
"Chang S. Bae" <chang.seok.bae@intel.com>,
Dave Hansen <dave.hansen@linux.intel.com>,
Thomas Gleixner <tglx@linutronix.de>
Cc: x86-ml <x86@kernel.org>, lkml <linux-kernel@vger.kernel.org>
Subject: Re: [GIT PULL] core/urgent for v5.16-rc6
Date: Sun, 19 Dec 2021 21:25:44 -0800 [thread overview]
Message-ID: <15b1a9af-f8ff-c3e2-ba3e-cdbd29ae38db@intel.com> (raw)
In-Reply-To: <CAHk-=wiNMghi=nZc432_Sj4QwG+BtxGUtovnpVQk-LpDj8r3ZA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2232 bytes --]
On 12/19/21 12:14 PM, Linus Torvalds wrote:
...
> The SS_DISABLE case shouldn't take the lock at all.
>
> And the actual modification of the values shouldn't need any locking
> at all, since it's all thread-local.
The modification is definitely thread-local, but the implications are
wider after the dynamic xfeature and sigframe support went in. Now,
(x86-only) no thread is allowed to enable dynamic features unless the
entire _process's_ altstacks pass validate_sigaltstack().
> I'm not convinced even the limit checking needs the lock, but
> whatever. I think it could maybe just use "read_once()" or something.
>
> I think the attached patch is an improvement, but I did *not* test
> this, and I'm just throwing this out as a "maybe something like this".
The patch definitely makes the code easier to read. But, it looks like
we need to invert the sigaltstack_size_valid() condition from the patch:
> + if (unlikely(ss_size < min_ss_size) ||
> + unlikely(sigaltstack_size_valid(ss_size))) {
^^^^^
> + sigaltstack_unlock();
> + return -ENOMEM;
> }
That should be !sigaltstack_size_valid(ss_size).
Also, the sigaltstack_lock() lock really is needed over the assignments
like this:
> t->sas_ss_sp = (unsigned long) ss_sp;
> t->sas_ss_size = ss_size;
> t->sas_ss_flags = ss_flags;
to prevent races with validate_sigaltstack(). We desperately need a
comment in there, but we probably shouldn't reference
validate_sigaltstack() itself since it's deeply x86-only. I've got a
shot at a comment in the attached patch.
As for the the:
> if (ss_mode == SS_DISABLE) {
> t->sas_ss_sp = 0;
> t->sas_ss_size = 0;
> t->sas_ss_flags = ss_flags;
> return 0;
> }
hunk, I think it's OK. Shrinking t->sas_ss_size without the lock is
safe-ish because it will never cause validate_sigaltstack() to fail. I
need to think about that bit more, though.
Another blatantly untested patch is attached. I'll try to give it a go
on some real hardware tomorrow.
[-- Attachment #2: patch2.diff --]
[-- Type: text/x-patch, Size: 2089 bytes --]
1 file changed, 19 insertions(+), 17 deletions(-)
index dfcee3888b00..f58f1d574931 100644
---
b/kernel/signal.c | 41 ++++++++++++++++++++++++-----------------
1 file changed, 24 insertions(+), 17 deletions(-)
diff -puN kernel/signal.c~linux-sigaltstack kernel/signal.c
--- a/kernel/signal.c~linux-sigaltstack 2021-12-19 16:50:41.411762535 -0800
+++ b/kernel/signal.c 2021-12-19 21:14:14.605399136 -0800
@@ -4161,7 +4161,6 @@ do_sigaltstack (const stack_t *ss, stack
size_t min_ss_size)
{
struct task_struct *t = current;
- int ret = 0;
if (oss) {
memset(oss, 0, sizeof(stack_t));
@@ -4181,8 +4180,15 @@ do_sigaltstack (const stack_t *ss, stack
return -EPERM;
ss_mode = ss_flags & ~SS_FLAG_BITS;
- if (unlikely(ss_mode != SS_DISABLE && ss_mode != SS_ONSTACK &&
- ss_mode != 0))
+
+ if (ss_mode == SS_DISABLE) {
+ t->sas_ss_sp = 0;
+ t->sas_ss_size = 0;
+ t->sas_ss_flags = ss_flags;
+ return 0;
+ }
+
+ if (unlikely(ss_mode != SS_ONSTACK && ss_mode != 0))
return -EINVAL;
/*
@@ -4194,24 +4200,25 @@ do_sigaltstack (const stack_t *ss, stack
t->sas_ss_flags == ss_flags)
return 0;
+ /*
+ * Lock out any changes to sigaltstack_size_valid()
+ * until the t->sas_ss_* changes are complete:
+ */
sigaltstack_lock();
- if (ss_mode == SS_DISABLE) {
- ss_size = 0;
- ss_sp = NULL;
- } else {
- if (unlikely(ss_size < min_ss_size))
- ret = -ENOMEM;
- if (!sigaltstack_size_valid(ss_size))
- ret = -ENOMEM;
- }
- if (!ret) {
- t->sas_ss_sp = (unsigned long) ss_sp;
- t->sas_ss_size = ss_size;
- t->sas_ss_flags = ss_flags;
+
+ if (unlikely(ss_size < min_ss_size) ||
+ unlikely(!sigaltstack_size_valid(ss_size))) {
+ sigaltstack_unlock();
+ return -ENOMEM;
}
+
+ t->sas_ss_sp = (unsigned long) ss_sp;
+ t->sas_ss_size = ss_size;
+ t->sas_ss_flags = ss_flags;
+
sigaltstack_unlock();
}
- return ret;
+ return 0;
}
SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss)
_
next prev parent reply other threads:[~2021-12-20 5:28 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-19 13:40 [GIT PULL] core/urgent for v5.16-rc6 Borislav Petkov
2021-12-19 20:14 ` Linus Torvalds
2021-12-19 20:16 ` Linus Torvalds
2021-12-20 5:25 ` Dave Hansen [this message]
2021-12-20 16:20 ` Linus Torvalds
2021-12-20 16:25 ` Linus Torvalds
2022-01-10 19:01 ` Thomas Gleixner
2021-12-19 20:34 ` pr-tracker-bot
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=15b1a9af-f8ff-c3e2-ba3e-cdbd29ae38db@intel.com \
--to=dave.hansen@intel.com \
--cc=bp@suse.de \
--cc=chang.seok.bae@intel.com \
--cc=dave.hansen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=tglx@linutronix.de \
--cc=torvalds@linux-foundation.org \
--cc=x86@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 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).