linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] rseq: minor optimizations
@ 2021-04-13  7:36 Eric Dumazet
  2021-04-13  7:36 ` [PATCH 1/3] rseq: optimize rseq_update_cpu_id() Eric Dumazet
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Eric Dumazet @ 2021-04-13  7:36 UTC (permalink / raw)
  To: Ingo Molnar, Mathieu Desnoyers, Peter Zijlstra
  Cc: Paul E . McKenney, Boqun Feng, Arjun Roy, linux-kernel,
	Eric Dumazet, Eric Dumazet

From: Eric Dumazet <edumazet@google.com>

rseq is a heavy user of copy to/from user data in fast paths.
This series tries to reduce the cost.

Eric Dumazet (3):
  rseq: optimize rseq_update_cpu_id()
  rseq: remove redundant access_ok()
  rseq: optimise for 64bit arches

 kernel/rseq.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

-- 
2.31.1.295.g9ea45b61b8-goog


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/3] rseq: optimize rseq_update_cpu_id()
  2021-04-13  7:36 [PATCH 0/3] rseq: minor optimizations Eric Dumazet
@ 2021-04-13  7:36 ` Eric Dumazet
  2021-04-13 14:29   ` Mathieu Desnoyers
  2021-04-13  7:36 ` [PATCH 2/3] rseq: remove redundant access_ok() Eric Dumazet
  2021-04-13  7:36 ` [PATCH 3/3] rseq: optimise for 64bit arches Eric Dumazet
  2 siblings, 1 reply; 13+ messages in thread
From: Eric Dumazet @ 2021-04-13  7:36 UTC (permalink / raw)
  To: Ingo Molnar, Mathieu Desnoyers, Peter Zijlstra
  Cc: Paul E . McKenney, Boqun Feng, Arjun Roy, linux-kernel,
	Eric Dumazet, Eric Dumazet

From: Eric Dumazet <edumazet@google.com>

Two put_user() in rseq_update_cpu_id() are replaced
by a pair of unsafe_put_user() with appropriate surroundings.

This removes one stac/clac pair on x86 in fast path.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: "Paul E. McKenney" <paulmck@kernel.org>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Arjun Roy <arjunroy@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
---
 kernel/rseq.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/kernel/rseq.c b/kernel/rseq.c
index a4f86a9d6937cdfa2f13d1dcc9be863c1943d06f..d2689ccbb132c0fc8ec0924008771e5ee1ca855e 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -84,13 +84,20 @@
 static int rseq_update_cpu_id(struct task_struct *t)
 {
 	u32 cpu_id = raw_smp_processor_id();
+	struct rseq *r = t->rseq;
 
-	if (put_user(cpu_id, &t->rseq->cpu_id_start))
-		return -EFAULT;
-	if (put_user(cpu_id, &t->rseq->cpu_id))
-		return -EFAULT;
+	if (!user_write_access_begin(r, sizeof(*r)))
+		goto efault;
+	unsafe_put_user(cpu_id, &r->cpu_id_start, efault_end);
+	unsafe_put_user(cpu_id, &r->cpu_id, efault_end);
+	user_write_access_end();
 	trace_rseq_update(t);
 	return 0;
+
+efault_end:
+	user_write_access_end();
+efault:
+	return -EFAULT;
 }
 
 static int rseq_reset_rseq_cpu_id(struct task_struct *t)
-- 
2.31.1.295.g9ea45b61b8-goog


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/3] rseq: remove redundant access_ok()
  2021-04-13  7:36 [PATCH 0/3] rseq: minor optimizations Eric Dumazet
  2021-04-13  7:36 ` [PATCH 1/3] rseq: optimize rseq_update_cpu_id() Eric Dumazet
@ 2021-04-13  7:36 ` Eric Dumazet
  2021-04-13 14:34   ` Mathieu Desnoyers
  2021-04-13  7:36 ` [PATCH 3/3] rseq: optimise for 64bit arches Eric Dumazet
  2 siblings, 1 reply; 13+ messages in thread
From: Eric Dumazet @ 2021-04-13  7:36 UTC (permalink / raw)
  To: Ingo Molnar, Mathieu Desnoyers, Peter Zijlstra
  Cc: Paul E . McKenney, Boqun Feng, Arjun Roy, linux-kernel,
	Eric Dumazet, Eric Dumazet

From: Eric Dumazet <edumazet@google.com>

After commit 8f2817701492 ("rseq: Use get_user/put_user rather
than __get_user/__put_user") we no longer need
an access_ok() call from __rseq_handle_notify_resume()

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: "Paul E. McKenney" <paulmck@kernel.org>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Arjun Roy <arjunroy@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
---
 kernel/rseq.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/kernel/rseq.c b/kernel/rseq.c
index d2689ccbb132c0fc8ec0924008771e5ee1ca855e..57344f9abb43905c7dd2b6081205ff508d963e1e 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -273,8 +273,6 @@ void __rseq_handle_notify_resume(struct ksignal *ksig, struct pt_regs *regs)
 
 	if (unlikely(t->flags & PF_EXITING))
 		return;
-	if (unlikely(!access_ok(t->rseq, sizeof(*t->rseq))))
-		goto error;
 	ret = rseq_ip_fixup(regs);
 	if (unlikely(ret < 0))
 		goto error;
-- 
2.31.1.295.g9ea45b61b8-goog


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/3] rseq: optimise for 64bit arches
  2021-04-13  7:36 [PATCH 0/3] rseq: minor optimizations Eric Dumazet
  2021-04-13  7:36 ` [PATCH 1/3] rseq: optimize rseq_update_cpu_id() Eric Dumazet
  2021-04-13  7:36 ` [PATCH 2/3] rseq: remove redundant access_ok() Eric Dumazet
@ 2021-04-13  7:36 ` Eric Dumazet
  2021-04-13  9:10   ` Peter Zijlstra
  2 siblings, 1 reply; 13+ messages in thread
From: Eric Dumazet @ 2021-04-13  7:36 UTC (permalink / raw)
  To: Ingo Molnar, Mathieu Desnoyers, Peter Zijlstra
  Cc: Paul E . McKenney, Boqun Feng, Arjun Roy, linux-kernel,
	Eric Dumazet, Eric Dumazet

From: Eric Dumazet <edumazet@google.com>

Commit ec9c82e03a74 ("rseq: uapi: Declare rseq_cs field as union,
update includes") added regressions for our servers.

Using copy_from_user() and clear_user() for 64bit values
on 64bit arches is suboptimal.

We might revisit this patch once all 32bit arches support
get_user() and/or put_user() for 8 bytes values.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: "Paul E. McKenney" <paulmck@kernel.org>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Arjun Roy <arjunroy@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
---
 kernel/rseq.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/kernel/rseq.c b/kernel/rseq.c
index 57344f9abb43905c7dd2b6081205ff508d963e1e..18a75a804008d2f564d1f7789f09216f1a8760bd 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -127,8 +127,13 @@ static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs)
 	u32 sig;
 	int ret;
 
+#ifdef CONFIG_64BIT
+	if (get_user(ptr, &t->rseq->rseq_cs.ptr64))
+		return -EFAULT;
+#else
 	if (copy_from_user(&ptr, &t->rseq->rseq_cs.ptr64, sizeof(ptr)))
 		return -EFAULT;
+#endif
 	if (!ptr) {
 		memset(rseq_cs, 0, sizeof(*rseq_cs));
 		return 0;
@@ -211,9 +216,13 @@ static int clear_rseq_cs(struct task_struct *t)
 	 *
 	 * Set rseq_cs to NULL.
 	 */
+#ifdef CONFIG_64BIT
+	return put_user(0ULL, &t->rseq->rseq_cs.ptr64);
+#else
 	if (clear_user(&t->rseq->rseq_cs.ptr64, sizeof(t->rseq->rseq_cs.ptr64)))
 		return -EFAULT;
 	return 0;
+#endif
 }
 
 /*
-- 
2.31.1.295.g9ea45b61b8-goog


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/3] rseq: optimise for 64bit arches
  2021-04-13  7:36 ` [PATCH 3/3] rseq: optimise for 64bit arches Eric Dumazet
@ 2021-04-13  9:10   ` Peter Zijlstra
  2021-04-13 10:36     ` David Laight
  0 siblings, 1 reply; 13+ messages in thread
From: Peter Zijlstra @ 2021-04-13  9:10 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Ingo Molnar, Mathieu Desnoyers, Paul E . McKenney, Boqun Feng,
	Arjun Roy, linux-kernel, Eric Dumazet

On Tue, Apr 13, 2021 at 12:36:57AM -0700, Eric Dumazet wrote:
> From: Eric Dumazet <edumazet@google.com>
> 
> Commit ec9c82e03a74 ("rseq: uapi: Declare rseq_cs field as union,
> update includes") added regressions for our servers.
> 
> Using copy_from_user() and clear_user() for 64bit values
> on 64bit arches is suboptimal.
> 
> We might revisit this patch once all 32bit arches support
> get_user() and/or put_user() for 8 bytes values.

Argh, what a mess :/ afaict only nios32 lacks put_user_8, but get_user_8
is missing in a fair number of archs.

That said; 32bit archs never have to actually set the top bits in that
word, so they _could_ only set the low 32 bits. That works provided
userspace itself keeps the high bits clear.

So I suppose that if we're going to #ifdef this, we might as well do the
whole thing.

Mathieu; did I forget a reason why this cannot work?

diff --git a/kernel/rseq.c b/kernel/rseq.c
index a4f86a9d6937..94006190b8eb 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -115,20 +115,25 @@ static int rseq_reset_rseq_cpu_id(struct task_struct *t)
 static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs)
 {
 	struct rseq_cs __user *urseq_cs;
-	u64 ptr;
+	unsigned long ptr;
 	u32 __user *usig;
 	u32 sig;
 	int ret;
 
-	if (copy_from_user(&ptr, &t->rseq->rseq_cs.ptr64, sizeof(ptr)))
+#ifdef CONFIG_64BIT
+	if (get_user(ptr, &t->rseq->rseq_cs.ptr64))
 		return -EFAULT;
+#else
+	if (get_user(ptr, &t->rseq->rseq_cs.ptr32))
+		return -EFAULT;
+#endif
 	if (!ptr) {
 		memset(rseq_cs, 0, sizeof(*rseq_cs));
 		return 0;
 	}
 	if (ptr >= TASK_SIZE)
 		return -EINVAL;
-	urseq_cs = (struct rseq_cs __user *)(unsigned long)ptr;
+	urseq_cs = (struct rseq_cs __user *)ptr;
 	if (copy_from_user(rseq_cs, urseq_cs, sizeof(*rseq_cs)))
 		return -EFAULT;
 

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* RE: [PATCH 3/3] rseq: optimise for 64bit arches
  2021-04-13  9:10   ` Peter Zijlstra
@ 2021-04-13 10:36     ` David Laight
  2021-04-13 14:21       ` Mathieu Desnoyers
  0 siblings, 1 reply; 13+ messages in thread
From: David Laight @ 2021-04-13 10:36 UTC (permalink / raw)
  To: 'Peter Zijlstra', Eric Dumazet
  Cc: Ingo Molnar, Mathieu Desnoyers, Paul E . McKenney, Boqun Feng,
	Arjun Roy, linux-kernel, Eric Dumazet

From: Peter Zijlstra
> Sent: 13 April 2021 10:10
> 
> On Tue, Apr 13, 2021 at 12:36:57AM -0700, Eric Dumazet wrote:
> > From: Eric Dumazet <edumazet@google.com>
> >
> > Commit ec9c82e03a74 ("rseq: uapi: Declare rseq_cs field as union,
> > update includes") added regressions for our servers.
> >
> > Using copy_from_user() and clear_user() for 64bit values
> > on 64bit arches is suboptimal.
> >
> > We might revisit this patch once all 32bit arches support
> > get_user() and/or put_user() for 8 bytes values.
> 
> Argh, what a mess :/ afaict only nios32 lacks put_user_8, but get_user_8
> is missing in a fair number of archs.
> 
> That said; 32bit archs never have to actually set the top bits in that
> word, so they _could_ only set the low 32 bits. That works provided
> userspace itself keeps the high bits clear.

Does that work for 32bit BE ?

	David

> So I suppose that if we're going to #ifdef this, we might as well do the
> whole thing.
> 
> Mathieu; did I forget a reason why this cannot work?
> 
> diff --git a/kernel/rseq.c b/kernel/rseq.c
> index a4f86a9d6937..94006190b8eb 100644
> --- a/kernel/rseq.c
> +++ b/kernel/rseq.c
> @@ -115,20 +115,25 @@ static int rseq_reset_rseq_cpu_id(struct task_struct *t)
>  static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs)
>  {
>  	struct rseq_cs __user *urseq_cs;
> -	u64 ptr;
> +	unsigned long ptr;
>  	u32 __user *usig;
>  	u32 sig;
>  	int ret;
> 
> -	if (copy_from_user(&ptr, &t->rseq->rseq_cs.ptr64, sizeof(ptr)))
> +#ifdef CONFIG_64BIT
> +	if (get_user(ptr, &t->rseq->rseq_cs.ptr64))
>  		return -EFAULT;
> +#else
> +	if (get_user(ptr, &t->rseq->rseq_cs.ptr32))
> +		return -EFAULT;
> +#endif
>  	if (!ptr) {
>  		memset(rseq_cs, 0, sizeof(*rseq_cs));
>  		return 0;
>  	}
>  	if (ptr >= TASK_SIZE)
>  		return -EINVAL;
> -	urseq_cs = (struct rseq_cs __user *)(unsigned long)ptr;
> +	urseq_cs = (struct rseq_cs __user *)ptr;
>  	if (copy_from_user(rseq_cs, urseq_cs, sizeof(*rseq_cs)))
>  		return -EFAULT;
> 

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/3] rseq: optimise for 64bit arches
  2021-04-13 10:36     ` David Laight
@ 2021-04-13 14:21       ` Mathieu Desnoyers
  2021-04-13 15:06         ` David Laight
  0 siblings, 1 reply; 13+ messages in thread
From: Mathieu Desnoyers @ 2021-04-13 14:21 UTC (permalink / raw)
  To: David Laight, Peter Zijlstra
  Cc: Eric Dumazet, Ingo Molnar, paulmck, Boqun Feng, Arjun Roy,
	linux-kernel, Eric Dumazet

----- On Apr 13, 2021, at 6:36 AM, David Laight David.Laight@ACULAB.COM wrote:

> From: Peter Zijlstra
>> Sent: 13 April 2021 10:10
>> 
>> On Tue, Apr 13, 2021 at 12:36:57AM -0700, Eric Dumazet wrote:
>> > From: Eric Dumazet <edumazet@google.com>
>> >
>> > Commit ec9c82e03a74 ("rseq: uapi: Declare rseq_cs field as union,
>> > update includes") added regressions for our servers.
>> >
>> > Using copy_from_user() and clear_user() for 64bit values
>> > on 64bit arches is suboptimal.
>> >
>> > We might revisit this patch once all 32bit arches support
>> > get_user() and/or put_user() for 8 bytes values.
>> 
>> Argh, what a mess :/ afaict only nios32 lacks put_user_8, but get_user_8
>> is missing in a fair number of archs.
>> 
>> That said; 32bit archs never have to actually set the top bits in that
>> word, so they _could_ only set the low 32 bits. That works provided
>> userspace itself keeps the high bits clear.
> 
> Does that work for 32bit BE ?

Yes, because uapi/linux/rseq.h defines the ptr32 as:

#if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined(__BIG_ENDIAN)
                        __u32 padding;          /* Initialized to zero. */
                        __u32 ptr32;
#else /* LITTLE */
                        __u32 ptr32;
                        __u32 padding;          /* Initialized to zero. */
#endif /* ENDIAN */

which takes care of BE vs LE.

> 
>	David
> 
>> So I suppose that if we're going to #ifdef this, we might as well do the
>> whole thing.
>> 
>> Mathieu; did I forget a reason why this cannot work?

The only difference it brings on 32-bit is that the truncation of high bits
will be done before the following validation:

        if (!ptr) {
                memset(rseq_cs, 0, sizeof(*rseq_cs));
                return 0;
        }
        if (ptr >= TASK_SIZE)
                return -EINVAL;

The question is whether we really want to issue a segmentation fault if 32-bit
user-space has set non-zero high bits, or if silently ignoring those high
bits is acceptable.

Nits below:

>> 
>> diff --git a/kernel/rseq.c b/kernel/rseq.c
>> index a4f86a9d6937..94006190b8eb 100644
>> --- a/kernel/rseq.c
>> +++ b/kernel/rseq.c
>> @@ -115,20 +115,25 @@ static int rseq_reset_rseq_cpu_id(struct task_struct *t)
>>  static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs)
>>  {
>>  	struct rseq_cs __user *urseq_cs;
>> -	u64 ptr;
>> +	unsigned long ptr;

I am always reluctant to use long/unsigned long type as type for the get/put_user
(x) argument, because it hides the cast deep within architecture-specific macros.
I understand that in this specific case it happens that on 64-bit archs we end up
casting a u64 to unsigned long (same size), and on 32-bit archs we end up casting a
u32 to unsigned long (also same size), so there is no practical concern about type
promotion and sign-extension, but I think it would be better to have something
explicit, e.g.:

#ifdef CONFIG_64BIT
static int rseq_get_cs_ptr(struct rseq_cs __user **uptrp, struct rseq_cs *rseq_cs)
{
    u64 ptr;

    if (get_user(ptr, &rseq_cs->ptr64))
        return -EFAULT;
    *ptrp = (struct rseq_cs __user *)ptr;
    return 0;
}
#else
static int rseq_get_cs_ptr(struct rseq_cs __user **uptrp, struct rseq_cs *rseq_cs)
{
    u32 ptr;

    if (get_user(ptr, &rseq_cs->ptr.ptr32))
        return -EFAULT;
    *ptrp = (struct rseq_cs __user *)ptr;
    return 0;
}
#endif

And use those helpers to get the ptr value.

>>  	u32 __user *usig;
>>  	u32 sig;
>>  	int ret;
>> 
>> -	if (copy_from_user(&ptr, &t->rseq->rseq_cs.ptr64, sizeof(ptr)))
>> +#ifdef CONFIG_64BIT
>> +	if (get_user(ptr, &t->rseq->rseq_cs.ptr64))
>>  		return -EFAULT;
>> +#else
>> +	if (get_user(ptr, &t->rseq->rseq_cs.ptr32))

Note that this is also not right. It should be &t->rseq->rseq_cs.ptr.ptr32.

Thanks,

Mathieu

>> +		return -EFAULT;
>> +#endif
>>  	if (!ptr) {
>>  		memset(rseq_cs, 0, sizeof(*rseq_cs));
>>  		return 0;
>>  	}
>>  	if (ptr >= TASK_SIZE)
>>  		return -EINVAL;
>> -	urseq_cs = (struct rseq_cs __user *)(unsigned long)ptr;
>> +	urseq_cs = (struct rseq_cs __user *)ptr;
>>  	if (copy_from_user(rseq_cs, urseq_cs, sizeof(*rseq_cs)))
>>  		return -EFAULT;
>> 
> 
> -
> Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT,
> UK
> Registration No: 1397386 (Wales)

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/3] rseq: optimize rseq_update_cpu_id()
  2021-04-13  7:36 ` [PATCH 1/3] rseq: optimize rseq_update_cpu_id() Eric Dumazet
@ 2021-04-13 14:29   ` Mathieu Desnoyers
  2021-04-13 15:24     ` Eric Dumazet
  0 siblings, 1 reply; 13+ messages in thread
From: Mathieu Desnoyers @ 2021-04-13 14:29 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Ingo Molnar, Peter Zijlstra, paulmck, Boqun Feng, Arjun Roy,
	linux-kernel, Eric Dumazet

----- On Apr 13, 2021, at 3:36 AM, Eric Dumazet eric.dumazet@gmail.com wrote:

> From: Eric Dumazet <edumazet@google.com>
> 
> Two put_user() in rseq_update_cpu_id() are replaced
> by a pair of unsafe_put_user() with appropriate surroundings.
> 
> This removes one stac/clac pair on x86 in fast path.
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: "Paul E. McKenney" <paulmck@kernel.org>
> Cc: Boqun Feng <boqun.feng@gmail.com>
> Cc: Arjun Roy <arjunroy@google.com>
> Cc: Ingo Molnar <mingo@kernel.org>
> ---
> kernel/rseq.c | 15 +++++++++++----
> 1 file changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/kernel/rseq.c b/kernel/rseq.c
> index
> a4f86a9d6937cdfa2f13d1dcc9be863c1943d06f..d2689ccbb132c0fc8ec0924008771e5ee1ca855e
> 100644
> --- a/kernel/rseq.c
> +++ b/kernel/rseq.c
> @@ -84,13 +84,20 @@
> static int rseq_update_cpu_id(struct task_struct *t)
> {
> 	u32 cpu_id = raw_smp_processor_id();
> +	struct rseq *r = t->rseq;

AFAIU the variable above should be a struct rseq __user *.

Elsewhere in the file we use "rseq" rather than "r" for struct rseq __user *
variable name, it would be better to keep the naming consistent across the file
if possible.

Thanks,

Mathieu

> 
> -	if (put_user(cpu_id, &t->rseq->cpu_id_start))
> -		return -EFAULT;
> -	if (put_user(cpu_id, &t->rseq->cpu_id))
> -		return -EFAULT;
> +	if (!user_write_access_begin(r, sizeof(*r)))
> +		goto efault;
> +	unsafe_put_user(cpu_id, &r->cpu_id_start, efault_end);
> +	unsafe_put_user(cpu_id, &r->cpu_id, efault_end);
> +	user_write_access_end();
> 	trace_rseq_update(t);
> 	return 0;
> +
> +efault_end:
> +	user_write_access_end();
> +efault:
> +	return -EFAULT;
> }
> 
> static int rseq_reset_rseq_cpu_id(struct task_struct *t)
> --
> 2.31.1.295.g9ea45b61b8-goog

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/3] rseq: remove redundant access_ok()
  2021-04-13  7:36 ` [PATCH 2/3] rseq: remove redundant access_ok() Eric Dumazet
@ 2021-04-13 14:34   ` Mathieu Desnoyers
  2021-04-13 15:19     ` Eric Dumazet
  0 siblings, 1 reply; 13+ messages in thread
From: Mathieu Desnoyers @ 2021-04-13 14:34 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Ingo Molnar, Peter Zijlstra, paulmck, Boqun Feng, Arjun Roy,
	linux-kernel, Eric Dumazet

----- On Apr 13, 2021, at 3:36 AM, Eric Dumazet eric.dumazet@gmail.com wrote:

> From: Eric Dumazet <edumazet@google.com>
> 
> After commit 8f2817701492 ("rseq: Use get_user/put_user rather
> than __get_user/__put_user") we no longer need
> an access_ok() call from __rseq_handle_notify_resume()

While we are doing that, should we also remove the access_ok() check in
rseq_syscall() ? It look like it can also be removed for the exact same
reason outlined here.

Thanks,

Mathieu

> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: "Paul E. McKenney" <paulmck@kernel.org>
> Cc: Boqun Feng <boqun.feng@gmail.com>
> Cc: Arjun Roy <arjunroy@google.com>
> Cc: Ingo Molnar <mingo@kernel.org>
> ---
> kernel/rseq.c | 2 --
> 1 file changed, 2 deletions(-)
> 
> diff --git a/kernel/rseq.c b/kernel/rseq.c
> index
> d2689ccbb132c0fc8ec0924008771e5ee1ca855e..57344f9abb43905c7dd2b6081205ff508d963e1e
> 100644
> --- a/kernel/rseq.c
> +++ b/kernel/rseq.c
> @@ -273,8 +273,6 @@ void __rseq_handle_notify_resume(struct ksignal *ksig,
> struct pt_regs *regs)
> 
> 	if (unlikely(t->flags & PF_EXITING))
> 		return;
> -	if (unlikely(!access_ok(t->rseq, sizeof(*t->rseq))))
> -		goto error;
> 	ret = rseq_ip_fixup(regs);
> 	if (unlikely(ret < 0))
> 		goto error;
> --
> 2.31.1.295.g9ea45b61b8-goog

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH 3/3] rseq: optimise for 64bit arches
  2021-04-13 14:21       ` Mathieu Desnoyers
@ 2021-04-13 15:06         ` David Laight
  2021-04-13 15:08           ` Mathieu Desnoyers
  0 siblings, 1 reply; 13+ messages in thread
From: David Laight @ 2021-04-13 15:06 UTC (permalink / raw)
  To: 'Mathieu Desnoyers', Peter Zijlstra
  Cc: Eric Dumazet, Ingo Molnar, paulmck, Boqun Feng, Arjun Roy,
	linux-kernel, Eric Dumazet

From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> Sent: 13 April 2021 15:22
...
> >	David
> >
> >> So I suppose that if we're going to #ifdef this, we might as well do the
> >> whole thing.
> >>
> >> Mathieu; did I forget a reason why this cannot work?
> 
> The only difference it brings on 32-bit is that the truncation of high bits
> will be done before the following validation:
> 
>         if (!ptr) {
>                 memset(rseq_cs, 0, sizeof(*rseq_cs));
>                 return 0;
>         }
>         if (ptr >= TASK_SIZE)
>                 return -EINVAL;
> 
> The question is whether we really want to issue a segmentation fault if 32-bit
> user-space has set non-zero high bits, or if silently ignoring those high
> bits is acceptable.

Well, 32bit programs running on 64bit kernels better zero the 'padding'.

It is a shame that the 32bit compilers don't have an attribute(64bit)
for pointers.

> ...
> I am always reluctant to use long/unsigned long type as type for the get/put_user
> (x) argument, because it hides the cast deep within architecture-specific macros.
> I understand that in this specific case it happens that on 64-bit archs we end up
> casting a u64 to unsigned long (same size), and on 32-bit archs we end up casting a
> u32 to unsigned long (also same size), so there is no practical concern about type
> promotion and sign-extension, but I think it would be better to have something
> explicit, e.g.:

If the ABI passes small structures in registers (most modern ones)
then user pointers probably ought to be encapsulated in a structure.
Possibly as a pointer to an unknown structure.
That would force all the required type checking.
Unfortunately the fallout/churn would be massive.

> #ifdef CONFIG_64BIT
> static int rseq_get_cs_ptr(struct rseq_cs __user **uptrp, struct rseq_cs *rseq_cs)
> {
>     u64 ptr;
> 
>     if (get_user(ptr, &rseq_cs->ptr64))
>         return -EFAULT;
>     *ptrp = (struct rseq_cs __user *)ptr;
>     return 0;
> }
> #else
> static int rseq_get_cs_ptr(struct rseq_cs __user **uptrp, struct rseq_cs *rseq_cs)
> {
>     u32 ptr;
> 
>     if (get_user(ptr, &rseq_cs->ptr.ptr32))
>         return -EFAULT;
>     *ptrp = (struct rseq_cs __user *)ptr;
>     return 0;
> }
> #endif

Hmmm... too much replication.
You could do:
#ifdef CONFIG_64BIT
#define PTR_TYPE u64
#define PTR_FLD ptr64
#else
#define PTR_TYPE u32
#define PTR_FLD ptr32
#endif

Then have one copy of the code and the #undefs.
...

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/3] rseq: optimise for 64bit arches
  2021-04-13 15:06         ` David Laight
@ 2021-04-13 15:08           ` Mathieu Desnoyers
  0 siblings, 0 replies; 13+ messages in thread
From: Mathieu Desnoyers @ 2021-04-13 15:08 UTC (permalink / raw)
  To: David Laight
  Cc: Peter Zijlstra, Eric Dumazet, Ingo Molnar, paulmck, Boqun Feng,
	Arjun Roy, linux-kernel, Eric Dumazet

----- On Apr 13, 2021, at 11:06 AM, David Laight David.Laight@ACULAB.COM wrote:
[...]
> 
> Hmmm... too much replication.
> You could do:
> #ifdef CONFIG_64BIT
> #define PTR_TYPE u64
> #define PTR_FLD ptr64
> #else
> #define PTR_TYPE u32
> #define PTR_FLD ptr32
> #endif
> 
> Then have one copy of the code and the #undefs.

Good point, agreed.

Thanks,

Mathieu

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/3] rseq: remove redundant access_ok()
  2021-04-13 14:34   ` Mathieu Desnoyers
@ 2021-04-13 15:19     ` Eric Dumazet
  0 siblings, 0 replies; 13+ messages in thread
From: Eric Dumazet @ 2021-04-13 15:19 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Eric Dumazet, Ingo Molnar, Peter Zijlstra, paulmck, Boqun Feng,
	Arjun Roy, linux-kernel

On Tue, Apr 13, 2021 at 4:34 PM Mathieu Desnoyers
<mathieu.desnoyers@efficios.com> wrote:
>
> ----- On Apr 13, 2021, at 3:36 AM, Eric Dumazet eric.dumazet@gmail.com wrote:
>
> > From: Eric Dumazet <edumazet@google.com>
> >
> > After commit 8f2817701492 ("rseq: Use get_user/put_user rather
> > than __get_user/__put_user") we no longer need
> > an access_ok() call from __rseq_handle_notify_resume()
>
> While we are doing that, should we also remove the access_ok() check in
> rseq_syscall() ? It look like it can also be removed for the exact same
> reason outlined here.

Yes, good idea.

 I was focusing in __rseq_handle_notify_resume() paths but
rseq_syscall() can get the same.

> Thanks,
>
> Mathieu
>
> >
> > Signed-off-by: Eric Dumazet <edumazet@google.com>
> > Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> > Cc: Peter Zijlstra <peterz@infradead.org>
> > Cc: "Paul E. McKenney" <paulmck@kernel.org>
> > Cc: Boqun Feng <boqun.feng@gmail.com>
> > Cc: Arjun Roy <arjunroy@google.com>
> > Cc: Ingo Molnar <mingo@kernel.org>
> > ---
> > kernel/rseq.c | 2 --
> > 1 file changed, 2 deletions(-)
> >
> > diff --git a/kernel/rseq.c b/kernel/rseq.c
> > index
> > d2689ccbb132c0fc8ec0924008771e5ee1ca855e..57344f9abb43905c7dd2b6081205ff508d963e1e
> > 100644
> > --- a/kernel/rseq.c
> > +++ b/kernel/rseq.c
> > @@ -273,8 +273,6 @@ void __rseq_handle_notify_resume(struct ksignal *ksig,
> > struct pt_regs *regs)
> >
> >       if (unlikely(t->flags & PF_EXITING))
> >               return;
> > -     if (unlikely(!access_ok(t->rseq, sizeof(*t->rseq))))
> > -             goto error;
> >       ret = rseq_ip_fixup(regs);
> >       if (unlikely(ret < 0))
> >               goto error;
> > --
> > 2.31.1.295.g9ea45b61b8-goog
>
> --
> Mathieu Desnoyers
> EfficiOS Inc.
> http://www.efficios.com

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/3] rseq: optimize rseq_update_cpu_id()
  2021-04-13 14:29   ` Mathieu Desnoyers
@ 2021-04-13 15:24     ` Eric Dumazet
  0 siblings, 0 replies; 13+ messages in thread
From: Eric Dumazet @ 2021-04-13 15:24 UTC (permalink / raw)
  To: Mathieu Desnoyers
  Cc: Eric Dumazet, Ingo Molnar, Peter Zijlstra, paulmck, Boqun Feng,
	Arjun Roy, linux-kernel

On Tue, Apr 13, 2021 at 4:29 PM Mathieu Desnoyers
<mathieu.desnoyers@efficios.com> wrote:
>
> ----- On Apr 13, 2021, at 3:36 AM, Eric Dumazet eric.dumazet@gmail.com wrote:
>
> > From: Eric Dumazet <edumazet@google.com>
> >
> > Two put_user() in rseq_update_cpu_id() are replaced
> > by a pair of unsafe_put_user() with appropriate surroundings.
> >
> > This removes one stac/clac pair on x86 in fast path.
> >
> > Signed-off-by: Eric Dumazet <edumazet@google.com>
> > Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> > Cc: Peter Zijlstra <peterz@infradead.org>
> > Cc: "Paul E. McKenney" <paulmck@kernel.org>
> > Cc: Boqun Feng <boqun.feng@gmail.com>
> > Cc: Arjun Roy <arjunroy@google.com>
> > Cc: Ingo Molnar <mingo@kernel.org>
> > ---
> > kernel/rseq.c | 15 +++++++++++----
> > 1 file changed, 11 insertions(+), 4 deletions(-)
> >
> > diff --git a/kernel/rseq.c b/kernel/rseq.c
> > index
> > a4f86a9d6937cdfa2f13d1dcc9be863c1943d06f..d2689ccbb132c0fc8ec0924008771e5ee1ca855e
> > 100644
> > --- a/kernel/rseq.c
> > +++ b/kernel/rseq.c
> > @@ -84,13 +84,20 @@
> > static int rseq_update_cpu_id(struct task_struct *t)
> > {
> >       u32 cpu_id = raw_smp_processor_id();
> > +     struct rseq *r = t->rseq;
>
> AFAIU the variable above should be a struct rseq __user *.
>
> Elsewhere in the file we use "rseq" rather than "r" for struct rseq __user *
> variable name, it would be better to keep the naming consistent across the file
> if possible.

Absolutely, thanks for the feedback.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2021-04-13 15:25 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-13  7:36 [PATCH 0/3] rseq: minor optimizations Eric Dumazet
2021-04-13  7:36 ` [PATCH 1/3] rseq: optimize rseq_update_cpu_id() Eric Dumazet
2021-04-13 14:29   ` Mathieu Desnoyers
2021-04-13 15:24     ` Eric Dumazet
2021-04-13  7:36 ` [PATCH 2/3] rseq: remove redundant access_ok() Eric Dumazet
2021-04-13 14:34   ` Mathieu Desnoyers
2021-04-13 15:19     ` Eric Dumazet
2021-04-13  7:36 ` [PATCH 3/3] rseq: optimise for 64bit arches Eric Dumazet
2021-04-13  9:10   ` Peter Zijlstra
2021-04-13 10:36     ` David Laight
2021-04-13 14:21       ` Mathieu Desnoyers
2021-04-13 15:06         ` David Laight
2021-04-13 15:08           ` Mathieu Desnoyers

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