From: Russell King - ARM Linux <linux@arm.linux.org.uk>
To: Peter Rosin <peda@axentia.se>
Cc: "'linux-kernel@vger.kernel.org'" <linux-kernel@vger.kernel.org>,
"'linux-arm-kernel@lists.infradead.org'"
<linux-arm-kernel@lists.infradead.org>,
"nico@fluxnic.net" <nico@fluxnic.net>,
Will Deacon <will.deacon@arm.com>
Subject: Re: Domain faults when CONFIG_CPU_SW_DOMAIN_PAN is enabled
Date: Thu, 3 Dec 2015 17:27:08 +0000 [thread overview]
Message-ID: <20151203172708.GT8644@n2100.arm.linux.org.uk> (raw)
In-Reply-To: <20151203164118.GR8644@n2100.arm.linux.org.uk>
[-- Attachment #1: Type: text/plain, Size: 1870 bytes --]
On Thu, Dec 03, 2015 at 04:41:18PM +0000, Russell King - ARM Linux wrote:
> On Thu, Dec 03, 2015 at 04:12:06PM +0000, Peter Rosin wrote:
> > * uaccess_with_memcpy.c:__copy_to_user() has a mode in which it copies
> > "non-atomically" (if faulthandler_disabled() returns 0). If a fault
> > happens during __copy_to_user, what prevents some other thread from
> > clobbering DACR?
>
> See the second point above. Moreover, if we sleep in down_read(),
> then __switch_to() reads the current DACR value and saves it in the
> thread information, and will restore that value when resuming the
> thread - even if the thread has been migrated to a different CPU.
I thought this was correct, but it isn't - that's what my original solution
did, but I think when Will reviewed it, we decided it wasn't necessary -
and it isn't necessary for every single case with the exception of this
one. This is exactly what's going wrong: the down_read() in these paths
calls into the scheduler, which switches away. When we come back, the
DACR value is reset by the other thread to 0x51.
There's a few ways to solve this:
1. Make the thread switching code save and restore the DACR register as
it would do for domains. This imposes an overhead on every single
context switch whether or not we happen to be in this _single_
troublesome code. (Patch attached - as there's several, I'm attaching
them.)
2. Add additional code to the uaccess-with-memcpy stuff to reset the
DACR value prior to using memcpy() or memset(). (Patch attached.)
3. Make uaccess-with-memcpy depend on !CPU_SW_DOMAINS_PAN (suggested by
Will)
4. Delete the uaccess-with-memcpy code (also suggested by Will.)
I think the best thing I can do is say... "Discuss amongst yourselves" :)
--
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
[-- Attachment #2: umemcpy1.diff --]
[-- Type: text/plain, Size: 1596 bytes --]
arch/arm/kernel/entry-armv.S | 4 ++--
arch/arm/kernel/process.c | 2 +-
arch/arm/lib/uaccess_with_memcpy.c | 0
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 3ce377f7251f..ae8a3ad763d9 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -782,7 +782,7 @@ ENTRY(__switch_to)
THUMB( str lr, [ip], #4 )
ldr r4, [r2, #TI_TP_VALUE]
ldr r5, [r2, #TI_TP_VALUE + 4]
-#ifdef CONFIG_CPU_USE_DOMAINS
+#if defined(CONFIG_CPU_USE_DOMAINS) || defined(CONFIG_CPU_SW_DOMAIN_PAN)
mrc p15, 0, r6, c3, c0, 0 @ Get domain register
str r6, [r1, #TI_CPU_DOMAIN] @ Save old domain register
ldr r6, [r2, #TI_CPU_DOMAIN]
@@ -793,7 +793,7 @@ ENTRY(__switch_to)
ldr r8, =__stack_chk_guard
ldr r7, [r7, #TSK_STACK_CANARY]
#endif
-#ifdef CONFIG_CPU_USE_DOMAINS
+#if defined(CONFIG_CPU_USE_DOMAINS) || defined(CONFIG_CPU_SW_DOMAIN_PAN)
mcr p15, 0, r6, c3, c0, 0 @ Set domain register
#endif
mov r5, r0
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 4adfb46e3ee9..9d80eb20488f 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -229,7 +229,7 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
-#ifdef CONFIG_CPU_USE_DOMAINS
+#if defined(CONFIG_CPU_USE_DOMAINS) || defined(CONFIG_CPU_SW_DOMAIN_PAN)
/*
* Copy the initial value of the domain access control register
* from the current thread: thread->addr_limit will have been
[-- Attachment #3: umemcpy2.diff --]
[-- Type: text/plain, Size: 1779 bytes --]
arch/arm/kernel/entry-armv.S | 0
arch/arm/kernel/process.c | 0
arch/arm/lib/uaccess_with_memcpy.c | 7 +++++++
3 files changed, 7 insertions(+)
diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c
index d72b90905132..110e3e272583 100644
--- a/arch/arm/lib/uaccess_with_memcpy.c
+++ b/arch/arm/lib/uaccess_with_memcpy.c
@@ -88,6 +88,7 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
static unsigned long noinline
__copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
{
+ unsigned long dacr;
int atomic;
if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
@@ -98,6 +99,7 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
/* the mmap semaphore is taken only if not in an atomic context */
atomic = faulthandler_disabled();
+ dacr = get_domain();
if (!atomic)
down_read(¤t->mm->mmap_sem);
while (n) {
@@ -118,6 +120,7 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
if (tocopy > n)
tocopy = n;
+ set_domain(dacr);
memcpy((void *)to, from, tocopy);
to += tocopy;
from += tocopy;
@@ -153,11 +156,14 @@ arm_copy_to_user(void __user *to, const void *from, unsigned long n)
static unsigned long noinline
__clear_user_memset(void __user *addr, unsigned long n)
{
+ unsigned long dacr;
+
if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
memset((void *)addr, 0, n);
return 0;
}
+ dacr = get_domain();
down_read(¤t->mm->mmap_sem);
while (n) {
pte_t *pte;
@@ -175,6 +181,7 @@ __clear_user_memset(void __user *addr, unsigned long n)
if (tocopy > n)
tocopy = n;
+ set_domain(dacr);
memset((void *)addr, 0, tocopy);
addr += tocopy;
n -= tocopy;
next prev parent reply other threads:[~2015-12-03 17:27 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-03 8:33 Peter Rosin
2015-12-03 11:00 ` Russell King - ARM Linux
2015-12-03 11:38 ` Peter Rosin
2015-12-03 11:51 ` Russell King - ARM Linux
2015-12-03 12:08 ` Peter Rosin
2015-12-03 13:37 ` Russell King - ARM Linux
2015-12-03 16:12 ` Peter Rosin
2015-12-03 16:41 ` Russell King - ARM Linux
2015-12-03 17:27 ` Russell King - ARM Linux [this message]
2015-12-03 18:28 ` Nicolas Pitre
2015-12-05 13:41 ` Russell King - ARM Linux
2015-12-03 21:37 ` Peter Rosin
2015-12-10 0:22 ` Russell King - ARM Linux
2015-12-10 15:29 ` Peter Rosin
2015-12-10 16:20 ` Russell King - ARM Linux
2015-12-10 18:32 ` Peter Rosin
2015-12-30 16:51 ` Peter Rosin
2015-12-30 16:57 ` Peter Rosin
-- strict thread matches above, loose matches on Subject: below --
2015-12-03 7:43 Peter Rosin
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=20151203172708.GT8644@n2100.arm.linux.org.uk \
--to=linux@arm.linux.org.uk \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=nico@fluxnic.net \
--cc=peda@axentia.se \
--cc=will.deacon@arm.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®