* Re: [PATCH] mtdchar: fix overflows in adjustment of `count`
From: Jann Horn @ 2018-07-07 9:03 UTC (permalink / raw)
To: boris.brezillon
Cc: richard, kernel list, marek.vasut, linux-mtd, Linux API,
computersforpeace, dwmw2
In-Reply-To: <20180707104412.1580a285@bbrezillon>
+cc linux-api
On Sat, Jul 7, 2018 at 10:44 AM Boris Brezillon
<boris.brezillon@bootlin.com> wrote:
>
> On Sat, 7 Jul 2018 05:37:22 +0200
> Jann Horn <jannh@google.com> wrote:
>
> > The first checks in mtdchar_read() and mtdchar_write() attempt to limit
> > `count` such that `*ppos + count <= mtd->size`. However, they ignore the
> > possibility of `*ppos > mtd->size`, allowing the calculation of `count` to
> > wrap around. `mtdchar_lseek()` prevents seeking beyond mtd->size, but the
> > pread/pwrite syscalls bypass this.
> >
> > I haven't found any codepath on which this actually causes dangerous
> > behavior, but it seems like a sensible change anyway.
> >
> > Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> > Signed-off-by: Jann Horn <jannh@google.com>
> > ---
> > drivers/mtd/mtdchar.c | 10 +++++++---
> > 1 file changed, 7 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
> > index cd67c85cc87d..02389528f622 100644
> > --- a/drivers/mtd/mtdchar.c
> > +++ b/drivers/mtd/mtdchar.c
> > @@ -160,8 +160,12 @@ static ssize_t mtdchar_read(struct file *file, char __user *buf, size_t count,
> >
> > pr_debug("MTD_read\n");
> >
> > - if (*ppos + count > mtd->size)
> > - count = mtd->size - *ppos;
> > + if (*ppos + count > mtd->size) {
> > + if (*ppos < mtd->size)
> > + count = mtd->size - *ppos;
> > + else
> > + count = 0;
> > + }
>
> Hm, shouldn't we return -ERANGE or -EINVAL if *ppos >= mtd->size?
Hmm, good question.
The pread() manpage says that pread() can return the same errors as
lseek(), and the lseek() manpage says that -EINVAL is for when you're
trying to seek beyond the end of a seekable device. So from the
documentation, it sounds as if you're right.
But testing pread() beyond end of file for various things on my
machine seems to just return 0:
# cat pread.c
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
char buf[0x1000];
off_t off = strtoul(argv[1], NULL, 0);
pread(0, buf, 0x1000, off);
}
# gcc -o pread pread.c
# strace -e trace=pread64 ./pread 200000000 < /dev/sda1
pread64(0, "", 4096, 200000000) = 0
+++ exited with 0 +++
# strace -e trace=pread64 ./pread 100000 <
/sys/kernel/debug/x86/tlb_single_page_flush_ceiling
pread64(0, "", 4096, 100000) = 0
+++ exited with 0 +++
# strace -e trace=pread64 ./pread 20000000000 < /dev/dm-2
pread64(0, "", 4096, 20000000000) = 0
+++ exited with 0 +++
Do you know of precedent for returning -EINVAL if *ppos is beyond the
end of the device?
> >
> > if (!count)
> > return 0;
> > @@ -246,7 +250,7 @@ static ssize_t mtdchar_write(struct file *file, const char __user *buf, size_t c
> >
> > pr_debug("MTD_write\n");
> >
> > - if (*ppos == mtd->size)
> > + if (*ppos >= mtd->size)
> > return -ENOSPC;
> >
> > if (*ppos + count > mtd->size)
>
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply
* Re: [RFC PATCH for 4.18 3/5] rseq: uapi: declare rseq_cs field as union, update includes
From: Russell King - ARM Linux @ 2018-07-07 15:06 UTC (permalink / raw)
To: Linus Torvalds
Cc: Mathieu Desnoyers, Thomas Gleixner, Linux Kernel Mailing List,
Linux API, Peter Zijlstra, Paul McKenney, Boqun Feng,
Andy Lutomirski, Dave Watson, Paul Turner, Andrew Morton,
Ingo Molnar, Peter Anvin, Andi Kleen, Christoph Lameter,
Ben Maurer, Steven Rostedt, Josh Triplett, Catalin Marinas,
Will Deacon
In-Reply-To: <CA+55aFzuxGtPE2NnL9+K4=OQ=-9oAXSqX-mP_QiHpzBz7zrq6A@mail.gmail.com>
On Fri, Jul 06, 2018 at 12:56:58PM -0700, Linus Torvalds wrote:
> On Fri, Jul 6, 2018 at 12:38 PM Mathieu Desnoyers
> <mathieu.desnoyers@efficios.com> wrote:
> >
> > Should I change all 4 bytes __get_user()/__put_user() in kernel/rseq.c
> > for get_user()/put_user() to ensure consistency ?
>
> Probably.
>
> *If* this actually turns out to be somethinig that shows up on
> profiles, it's almost certainly going to be the STAC/CLAC instructions
> ("perf report" tends to report them as three one-byte nop's because
> that's how they look before instruction replacement).
>
> And then it's not __get/put_user() that will improve things, but doing a
>
> user_access_begin();
>
> .. do unsafe_get/put_user() ..
>
> user_access_end();
>
> that will improve performance.
>
> But it is *very* seldom useful. We have it in a handful of places in
> the kernel, and the most noticeable one is
> lib/{strnlen,strncpy_from}_user.c
Also, __get_user() is probably going to become the same as get_user()
when I finish the Spectre v1 ARM mitigations, because there'll be no
point in __get_user() being any different. For those mitigations,
we're going to have to check the pointer against the address limit
inside __get_user() and NULL it out, just like get_user() does, which
makes the whole distinction between the two completely pointless.
Is this not also the case on other architectures affected by Spectre
variant 1, hmm?
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 13.8Mbps down 630kbps up
According to speedtest.net: 13Mbps down 490kbps up
^ permalink raw reply
* Re: [PATCH] mtdchar: fix overflows in adjustment of `count`
From: Boris Brezillon @ 2018-07-08 12:45 UTC (permalink / raw)
To: Jann Horn
Cc: richard, kernel list, marek.vasut, linux-mtd, Linux API,
computersforpeace, dwmw2
In-Reply-To: <CAG48ez3MUm=0iJSY21BNOFBJt=gWgGAQTwM8cz5d_wNwpMyQeg@mail.gmail.com>
On Sat, 7 Jul 2018 11:03:00 +0200
Jann Horn <jannh@google.com> wrote:
> +cc linux-api
>
> On Sat, Jul 7, 2018 at 10:44 AM Boris Brezillon
> <boris.brezillon@bootlin.com> wrote:
> >
> > On Sat, 7 Jul 2018 05:37:22 +0200
> > Jann Horn <jannh@google.com> wrote:
> >
> > > The first checks in mtdchar_read() and mtdchar_write() attempt to limit
> > > `count` such that `*ppos + count <= mtd->size`. However, they ignore the
> > > possibility of `*ppos > mtd->size`, allowing the calculation of `count` to
> > > wrap around. `mtdchar_lseek()` prevents seeking beyond mtd->size, but the
> > > pread/pwrite syscalls bypass this.
> > >
> > > I haven't found any codepath on which this actually causes dangerous
> > > behavior, but it seems like a sensible change anyway.
> > >
> > > Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> > > Signed-off-by: Jann Horn <jannh@google.com>
> > > ---
> > > drivers/mtd/mtdchar.c | 10 +++++++---
> > > 1 file changed, 7 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
> > > index cd67c85cc87d..02389528f622 100644
> > > --- a/drivers/mtd/mtdchar.c
> > > +++ b/drivers/mtd/mtdchar.c
> > > @@ -160,8 +160,12 @@ static ssize_t mtdchar_read(struct file *file, char __user *buf, size_t count,
> > >
> > > pr_debug("MTD_read\n");
> > >
> > > - if (*ppos + count > mtd->size)
> > > - count = mtd->size - *ppos;
> > > + if (*ppos + count > mtd->size) {
> > > + if (*ppos < mtd->size)
> > > + count = mtd->size - *ppos;
> > > + else
> > > + count = 0;
> > > + }
> >
> > Hm, shouldn't we return -ERANGE or -EINVAL if *ppos >= mtd->size?
>
> Hmm, good question.
> The pread() manpage says that pread() can return the same errors as
> lseek(), and the lseek() manpage says that -EINVAL is for when you're
> trying to seek beyond the end of a seekable device. So from the
> documentation, it sounds as if you're right.
> But testing pread() beyond end of file for various things on my
> machine seems to just return 0:
>
> # cat pread.c
> #include <unistd.h>
> #include <stdlib.h>
> int main(int argc, char **argv) {
> char buf[0x1000];
> off_t off = strtoul(argv[1], NULL, 0);
> pread(0, buf, 0x1000, off);
> }
> # gcc -o pread pread.c
> # strace -e trace=pread64 ./pread 200000000 < /dev/sda1
> pread64(0, "", 4096, 200000000) = 0
> +++ exited with 0 +++
> # strace -e trace=pread64 ./pread 100000 <
> /sys/kernel/debug/x86/tlb_single_page_flush_ceiling
> pread64(0, "", 4096, 100000) = 0
> +++ exited with 0 +++
> # strace -e trace=pread64 ./pread 20000000000 < /dev/dm-2
> pread64(0, "", 4096, 20000000000) = 0
> +++ exited with 0 +++
>
> Do you know of precedent for returning -EINVAL if *ppos is beyond the
> end of the device?
Nope, it just made more sense to me than returning 0. Anyway, let's
keep the most common behavior, even if it's not documented this way ;-).
>
> > >
> > > if (!count)
> > > return 0;
> > > @@ -246,7 +250,7 @@ static ssize_t mtdchar_write(struct file *file, const char __user *buf, size_t c
> > >
> > > pr_debug("MTD_write\n");
> > >
> > > - if (*ppos == mtd->size)
> > > + if (*ppos >= mtd->size)
> > > return -ENOSPC;
> > >
> > > if (*ppos + count > mtd->size)
> >
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
^ permalink raw reply
* Re: [PATCH 7/7] aio: implement io_pgetevents
From: Christoph Hellwig @ 2018-07-08 20:44 UTC (permalink / raw)
To: Adrian Reber
Cc: Christoph Hellwig, viro, Avi Kivity, linux-aio, linux-fsdevel,
linux-api, linux-kernel
In-Reply-To: <20180704142116.GM17048@lisas.de>
On Wed, Jul 04, 2018 at 04:21:16PM +0200, Adrian Reber wrote:
> In file included from /usr/include/linux/signal.h:5,
> from /usr/include/linux/aio_abi.h:32,
> from include.c:2:
> /usr/include/asm/signal.h:16:23: error: conflicting types for ‘sigset_t’
> typedef unsigned long sigset_t;
> ^~~~~~~~
> In file included from /usr/include/signal.h:35,
> from include.c:1:
> /usr/include/bits/types/sigset_t.h:7:20: note: previous declaration of ‘sigset_t’ was here
> typedef __sigset_t sigset_t;
I guess we could do something like the patch below, although it is
rather ugly:
diff --git a/include/uapi/linux/aio_abi.h b/include/uapi/linux/aio_abi.h
index 75846164290e..b7705ad66d78 100644
--- a/include/uapi/linux/aio_abi.h
+++ b/include/uapi/linux/aio_abi.h
@@ -29,7 +29,11 @@
#include <linux/types.h>
#include <linux/fs.h>
+#ifdef __KERNEL__
#include <linux/signal.h>
+#else
+#include <signal.h>
+#endif
#include <asm/byteorder.h>
typedef __kernel_ulong_t aio_context_t;
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply related
* [PATCH for 4.18 0/6] Restartable Sequences updates
From: Mathieu Desnoyers @ 2018-07-08 21:03 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E . McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Ingo Molnar, H . Peter Anvin,
Andi Kleen, Chris Lameter, Ben Maurer, Steven Rostedt,
Josh Triplett, Linus Torvalds, Catalin Marinas, Will Deacon,
Michael Kerrisk
Following the recent discussion thread [1] about rseq uapi, here is
a set of updates submitted for integration into 4.18. Those change all
rseq __get_user/__put_user for get_user/put_user as discussed.
Thanks,
Mathieu
[1] https://lkml.kernel.org/r/20180702223143.4663-1-mathieu.desnoyers@efficios.com
Mathieu Desnoyers (6):
rseq: use __u64 for rseq_cs fields, validate user inputs
rseq: use get_user/put_user rather than __get_user/__put_user
rseq: uapi: update uapi comments
rseq: uapi: declare rseq_cs field as union, update includes
rseq: remove unused types_32_64.h uapi header
rseq/selftests: cleanup: update comment above rseq_prepare_unload
include/uapi/linux/rseq.h | 102 ++++++++++++++++++++----------------
include/uapi/linux/types_32_64.h | 50 ------------------
kernel/rseq.c | 36 ++++++++-----
tools/testing/selftests/rseq/rseq.h | 24 ++++++---
4 files changed, 97 insertions(+), 115 deletions(-)
delete mode 100644 include/uapi/linux/types_32_64.h
--
2.11.0
^ permalink raw reply
* [PATCH for 4.18 1/6] rseq: use __u64 for rseq_cs fields, validate user inputs
From: Mathieu Desnoyers @ 2018-07-08 21:03 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E . McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Ingo Molnar, H . Peter Anvin,
Andi Kleen, Chris Lameter, Ben Maurer, Steven Rostedt,
Josh Triplett, Linus Torvalds, Catalin Marinas, Will Deacon,
Michael Kerrisk
In-Reply-To: <20180708210330.27324-1-mathieu.desnoyers@efficios.com>
Change the rseq ABI so rseq_cs start_ip, post_commit_offset and abort_ip
fields are seen as 64-bit fields by both 32-bit and 64-bit kernels rather
that ignoring the 32 upper bits on 32-bit kernels. This ensures we have a
consistent behavior for a 32-bit binary executed on 32-bit kernels and in
compat mode on 64-bit kernels.
Validating the value of abort_ip field to be below TASK_SIZE ensures the
kernel don't return to an invalid address when returning to userspace
after an abort. I don't fully trust each architecture code to consistently
deal with invalid return addresses.
Validating the value of the start_ip and post_commit_offset fields
prevents overflow on arithmetic performed on those values, used to
check whether abort_ip is within the rseq critical section.
If validation fails, the process is killed with a segmentation fault.
When the signature encountered before abort_ip does not match the expected
signature, return -EINVAL rather than -EPERM to be consistent with other
input validation return codes from rseq_get_rseq_cs().
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: Paul Turner <pjt@google.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Andi Kleen <andi@firstfloor.org>
CC: Dave Watson <davejwatson@fb.com>
CC: Chris Lameter <cl@linux.com>
CC: Ingo Molnar <mingo@redhat.com>
CC: "H. Peter Anvin" <hpa@zytor.com>
CC: Ben Maurer <bmaurer@fb.com>
CC: Steven Rostedt <rostedt@goodmis.org>
CC: Josh Triplett <josh@joshtriplett.org>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Russell King <linux@arm.linux.org.uk>
CC: Catalin Marinas <catalin.marinas@arm.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Michael Kerrisk <mtk.manpages@gmail.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: linux-api@vger.kernel.org
---
include/uapi/linux/rseq.h | 6 +++---
kernel/rseq.c | 14 ++++++++++----
2 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/include/uapi/linux/rseq.h b/include/uapi/linux/rseq.h
index d620fa43756c..519ad6e176d1 100644
--- a/include/uapi/linux/rseq.h
+++ b/include/uapi/linux/rseq.h
@@ -52,10 +52,10 @@ struct rseq_cs {
__u32 version;
/* enum rseq_cs_flags */
__u32 flags;
- LINUX_FIELD_u32_u64(start_ip);
+ __u64 start_ip;
/* Offset from start_ip. */
- LINUX_FIELD_u32_u64(post_commit_offset);
- LINUX_FIELD_u32_u64(abort_ip);
+ __u64 post_commit_offset;
+ __u64 abort_ip;
} __attribute__((aligned(4 * sizeof(__u64))));
/*
diff --git a/kernel/rseq.c b/kernel/rseq.c
index 22b6acf1ad63..16b38c5342f9 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -130,14 +130,20 @@ static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs)
urseq_cs = (struct rseq_cs __user *)ptr;
if (copy_from_user(rseq_cs, urseq_cs, sizeof(*rseq_cs)))
return -EFAULT;
- if (rseq_cs->version > 0)
- return -EINVAL;
+ if (rseq_cs->start_ip >= TASK_SIZE ||
+ rseq_cs->start_ip + rseq_cs->post_commit_offset >= TASK_SIZE ||
+ rseq_cs->abort_ip >= TASK_SIZE ||
+ rseq_cs->version > 0)
+ return -EINVAL;
+ /* Check for overflow. */
+ if (rseq_cs->start_ip + rseq_cs->post_commit_offset < rseq_cs->start_ip)
+ return -EINVAL;
/* Ensure that abort_ip is not in the critical section. */
if (rseq_cs->abort_ip - rseq_cs->start_ip < rseq_cs->post_commit_offset)
return -EINVAL;
- usig = (u32 __user *)(rseq_cs->abort_ip - sizeof(u32));
+ usig = (u32 __user *)(unsigned long)(rseq_cs->abort_ip - sizeof(u32));
ret = get_user(sig, usig);
if (ret)
return ret;
@@ -146,7 +152,7 @@ static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs)
printk_ratelimited(KERN_WARNING
"Possible attack attempt. Unexpected rseq signature 0x%x, expecting 0x%x (pid=%d, addr=%p).\n",
sig, current->rseq_sig, current->pid, usig);
- return -EPERM;
+ return -EINVAL;
}
return 0;
}
--
2.11.0
^ permalink raw reply related
* [PATCH for 4.18 2/6] rseq: use get_user/put_user rather than __get_user/__put_user
From: Mathieu Desnoyers @ 2018-07-08 21:03 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E . McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Ingo Molnar, H . Peter Anvin,
Andi Kleen, Chris Lameter, Ben Maurer, Steven Rostedt,
Josh Triplett, Linus Torvalds, Catalin Marinas, Will Deacon,
Michael Kerrisk
In-Reply-To: <20180708210330.27324-1-mathieu.desnoyers@efficios.com>
In preparation to use __u64 for the rseq_cs pointer field, 32-bit
architectures need to read this 64-bit value located in user-space
addresses.
__get_user is used to read this value, given that its access check has
already been performed with access_ok() on rseq registration.
arm does not implement 8-byte __get_user. Rather than trying to
improve __get_user on ARM, use get_user/put_user across rseq instead.
If those end up showing up in benchmarks, the proper approach would be to
use user_access_begin() / unsafe_get/put_user() / user_access_end()
anyway.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: Thomas Gleixner <tglx@linutronix.de>
Cc: Joel Fernandes <joelaf@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Watson <davejwatson@fb.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: "H . Peter Anvin" <hpa@zytor.com>
Cc: Chris Lameter <cl@linux.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Andrew Hunter <ahh@google.com>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: "Paul E . McKenney" <paulmck@linux.vnet.ibm.com>
Cc: Paul Turner <pjt@google.com>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Josh Triplett <josh@joshtriplett.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Ben Maurer <bmaurer@fb.com>
Cc: linux-api@vger.kernel.org
CC: linux-arm-kernel@lists.infradead.org
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
---
kernel/rseq.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/kernel/rseq.c b/kernel/rseq.c
index 16b38c5342f9..2c8463acb50d 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -85,9 +85,9 @@ static int rseq_update_cpu_id(struct task_struct *t)
{
u32 cpu_id = raw_smp_processor_id();
- if (__put_user(cpu_id, &t->rseq->cpu_id_start))
+ if (put_user(cpu_id, &t->rseq->cpu_id_start))
return -EFAULT;
- if (__put_user(cpu_id, &t->rseq->cpu_id))
+ if (put_user(cpu_id, &t->rseq->cpu_id))
return -EFAULT;
trace_rseq_update(t);
return 0;
@@ -100,14 +100,14 @@ static int rseq_reset_rseq_cpu_id(struct task_struct *t)
/*
* Reset cpu_id_start to its initial state (0).
*/
- if (__put_user(cpu_id_start, &t->rseq->cpu_id_start))
+ if (put_user(cpu_id_start, &t->rseq->cpu_id_start))
return -EFAULT;
/*
* Reset cpu_id to RSEQ_CPU_ID_UNINITIALIZED, so any user coming
* in after unregistration can figure out that rseq needs to be
* registered again.
*/
- if (__put_user(cpu_id, &t->rseq->cpu_id))
+ if (put_user(cpu_id, &t->rseq->cpu_id))
return -EFAULT;
return 0;
}
@@ -120,7 +120,7 @@ static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs)
u32 sig;
int ret;
- ret = __get_user(ptr, &t->rseq->rseq_cs);
+ ret = get_user(ptr, &t->rseq->rseq_cs);
if (ret)
return ret;
if (!ptr) {
@@ -163,7 +163,7 @@ static int rseq_need_restart(struct task_struct *t, u32 cs_flags)
int ret;
/* Get thread flags. */
- ret = __get_user(flags, &t->rseq->flags);
+ ret = get_user(flags, &t->rseq->flags);
if (ret)
return ret;
@@ -203,7 +203,7 @@ static int clear_rseq_cs(struct task_struct *t)
*
* Set rseq_cs to NULL with single-copy atomicity.
*/
- return __put_user(0UL, &t->rseq->rseq_cs);
+ return put_user(0UL, &t->rseq->rseq_cs);
}
/*
--
2.11.0
^ permalink raw reply related
* [PATCH for 4.18 3/6] rseq: uapi: update uapi comments
From: Mathieu Desnoyers @ 2018-07-08 21:03 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E . McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Ingo Molnar, H . Peter Anvin,
Andi Kleen, Chris Lameter, Ben Maurer, Steven Rostedt,
Josh Triplett, Linus Torvalds, Catalin Marinas, Will Deacon,
Michael Kerrisk
In-Reply-To: <20180708210330.27324-1-mathieu.desnoyers@efficios.com>
Update rseq uapi header comments to reflect that user-space need to do
thread-local loads/stores from/to the struct rseq fields.
As a consequence of this added requirement, the kernel does not need
to perform loads/stores with single-copy atomicity.
Update the comment associated to the "flags" fields to describe
more accurately that it's only useful to facilitate single-stepping
through rseq critical sections with debuggers.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: Paul Turner <pjt@google.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Andi Kleen <andi@firstfloor.org>
CC: Dave Watson <davejwatson@fb.com>
CC: Chris Lameter <cl@linux.com>
CC: Ingo Molnar <mingo@redhat.com>
CC: "H. Peter Anvin" <hpa@zytor.com>
CC: Ben Maurer <bmaurer@fb.com>
CC: Steven Rostedt <rostedt@goodmis.org>
CC: Josh Triplett <josh@joshtriplett.org>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Russell King <linux@arm.linux.org.uk>
CC: Catalin Marinas <catalin.marinas@arm.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Michael Kerrisk <mtk.manpages@gmail.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: linux-api@vger.kernel.org
---
include/uapi/linux/rseq.h | 69 ++++++++++++++++++++++++-----------------------
kernel/rseq.c | 2 +-
2 files changed, 37 insertions(+), 34 deletions(-)
diff --git a/include/uapi/linux/rseq.h b/include/uapi/linux/rseq.h
index 519ad6e176d1..bf4188c13bec 100644
--- a/include/uapi/linux/rseq.h
+++ b/include/uapi/linux/rseq.h
@@ -67,28 +67,30 @@ struct rseq_cs {
struct rseq {
/*
* Restartable sequences cpu_id_start field. Updated by the
- * kernel, and read by user-space with single-copy atomicity
- * semantics. Aligned on 32-bit. Always contains a value in the
- * range of possible CPUs, although the value may not be the
- * actual current CPU (e.g. if rseq is not initialized). This
- * CPU number value should always be compared against the value
- * of the cpu_id field before performing a rseq commit or
- * returning a value read from a data structure indexed using
- * the cpu_id_start value.
+ * kernel. Read by user-space with single-copy atomicity
+ * semantics. This field should only be read by the thread which
+ * registered this data structure. Aligned on 32-bit. Always
+ * contains a value in the range of possible CPUs, although the
+ * value may not be the actual current CPU (e.g. if rseq is not
+ * initialized). This CPU number value should always be compared
+ * against the value of the cpu_id field before performing a rseq
+ * commit or returning a value read from a data structure indexed
+ * using the cpu_id_start value.
*/
__u32 cpu_id_start;
/*
- * Restartable sequences cpu_id field. Updated by the kernel,
- * and read by user-space with single-copy atomicity semantics.
- * Aligned on 32-bit. Values RSEQ_CPU_ID_UNINITIALIZED and
- * RSEQ_CPU_ID_REGISTRATION_FAILED have a special semantic: the
- * former means "rseq uninitialized", and latter means "rseq
- * initialization failed". This value is meant to be read within
- * rseq critical sections and compared with the cpu_id_start
- * value previously read, before performing the commit instruction,
- * or read and compared with the cpu_id_start value before returning
- * a value loaded from a data structure indexed using the
- * cpu_id_start value.
+ * Restartable sequences cpu_id field. Updated by the kernel.
+ * Read by user-space with single-copy atomicity semantics. This
+ * field should only be read by the thread which registered this
+ * data structure. Aligned on 32-bit. Values
+ * RSEQ_CPU_ID_UNINITIALIZED and RSEQ_CPU_ID_REGISTRATION_FAILED
+ * have a special semantic: the former means "rseq uninitialized",
+ * and latter means "rseq initialization failed". This value is
+ * meant to be read within rseq critical sections and compared
+ * with the cpu_id_start value previously read, before performing
+ * the commit instruction, or read and compared with the
+ * cpu_id_start value before returning a value loaded from a data
+ * structure indexed using the cpu_id_start value.
*/
__u32 cpu_id;
/*
@@ -105,27 +107,28 @@ struct rseq {
* targeted by the rseq_cs. Also needs to be set to NULL by user-space
* before reclaiming memory that contains the targeted struct rseq_cs.
*
- * Read and set by the kernel with single-copy atomicity semantics.
- * Set by user-space with single-copy atomicity semantics. Aligned
- * on 64-bit.
+ * Read and set by the kernel. Set by user-space with single-copy
+ * atomicity semantics. This field should only be updated by the
+ * thread which registered this data structure. Aligned on 64-bit.
*/
LINUX_FIELD_u32_u64(rseq_cs);
/*
- * - RSEQ_DISABLE flag:
+ * Restartable sequences flags field.
+ *
+ * This field should only be updated by the thread which
+ * registered this data structure. Read by the kernel.
+ * Mainly used for single-stepping through rseq critical sections
+ * with debuggers.
*
- * Fallback fast-track flag for single-stepping.
- * Set by user-space if lack of progress is detected.
- * Cleared by user-space after rseq finish.
- * Read by the kernel.
* - RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT
- * Inhibit instruction sequence block restart and event
- * counter increment on preemption for this thread.
+ * Inhibit instruction sequence block restart on preemption
+ * for this thread.
* - RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL
- * Inhibit instruction sequence block restart and event
- * counter increment on signal delivery for this thread.
+ * Inhibit instruction sequence block restart on signal
+ * delivery for this thread.
* - RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE
- * Inhibit instruction sequence block restart and event
- * counter increment on migration for this thread.
+ * Inhibit instruction sequence block restart on migration for
+ * this thread.
*/
__u32 flags;
} __attribute__((aligned(4 * sizeof(__u64))));
diff --git a/kernel/rseq.c b/kernel/rseq.c
index 2c8463acb50d..2a7748675be7 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -201,7 +201,7 @@ static int clear_rseq_cs(struct task_struct *t)
* of code outside of the rseq assembly block. This performs
* a lazy clear of the rseq_cs field.
*
- * Set rseq_cs to NULL with single-copy atomicity.
+ * Set rseq_cs to NULL.
*/
return put_user(0UL, &t->rseq->rseq_cs);
}
--
2.11.0
^ permalink raw reply related
* [PATCH for 4.18 4/6] rseq: uapi: declare rseq_cs field as union, update includes
From: Mathieu Desnoyers @ 2018-07-08 21:03 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E . McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Ingo Molnar, H . Peter Anvin,
Andi Kleen, Chris Lameter, Ben Maurer, Steven Rostedt,
Josh Triplett, Linus Torvalds, Catalin Marinas, Will Deacon,
Michael Kerrisk
In-Reply-To: <20180708210330.27324-1-mathieu.desnoyers@efficios.com>
Declaring the rseq_cs field as a union between __u64 and two __u32
allows both 32-bit and 64-bit kernels to read the full __u64, and
therefore validate that a 32-bit user-space cleared the upper 32
bits, thus ensuring a consistent behavior between native 32-bit
kernels and 32-bit compat tasks on 64-bit kernels.
Check that the rseq_cs value read is < TASK_SIZE.
The asm/byteorder.h header needs to be included by rseq.h, now
that it is not using linux/types_32_64.h anymore.
Considering that only __32 and __u64 types are declared in linux/rseq.h,
the linux/types.h header should always be included for both kernel and
user-space code: including stdint.h is just for u64 and u32, which are
not used in this header at all.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: Paul Turner <pjt@google.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Andi Kleen <andi@firstfloor.org>
CC: Dave Watson <davejwatson@fb.com>
CC: Chris Lameter <cl@linux.com>
CC: Ingo Molnar <mingo@redhat.com>
CC: "H. Peter Anvin" <hpa@zytor.com>
CC: Ben Maurer <bmaurer@fb.com>
CC: Steven Rostedt <rostedt@goodmis.org>
CC: Josh Triplett <josh@joshtriplett.org>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Russell King <linux@arm.linux.org.uk>
CC: Catalin Marinas <catalin.marinas@arm.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Michael Kerrisk <mtk.manpages@gmail.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: linux-api@vger.kernel.org
---
include/uapi/linux/rseq.h | 27 +++++++++++++++++++--------
kernel/rseq.c | 10 ++++++----
tools/testing/selftests/rseq/rseq.h | 11 ++++++++++-
3 files changed, 35 insertions(+), 13 deletions(-)
diff --git a/include/uapi/linux/rseq.h b/include/uapi/linux/rseq.h
index bf4188c13bec..9a402fdb60e9 100644
--- a/include/uapi/linux/rseq.h
+++ b/include/uapi/linux/rseq.h
@@ -10,13 +10,8 @@
* Copyright (c) 2015-2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*/
-#ifdef __KERNEL__
-# include <linux/types.h>
-#else
-# include <stdint.h>
-#endif
-
-#include <linux/types_32_64.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
enum rseq_cpu_id_state {
RSEQ_CPU_ID_UNINITIALIZED = -1,
@@ -111,7 +106,23 @@ struct rseq {
* atomicity semantics. This field should only be updated by the
* thread which registered this data structure. Aligned on 64-bit.
*/
- LINUX_FIELD_u32_u64(rseq_cs);
+ union {
+ __u64 ptr64;
+#ifdef __LP64__
+ __u64 ptr;
+#else
+ struct {
+#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 */
+ } ptr;
+#endif
+ } rseq_cs;
+
/*
* Restartable sequences flags field.
*
diff --git a/kernel/rseq.c b/kernel/rseq.c
index 2a7748675be7..fcc5ea1daa1f 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -115,19 +115,21 @@ 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;
- unsigned long ptr;
+ u64 ptr;
u32 __user *usig;
u32 sig;
int ret;
- ret = get_user(ptr, &t->rseq->rseq_cs);
+ ret = get_user(ptr, &t->rseq->rseq_cs.ptr64);
if (ret)
return ret;
if (!ptr) {
memset(rseq_cs, 0, sizeof(*rseq_cs));
return 0;
}
- urseq_cs = (struct rseq_cs __user *)ptr;
+ if (ptr >= TASK_SIZE)
+ return -EINVAL;
+ urseq_cs = (struct rseq_cs __user *)(unsigned long)ptr;
if (copy_from_user(rseq_cs, urseq_cs, sizeof(*rseq_cs)))
return -EFAULT;
@@ -203,7 +205,7 @@ static int clear_rseq_cs(struct task_struct *t)
*
* Set rseq_cs to NULL.
*/
- return put_user(0UL, &t->rseq->rseq_cs);
+ return put_user(0ULL, &t->rseq->rseq_cs.ptr64);
}
/*
diff --git a/tools/testing/selftests/rseq/rseq.h b/tools/testing/selftests/rseq/rseq.h
index a4684112676c..f2073cfa4448 100644
--- a/tools/testing/selftests/rseq/rseq.h
+++ b/tools/testing/selftests/rseq/rseq.h
@@ -133,6 +133,15 @@ static inline uint32_t rseq_current_cpu(void)
return cpu;
}
+static inline void rseq_clear_rseq_cs(void)
+{
+#ifdef __LP64__
+ __rseq_abi.rseq_cs.ptr = 0;
+#else
+ __rseq_abi.rseq_cs.ptr.ptr32 = 0;
+#endif
+}
+
/*
* rseq_prepare_unload() should be invoked by each thread using rseq_finish*()
* at least once between their last rseq_finish*() and library unload of the
@@ -143,7 +152,7 @@ static inline uint32_t rseq_current_cpu(void)
*/
static inline void rseq_prepare_unload(void)
{
- __rseq_abi.rseq_cs = 0;
+ rseq_clear_rseq_cs();
}
#endif /* RSEQ_H_ */
--
2.11.0
^ permalink raw reply related
* [PATCH for 4.18 5/6] rseq: remove unused types_32_64.h uapi header
From: Mathieu Desnoyers @ 2018-07-08 21:03 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E . McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Ingo Molnar, H . Peter Anvin,
Andi Kleen, Chris Lameter, Ben Maurer, Steven Rostedt,
Josh Triplett, Linus Torvalds, Catalin Marinas, Will Deacon,
Michael Kerrisk
In-Reply-To: <20180708210330.27324-1-mathieu.desnoyers@efficios.com>
This header was introduced in the 4.18 merge window, and rseq does
not need it anymore. Nuke it before the final release.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: Paul Turner <pjt@google.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Andi Kleen <andi@firstfloor.org>
CC: Dave Watson <davejwatson@fb.com>
CC: Chris Lameter <cl@linux.com>
CC: Ingo Molnar <mingo@redhat.com>
CC: "H. Peter Anvin" <hpa@zytor.com>
CC: Ben Maurer <bmaurer@fb.com>
CC: Steven Rostedt <rostedt@goodmis.org>
CC: Josh Triplett <josh@joshtriplett.org>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Russell King <linux@arm.linux.org.uk>
CC: Catalin Marinas <catalin.marinas@arm.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Michael Kerrisk <mtk.manpages@gmail.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: linux-api@vger.kernel.org
---
include/uapi/linux/types_32_64.h | 50 ----------------------------------------
1 file changed, 50 deletions(-)
delete mode 100644 include/uapi/linux/types_32_64.h
diff --git a/include/uapi/linux/types_32_64.h b/include/uapi/linux/types_32_64.h
deleted file mode 100644
index 0a87ace34a57..000000000000
--- a/include/uapi/linux/types_32_64.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-#ifndef _UAPI_LINUX_TYPES_32_64_H
-#define _UAPI_LINUX_TYPES_32_64_H
-
-/*
- * linux/types_32_64.h
- *
- * Integer type declaration for pointers across 32-bit and 64-bit systems.
- *
- * Copyright (c) 2015-2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- */
-
-#ifdef __KERNEL__
-# include <linux/types.h>
-#else
-# include <stdint.h>
-#endif
-
-#include <asm/byteorder.h>
-
-#ifdef __BYTE_ORDER
-# if (__BYTE_ORDER == __BIG_ENDIAN)
-# define LINUX_BYTE_ORDER_BIG_ENDIAN
-# else
-# define LINUX_BYTE_ORDER_LITTLE_ENDIAN
-# endif
-#else
-# ifdef __BIG_ENDIAN
-# define LINUX_BYTE_ORDER_BIG_ENDIAN
-# else
-# define LINUX_BYTE_ORDER_LITTLE_ENDIAN
-# endif
-#endif
-
-#ifdef __LP64__
-# define LINUX_FIELD_u32_u64(field) __u64 field
-# define LINUX_FIELD_u32_u64_INIT_ONSTACK(field, v) field = (intptr_t)v
-#else
-# ifdef LINUX_BYTE_ORDER_BIG_ENDIAN
-# define LINUX_FIELD_u32_u64(field) __u32 field ## _padding, field
-# define LINUX_FIELD_u32_u64_INIT_ONSTACK(field, v) \
- field ## _padding = 0, field = (intptr_t)v
-# else
-# define LINUX_FIELD_u32_u64(field) __u32 field, field ## _padding
-# define LINUX_FIELD_u32_u64_INIT_ONSTACK(field, v) \
- field = (intptr_t)v, field ## _padding = 0
-# endif
-#endif
-
-#endif /* _UAPI_LINUX_TYPES_32_64_H */
--
2.11.0
^ permalink raw reply related
* [PATCH for 4.18 6/6] rseq/selftests: cleanup: update comment above rseq_prepare_unload
From: Mathieu Desnoyers @ 2018-07-08 21:03 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E . McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Ingo Molnar, H . Peter Anvin,
Andi Kleen, Chris Lameter, Ben Maurer, Steven Rostedt,
Josh Triplett, Linus Torvalds, Catalin Marinas, Will Deacon,
Michael Kerrisk
In-Reply-To: <20180708210330.27324-1-mathieu.desnoyers@efficios.com>
rseq as it was merged does not have rseq_finish_*() in the user-space
selftests anymore. Update the rseq_prepare_unload() helper comment to
adapt to this reality.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: Paul Turner <pjt@google.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Andi Kleen <andi@firstfloor.org>
CC: Dave Watson <davejwatson@fb.com>
CC: Chris Lameter <cl@linux.com>
CC: Ingo Molnar <mingo@redhat.com>
CC: "H. Peter Anvin" <hpa@zytor.com>
CC: Ben Maurer <bmaurer@fb.com>
CC: Steven Rostedt <rostedt@goodmis.org>
CC: Josh Triplett <josh@joshtriplett.org>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Russell King <linux@arm.linux.org.uk>
CC: Catalin Marinas <catalin.marinas@arm.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Michael Kerrisk <mtk.manpages@gmail.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: linux-api@vger.kernel.org
---
tools/testing/selftests/rseq/rseq.h | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/tools/testing/selftests/rseq/rseq.h b/tools/testing/selftests/rseq/rseq.h
index f2073cfa4448..86ce22417e0d 100644
--- a/tools/testing/selftests/rseq/rseq.h
+++ b/tools/testing/selftests/rseq/rseq.h
@@ -143,12 +143,13 @@ static inline void rseq_clear_rseq_cs(void)
}
/*
- * rseq_prepare_unload() should be invoked by each thread using rseq_finish*()
- * at least once between their last rseq_finish*() and library unload of the
- * library defining the rseq critical section (struct rseq_cs). This also
- * applies to use of rseq in code generated by JIT: rseq_prepare_unload()
- * should be invoked at least once by each thread using rseq_finish*() before
- * reclaim of the memory holding the struct rseq_cs.
+ * rseq_prepare_unload() should be invoked by each thread executing a rseq
+ * critical section at least once between their last critical section and
+ * library unload of the library defining the rseq critical section
+ * (struct rseq_cs). This also applies to use of rseq in code generated by
+ * JIT: rseq_prepare_unload() should be invoked at least once by each
+ * thread executing a rseq critical section before reclaim of the memory
+ * holding the struct rseq_cs.
*/
static inline void rseq_prepare_unload(void)
{
--
2.11.0
^ permalink raw reply related
* Re: [PATCH for 4.18 0/6] Restartable Sequences updates
From: Linus Torvalds @ 2018-07-08 21:12 UTC (permalink / raw)
To: Mathieu Desnoyers
Cc: Thomas Gleixner, Linux Kernel Mailing List, Linux API,
Peter Zijlstra, Paul McKenney, Boqun Feng, Andy Lutomirski,
Dave Watson, Paul Turner, Andrew Morton, Russell King - ARM Linux,
Ingo Molnar, Peter Anvin, Andi Kleen, Christoph Lameter,
Ben Maurer, Steven Rostedt, Josh Triplett, Catalin Marinas,
Will Deacon
In-Reply-To: <20180708210330.27324-1-mathieu.desnoyers@efficios.com>
On Sun, Jul 8, 2018 at 2:03 PM Mathieu Desnoyers
<mathieu.desnoyers@efficios.com> wrote:
>
> Following the recent discussion thread [1] about rseq uapi, here is
> a set of updates submitted for integration into 4.18. Those change all
> rseq __get_user/__put_user for get_user/put_user as discussed.
LGTM, FWIW. I didn't test it, but the patches look sane.
Linus
^ permalink raw reply
* Re: [PATCH v7 00/29] FPGA Device Feature List (DFL) Device Drivers
From: Alan Tull @ 2018-07-09 16:34 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Wu Hao, Moritz Fischer, linux-fpga, linux-kernel, linux-api,
Kang, Luwei, Zhang, Yi Z
In-Reply-To: <1530320016-24712-1-git-send-email-hao.wu@intel.com>
On Fri, Jun 29, 2018 at 7:53 PM, Wu Hao <hao.wu@intel.com> wrote:
> Hi All,
>
> Here is v7 patch-series adding drivers for FPGA DFL devices.
Hi Greg,
Could you please take this v7 patchset for 4.19?
Alan
>
> This patch series provides a common framework to support FPGA Device
> Feature List (DFL) and also feature dev drivers under this DFL framework
> to provide interfaces for userspace applications to configure, enumerate,
> open and access FPGA accelerators on DFL based FPGA device and enables
> system level management functions such as FPGA partial reconfiguration,
> power management and virtualization.
>
> This patch series only adds the basic functions for FPGA accelerators and
> partial reconfiguration. Patches for more functions, e.g. power management
> and virtualization, will be submitted after this series gets reviewed.
>
> Note this patch series is only verified on DFL based Intel(R) FPGA PCIe
> devices (e.g. Intel Server Platform with In-package FPGA and Intel FPGA
> PCIe Acceleration Cards).
>
> Patch 1: add a document for FPGA DFL framework driver overview, including
> Device Feature List (DFL) introduction, the HW architecture, driver
> organization, device enumeration and opens.
>
> Patch 2: add region_id for fpga_image_info data structure, which allows
> driver to pass region id information to fpga-mgr for FPGA reconfiguration
> function. (Used by Patch 17)
>
> Patch 3: add a 'status' sysfs interface to fpga-mgr class, it reflects
> the status of the fpga-mgr including reconfiguration errors. (Used by
> Patch 18)
>
> Patch 4-5: add compat_id support in fpga manager and region, this compat
> id is used for compatibility check before further actions (e.g. partial
> reconfiguration). (Used by Patch 19 and 22)
>
> Patch 6-11: add FPGA device feature list support, it provides common
> enumeration interfaces which creates container device (FPGA base region)
> and all feature devices by walking through all the 'Device Feature Lists'
> provided low level drivers. A global list is added to DFL framework to
> manage port ops from different ports.
>
> Patch 12-13: implement FPGA PCIe device driver. It locates all 'Device
> Feature Lists' in PCIe device memory and invokes common interfaces from
> above device feature list framework to finish the enumeration.
>
> Patch 14-17: implement FPGA Management Engine (FME) driver. It's a
> platform driver matching with the FME platform device created by above
> device feature list framework during enumeration. Sysfs and device file
> ioctls are exposed as user interfaces to allow partial reconfiguration
> to Accelerated Function Units (AFUs) from user space applications.
>
> Patch 18-22: implement FPGA manager/bridge/region platform drivers for
> Intel FPGA Management Engine (FME). These platform drivers match with
> platform devices created by above FME driver, they use the generic
> fpga-mgr/bridge/region class infrastructure to implement FPGA partial
> reconfiguration function.
>
> Patch 23-28: implement FPGA Accelerated Function Unit (AFU) driver.
> It's a platform driver matching with AFU platform device created by above
> device feature list framework during enumeration. It provides user
> interfaces to expose the AFU MMIO region, map/unmap dma buffer and
> control the port which AFU connects to.
>
> Patch 29: add a entry in MAINTAINERS for this FPGA DFL drivers patchset.
>
> Changes from v6:
> - Improve Kconfig description, fix typos and other comments.
> - Update target kernelversion in sysfs doc.
> - Fix issues reported by kbuild.
> - Simplify pcie driver by using pcim_xxx functions.
>
> Changes from v5:
> - Improve functions/APIs naming per suggestion from Alan Tull.
> - Improve DFL framework code and comments to simplify the work for adding
> a new feature device support.
> - Correct the time in copyright and fix other comments from Alan Tull.
> - Add a entry in MAINTAINERS for this FPGA DFL drivers patchset.
>
> Changes from v4:
> - Update the dfl.txt documentation, remove descriptions for the APIs and
> features which are not implemented in this patch series.
> - Add DFL_ / dfl_ prefix for APIs and data structure, to avoid directly
> using fpga_xxx as definition.
> - Use "static region" and "PR bistream" instead of "blue bitstream" and
> "green bistream" in description to avoid misunderstanding.
> - Fix building issues caused by BIT() on 64bit register definition and
> missing correct header file for readq and writeq.
> - Remove port specific code in DFL framework and introduce port ops
> support to resolve the dependency issue between FME driver module and
> Port driver module. (more details in Patch 8).
> - Add compat id to fpga manager, as in case some hardware implements the
> compat id in fpga manager's register, not register belongs to fpga region
> and it's value is shared by all related fpga regions.
> - Pass mapped ioaddr to fme manager platform device from dfl-fme-pr via
> pdata.
> - Fix other comments from Alan and Moritze, including description
> improvement, coding style issue and etc.
>
> Changes from v3:
> - Fix SPDX license issue.
> - Rename documentation to dfl.txt, add introduction for Device Feature List
> (DFL) and re-organize the content.
> - Rename to FPGA Device Feature List (DFL) drivers from Intel FPGA device
> drivers for better reuse purposes. Unified driver and files to dfl-*.*
> - Remove static feature_info table from common enumeration code and switch
> to use feature id for sub feature driver matching.
> - Remove next_afu register checking for AFU from common enumeration code.
> - Remove interface_id sysfs for dfl-fme-mgr and use per fpga-region
> compat_id instead. (new patch 13, 15, 19).
> - Add more comments for driver data structures and functions.
> - Fix typos, issues in debug message/commit message and other places.
>
> Changes from v2:
> - Split common enumeration code from pcie driver to a separated module
> which for device feature list support.
> - Drop fpga-dev class and switch to use fpga base region as container.
> - Update the intel-fpga.txt documentation for new driver organization.
> - Rename feature device drivers for future code reuse.
> - Rebase code due to fpga APIs changes
> - replace bitfields with marco and shift.
> - fix typos, checkpatch issue and other comments.
>
> Changes from v1:
> - Use GPLv2 license instead of Dual BSD/GPL.
> - Move the code to drivers/fpga folder.
> - Update the intel-fpga.txt documentation for new driver organization.
> - Add documentation for new sysfs interfaces.
> - Switch to use common fpga-region interface for partial reconfiguration
> (PR) function in FME. It creates fpga-region/fpga-mgr/fpga-bridge
> platform devices and leave the implementation to their platform drivers.
> - Add platform drivers for FME fpga-mgr/bridge/region platform devices.
> - Fix kbuild warnings, typos and other comments.
>
> Kang Luwei (3):
> fpga: dfl: add FPGA Management Engine driver basic framework
> fpga: dfl: fme: add header sub feature support
> fpga: dfl: fme: add partial reconfiguration sub feature support
>
> Wu Hao (23):
> docs: fpga: add a document for FPGA Device Feature List (DFL)
> Framework Overview
> fpga: mgr: add region_id to fpga_image_info
> fpga: mgr: add status for fpga-manager
> fpga: mgr: add compat_id support
> fpga: region: add compat_id support
> fpga: add device feature list support
> fpga: dfl: add chardev support for feature devices
> fpga: dfl: add dfl_fpga_cdev_find_port
> fpga: dfl: add dfl_fpga_port_ops support.
> fpga: dfl: add dfl_fpga_check_port_id function.
> fpga: dfl-pci: add enumeration for feature devices
> fpga: dfl: fme: add DFL_FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls
> support
> fpga: dfl: add fpga manager platform driver for FME
> fpga: dfl: fme-mgr: add compat_id support
> fpga: dfl: add fpga bridge platform driver for FME
> fpga: dfl: add fpga region platform driver for FME
> fpga: dfl: fme-region: add support for compat_id
> fpga: dfl: add FPGA Accelerated Function Unit driver basic framework
> fpga: dfl: afu: add port ops support
> fpga: dfl: afu: add header sub feature support
> fpga: dfl: afu: add DFL_FPGA_GET_API_VERSION/CHECK_EXTENSION ioctls
> support
> fpga: dfl: afu: add DFL_FPGA_PORT_DMA_MAP/UNMAP ioctls support
> MAINTAINERS: add entry for FPGA DFL drivers
>
> Xiao Guangrong (2):
> fpga: dfl: add feature device infrastructure
> fpga: dfl: afu: add afu sub feature support
>
> Zhang Yi (1):
> fpga: add FPGA DFL PCIe device driver
>
> Documentation/ABI/testing/sysfs-class-fpga-manager | 24 +
> Documentation/ABI/testing/sysfs-class-fpga-region | 9 +
> Documentation/ABI/testing/sysfs-platform-dfl-fme | 23 +
> Documentation/ABI/testing/sysfs-platform-dfl-port | 16 +
> Documentation/fpga/dfl.txt | 285 ++++++
> Documentation/ioctl/ioctl-number.txt | 1 +
> MAINTAINERS | 8 +
> drivers/fpga/Kconfig | 68 ++
> drivers/fpga/Makefile | 14 +
> drivers/fpga/dfl-afu-dma-region.c | 463 +++++++++
> drivers/fpga/dfl-afu-main.c | 636 ++++++++++++
> drivers/fpga/dfl-afu-region.c | 166 ++++
> drivers/fpga/dfl-afu.h | 100 ++
> drivers/fpga/dfl-fme-br.c | 114 +++
> drivers/fpga/dfl-fme-main.c | 279 ++++++
> drivers/fpga/dfl-fme-mgr.c | 349 +++++++
> drivers/fpga/dfl-fme-pr.c | 479 +++++++++
> drivers/fpga/dfl-fme-pr.h | 84 ++
> drivers/fpga/dfl-fme-region.c | 89 ++
> drivers/fpga/dfl-fme.h | 38 +
> drivers/fpga/dfl-pci.c | 243 +++++
> drivers/fpga/dfl.c | 1044 ++++++++++++++++++++
> drivers/fpga/dfl.h | 410 ++++++++
> drivers/fpga/fpga-mgr.c | 28 +
> drivers/fpga/fpga-region.c | 22 +
> include/linux/fpga/fpga-mgr.h | 24 +
> include/linux/fpga/fpga-region.h | 2 +
> include/uapi/linux/fpga-dfl.h | 179 ++++
> 28 files changed, 5197 insertions(+)
> create mode 100644 Documentation/ABI/testing/sysfs-class-fpga-region
> create mode 100644 Documentation/ABI/testing/sysfs-platform-dfl-fme
> create mode 100644 Documentation/ABI/testing/sysfs-platform-dfl-port
> create mode 100644 Documentation/fpga/dfl.txt
> create mode 100644 drivers/fpga/dfl-afu-dma-region.c
> create mode 100644 drivers/fpga/dfl-afu-main.c
> create mode 100644 drivers/fpga/dfl-afu-region.c
> create mode 100644 drivers/fpga/dfl-afu.h
> create mode 100644 drivers/fpga/dfl-fme-br.c
> create mode 100644 drivers/fpga/dfl-fme-main.c
> create mode 100644 drivers/fpga/dfl-fme-mgr.c
> create mode 100644 drivers/fpga/dfl-fme-pr.c
> create mode 100644 drivers/fpga/dfl-fme-pr.h
> create mode 100644 drivers/fpga/dfl-fme-region.c
> create mode 100644 drivers/fpga/dfl-fme.h
> create mode 100644 drivers/fpga/dfl-pci.c
> create mode 100644 drivers/fpga/dfl.c
> create mode 100644 drivers/fpga/dfl.h
> create mode 100644 include/uapi/linux/fpga-dfl.h
>
> --
> 1.8.3.1
>
^ permalink raw reply
* Re: [PATCH 7/7] aio: implement io_pgetevents
From: Stephan Müller @ 2018-07-09 17:20 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Adrian Reber, viro, Avi Kivity, linux-aio, linux-fsdevel,
linux-api, linux-kernel, Ondrej Mosnacek
In-Reply-To: <20180708204359.GA19198@lst.de>
Am Sonntag, 8. Juli 2018, 22:44:00 CEST schrieb Christoph Hellwig:
Hi Christoph,
>
> diff --git a/include/uapi/linux/aio_abi.h b/include/uapi/linux/aio_abi.h
> index 75846164290e..b7705ad66d78 100644
> --- a/include/uapi/linux/aio_abi.h
> +++ b/include/uapi/linux/aio_abi.h
> @@ -29,7 +29,11 @@
>
> #include <linux/types.h>
> #include <linux/fs.h>
> +#ifdef __KERNEL__
> #include <linux/signal.h>
> +#else
> +#include <signal.h>
> +#endif
> #include <asm/byteorder.h>
Without such a patch, libkcapi fails to compile as well. See [1].
Apart from your suggested patch above, do you have another suggestion how make
the user space code compile?
[1] https://github.com/smuellerDD/libkcapi/issues/59
Thanks
Stephan
^ permalink raw reply
* Re: [PATCH for 4.18 2/6] rseq: use get_user/put_user rather than __get_user/__put_user
From: Mathieu Desnoyers @ 2018-07-09 17:28 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E. McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Ingo Molnar, H. Peter Anvin,
Andi Kleen, Chris Lameter, Ben Maurer, rostedt, Josh Triplett,
Linus Torvalds, Catalin Marinas, Will Deacon, Michael
In-Reply-To: <20180708210330.27324-3-mathieu.desnoyers@efficios.com>
----- On Jul 8, 2018, at 5:03 PM, Mathieu Desnoyers mathieu.desnoyers@efficios.com wrote:
> In preparation to use __u64 for the rseq_cs pointer field, 32-bit
> architectures need to read this 64-bit value located in user-space
> addresses.
>
> __get_user is used to read this value, given that its access check has
> already been performed with access_ok() on rseq registration.
>
> arm does not implement 8-byte __get_user. Rather than trying to
> improve __get_user on ARM, use get_user/put_user across rseq instead.
>
> If those end up showing up in benchmarks, the proper approach would be to
> use user_access_begin() / unsafe_get/put_user() / user_access_end()
> anyway.
So, another twist to this story: ppc32 does not implement u64 get_user().
I am tempted to ditch this patch (leaving the __get_user()/__put_user as is
for 32-bit accesses), and simply use __copy_from_user()/__copy_to_user() to
load/store the rseq_cs pointer. Considering that we don't need to load/store
the rseq_cs field with single-copy atomicity from the kernel anymore, it
should be fine.
Any objection ?
tree: https://git.kernel.org/pub/scm/linux/kernel/git/rseq/linux-rseq.git rseq/dev
head: a100323919af0c11a150a9ba58c3f8ac986ea42d
commit: 23d0f99d280fa97ebcf8b915157468f457bc6e11 [4/21] rseq: uapi: declare rseq_cs field as union, update includes
config: powerpc-ppc6xx_defconfig (attached as .config)
compiler: powerpc-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
git checkout 23d0f99d280fa97ebcf8b915157468f457bc6e11
# save the attached .config to linux build tree
GCC_VERSION=7.2.0 make.cross ARCH=powerpc
All errors (new ones prefixed by >>):
kernel/rseq.o: In function `__rseq_handle_notify_resume':
>> (.text+0x648): undefined reference to `__get_user_bad'
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Thanks,
Mathieu
>
> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> CC: Thomas Gleixner <tglx@linutronix.de>
> Cc: Joel Fernandes <joelaf@google.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Dave Watson <davejwatson@fb.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Andi Kleen <andi@firstfloor.org>
> Cc: "H . Peter Anvin" <hpa@zytor.com>
> Cc: Chris Lameter <cl@linux.com>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Andrew Hunter <ahh@google.com>
> Cc: Michael Kerrisk <mtk.manpages@gmail.com>
> Cc: "Paul E . McKenney" <paulmck@linux.vnet.ibm.com>
> Cc: Paul Turner <pjt@google.com>
> Cc: Boqun Feng <boqun.feng@gmail.com>
> Cc: Josh Triplett <josh@joshtriplett.org>
> Cc: Steven Rostedt <rostedt@goodmis.org>
> Cc: Ben Maurer <bmaurer@fb.com>
> Cc: linux-api@vger.kernel.org
> CC: linux-arm-kernel@lists.infradead.org
> Cc: Andy Lutomirski <luto@amacapital.net>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Linus Torvalds <torvalds@linux-foundation.org>
> ---
> kernel/rseq.c | 14 +++++++-------
> 1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/kernel/rseq.c b/kernel/rseq.c
> index 16b38c5342f9..2c8463acb50d 100644
> --- a/kernel/rseq.c
> +++ b/kernel/rseq.c
> @@ -85,9 +85,9 @@ static int rseq_update_cpu_id(struct task_struct *t)
> {
> u32 cpu_id = raw_smp_processor_id();
>
> - if (__put_user(cpu_id, &t->rseq->cpu_id_start))
> + if (put_user(cpu_id, &t->rseq->cpu_id_start))
> return -EFAULT;
> - if (__put_user(cpu_id, &t->rseq->cpu_id))
> + if (put_user(cpu_id, &t->rseq->cpu_id))
> return -EFAULT;
> trace_rseq_update(t);
> return 0;
> @@ -100,14 +100,14 @@ static int rseq_reset_rseq_cpu_id(struct task_struct *t)
> /*
> * Reset cpu_id_start to its initial state (0).
> */
> - if (__put_user(cpu_id_start, &t->rseq->cpu_id_start))
> + if (put_user(cpu_id_start, &t->rseq->cpu_id_start))
> return -EFAULT;
> /*
> * Reset cpu_id to RSEQ_CPU_ID_UNINITIALIZED, so any user coming
> * in after unregistration can figure out that rseq needs to be
> * registered again.
> */
> - if (__put_user(cpu_id, &t->rseq->cpu_id))
> + if (put_user(cpu_id, &t->rseq->cpu_id))
> return -EFAULT;
> return 0;
> }
> @@ -120,7 +120,7 @@ static int rseq_get_rseq_cs(struct task_struct *t, struct
> rseq_cs *rseq_cs)
> u32 sig;
> int ret;
>
> - ret = __get_user(ptr, &t->rseq->rseq_cs);
> + ret = get_user(ptr, &t->rseq->rseq_cs);
> if (ret)
> return ret;
> if (!ptr) {
> @@ -163,7 +163,7 @@ static int rseq_need_restart(struct task_struct *t, u32
> cs_flags)
> int ret;
>
> /* Get thread flags. */
> - ret = __get_user(flags, &t->rseq->flags);
> + ret = get_user(flags, &t->rseq->flags);
> if (ret)
> return ret;
>
> @@ -203,7 +203,7 @@ static int clear_rseq_cs(struct task_struct *t)
> *
> * Set rseq_cs to NULL with single-copy atomicity.
> */
> - return __put_user(0UL, &t->rseq->rseq_cs);
> + return put_user(0UL, &t->rseq->rseq_cs);
> }
>
> /*
> --
> 2.11.0
--
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com
^ permalink raw reply
* Re: [PATCH for 4.18 2/6] rseq: use get_user/put_user rather than __get_user/__put_user
From: Linus Torvalds @ 2018-07-09 18:04 UTC (permalink / raw)
To: Mathieu Desnoyers
Cc: Thomas Gleixner, Linux Kernel Mailing List, Linux API,
Peter Zijlstra, Paul McKenney, Boqun Feng, Andy Lutomirski,
Dave Watson, Paul Turner, Andrew Morton, Russell King - ARM Linux,
Ingo Molnar, Peter Anvin, Andi Kleen, Christoph Lameter,
Ben Maurer, Steven Rostedt, Josh Triplett, Catalin Marinas,
Will Deacon
In-Reply-To: <854203778.2272.1531157327328.JavaMail.zimbra@efficios.com>
On Mon, Jul 9, 2018 at 10:28 AM Mathieu Desnoyers
<mathieu.desnoyers@efficios.com> wrote:
>
> So, another twist to this story: ppc32 does not implement u64 get_user().
I was going to say that "that's not possible", since we actually have
64-bit arguments at least in the form of "loff_t __user *".
But when I started looking, it turns out that yeah, we do
"copy_from_user()" on them, and instead made the x86 copy_from_user()
have special cases for constant sizes.
So a 8-byte copy_from_user() is fine. It ends up being a "get_user()"
on x86 anyway.
Linus
^ permalink raw reply
* Re: [PATCH for 4.18 0/6] Restartable Sequences updates
From: Mathieu Desnoyers @ 2018-07-09 18:04 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E. McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Ingo Molnar, H. Peter Anvin,
Andi Kleen, Chris Lameter, Ben Maurer, rostedt, Josh Triplett,
Linus Torvalds, Catalin Marinas, Will Deacon, Michael
In-Reply-To: <20180708210330.27324-1-mathieu.desnoyers@efficios.com>
----- On Jul 8, 2018, at 5:03 PM, Mathieu Desnoyers mathieu.desnoyers@efficios.com wrote:
> Following the recent discussion thread [1] about rseq uapi, here is
> a set of updates submitted for integration into 4.18. Those change all
> rseq __get_user/__put_user for get_user/put_user as discussed.
Considering that ppc32 does not implement 64-bit get_user(), I will re-spin
the whole series using __copy_from_user/__copy_to_user() to replace
__get_user()/__put_user() to load/store the 64-bit rseq_cs field.
I'm aiming for a minimal change at this stage of the rc cycle.
Thanks,
Mathieu
>
> Thanks,
>
> Mathieu
>
> [1]
> https://lkml.kernel.org/r/20180702223143.4663-1-mathieu.desnoyers@efficios.com
>
> Mathieu Desnoyers (6):
> rseq: use __u64 for rseq_cs fields, validate user inputs
> rseq: use get_user/put_user rather than __get_user/__put_user
> rseq: uapi: update uapi comments
> rseq: uapi: declare rseq_cs field as union, update includes
> rseq: remove unused types_32_64.h uapi header
> rseq/selftests: cleanup: update comment above rseq_prepare_unload
>
> include/uapi/linux/rseq.h | 102 ++++++++++++++++++++----------------
> include/uapi/linux/types_32_64.h | 50 ------------------
> kernel/rseq.c | 36 ++++++++-----
> tools/testing/selftests/rseq/rseq.h | 24 ++++++---
> 4 files changed, 97 insertions(+), 115 deletions(-)
> delete mode 100644 include/uapi/linux/types_32_64.h
>
> --
> 2.11.0
--
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com
^ permalink raw reply
* Re: [PATCH for 4.18 2/6] rseq: use get_user/put_user rather than __get_user/__put_user
From: Mathieu Desnoyers @ 2018-07-09 18:19 UTC (permalink / raw)
To: Linus Torvalds
Cc: Thomas Gleixner, linux-kernel, linux-api, Peter Zijlstra,
Paul E. McKenney, Boqun Feng, Andy Lutomirski, Dave Watson,
Paul Turner, Andrew Morton, Russell King, Ingo Molnar,
H. Peter Anvin, Andi Kleen, Chris Lameter, Ben Maurer, rostedt,
Josh Triplett, Catalin Marinas, Will Deacon,
Michael Kerrisk <mtk.ma>
In-Reply-To: <CA+55aFzpjA3r9HdfCU5LrEhSt6S=+RfKuJ2GVc8Wv5Hz-_Me8Q@mail.gmail.com>
----- On Jul 9, 2018, at 2:04 PM, Linus Torvalds torvalds@linux-foundation.org wrote:
> On Mon, Jul 9, 2018 at 10:28 AM Mathieu Desnoyers
> <mathieu.desnoyers@efficios.com> wrote:
>>
>> So, another twist to this story: ppc32 does not implement u64 get_user().
>
> I was going to say that "that's not possible", since we actually have
> 64-bit arguments at least in the form of "loff_t __user *".
>
> But when I started looking, it turns out that yeah, we do
> "copy_from_user()" on them, and instead made the x86 copy_from_user()
> have special cases for constant sizes.
>
> So a 8-byte copy_from_user() is fine. It ends up being a "get_user()"
> on x86 anyway.
Given that this memory area has already been checked with access_ok()
on rseq registration, are you fine with leaving
__get_user/__put_user/__copy_{from,to}_user in place so we do the
minimal change at this stage of rc, or should I go ahead and replace
the lot with get_user/put_user/copy_{from,to}_user ?
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com
^ permalink raw reply
* Re: [PATCH for 4.18 2/6] rseq: use get_user/put_user rather than __get_user/__put_user
From: Linus Torvalds @ 2018-07-09 19:04 UTC (permalink / raw)
To: Mathieu Desnoyers
Cc: Thomas Gleixner, Linux Kernel Mailing List, Linux API,
Peter Zijlstra, Paul McKenney, Boqun Feng, Andy Lutomirski,
Dave Watson, Paul Turner, Andrew Morton, Russell King - ARM Linux,
Ingo Molnar, Peter Anvin, Andi Kleen, Christoph Lameter,
Ben Maurer, Steven Rostedt, Josh Triplett, Catalin Marinas,
Will Deacon
In-Reply-To: <1519037424.2393.1531160359475.JavaMail.zimbra@efficios.com>
On Mon, Jul 9, 2018 at 11:19 AM Mathieu Desnoyers
<mathieu.desnoyers@efficios.com> wrote:
>
> Given that this memory area has already been checked with access_ok()
> on rseq registration, are you fine with leaving
> __get_user/__put_user/__copy_{from,to}_user in place so we do the
> minimal change at this stage of rc, or should I go ahead and replace
> the lot with get_user/put_user/copy_{from,to}_user ?
Do the full replacement, and let's get this over and done with.
Linus
^ permalink raw reply
* Re: [PATCH 7/7] aio: implement io_pgetevents
From: Stephan Müller @ 2018-07-09 19:21 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Adrian Reber, viro, Avi Kivity, linux-aio, linux-fsdevel,
linux-api, linux-kernel, Ondrej Mosnacek
In-Reply-To: <20180708204359.GA19198@lst.de>
Am Sonntag, 8. Juli 2018, 22:44:00 CEST schrieb Christoph Hellwig:
Hi Christoph,
>
> diff --git a/include/uapi/linux/aio_abi.h b/include/uapi/linux/aio_abi.h
> index 75846164290e..b7705ad66d78 100644
> --- a/include/uapi/linux/aio_abi.h
> +++ b/include/uapi/linux/aio_abi.h
> @@ -29,7 +29,11 @@
>
> #include <linux/types.h>
> #include <linux/fs.h>
> +#ifdef __KERNEL__
> #include <linux/signal.h>
> +#else
> +#include <signal.h>
> +#endif
> #include <asm/byteorder.h>
Without such a patch, libkcapi fails to compile as well. See [1].
Apart from your suggested patch above, do you have another suggestion how make
the user space code compile?
[1] https://github.com/smuellerDD/libkcapi/issues/59
Thanks
Stephan
^ permalink raw reply
* [PATCH v2 for 4.18 0/6] Restartable Sequences updates
From: Mathieu Desnoyers @ 2018-07-09 19:51 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E . McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Ingo Molnar, H . Peter Anvin,
Andi Kleen, Chris Lameter, Ben Maurer, Steven Rostedt,
Josh Triplett, Linus Torvalds, Catalin Marinas, Will Deacon,
Michael Kerrisk
Following the recent discussion thread [1] about rseq uapi, here is
a set of updates submitted for integration into 4.18. Those change all
rseq __get_user/__put_user for get_user/put_user as discussed, and
use copy_from_user()/clear_user() to load and clear the rseq_cs __u64.
Thanks,
Mathieu
[1] https://lkml.kernel.org/r/20180702223143.4663-1-mathieu.desnoyers@efficios.com
Mathieu Desnoyers (6):
rseq: use __u64 for rseq_cs fields, validate user inputs
rseq: use get_user/put_user rather than __get_user/__put_user
rseq: uapi: update uapi comments
rseq: uapi: declare rseq_cs field as union, update includes
rseq: remove unused types_32_64.h uapi header
rseq/selftests: cleanup: update comment above rseq_prepare_unload
include/uapi/linux/rseq.h | 102 ++++++++++++++++++++----------------
include/uapi/linux/types_32_64.h | 50 ------------------
kernel/rseq.c | 41 +++++++++------
tools/testing/selftests/rseq/rseq.h | 24 ++++++---
4 files changed, 100 insertions(+), 117 deletions(-)
delete mode 100644 include/uapi/linux/types_32_64.h
--
2.11.0
^ permalink raw reply
* [PATCH for 4.18 1/6] rseq: use __u64 for rseq_cs fields, validate user inputs
From: Mathieu Desnoyers @ 2018-07-09 19:51 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E . McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Ingo Molnar, H . Peter Anvin,
Andi Kleen, Chris Lameter, Ben Maurer, Steven Rostedt,
Josh Triplett, Linus Torvalds, Catalin Marinas, Will Deacon,
Michael Kerrisk
In-Reply-To: <20180709195155.7654-1-mathieu.desnoyers@efficios.com>
Change the rseq ABI so rseq_cs start_ip, post_commit_offset and abort_ip
fields are seen as 64-bit fields by both 32-bit and 64-bit kernels rather
that ignoring the 32 upper bits on 32-bit kernels. This ensures we have a
consistent behavior for a 32-bit binary executed on 32-bit kernels and in
compat mode on 64-bit kernels.
Validating the value of abort_ip field to be below TASK_SIZE ensures the
kernel don't return to an invalid address when returning to userspace
after an abort. I don't fully trust each architecture code to consistently
deal with invalid return addresses.
Validating the value of the start_ip and post_commit_offset fields
prevents overflow on arithmetic performed on those values, used to
check whether abort_ip is within the rseq critical section.
If validation fails, the process is killed with a segmentation fault.
When the signature encountered before abort_ip does not match the expected
signature, return -EINVAL rather than -EPERM to be consistent with other
input validation return codes from rseq_get_rseq_cs().
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: Paul Turner <pjt@google.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Andi Kleen <andi@firstfloor.org>
CC: Dave Watson <davejwatson@fb.com>
CC: Chris Lameter <cl@linux.com>
CC: Ingo Molnar <mingo@redhat.com>
CC: "H. Peter Anvin" <hpa@zytor.com>
CC: Ben Maurer <bmaurer@fb.com>
CC: Steven Rostedt <rostedt@goodmis.org>
CC: Josh Triplett <josh@joshtriplett.org>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Russell King <linux@arm.linux.org.uk>
CC: Catalin Marinas <catalin.marinas@arm.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Michael Kerrisk <mtk.manpages@gmail.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: linux-api@vger.kernel.org
---
include/uapi/linux/rseq.h | 6 +++---
kernel/rseq.c | 14 ++++++++++----
2 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/include/uapi/linux/rseq.h b/include/uapi/linux/rseq.h
index d620fa43756c..519ad6e176d1 100644
--- a/include/uapi/linux/rseq.h
+++ b/include/uapi/linux/rseq.h
@@ -52,10 +52,10 @@ struct rseq_cs {
__u32 version;
/* enum rseq_cs_flags */
__u32 flags;
- LINUX_FIELD_u32_u64(start_ip);
+ __u64 start_ip;
/* Offset from start_ip. */
- LINUX_FIELD_u32_u64(post_commit_offset);
- LINUX_FIELD_u32_u64(abort_ip);
+ __u64 post_commit_offset;
+ __u64 abort_ip;
} __attribute__((aligned(4 * sizeof(__u64))));
/*
diff --git a/kernel/rseq.c b/kernel/rseq.c
index 22b6acf1ad63..16b38c5342f9 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -130,14 +130,20 @@ static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs)
urseq_cs = (struct rseq_cs __user *)ptr;
if (copy_from_user(rseq_cs, urseq_cs, sizeof(*rseq_cs)))
return -EFAULT;
- if (rseq_cs->version > 0)
- return -EINVAL;
+ if (rseq_cs->start_ip >= TASK_SIZE ||
+ rseq_cs->start_ip + rseq_cs->post_commit_offset >= TASK_SIZE ||
+ rseq_cs->abort_ip >= TASK_SIZE ||
+ rseq_cs->version > 0)
+ return -EINVAL;
+ /* Check for overflow. */
+ if (rseq_cs->start_ip + rseq_cs->post_commit_offset < rseq_cs->start_ip)
+ return -EINVAL;
/* Ensure that abort_ip is not in the critical section. */
if (rseq_cs->abort_ip - rseq_cs->start_ip < rseq_cs->post_commit_offset)
return -EINVAL;
- usig = (u32 __user *)(rseq_cs->abort_ip - sizeof(u32));
+ usig = (u32 __user *)(unsigned long)(rseq_cs->abort_ip - sizeof(u32));
ret = get_user(sig, usig);
if (ret)
return ret;
@@ -146,7 +152,7 @@ static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs)
printk_ratelimited(KERN_WARNING
"Possible attack attempt. Unexpected rseq signature 0x%x, expecting 0x%x (pid=%d, addr=%p).\n",
sig, current->rseq_sig, current->pid, usig);
- return -EPERM;
+ return -EINVAL;
}
return 0;
}
--
2.11.0
^ permalink raw reply related
* [PATCH for 4.18 2/6] rseq: use get_user/put_user rather than __get_user/__put_user
From: Mathieu Desnoyers @ 2018-07-09 19:51 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Joel Fernandes, Peter Zijlstra, Catalin Marinas, Dave Watson,
Will Deacon, Andi Kleen, H . Peter Anvin, Chris Lameter,
Russell King, Ingo Molnar, Michael Kerrisk, Paul E . McKenney,
Paul Turner, Boqun Feng, Josh Triplett, Steven Rostedt,
Ben Maurer, Mathieu Desnoyers, linux-arm-kernel, linux-api,
linux-kernel, Andy Lutomirski, Andrew Morton, Linus Torvalds
In-Reply-To: <20180709195155.7654-1-mathieu.desnoyers@efficios.com>
__get_user()/__put_user() is used to read values for address ranges that
were already checked with access_ok() on rseq registration.
It has been recognized that __get_user/__put_user are optimizing the
wrong thing. Replace them by get_user/put_user across rseq instead.
If those end up showing up in benchmarks, the proper approach would be to
use user_access_begin() / unsafe_{get,put}_user() / user_access_end()
anyway.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: Thomas Gleixner <tglx@linutronix.de>
Cc: Joel Fernandes <joelaf@google.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Watson <davejwatson@fb.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: "H . Peter Anvin" <hpa@zytor.com>
Cc: Chris Lameter <cl@linux.com>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: "Paul E . McKenney" <paulmck@linux.vnet.ibm.com>
Cc: Paul Turner <pjt@google.com>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Josh Triplett <josh@joshtriplett.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Ben Maurer <bmaurer@fb.com>
Cc: linux-api@vger.kernel.org
CC: linux-arm-kernel@lists.infradead.org
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
---
kernel/rseq.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/kernel/rseq.c b/kernel/rseq.c
index 16b38c5342f9..2c8463acb50d 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -85,9 +85,9 @@ static int rseq_update_cpu_id(struct task_struct *t)
{
u32 cpu_id = raw_smp_processor_id();
- if (__put_user(cpu_id, &t->rseq->cpu_id_start))
+ if (put_user(cpu_id, &t->rseq->cpu_id_start))
return -EFAULT;
- if (__put_user(cpu_id, &t->rseq->cpu_id))
+ if (put_user(cpu_id, &t->rseq->cpu_id))
return -EFAULT;
trace_rseq_update(t);
return 0;
@@ -100,14 +100,14 @@ static int rseq_reset_rseq_cpu_id(struct task_struct *t)
/*
* Reset cpu_id_start to its initial state (0).
*/
- if (__put_user(cpu_id_start, &t->rseq->cpu_id_start))
+ if (put_user(cpu_id_start, &t->rseq->cpu_id_start))
return -EFAULT;
/*
* Reset cpu_id to RSEQ_CPU_ID_UNINITIALIZED, so any user coming
* in after unregistration can figure out that rseq needs to be
* registered again.
*/
- if (__put_user(cpu_id, &t->rseq->cpu_id))
+ if (put_user(cpu_id, &t->rseq->cpu_id))
return -EFAULT;
return 0;
}
@@ -120,7 +120,7 @@ static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs)
u32 sig;
int ret;
- ret = __get_user(ptr, &t->rseq->rseq_cs);
+ ret = get_user(ptr, &t->rseq->rseq_cs);
if (ret)
return ret;
if (!ptr) {
@@ -163,7 +163,7 @@ static int rseq_need_restart(struct task_struct *t, u32 cs_flags)
int ret;
/* Get thread flags. */
- ret = __get_user(flags, &t->rseq->flags);
+ ret = get_user(flags, &t->rseq->flags);
if (ret)
return ret;
@@ -203,7 +203,7 @@ static int clear_rseq_cs(struct task_struct *t)
*
* Set rseq_cs to NULL with single-copy atomicity.
*/
- return __put_user(0UL, &t->rseq->rseq_cs);
+ return put_user(0UL, &t->rseq->rseq_cs);
}
/*
--
2.11.0
^ permalink raw reply related
* [PATCH for 4.18 3/6] rseq: uapi: update uapi comments
From: Mathieu Desnoyers @ 2018-07-09 19:51 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E . McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Ingo Molnar, H . Peter Anvin,
Andi Kleen, Chris Lameter, Ben Maurer, Steven Rostedt,
Josh Triplett, Linus Torvalds, Catalin Marinas, Will Deacon,
Michael Kerrisk
In-Reply-To: <20180709195155.7654-1-mathieu.desnoyers@efficios.com>
Update rseq uapi header comments to reflect that user-space need to do
thread-local loads/stores from/to the struct rseq fields.
As a consequence of this added requirement, the kernel does not need
to perform loads/stores with single-copy atomicity.
Update the comment associated to the "flags" fields to describe
more accurately that it's only useful to facilitate single-stepping
through rseq critical sections with debuggers.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: Paul Turner <pjt@google.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Andi Kleen <andi@firstfloor.org>
CC: Dave Watson <davejwatson@fb.com>
CC: Chris Lameter <cl@linux.com>
CC: Ingo Molnar <mingo@redhat.com>
CC: "H. Peter Anvin" <hpa@zytor.com>
CC: Ben Maurer <bmaurer@fb.com>
CC: Steven Rostedt <rostedt@goodmis.org>
CC: Josh Triplett <josh@joshtriplett.org>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Russell King <linux@arm.linux.org.uk>
CC: Catalin Marinas <catalin.marinas@arm.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Michael Kerrisk <mtk.manpages@gmail.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: linux-api@vger.kernel.org
---
include/uapi/linux/rseq.h | 69 ++++++++++++++++++++++++-----------------------
kernel/rseq.c | 2 +-
2 files changed, 37 insertions(+), 34 deletions(-)
diff --git a/include/uapi/linux/rseq.h b/include/uapi/linux/rseq.h
index 519ad6e176d1..bf4188c13bec 100644
--- a/include/uapi/linux/rseq.h
+++ b/include/uapi/linux/rseq.h
@@ -67,28 +67,30 @@ struct rseq_cs {
struct rseq {
/*
* Restartable sequences cpu_id_start field. Updated by the
- * kernel, and read by user-space with single-copy atomicity
- * semantics. Aligned on 32-bit. Always contains a value in the
- * range of possible CPUs, although the value may not be the
- * actual current CPU (e.g. if rseq is not initialized). This
- * CPU number value should always be compared against the value
- * of the cpu_id field before performing a rseq commit or
- * returning a value read from a data structure indexed using
- * the cpu_id_start value.
+ * kernel. Read by user-space with single-copy atomicity
+ * semantics. This field should only be read by the thread which
+ * registered this data structure. Aligned on 32-bit. Always
+ * contains a value in the range of possible CPUs, although the
+ * value may not be the actual current CPU (e.g. if rseq is not
+ * initialized). This CPU number value should always be compared
+ * against the value of the cpu_id field before performing a rseq
+ * commit or returning a value read from a data structure indexed
+ * using the cpu_id_start value.
*/
__u32 cpu_id_start;
/*
- * Restartable sequences cpu_id field. Updated by the kernel,
- * and read by user-space with single-copy atomicity semantics.
- * Aligned on 32-bit. Values RSEQ_CPU_ID_UNINITIALIZED and
- * RSEQ_CPU_ID_REGISTRATION_FAILED have a special semantic: the
- * former means "rseq uninitialized", and latter means "rseq
- * initialization failed". This value is meant to be read within
- * rseq critical sections and compared with the cpu_id_start
- * value previously read, before performing the commit instruction,
- * or read and compared with the cpu_id_start value before returning
- * a value loaded from a data structure indexed using the
- * cpu_id_start value.
+ * Restartable sequences cpu_id field. Updated by the kernel.
+ * Read by user-space with single-copy atomicity semantics. This
+ * field should only be read by the thread which registered this
+ * data structure. Aligned on 32-bit. Values
+ * RSEQ_CPU_ID_UNINITIALIZED and RSEQ_CPU_ID_REGISTRATION_FAILED
+ * have a special semantic: the former means "rseq uninitialized",
+ * and latter means "rseq initialization failed". This value is
+ * meant to be read within rseq critical sections and compared
+ * with the cpu_id_start value previously read, before performing
+ * the commit instruction, or read and compared with the
+ * cpu_id_start value before returning a value loaded from a data
+ * structure indexed using the cpu_id_start value.
*/
__u32 cpu_id;
/*
@@ -105,27 +107,28 @@ struct rseq {
* targeted by the rseq_cs. Also needs to be set to NULL by user-space
* before reclaiming memory that contains the targeted struct rseq_cs.
*
- * Read and set by the kernel with single-copy atomicity semantics.
- * Set by user-space with single-copy atomicity semantics. Aligned
- * on 64-bit.
+ * Read and set by the kernel. Set by user-space with single-copy
+ * atomicity semantics. This field should only be updated by the
+ * thread which registered this data structure. Aligned on 64-bit.
*/
LINUX_FIELD_u32_u64(rseq_cs);
/*
- * - RSEQ_DISABLE flag:
+ * Restartable sequences flags field.
+ *
+ * This field should only be updated by the thread which
+ * registered this data structure. Read by the kernel.
+ * Mainly used for single-stepping through rseq critical sections
+ * with debuggers.
*
- * Fallback fast-track flag for single-stepping.
- * Set by user-space if lack of progress is detected.
- * Cleared by user-space after rseq finish.
- * Read by the kernel.
* - RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT
- * Inhibit instruction sequence block restart and event
- * counter increment on preemption for this thread.
+ * Inhibit instruction sequence block restart on preemption
+ * for this thread.
* - RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL
- * Inhibit instruction sequence block restart and event
- * counter increment on signal delivery for this thread.
+ * Inhibit instruction sequence block restart on signal
+ * delivery for this thread.
* - RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE
- * Inhibit instruction sequence block restart and event
- * counter increment on migration for this thread.
+ * Inhibit instruction sequence block restart on migration for
+ * this thread.
*/
__u32 flags;
} __attribute__((aligned(4 * sizeof(__u64))));
diff --git a/kernel/rseq.c b/kernel/rseq.c
index 2c8463acb50d..2a7748675be7 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -201,7 +201,7 @@ static int clear_rseq_cs(struct task_struct *t)
* of code outside of the rseq assembly block. This performs
* a lazy clear of the rseq_cs field.
*
- * Set rseq_cs to NULL with single-copy atomicity.
+ * Set rseq_cs to NULL.
*/
return put_user(0UL, &t->rseq->rseq_cs);
}
--
2.11.0
^ permalink raw reply related
* [PATCH for 4.18 4/6] rseq: uapi: declare rseq_cs field as union, update includes
From: Mathieu Desnoyers @ 2018-07-09 19:51 UTC (permalink / raw)
To: Thomas Gleixner
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E . McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Ingo Molnar, H . Peter Anvin,
Andi Kleen, Chris Lameter, Ben Maurer, Steven Rostedt,
Josh Triplett, Linus Torvalds, Catalin Marinas, Will Deacon,
Michael Kerrisk
In-Reply-To: <20180709195155.7654-1-mathieu.desnoyers@efficios.com>
Declaring the rseq_cs field as a union between __u64 and two __u32
allows both 32-bit and 64-bit kernels to read the full __u64, and
therefore validate that a 32-bit user-space cleared the upper 32
bits, thus ensuring a consistent behavior between native 32-bit
kernels and 32-bit compat tasks on 64-bit kernels.
Check that the rseq_cs value read is < TASK_SIZE.
The asm/byteorder.h header needs to be included by rseq.h, now
that it is not using linux/types_32_64.h anymore.
Considering that only __32 and __u64 types are declared in linux/rseq.h,
the linux/types.h header should always be included for both kernel and
user-space code: including stdint.h is just for u64 and u32, which are
not used in this header at all.
Use copy_from_user()/clear_user() to interact with a 64-bit field,
because arm32 does not implement 64-bit __get_user, and ppc32 does not
64-bit get_user. Considering that the rseq_cs pointer does not need to
be loaded/stored with single-copy atomicity from the kernel anymore, we
can simply use copy_from_user()/clear_user().
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: Paul Turner <pjt@google.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Andy Lutomirski <luto@amacapital.net>
CC: Andi Kleen <andi@firstfloor.org>
CC: Dave Watson <davejwatson@fb.com>
CC: Chris Lameter <cl@linux.com>
CC: Ingo Molnar <mingo@redhat.com>
CC: "H. Peter Anvin" <hpa@zytor.com>
CC: Ben Maurer <bmaurer@fb.com>
CC: Steven Rostedt <rostedt@goodmis.org>
CC: Josh Triplett <josh@joshtriplett.org>
CC: Linus Torvalds <torvalds@linux-foundation.org>
CC: Andrew Morton <akpm@linux-foundation.org>
CC: Russell King <linux@arm.linux.org.uk>
CC: Catalin Marinas <catalin.marinas@arm.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Michael Kerrisk <mtk.manpages@gmail.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: linux-api@vger.kernel.org
---
include/uapi/linux/rseq.h | 27 +++++++++++++++++++--------
kernel/rseq.c | 15 +++++++++------
tools/testing/selftests/rseq/rseq.h | 11 ++++++++++-
3 files changed, 38 insertions(+), 15 deletions(-)
diff --git a/include/uapi/linux/rseq.h b/include/uapi/linux/rseq.h
index bf4188c13bec..9a402fdb60e9 100644
--- a/include/uapi/linux/rseq.h
+++ b/include/uapi/linux/rseq.h
@@ -10,13 +10,8 @@
* Copyright (c) 2015-2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*/
-#ifdef __KERNEL__
-# include <linux/types.h>
-#else
-# include <stdint.h>
-#endif
-
-#include <linux/types_32_64.h>
+#include <linux/types.h>
+#include <asm/byteorder.h>
enum rseq_cpu_id_state {
RSEQ_CPU_ID_UNINITIALIZED = -1,
@@ -111,7 +106,23 @@ struct rseq {
* atomicity semantics. This field should only be updated by the
* thread which registered this data structure. Aligned on 64-bit.
*/
- LINUX_FIELD_u32_u64(rseq_cs);
+ union {
+ __u64 ptr64;
+#ifdef __LP64__
+ __u64 ptr;
+#else
+ struct {
+#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 */
+ } ptr;
+#endif
+ } rseq_cs;
+
/*
* Restartable sequences flags field.
*
diff --git a/kernel/rseq.c b/kernel/rseq.c
index 2a7748675be7..c6242d8594dc 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -115,19 +115,20 @@ 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;
- unsigned long ptr;
+ u64 ptr;
u32 __user *usig;
u32 sig;
int ret;
- ret = get_user(ptr, &t->rseq->rseq_cs);
- if (ret)
- return ret;
+ if (copy_from_user(&ptr, &t->rseq->rseq_cs.ptr64, sizeof(ptr)))
+ return -EFAULT;
if (!ptr) {
memset(rseq_cs, 0, sizeof(*rseq_cs));
return 0;
}
- urseq_cs = (struct rseq_cs __user *)ptr;
+ if (ptr >= TASK_SIZE)
+ return -EINVAL;
+ urseq_cs = (struct rseq_cs __user *)(unsigned long)ptr;
if (copy_from_user(rseq_cs, urseq_cs, sizeof(*rseq_cs)))
return -EFAULT;
@@ -203,7 +204,9 @@ static int clear_rseq_cs(struct task_struct *t)
*
* Set rseq_cs to NULL.
*/
- return put_user(0UL, &t->rseq->rseq_cs);
+ if (clear_user(&t->rseq->rseq_cs.ptr64, sizeof(t->rseq->rseq_cs.ptr64)))
+ return -EFAULT;
+ return 0;
}
/*
diff --git a/tools/testing/selftests/rseq/rseq.h b/tools/testing/selftests/rseq/rseq.h
index a4684112676c..f2073cfa4448 100644
--- a/tools/testing/selftests/rseq/rseq.h
+++ b/tools/testing/selftests/rseq/rseq.h
@@ -133,6 +133,15 @@ static inline uint32_t rseq_current_cpu(void)
return cpu;
}
+static inline void rseq_clear_rseq_cs(void)
+{
+#ifdef __LP64__
+ __rseq_abi.rseq_cs.ptr = 0;
+#else
+ __rseq_abi.rseq_cs.ptr.ptr32 = 0;
+#endif
+}
+
/*
* rseq_prepare_unload() should be invoked by each thread using rseq_finish*()
* at least once between their last rseq_finish*() and library unload of the
@@ -143,7 +152,7 @@ static inline uint32_t rseq_current_cpu(void)
*/
static inline void rseq_prepare_unload(void)
{
- __rseq_abi.rseq_cs = 0;
+ rseq_clear_rseq_cs();
}
#endif /* RSEQ_H_ */
--
2.11.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox