* Re: [RFC PATCH] glibc: Perform rseq(2) registration at nptl init and thread creation
From: Joseph Myers @ 2018-09-19 19:49 UTC (permalink / raw)
To: Szabolcs Nagy
Cc: Mathieu Desnoyers, Carlos O'Donell, Florian Weimer, nd,
Thomas Gleixner, Ben Maurer, Peter Zijlstra, Paul E. McKenney,
Boqun Feng, Will Deacon, Dave Watson, Paul Turner, libc-alpha,
linux-kernel, linux-api
In-Reply-To: <c58d4d6e-f22a-f5d9-e23a-5bd72cec1a86@arm.com>
On Wed, 19 Sep 2018, Szabolcs Nagy wrote:
> i don't think there is precedent for exposing tls symbol in glibc
> (e.g. errno is exposed via __errno_location function) so there
> might be issues with this (but i don't have immediate concerns).
There have been suggestions to expose TLS errno - but also suggestions
that use of __errno_location is more efficient, at least in terms of code
size everywhere errno is accessed (for some ABIs, anyway).
The ABI tests have code that would list .tbss symbols as "T" in ABI test
baselines, but no existing ABI baselines use that.
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply
* Re: [RFC PATCH] glibc: Perform rseq(2) registration at nptl init and thread creation
From: Szabolcs Nagy @ 2018-09-19 17:38 UTC (permalink / raw)
To: Mathieu Desnoyers, Carlos O'Donell, Florian Weimer
Cc: nd, Thomas Gleixner, Ben Maurer, Peter Zijlstra, Paul E. McKenney,
Boqun Feng, Will Deacon, Dave Watson, Paul Turner, libc-alpha,
linux-kernel, linux-api
In-Reply-To: <20180919144438.1066-1-mathieu.desnoyers@efficios.com>
On 19/09/18 15:44, Mathieu Desnoyers wrote:
> Things to consider:
>
> - Move __rseq_refcount to an extra field at the end of __rseq_abi to
> eliminate one symbol. This would require to wrap struct rseq into
> e.g. struct rseq_lib or such, e.g.:
>
> struct rseq_lib {
> struct rseq kabi;
> int refcount;
> };
>
> All libraries/programs which try to register rseq (glibc, early-adopter
> applications, early-adopter libraries) should use the rseq refcount.
> It becomes part of the ABI within a user-space process, but it's not
> part of the ABI shared with the kernel per se.
>
> - Restructure how this code is organized so glibc keeps building on
> non-Linux targets.
>
> - We do not need an atomic increment/decrement for the refcount per
> se. Just being atomic with respect to the current thread (and nested
> signals) would be enough. What is the proper API to use there ?
> Should we expose struct rseq_lib in a public glibc header ? Should
> we create a rseq(3) man page ?
>
> - Revisit use of "weak" symbol for __rseq_abi in glibc. Perhaps we
> want a non-weak symbol there ? (and let all other early user
> libraries use weak)
>
i don't think there is precedent for exposing tls symbol in glibc
(e.g. errno is exposed via __errno_location function) so there
might be issues with this (but i don't have immediate concerns).
> diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
> index fe75d04113..20ee197d94 100644
> --- a/nptl/pthread_create.c
> +++ b/nptl/pthread_create.c
> @@ -52,6 +52,13 @@ static struct pthread *__nptl_last_event __attribute_used__;
> /* Number of threads running. */
> unsigned int __nptl_nthreads = 1;
>
> +__attribute__((weak, tls_model("initial-exec"))) __thread
> +volatile struct rseq __rseq_abi = {
> + .cpu_id = RSEQ_CPU_ID_UNINITIALIZED,
> +};
> +
> +__attribute__((weak, tls_model("initial-exec"))) __thread
> +volatile int __rseq_refcount;
>
note that libpthread.so is built with -ftls-model=initial-exec
(and if it wasn't then you'd want to put the attribute on the
declaration in the internal header file, not on the definition,
so the actual tls accesses generate the right code)
^ permalink raw reply
* Re: [RFC PATCH] glibc: Perform rseq(2) registration at nptl init and thread creation
From: Joseph Myers @ 2018-09-19 17:10 UTC (permalink / raw)
To: Mathieu Desnoyers
Cc: carlos, Florian Weimer, Thomas Gleixner, Ben Maurer,
Peter Zijlstra, Paul E. McKenney, Boqun Feng, Will Deacon,
Dave Watson, Paul Turner, libc-alpha, linux-kernel, linux-api
In-Reply-To: <67473000.8399.1537375994645.JavaMail.zimbra@efficios.com>
On Wed, 19 Sep 2018, Mathieu Desnoyers wrote:
> > This looks like it's coming from the Linux kernel. Can't the relevant
> > uapi header just be used directly without copying into glibc (with due
> > care to ensure that glibc still builds if the kernel headers used for the
> > build are too old - you need such conditionals anyway if they don't define
> > the relevant syscall number)?
>
> This is indeed in the list of "things to consider" I've put in the patch
> commit message. If the usual practice is to build against uapi kernel headers
> outside of the glibc tree, I'm fine with that.
We build with, currently, 3.2 or later headers (since 3.2 is EOL there's a
case for updating the minimum in glibc for both compile time and runtime,
but I haven't proposed that since there isn't much cleanup that would
enable and there's the open question of Carlos's proposal to eliminate the
runtime check on the kernel version and just let things try to run anyway
even if it's older than the configured minimum). Functions depending on
new syscalls may return ENOSYS errors if the headers used to build glibc
were too old. Since this patch is providing a data interface rather than
functions that can set errno to ENOSYS, presumably you have some other way
of signalling unavailability which would apply both with a too-old kernel
at runtime and too-old headers at compile time.
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply
* Re: [RFC PATCH] glibc: Perform rseq(2) registration at nptl init and thread creation
From: Mathieu Desnoyers @ 2018-09-19 16:53 UTC (permalink / raw)
To: Joseph Myers
Cc: carlos, Florian Weimer, Thomas Gleixner, Ben Maurer,
Peter Zijlstra, Paul E. McKenney, Boqun Feng, Will Deacon,
Dave Watson, Paul Turner, libc-alpha, linux-kernel, linux-api
In-Reply-To: <alpine.DEB.2.21.1809191630260.26757@digraph.polyomino.org.uk>
----- On Sep 19, 2018, at 12:37 PM, Joseph Myers joseph@codesourcery.com wrote:
> On Wed, 19 Sep 2018, Mathieu Desnoyers wrote:
>
>> Here is a rough prototype registering rseq(2) TLS for each thread
>> (including main), and unregistering for each thread (excluding
>> main). "rseq" stands for Restartable Sequences.
>
> A final patch would need to add documentation and tests and a NEWS entry
> and fix various coding style issues.
>
>> diff --git a/nptl/Versions b/nptl/Versions
>> index e7f691da7a..7316c2815d 100644
>> --- a/nptl/Versions
>> +++ b/nptl/Versions
>> @@ -275,6 +275,7 @@ libpthread {
>> mtx_init; mtx_lock; mtx_timedlock; mtx_trylock; mtx_unlock; mtx_destroy;
>> call_once; cnd_broadcast; cnd_destroy; cnd_init; cnd_signal;
>> cnd_timedwait; cnd_wait; tss_create; tss_delete; tss_get; tss_set;
>> + __rseq_abi; __rseq_refcount;
>
> That's the GLIBC_2.28 section, but 2.28 is already out. New symbols would
> need to go in GLIBC_2.29 or later (and the ABI test baselines would all
> need updating).
Certainly. I'm just not sure where I need to poke to update the ABI version
from 2.28 to 2.29 in my dev branch.
>
>> diff --git a/sysdeps/unix/sysv/linux/rseq.h b/sysdeps/unix/sysv/linux/rseq.h
>
> This looks like it's coming from the Linux kernel. Can't the relevant
> uapi header just be used directly without copying into glibc (with due
> care to ensure that glibc still builds if the kernel headers used for the
> build are too old - you need such conditionals anyway if they don't define
> the relevant syscall number)?
This is indeed in the list of "things to consider" I've put in the patch
commit message. If the usual practice is to build against uapi kernel headers
outside of the glibc tree, I'm fine with that.
Thanks,
Mathieu
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
--
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com
^ permalink raw reply
* Re: [RFC PATCH] glibc: Perform rseq(2) registration at nptl init and thread creation
From: Joseph Myers @ 2018-09-19 16:37 UTC (permalink / raw)
To: Mathieu Desnoyers
Cc: Carlos O'Donell, Florian Weimer, Thomas Gleixner, Ben Maurer,
Peter Zijlstra, Paul E. McKenney, Boqun Feng, Will Deacon,
Dave Watson, Paul Turner, libc-alpha, linux-kernel, linux-api
In-Reply-To: <20180919144438.1066-1-mathieu.desnoyers@efficios.com>
On Wed, 19 Sep 2018, Mathieu Desnoyers wrote:
> Here is a rough prototype registering rseq(2) TLS for each thread
> (including main), and unregistering for each thread (excluding
> main). "rseq" stands for Restartable Sequences.
A final patch would need to add documentation and tests and a NEWS entry
and fix various coding style issues.
> diff --git a/nptl/Versions b/nptl/Versions
> index e7f691da7a..7316c2815d 100644
> --- a/nptl/Versions
> +++ b/nptl/Versions
> @@ -275,6 +275,7 @@ libpthread {
> mtx_init; mtx_lock; mtx_timedlock; mtx_trylock; mtx_unlock; mtx_destroy;
> call_once; cnd_broadcast; cnd_destroy; cnd_init; cnd_signal;
> cnd_timedwait; cnd_wait; tss_create; tss_delete; tss_get; tss_set;
> + __rseq_abi; __rseq_refcount;
That's the GLIBC_2.28 section, but 2.28 is already out. New symbols would
need to go in GLIBC_2.29 or later (and the ABI test baselines would all
need updating).
> diff --git a/sysdeps/unix/sysv/linux/rseq.h b/sysdeps/unix/sysv/linux/rseq.h
This looks like it's coming from the Linux kernel. Can't the relevant
uapi header just be used directly without copying into glibc (with due
care to ensure that glibc still builds if the kernel headers used for the
build are too old - you need such conditionals anyway if they don't define
the relevant syscall number)?
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply
* [RFC PATCH] glibc: Perform rseq(2) registration at nptl init and thread creation
From: Mathieu Desnoyers @ 2018-09-19 14:44 UTC (permalink / raw)
To: Carlos O'Donell, Florian Weimer
Cc: Mathieu Desnoyers, Thomas Gleixner, Ben Maurer, Peter Zijlstra,
Paul E. McKenney, Boqun Feng, Will Deacon, Dave Watson,
Paul Turner, libc-alpha, linux-kernel, linux-api
Here is a rough prototype registering rseq(2) TLS for each thread
(including main), and unregistering for each thread (excluding
main). "rseq" stands for Restartable Sequences.
Things to consider:
- Move __rseq_refcount to an extra field at the end of __rseq_abi to
eliminate one symbol. This would require to wrap struct rseq into
e.g. struct rseq_lib or such, e.g.:
struct rseq_lib {
struct rseq kabi;
int refcount;
};
All libraries/programs which try to register rseq (glibc, early-adopter
applications, early-adopter libraries) should use the rseq refcount.
It becomes part of the ABI within a user-space process, but it's not
part of the ABI shared with the kernel per se.
- Restructure how this code is organized so glibc keeps building on
non-Linux targets.
- We do not need an atomic increment/decrement for the refcount per
se. Just being atomic with respect to the current thread (and nested
signals) would be enough. What is the proper API to use there ?
Should we expose struct rseq_lib in a public glibc header ? Should
we create a rseq(3) man page ?
- Revisit use of "weak" symbol for __rseq_abi in glibc. Perhaps we
want a non-weak symbol there ? (and let all other early user
libraries use weak)
- Should we pull linux/rseq.h from the Linux kernel into the glibc
tree or keep a dependency on installed kernel headers ?
- I plan to host a librseq library containing mostly helper headers
that vastly simplify using rseq. It will contain a librseq.so
which provides an API to explicitly register rseq to the
kernel (for early adopters). The refcounting mechanism in the TLS
would be used to ensure combining librseq.so and libc.so.6 with rseq
support works fine.
- How early do we want to register rseq and how late do we want to
unregister it ? It's important to consider if we expect rseq to
be used by the memory allocator and within destructor callbacks.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
CC: Carlos O'Donell <carlos@redhat.com>
CC: Florian Weimer <fweimer@redhat.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Ben Maurer <bmaurer@fb.com>
CC: Peter Zijlstra <peterz@infradead.org>
CC: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
CC: Boqun Feng <boqun.feng@gmail.com>
CC: Will Deacon <will.deacon@arm.com>
CC: Dave Watson <davejwatson@fb.com>
CC: Paul Turner <pjt@google.com>
CC: libc-alpha@sourceware.org
CC: linux-kernel@vger.kernel.org
CC: linux-api@vger.kernel.org
---
nptl/Versions | 1 +
nptl/nptl-init.c | 3 +
nptl/pthreadP.h | 45 ++++++++++
nptl/pthread_create.c | 15 ++++
sysdeps/unix/sysv/linux/rseq.h | 147 +++++++++++++++++++++++++++++++++
5 files changed, 211 insertions(+)
create mode 100644 sysdeps/unix/sysv/linux/rseq.h
diff --git a/nptl/Versions b/nptl/Versions
index e7f691da7a..7316c2815d 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -275,6 +275,7 @@ libpthread {
mtx_init; mtx_lock; mtx_timedlock; mtx_trylock; mtx_unlock; mtx_destroy;
call_once; cnd_broadcast; cnd_destroy; cnd_init; cnd_signal;
cnd_timedwait; cnd_wait; tss_create; tss_delete; tss_get; tss_set;
+ __rseq_abi; __rseq_refcount;
}
GLIBC_PRIVATE {
diff --git a/nptl/nptl-init.c b/nptl/nptl-init.c
index 907411d5bc..0c056c3fce 100644
--- a/nptl/nptl-init.c
+++ b/nptl/nptl-init.c
@@ -431,6 +431,9 @@ __pthread_initialize_minimal_internal (void)
/* Determine whether the machine is SMP or not. */
__is_smp = is_smp_system ();
+
+ /* Register rseq ABI to the kernel. */
+ (void) rseq_register_current_thread();
}
strong_alias (__pthread_initialize_minimal_internal,
__pthread_initialize_minimal)
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index 13bdb11133..94f54c630e 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -33,6 +33,8 @@
#include <kernel-features.h>
#include <errno.h>
#include <internal-signals.h>
+//TODO: fix sysdeps include to make it portable to non-Linux systems.
+#include <sysdeps/unix/sysv/linux/rseq.h>
/* Atomic operations on TLS memory. */
@@ -660,4 +662,47 @@ check_stacksize_attr (size_t st)
"offset of " #member " field of " #type " != " \
ASSERT_PTHREAD_STRING (offset))
+//TODO: we may want to move the rseq code to a linux sysdeps file.
+#define RSEQ_SIG 0x53053053
+
+extern __thread volatile struct rseq __rseq_abi;
+extern __thread volatile int __rseq_refcount;
+
+static inline int
+rseq_register_current_thread (void)
+{
+ int rc, ret = 0;
+ INTERNAL_SYSCALL_DECL (err);
+
+ if (atomic_increment_val(&__rseq_refcount) - 1)
+ goto end;
+ rc = INTERNAL_SYSCALL_CALL(rseq, err, &__rseq_abi, sizeof(struct rseq),
+ 0, RSEQ_SIG);
+ if (!rc)
+ goto end;
+ if (INTERNAL_SYSCALL_ERRNO(rc, err) != EBUSY)
+ __rseq_abi.cpu_id = -2;
+ ret = -1;
+ atomic_decrement(&__rseq_refcount);
+end:
+ return ret;
+}
+
+static inline int
+rseq_unregister_current_thread (void)
+{
+ int rc, ret = 0;
+ INTERNAL_SYSCALL_DECL (err);
+
+ if (atomic_decrement_val(&__rseq_refcount))
+ goto end;
+ rc = INTERNAL_SYSCALL_CALL(rseq, err, &__rseq_abi, sizeof(struct rseq),
+ RSEQ_FLAG_UNREGISTER, RSEQ_SIG);
+ if (!rc)
+ goto end;
+ ret = -1;
+end:
+ return ret;
+}
+
#endif /* pthreadP.h */
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index fe75d04113..20ee197d94 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -52,6 +52,13 @@ static struct pthread *__nptl_last_event __attribute_used__;
/* Number of threads running. */
unsigned int __nptl_nthreads = 1;
+__attribute__((weak, tls_model("initial-exec"))) __thread
+volatile struct rseq __rseq_abi = {
+ .cpu_id = RSEQ_CPU_ID_UNINITIALIZED,
+};
+
+__attribute__((weak, tls_model("initial-exec"))) __thread
+volatile int __rseq_refcount;
/* Code to allocate and deallocate a stack. */
#include "allocatestack.c"
@@ -378,6 +385,7 @@ __free_tcb (struct pthread *pd)
START_THREAD_DEFN
{
struct pthread *pd = START_THREAD_SELF;
+ bool has_rseq = false;
#if HP_TIMING_AVAIL
/* Remember the time when the thread was started. */
@@ -445,6 +453,9 @@ START_THREAD_DEFN
unwind_buf.priv.data.prev = NULL;
unwind_buf.priv.data.cleanup = NULL;
+ /* Register rseq TLS to the kernel. */
+ has_rseq = !rseq_register_current_thread();
+
if (__glibc_likely (! not_first_call))
{
/* Store the new cleanup handler info. */
@@ -487,6 +498,10 @@ START_THREAD_DEFN
THREAD_SETMEM (pd, result, ret);
}
+ /* Unregister rseq TLS from kernel. */
+ if (has_rseq && rseq_unregister_current_thread())
+ abort();
+
/* Call destructors for the thread_local TLS variables. */
#ifndef SHARED
if (&__call_tls_dtors != NULL)
diff --git a/sysdeps/unix/sysv/linux/rseq.h b/sysdeps/unix/sysv/linux/rseq.h
new file mode 100644
index 0000000000..9a402fdb60
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/rseq.h
@@ -0,0 +1,147 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+#ifndef _UAPI_LINUX_RSEQ_H
+#define _UAPI_LINUX_RSEQ_H
+
+/*
+ * linux/rseq.h
+ *
+ * Restartable sequences system call API
+ *
+ * Copyright (c) 2015-2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+enum rseq_cpu_id_state {
+ RSEQ_CPU_ID_UNINITIALIZED = -1,
+ RSEQ_CPU_ID_REGISTRATION_FAILED = -2,
+};
+
+enum rseq_flags {
+ RSEQ_FLAG_UNREGISTER = (1 << 0),
+};
+
+enum rseq_cs_flags_bit {
+ RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0,
+ RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1,
+ RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2,
+};
+
+enum rseq_cs_flags {
+ RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT =
+ (1U << RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT),
+ RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL =
+ (1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),
+ RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE =
+ (1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),
+};
+
+/*
+ * struct rseq_cs is aligned on 4 * 8 bytes to ensure it is always
+ * contained within a single cache-line. It is usually declared as
+ * link-time constant data.
+ */
+struct rseq_cs {
+ /* Version of this structure. */
+ __u32 version;
+ /* enum rseq_cs_flags */
+ __u32 flags;
+ __u64 start_ip;
+ /* Offset from start_ip. */
+ __u64 post_commit_offset;
+ __u64 abort_ip;
+} __attribute__((aligned(4 * sizeof(__u64))));
+
+/*
+ * struct rseq is aligned on 4 * 8 bytes to ensure it is always
+ * contained within a single cache-line.
+ *
+ * A single struct rseq per thread is allowed.
+ */
+struct rseq {
+ /*
+ * Restartable sequences cpu_id_start 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. 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.
+ * 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;
+ /*
+ * Restartable sequences rseq_cs field.
+ *
+ * Contains NULL when no critical section is active for the current
+ * thread, or holds a pointer to the currently active struct rseq_cs.
+ *
+ * Updated by user-space, which sets the address of the currently
+ * active rseq_cs at the beginning of assembly instruction sequence
+ * block, and set to NULL by the kernel when it restarts an assembly
+ * instruction sequence block, as well as when the kernel detects that
+ * it is preempting or delivering a signal outside of the range
+ * 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. 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.
+ */
+ 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.
+ *
+ * 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.
+ *
+ * - RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT
+ * Inhibit instruction sequence block restart on preemption
+ * for this thread.
+ * - RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL
+ * Inhibit instruction sequence block restart on signal
+ * delivery for this thread.
+ * - RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE
+ * Inhibit instruction sequence block restart on migration for
+ * this thread.
+ */
+ __u32 flags;
+} __attribute__((aligned(4 * sizeof(__u64))));
+
+#endif /* _UAPI_LINUX_RSEQ_H */
--
2.17.1
^ permalink raw reply related
* [PATCH man-pages] Add rseq manpage
From: Mathieu Desnoyers @ 2018-09-19 14:40 UTC (permalink / raw)
To: Michael Kerrisk
Cc: linux-kernel, linux-api, Peter Zijlstra, Paul E . McKenney,
Boqun Feng, Andy Lutomirski, Dave Watson, Paul Turner,
Andrew Morton, Russell King, Thomas Gleixner, Ingo Molnar,
H . Peter Anvin, Andi Kleen, Chris Lameter, Ben Maurer,
Steven Rostedt, Josh Triplett, Linus Torvalds, Catalin Marinas,
Will Deacon
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
---
man2/rseq.2 | 291 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 291 insertions(+)
create mode 100644 man2/rseq.2
diff --git a/man2/rseq.2 b/man2/rseq.2
new file mode 100644
index 000000000..a381963ba
--- /dev/null
+++ b/man2/rseq.2
@@ -0,0 +1,291 @@
+.\" Copyright 2015-2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+.\"
+.\" %%%LICENSE_START(VERBATIM)
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" Since the Linux kernel and libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\" %%%LICENSE_END
+.\"
+.TH RSEQ 2 2018-09-19 "Linux" "Linux Programmer's Manual"
+.SH NAME
+rseq \- Restartable sequences and cpu number cache
+.SH SYNOPSIS
+.nf
+.B #include <linux/rseq.h>
+.sp
+.BI "int rseq(struct rseq * " rseq ", uint32_t " rseq_len ", int " flags ", uint32_t " sig ");
+.sp
+.SH DESCRIPTION
+The
+.BR rseq ()
+ABI accelerates user-space operations on per-cpu data by defining a
+shared data structure ABI between each user-space thread and the kernel.
+
+It allows user-space to perform update operations on per-cpu data
+without requiring heavy-weight atomic operations.
+
+The term CPU used in this documentation refers to a hardware execution
+context.
+
+Restartable sequences are atomic with respect to preemption (making it
+atomic with respect to other threads running on the same CPU), as well
+as signal delivery (user-space execution contexts nested over the same
+thread). They either complete atomically with respect to preemption on
+the current CPU and signal delivery, or they are aborted.
+
+It is suited for update operations on per-cpu data.
+
+It can be used on data structures shared between threads within a
+process, and on data structures shared between threads across different
+processes.
+
+.PP
+Some examples of operations that can be accelerated or improved
+by this ABI:
+.IP \[bu] 2
+Memory allocator per-cpu free-lists,
+.IP \[bu] 2
+Querying the current CPU number,
+.IP \[bu] 2
+Incrementing per-CPU counters,
+.IP \[bu] 2
+Modifying data protected by per-CPU spinlocks,
+.IP \[bu] 2
+Inserting/removing elements in per-CPU linked-lists,
+.IP \[bu] 2
+Writing/reading per-CPU ring buffers content.
+.IP \[bu] 2
+Accurately reading performance monitoring unit counters
+with respect to thread migration.
+
+.PP
+Restartable sequences must not perform system calls. Doing so may result
+in termination of the process by a segmentation fault.
+
+.PP
+The
+.I rseq
+argument is a pointer to the thread-local rseq structure to be shared
+between kernel and user-space.
+
+.PP
+The layout of
+.B struct rseq
+is as follows:
+.TP
+.B Structure alignment
+This structure is aligned on 32-byte boundary.
+.TP
+.B Structure size
+This structure is extensible. Its size is passed as parameter to the
+rseq system call.
+.TP
+.B Fields
+
+.TP
+.in +4n
+.I cpu_id_start
+Optimistic cache of the CPU number on which the current thread is
+running. Its value is guaranteed to always be a possible CPU number,
+even when rseq is not initialized. The value it contains should always
+be confirmed by reading the cpu_id field.
+
+This field is an optimistic cache in the sense that it is always
+guaranteed to hold a valid CPU number in the range [ 0 ..
+nr_possible_cpus - 1 ]. It can therefore be loaded by user-space and
+used as an offset in per-cpu data structures without having to
+check whether its value is within the valid bounds compared to the
+number of possible CPUs in the system.
+
+For user-space applications executed on a kernel without rseq support,
+the cpu_id_start field stays initialized at 0, which is indeed a valid
+CPU number. It is therefore valid to use it as an offset in per-cpu data
+structures, and only validate whether it's actually the current CPU
+number by comparing it with the cpu_id field within the rseq critical
+section. If the kernel does not provide rseq support, that cpu_id field
+stays initialized at -1, so the comparison always fails, as intended.
+
+It is then up to user-space to use a fall-back mechanism, considering
+that rseq is not available.
+
+.in
+.TP
+.in +4n
+.I cpu_id
+Cache of the CPU number on which the current thread is running.
+-1 if uninitialized.
+.in
+.TP
+.in +4n
+.I rseq_cs
+The rseq_cs field is a pointer to a struct rseq_cs. Is is NULL when no
+rseq assembly block critical section is active for the current thread.
+Setting it to point to a critical section descriptor (struct rseq_cs)
+marks the beginning of the critical section.
+.in
+.TP
+.in +4n
+.I flags
+Flags indicating the restart behavior for the current thread. This is
+mainly used for debugging purposes. Can be either:
+.IP \[bu]
+RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT
+.IP \[bu]
+RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL
+.IP \[bu]
+RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE
+.in
+
+.PP
+The layout of
+.B struct rseq_cs
+version 0 is as follows:
+.TP
+.B Structure alignment
+This structure is aligned on 32-byte boundary.
+.TP
+.B Structure size
+This structure has a fixed size of 32 bytes.
+.TP
+.B Fields
+
+.TP
+.in +4n
+.I version
+Version of this structure.
+.in
+.TP
+.in +4n
+.I flags
+Flags indicating the restart behavior of this structure. Can be
+a combination of:
+.IP \[bu]
+RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT
+.IP \[bu]
+RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL
+.IP \[bu]
+RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE
+.TP
+.in +4n
+.I start_ip
+Instruction pointer address of the first instruction of the sequence of
+consecutive assembly instructions.
+.in
+.TP
+.in +4n
+.I post_commit_offset
+Offset (from start_ip address) of the address after the last instruction
+of the sequence of consecutive assembly instructions.
+.in
+.TP
+.in +4n
+.I abort_ip
+Instruction pointer address where to move the execution flow in case of
+abort of the sequence of consecutive assembly instructions.
+.in
+
+.PP
+The
+.I rseq_len
+argument is the size of the
+.I struct rseq
+to register.
+
+.PP
+The
+.I flags
+argument is 0 for registration, and
+.IR RSEQ_FLAG_UNREGISTER
+for unregistration.
+
+.PP
+The
+.I sig
+argument is the 32-bit signature to be expected before the abort
+handler code.
+
+.PP
+A single library per process should keep the rseq structure in a
+thread-local storage variable.
+The
+.I cpu_id
+field should be initialized to -1, and the
+.I cpu_id_start
+field should be initialized to a possible CPU value (typically 0).
+
+.PP
+Each thread is responsible for registering and unregistering its rseq
+structure. No more than one rseq structure address can be registered
+per thread at a given time.
+
+.PP
+In a typical usage scenario, the thread registering the rseq
+structure will be performing loads and stores from/to that structure. It
+is however also allowed to read that structure from other threads.
+The rseq field updates performed by the kernel provide relaxed atomicity
+semantics, which guarantee that other threads performing relaxed atomic
+reads of the cpu number cache will always observe a consistent value.
+
+.SH RETURN VALUE
+A return value of 0 indicates success. On error, \-1 is returned, and
+.I errno
+is set appropriately.
+
+.SH ERRORS
+.TP
+.B EINVAL
+Either
+.I flags
+contains an invalid value, or
+.I rseq
+contains an address which is not appropriately aligned, or
+.I rseq_len
+contains a size that does not match the size received on registration.
+.TP
+.B ENOSYS
+The
+.BR rseq ()
+system call is not implemented by this kernel.
+.TP
+.B EFAULT
+.I rseq
+is an invalid address.
+.TP
+.B EBUSY
+Restartable sequence is already registered for this thread.
+.TP
+.B EPERM
+The
+.I sig
+argument on unregistration does not match the signature received
+on registration.
+
+.SH VERSIONS
+The
+.BR rseq ()
+system call was added in Linux 4.18.
+
+.SH CONFORMING TO
+.BR rseq ()
+is Linux-specific.
+
+.in
+.SH SEE ALSO
+.BR sched_getcpu (3) ,
+.BR membarrier (2)
--
2.11.0
^ permalink raw reply related
* Re: [PATCH v6 4/5] seccomp: add support for passing fds via USER_NOTIF
From: Tycho Andersen @ 2018-09-19 14:38 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Kees Cook, LKML, Linux Containers, Linux API, Oleg Nesterov,
Eric W . Biederman, Serge E . Hallyn, Christian Brauner,
Tyler Hicks, Akihiro Suda, Jann Horn
In-Reply-To: <C1406292-7496-459F-A76A-20C9EFBB12D6@amacapital.net>
On Wed, Sep 19, 2018 at 07:19:56AM -0700, Andy Lutomirski wrote:
>
>
> > On Sep 19, 2018, at 2:55 AM, Tycho Andersen <tycho@tycho.ws> wrote:
> >
> >> On Wed, Sep 12, 2018 at 04:52:38PM -0700, Andy Lutomirski wrote:
> >>> On Thu, Sep 6, 2018 at 8:28 AM, Tycho Andersen <tycho@tycho.ws> wrote:
> >>> The idea here is that the userspace handler should be able to pass an fd
> >>> back to the trapped task, for example so it can be returned from socket().
> >>>
> >>> I've proposed one API here, but I'm open to other options. In particular,
> >>> this only lets you return an fd from a syscall, which may not be enough in
> >>> all cases. For example, if an fd is written to an output parameter instead
> >>> of returned, the current API can't handle this. Another case is that
> >>> netlink takes as input fds sometimes (IFLA_NET_NS_FD, e.g.). If netlink
> >>> ever decides to install an fd and output it, we wouldn't be able to handle
> >>> this either.
> >>
> >> An alternative could be to have an API (an ioctl on the listener,
> >> perhaps) that just copies an fd into the tracee. There would be the
> >> obvious set of options: do we replace an existing fd or allocate a new
> >> one, and is it CLOEXEC. Then the tracer could add an fd and then
> >> return it just like it's a regular number.
> >>
> >> I feel like this would be more flexible and conceptually simpler, but
> >> maybe a little slower for the common cases. What do you think?
> >
> > I'm just implementing this now, and there's one question: when do we
> > actually do the fd install? Should we do it when the user calls
> > SECCOMP_NOTIF_PUT_FD, or when the actual response is sent? It feels
> > like we should do it when the response is sent, instead of doing it
> > right when SECCOMP_NOTIF_PUT_FD is called, since if there's a
> > subsequent signal and the tracer decides to discard the response,
> > we'll have to implement some delete mechanism to delete the fd, but it
> > would have already been visible to the process, etc. So I'll go
> > forward with this unless there are strong objections, but I thought
> > I'd point it out just to avoid another round trip.
> >
> >
>
> Can you do that non-racily? That is, you need to commit to an fd *number* right away, but what if another thread uses the number before you actually install the fd?
I was thinking we could just do an __alloc_fd() and then do the
fd_install() when the response is sent or clean up the case that the
listener or task dies. I haven't actually tried to run the code yet,
so it's possible the locking won't work :)
> Do we really allow non-“kill” signals to interrupt the whole process? It might be the case that we don’t really need to clean up from signals if there’s a guarantee that the thread dies.
Yes, we do, because of this: https://lkml.org/lkml/2018/3/15/1122
I could change that to just be a killable wait, though; I don't have
strong opinions about it and several people have commented that the
code is kind of weird.
Tycho
^ permalink raw reply
* Re: [PATCH v6 4/5] seccomp: add support for passing fds via USER_NOTIF
From: Andy Lutomirski @ 2018-09-19 14:19 UTC (permalink / raw)
To: Tycho Andersen
Cc: Kees Cook, LKML, Linux Containers, Linux API, Oleg Nesterov,
Eric W . Biederman, Serge E . Hallyn, Christian Brauner,
Tyler Hicks, Akihiro Suda, Jann Horn
In-Reply-To: <20180919095536.GM4672@cisco>
> On Sep 19, 2018, at 2:55 AM, Tycho Andersen <tycho@tycho.ws> wrote:
>
>> On Wed, Sep 12, 2018 at 04:52:38PM -0700, Andy Lutomirski wrote:
>>> On Thu, Sep 6, 2018 at 8:28 AM, Tycho Andersen <tycho@tycho.ws> wrote:
>>> The idea here is that the userspace handler should be able to pass an fd
>>> back to the trapped task, for example so it can be returned from socket().
>>>
>>> I've proposed one API here, but I'm open to other options. In particular,
>>> this only lets you return an fd from a syscall, which may not be enough in
>>> all cases. For example, if an fd is written to an output parameter instead
>>> of returned, the current API can't handle this. Another case is that
>>> netlink takes as input fds sometimes (IFLA_NET_NS_FD, e.g.). If netlink
>>> ever decides to install an fd and output it, we wouldn't be able to handle
>>> this either.
>>
>> An alternative could be to have an API (an ioctl on the listener,
>> perhaps) that just copies an fd into the tracee. There would be the
>> obvious set of options: do we replace an existing fd or allocate a new
>> one, and is it CLOEXEC. Then the tracer could add an fd and then
>> return it just like it's a regular number.
>>
>> I feel like this would be more flexible and conceptually simpler, but
>> maybe a little slower for the common cases. What do you think?
>
> I'm just implementing this now, and there's one question: when do we
> actually do the fd install? Should we do it when the user calls
> SECCOMP_NOTIF_PUT_FD, or when the actual response is sent? It feels
> like we should do it when the response is sent, instead of doing it
> right when SECCOMP_NOTIF_PUT_FD is called, since if there's a
> subsequent signal and the tracer decides to discard the response,
> we'll have to implement some delete mechanism to delete the fd, but it
> would have already been visible to the process, etc. So I'll go
> forward with this unless there are strong objections, but I thought
> I'd point it out just to avoid another round trip.
>
>
Can you do that non-racily? That is, you need to commit to an fd *number* right away, but what if another thread uses the number before you actually install the fd?
Do we really allow non-“kill” signals to interrupt the whole process? It might be the case that we don’t really need to clean up from signals if there’s a guarantee that the thread dies.
^ permalink raw reply
* Re: [PATCH v6 4/5] seccomp: add support for passing fds via USER_NOTIF
From: Tycho Andersen @ 2018-09-19 9:55 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Kees Cook, LKML, Linux Containers, Linux API, Oleg Nesterov,
Eric W . Biederman, Serge E . Hallyn, Christian Brauner,
Tyler Hicks, Akihiro Suda, Jann Horn
In-Reply-To: <CALCETrWZmN4FeCSwemfMeayupBmQ-NqpVWQuqSU34CLvzdx8gw@mail.gmail.com>
On Wed, Sep 12, 2018 at 04:52:38PM -0700, Andy Lutomirski wrote:
> On Thu, Sep 6, 2018 at 8:28 AM, Tycho Andersen <tycho@tycho.ws> wrote:
> > The idea here is that the userspace handler should be able to pass an fd
> > back to the trapped task, for example so it can be returned from socket().
> >
> > I've proposed one API here, but I'm open to other options. In particular,
> > this only lets you return an fd from a syscall, which may not be enough in
> > all cases. For example, if an fd is written to an output parameter instead
> > of returned, the current API can't handle this. Another case is that
> > netlink takes as input fds sometimes (IFLA_NET_NS_FD, e.g.). If netlink
> > ever decides to install an fd and output it, we wouldn't be able to handle
> > this either.
>
> An alternative could be to have an API (an ioctl on the listener,
> perhaps) that just copies an fd into the tracee. There would be the
> obvious set of options: do we replace an existing fd or allocate a new
> one, and is it CLOEXEC. Then the tracer could add an fd and then
> return it just like it's a regular number.
>
> I feel like this would be more flexible and conceptually simpler, but
> maybe a little slower for the common cases. What do you think?
I'm just implementing this now, and there's one question: when do we
actually do the fd install? Should we do it when the user calls
SECCOMP_NOTIF_PUT_FD, or when the actual response is sent? It feels
like we should do it when the response is sent, instead of doing it
right when SECCOMP_NOTIF_PUT_FD is called, since if there's a
subsequent signal and the tracer decides to discard the response,
we'll have to implement some delete mechanism to delete the fd, but it
would have already been visible to the process, etc. So I'll go
forward with this unless there are strong objections, but I thought
I'd point it out just to avoid another round trip.
Tycho
^ permalink raw reply
* Re: [PATCH] [RFC] making uapi/linux/elfcore.h useful again
From: Arnd Bergmann @ 2018-09-18 14:21 UTC (permalink / raw)
To: Joseph Myers
Cc: linux-arch, Linux API, David Howells, GNU C Library,
Thomas Gleixner, Ingo Molnar, H. Peter Anvin,
the arch/x86 maintainers, Linux Kernel Mailing List
In-Reply-To: <alpine.DEB.2.21.1809171204350.13789@digraph.polyomino.org.uk>
On Mon, Sep 17, 2018 at 5:05 AM Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Fri, 14 Sep 2018, Arnd Bergmann wrote:
>
> > +typedef unsigned long elf_greg_t;
>
> Does that need to be unsigned long long for x32? (At least glibc thinks
> so; I've not tested what an x32 core dump actually looks like, but to be
> useful it certainly ought to have 64-bit registers.)
Yes, I think that's right. 'unsigned long' was correct inside of the kernel,
but copying it into a uapi header means we have to use '__kernel_ulong_t'
so it gets interpreted right by x32 user space.
Arnd
^ permalink raw reply
* [PATCH] rseq/selftests: fix parametrized test with -fpie
From: Mathieu Desnoyers @ 2018-09-18 13:53 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
On x86-64, the parametrized selftest code for rseq crashes with a
segmentation fault when compiled with -fpie. This happens when the
param_test binary is loaded at an address beyond 32-bit on x86-64.
The issue is caused by use of a 32-bit register to hold the address
of the loop counter variable.
Fix this by using a 64-bit register to calculate the address of the
loop counter variables as an offset from rip.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: <stable@vger.kernel.org> # v4.18
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: Shuah Khan <shuahkh@osg.samsung.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: linux-kselftest@vger.kernel.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: Andy Lutomirski <luto@amacapital.net>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
---
tools/testing/selftests/rseq/param_test.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/tools/testing/selftests/rseq/param_test.c b/tools/testing/selftests/rseq/param_test.c
index 615252331813..4bc071525bf7 100644
--- a/tools/testing/selftests/rseq/param_test.c
+++ b/tools/testing/selftests/rseq/param_test.c
@@ -56,15 +56,13 @@ unsigned int yield_mod_cnt, nr_abort;
printf(fmt, ## __VA_ARGS__); \
} while (0)
-#if defined(__x86_64__) || defined(__i386__)
+#ifdef __i386__
#define INJECT_ASM_REG "eax"
#define RSEQ_INJECT_CLOBBER \
, INJECT_ASM_REG
-#ifdef __i386__
-
#define RSEQ_INJECT_ASM(n) \
"mov asm_loop_cnt_" #n ", %%" INJECT_ASM_REG "\n\t" \
"test %%" INJECT_ASM_REG ",%%" INJECT_ASM_REG "\n\t" \
@@ -76,9 +74,16 @@ unsigned int yield_mod_cnt, nr_abort;
#elif defined(__x86_64__)
+#define INJECT_ASM_REG_P "rax"
+#define INJECT_ASM_REG "eax"
+
+#define RSEQ_INJECT_CLOBBER \
+ , INJECT_ASM_REG_P \
+ , INJECT_ASM_REG
+
#define RSEQ_INJECT_ASM(n) \
- "lea asm_loop_cnt_" #n "(%%rip), %%" INJECT_ASM_REG "\n\t" \
- "mov (%%" INJECT_ASM_REG "), %%" INJECT_ASM_REG "\n\t" \
+ "lea asm_loop_cnt_" #n "(%%rip), %%" INJECT_ASM_REG_P "\n\t" \
+ "mov (%%" INJECT_ASM_REG_P "), %%" INJECT_ASM_REG "\n\t" \
"test %%" INJECT_ASM_REG ",%%" INJECT_ASM_REG "\n\t" \
"jz 333f\n\t" \
"222:\n\t" \
@@ -86,10 +91,6 @@ unsigned int yield_mod_cnt, nr_abort;
"jnz 222b\n\t" \
"333:\n\t"
-#else
-#error "Unsupported architecture"
-#endif
-
#elif defined(__ARMEL__)
#define RSEQ_INJECT_INPUT \
--
2.11.0
^ permalink raw reply related
* Re: [PATCH v3 4/5] pselect6: use __kernel_timespec
From: Deepa Dinamani @ 2018-09-17 21:16 UTC (permalink / raw)
To: stepan
Cc: Alexander Viro, Thomas Gleixner, Linux Kernel Mailing List,
Arnd Bergmann, y2038 Mailman List, Linux FS-devel Mailing List,
Linux API, linux-aio
In-Reply-To: <20180917203438.maary2eo64dbuhw2@sghpc.golosunov.pp.ru>
On Mon, Sep 17, 2018 at 1:34 PM Stepan Golosunov <stepan@golosunov.pp.ru> wrote:
>
> On Sun, Sep 16, 2018 at 06:04:57PM -0700, Deepa Dinamani wrote:
> > static long do_compat_pselect(int n, compat_ulong_t __user *inp,
> > compat_ulong_t __user *outp, compat_ulong_t __user *exp,
> > - struct old_timespec32 __user *tsp, compat_sigset_t __user *sigmask,
> > - compat_size_t sigsetsize)
> > + void __user *tsp, compat_sigset_t __user *sigmask,
> > + compat_size_t sigsetsize, enum poll_time_type type)
> > {
> > sigset_t ksigmask, sigsaved;
> > struct timespec64 ts, end_time, *to = NULL;
> > int ret;
> >
> > if (tsp) {
> > - if (get_old_timespec32(&ts, tsp))
> > - return -EFAULT;
> > + switch (type) {
> > + case PT_OLD_TIMESPEC:
> > + if (get_old_timespec32(&ts, tsp))
> > + return -EFAULT;
> > + break;
> > + case PT_TIMESPEC:
> > + if (get_old_timespec32(&ts, tsp))
> > + return -EFAULT;
> > + break;
> > + default:
> > + BUG();
> > + }
>
> One of the two get_old_timespec32 calls here should be
> get_timespec64.
Right. It is a copy paste bug.
Thanks,
Deepa
^ permalink raw reply
* Re: [PATCH v3 4/5] pselect6: use __kernel_timespec
From: Stepan Golosunov @ 2018-09-17 20:34 UTC (permalink / raw)
To: Deepa Dinamani
Cc: viro, tglx, linux-kernel, arnd, y2038, linux-fsdevel, linux-api,
linux-aio
In-Reply-To: <20180917010458.23159-5-deepa.kernel@gmail.com>
On Sun, Sep 16, 2018 at 06:04:57PM -0700, Deepa Dinamani wrote:
> static long do_compat_pselect(int n, compat_ulong_t __user *inp,
> compat_ulong_t __user *outp, compat_ulong_t __user *exp,
> - struct old_timespec32 __user *tsp, compat_sigset_t __user *sigmask,
> - compat_size_t sigsetsize)
> + void __user *tsp, compat_sigset_t __user *sigmask,
> + compat_size_t sigsetsize, enum poll_time_type type)
> {
> sigset_t ksigmask, sigsaved;
> struct timespec64 ts, end_time, *to = NULL;
> int ret;
>
> if (tsp) {
> - if (get_old_timespec32(&ts, tsp))
> - return -EFAULT;
> + switch (type) {
> + case PT_OLD_TIMESPEC:
> + if (get_old_timespec32(&ts, tsp))
> + return -EFAULT;
> + break;
> + case PT_TIMESPEC:
> + if (get_old_timespec32(&ts, tsp))
> + return -EFAULT;
> + break;
> + default:
> + BUG();
> + }
One of the two get_old_timespec32 calls here should be
get_timespec64.
--
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
* Re: [PATCH] [RFC] making uapi/linux/elfcore.h useful again
From: Joseph Myers @ 2018-09-17 12:05 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-arch, linux-api, David Howells, libc-alpha, Thomas Gleixner,
Ingo Molnar, H. Peter Anvin, x86, linux-kernel
In-Reply-To: <20180914113929.953895-1-arnd@arndb.de>
On Fri, 14 Sep 2018, Arnd Bergmann wrote:
> +typedef unsigned long elf_greg_t;
Does that need to be unsigned long long for x32? (At least glibc thinks
so; I've not tested what an x32 core dump actually looks like, but to be
useful it certainly ought to have 64-bit registers.)
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply
* [PATCH v3 5/5] io_pgetevents: use __kernel_timespec
From: Deepa Dinamani @ 2018-09-17 1:04 UTC (permalink / raw)
To: viro, tglx, linux-kernel; +Cc: arnd, y2038, linux-fsdevel, linux-api, linux-aio
In-Reply-To: <20180917010458.23159-1-deepa.kernel@gmail.com>
struct timespec is not y2038 safe.
struct __kernel_timespec is the new y2038 safe structure for all
syscalls that are using struct timespec.
Update io_pgetevents interfaces to use struct __kernel_timespec.
sigset_t also has different representations on 32 bit and 64 bit
architectures. Hence, we need to support the following different
syscalls:
New y2038 safe syscalls:
(Controlled by CONFIG_64BIT_TIME for 32 bit ABIs)
Native 64 bit(unchanged) and native 32 bit : sys_io_pgetevents
Compat : compat_sys_io_pgetevents_time64
Older y2038 unsafe syscalls:
(Controlled by CONFIG_32BIT_COMPAT_TIME for 32 bit ABIs)
Native 32 bit : sys_io_pgetevents_time32
Compat : compat_sys_io_pgetevents
Note that io_getevents syscalls do not have a y2038 safe solution.
Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
---
fs/aio.c | 85 ++++++++++++++++++++++++++++++++++++++--
include/linux/compat.h | 6 +++
include/linux/syscalls.h | 10 ++++-
3 files changed, 96 insertions(+), 5 deletions(-)
diff --git a/fs/aio.c b/fs/aio.c
index b81c216534d6..72dbce38a628 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -2063,11 +2063,13 @@ static long do_io_getevents(aio_context_t ctx_id,
* specifies an infinite timeout. Note that the timeout pointed to by
* timeout is relative. Will fail with -ENOSYS if not implemented.
*/
+#if !defined(CONFIG_64BIT_TIME) || defined(CONFIG_64BIT)
+
SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
long, min_nr,
long, nr,
struct io_event __user *, events,
- struct timespec __user *, timeout)
+ struct __kernel_timespec __user *, timeout)
{
struct timespec64 ts;
int ret;
@@ -2081,6 +2083,8 @@ SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
return ret;
}
+#endif
+
struct __aio_sigset {
const sigset_t __user *sigmask;
size_t sigsetsize;
@@ -2091,7 +2095,7 @@ SYSCALL_DEFINE6(io_pgetevents,
long, min_nr,
long, nr,
struct io_event __user *, events,
- struct timespec __user *, timeout,
+ struct __kernel_timespec __user *, timeout,
const struct __aio_sigset __user *, usig)
{
struct __aio_sigset ksig = { NULL, };
@@ -2118,7 +2122,44 @@ SYSCALL_DEFINE6(io_pgetevents,
return ret;
}
-#ifdef CONFIG_COMPAT
+#if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT)
+
+SYSCALL_DEFINE6(io_pgetevents_time32,
+ aio_context_t, ctx_id,
+ long, min_nr,
+ long, nr,
+ struct io_event __user *, events,
+ struct old_timespec32 __user *, timeout,
+ const struct __aio_sigset __user *, usig)
+{
+ struct __aio_sigset ksig = { NULL, };
+ sigset_t ksigmask, sigsaved;
+ struct timespec64 ts;
+ int ret;
+
+ if (timeout && unlikely(get_old_timespec32(&ts, timeout)))
+ return -EFAULT;
+
+ if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
+ return -EFAULT;
+
+
+ ret = set_user_sigmask(ksig.sigmask, &ksigmask, &sigsaved, ksig.sigsetsize);
+ if (ret)
+ return ret;
+
+ ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL);
+ restore_user_sigmask(ksig.sigmask, &sigsaved);
+ if (signal_pending(current) && !ret)
+ ret = -ERESTARTNOHAND;
+
+ return ret;
+}
+
+#endif
+
+#if defined(CONFIG_COMPAT_32BIT_TIME)
+
COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id,
compat_long_t, min_nr,
compat_long_t, nr,
@@ -2137,12 +2178,17 @@ COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id,
return ret;
}
+#endif
+
+#ifdef CONFIG_COMPAT
struct __compat_aio_sigset {
compat_sigset_t __user *sigmask;
compat_size_t sigsetsize;
};
+#if defined(CONFIG_COMPAT_32BIT_TIME)
+
COMPAT_SYSCALL_DEFINE6(io_pgetevents,
compat_aio_context_t, ctx_id,
compat_long_t, min_nr,
@@ -2173,4 +2219,37 @@ COMPAT_SYSCALL_DEFINE6(io_pgetevents,
return ret;
}
+
+#endif
+
+COMPAT_SYSCALL_DEFINE6(io_pgetevents_time64,
+ compat_aio_context_t, ctx_id,
+ compat_long_t, min_nr,
+ compat_long_t, nr,
+ struct io_event __user *, events,
+ struct __kernel_timespec __user *, timeout,
+ const struct __compat_aio_sigset __user *, usig)
+{
+ struct __compat_aio_sigset ksig = { NULL, };
+ sigset_t ksigmask, sigsaved;
+ struct timespec64 t;
+ int ret;
+
+ if (timeout && get_timespec64(&t, timeout))
+ return -EFAULT;
+
+ if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
+ return -EFAULT;
+
+ ret = set_compat_user_sigmask(ksig.sigmask, &ksigmask, &sigsaved, ksig.sigsetsize);
+ if (ret)
+ return ret;
+
+ ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL);
+ restore_user_sigmask(ksig.sigmask, &sigsaved);
+ if (signal_pending(current) && !ret)
+ ret = -ERESTARTNOHAND;
+
+ return ret;
+}
#endif
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 6896e6e51c00..50cd0329c8bf 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -556,6 +556,12 @@ asmlinkage long compat_sys_io_pgetevents(compat_aio_context_t ctx_id,
struct io_event __user *events,
struct old_timespec32 __user *timeout,
const struct __compat_aio_sigset __user *usig);
+asmlinkage long compat_sys_io_pgetevents_time64(compat_aio_context_t ctx_id,
+ compat_long_t min_nr,
+ compat_long_t nr,
+ struct io_event __user *events,
+ struct __kernel_timespec __user *timeout,
+ const struct __compat_aio_sigset __user *usig);
/* fs/cookies.c */
asmlinkage long compat_sys_lookup_dcookie(u32, u32, char __user *, compat_size_t);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index e9cd0409c3fe..3ff0e29c082c 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -297,12 +297,18 @@ asmlinkage long sys_io_getevents(aio_context_t ctx_id,
long min_nr,
long nr,
struct io_event __user *events,
- struct timespec __user *timeout);
+ struct __kernel_timespec __user *timeout);
asmlinkage long sys_io_pgetevents(aio_context_t ctx_id,
long min_nr,
long nr,
struct io_event __user *events,
- struct timespec __user *timeout,
+ struct __kernel_timespec __user *timeout,
+ const struct __aio_sigset *sig);
+asmlinkage long sys_io_pgetevents_time32(aio_context_t ctx_id,
+ long min_nr,
+ long nr,
+ struct io_event __user *events,
+ struct old_timespec32 __user *timeout,
const struct __aio_sigset *sig);
/* fs/xattr.c */
--
2.17.1
--
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 v3 4/5] pselect6: use __kernel_timespec
From: Deepa Dinamani @ 2018-09-17 1:04 UTC (permalink / raw)
To: viro, tglx, linux-kernel; +Cc: arnd, y2038, linux-fsdevel, linux-api, linux-aio
In-Reply-To: <20180917010458.23159-1-deepa.kernel@gmail.com>
struct timespec is not y2038 safe.
struct __kernel_timespec is the new y2038 safe structure for all
syscalls that are using struct timespec.
Update pselect interfaces to use struct __kernel_timespec.
sigset_t also has different representations on 32 bit and 64 bit
architectures. Hence, we need to support the following different
syscalls:
New y2038 safe syscalls:
(Controlled by CONFIG_64BIT_TIME for 32 bit ABIs)
Native 64 bit(unchanged) and native 32 bit : sys_pselect6
Compat : compat_sys_pselect6_time64
Older y2038 unsafe syscalls:
(Controlled by CONFIG_32BIT_COMPAT_TIME for 32 bit ABIs)
Native 32 bit : pselect6_time32
Compat : compat_sys_pselect6
Note that all other versions of select syscalls will not have
y2038 safe versions.
Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
---
fs/select.c | 94 ++++++++++++++++++++++++++++++++++------
include/linux/compat.h | 5 +++
include/linux/syscalls.h | 5 ++-
3 files changed, 90 insertions(+), 14 deletions(-)
diff --git a/fs/select.c b/fs/select.c
index d332be059487..fb425eaaa9a8 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -729,16 +729,27 @@ SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_set __user *, outp,
}
static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
- fd_set __user *exp, struct timespec __user *tsp,
- const sigset_t __user *sigmask, size_t sigsetsize)
+ fd_set __user *exp, void __user *tsp,
+ const sigset_t __user *sigmask, size_t sigsetsize,
+ enum poll_time_type type)
{
sigset_t ksigmask, sigsaved;
struct timespec64 ts, end_time, *to = NULL;
int ret;
if (tsp) {
- if (get_timespec64(&ts, tsp))
- return -EFAULT;
+ switch (type) {
+ case PT_TIMESPEC:
+ if (get_timespec64(&ts, tsp))
+ return -EFAULT;
+ break;
+ case PT_OLD_TIMESPEC:
+ if (get_old_timespec32(&ts, tsp))
+ return -EFAULT;
+ break;
+ default:
+ BUG();
+ }
to = &end_time;
if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
@@ -750,7 +761,7 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
return ret;
ret = core_sys_select(n, inp, outp, exp, to);
- ret = poll_select_copy_remaining(&end_time, tsp, PT_TIMESPEC, ret);
+ ret = poll_select_copy_remaining(&end_time, tsp, type, ret);
restore_user_sigmask(sigmask, &sigsaved);
@@ -764,7 +775,27 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
* the sigset size.
*/
SYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp,
- fd_set __user *, exp, struct timespec __user *, tsp,
+ fd_set __user *, exp, struct __kernel_timespec __user *, tsp,
+ void __user *, sig)
+{
+ size_t sigsetsize = 0;
+ sigset_t __user *up = NULL;
+
+ if (sig) {
+ if (!access_ok(VERIFY_READ, sig, sizeof(void *)+sizeof(size_t))
+ || __get_user(up, (sigset_t __user * __user *)sig)
+ || __get_user(sigsetsize,
+ (size_t __user *)(sig+sizeof(void *))))
+ return -EFAULT;
+ }
+
+ return do_pselect(n, inp, outp, exp, tsp, up, sigsetsize, PT_TIMESPEC);
+}
+
+#if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT)
+
+SYSCALL_DEFINE6(pselect6_time32, int, n, fd_set __user *, inp, fd_set __user *, outp,
+ fd_set __user *, exp, struct old_timespec32 __user *, tsp,
void __user *, sig)
{
size_t sigsetsize = 0;
@@ -778,9 +809,11 @@ SYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp,
return -EFAULT;
}
- return do_pselect(n, inp, outp, exp, tsp, up, sigsetsize);
+ return do_pselect(n, inp, outp, exp, tsp, up, sigsetsize, PT_OLD_TIMESPEC);
}
+#endif
+
#ifdef __ARCH_WANT_SYS_OLD_SELECT
struct sel_arg_struct {
unsigned long n;
@@ -1289,16 +1322,26 @@ COMPAT_SYSCALL_DEFINE1(old_select, struct compat_sel_arg_struct __user *, arg)
static long do_compat_pselect(int n, compat_ulong_t __user *inp,
compat_ulong_t __user *outp, compat_ulong_t __user *exp,
- struct old_timespec32 __user *tsp, compat_sigset_t __user *sigmask,
- compat_size_t sigsetsize)
+ void __user *tsp, compat_sigset_t __user *sigmask,
+ compat_size_t sigsetsize, enum poll_time_type type)
{
sigset_t ksigmask, sigsaved;
struct timespec64 ts, end_time, *to = NULL;
int ret;
if (tsp) {
- if (get_old_timespec32(&ts, tsp))
- return -EFAULT;
+ switch (type) {
+ case PT_OLD_TIMESPEC:
+ if (get_old_timespec32(&ts, tsp))
+ return -EFAULT;
+ break;
+ case PT_TIMESPEC:
+ if (get_old_timespec32(&ts, tsp))
+ return -EFAULT;
+ break;
+ default:
+ BUG();
+ }
to = &end_time;
if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
@@ -1310,13 +1353,35 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp,
return ret;
ret = compat_core_sys_select(n, inp, outp, exp, to);
- ret = poll_select_copy_remaining(&end_time, tsp, PT_OLD_TIMESPEC, ret);
+ ret = poll_select_copy_remaining(&end_time, tsp, type, ret);
restore_user_sigmask(sigmask, &sigsaved);
return ret;
}
+COMPAT_SYSCALL_DEFINE6(pselect6_time64, int, n, compat_ulong_t __user *, inp,
+ compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
+ struct __kernel_timespec __user *, tsp, void __user *, sig)
+{
+ compat_size_t sigsetsize = 0;
+ compat_uptr_t up = 0;
+
+ if (sig) {
+ if (!access_ok(VERIFY_READ, sig,
+ sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
+ __get_user(up, (compat_uptr_t __user *)sig) ||
+ __get_user(sigsetsize,
+ (compat_size_t __user *)(sig+sizeof(up))))
+ return -EFAULT;
+ }
+
+ return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up),
+ sigsetsize, PT_TIMESPEC);
+}
+
+#if defined(CONFIG_COMPAT_32BIT_TIME)
+
COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp,
compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
struct old_timespec32 __user *, tsp, void __user *, sig)
@@ -1332,10 +1397,13 @@ COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp,
(compat_size_t __user *)(sig+sizeof(up))))
return -EFAULT;
}
+
return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up),
- sigsetsize);
+ sigsetsize, PT_OLD_TIMESPEC);
}
+#endif
+
#if defined(CONFIG_COMPAT_32BIT_TIME)
COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
unsigned int, nfds, struct old_timespec32 __user *, tsp,
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 349a2d98e450..6896e6e51c00 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -641,6 +641,11 @@ asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
compat_ulong_t __user *exp,
struct old_timespec32 __user *tsp,
void __user *sig);
+asmlinkage long compat_sys_pselect6_time64(int n, compat_ulong_t __user *inp,
+ compat_ulong_t __user *outp,
+ compat_ulong_t __user *exp,
+ struct __kernel_timespec __user *tsp,
+ void __user *sig);
asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
unsigned int nfds,
struct old_timespec32 __user *tsp,
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 9755e70cfbb0..e9cd0409c3fe 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -467,7 +467,10 @@ asmlinkage long sys_sendfile64(int out_fd, int in_fd,
/* fs/select.c */
asmlinkage long sys_pselect6(int, fd_set __user *, fd_set __user *,
- fd_set __user *, struct timespec __user *,
+ fd_set __user *, struct __kernel_timespec __user *,
+ void __user *);
+asmlinkage long sys_pselect6_time32(int, fd_set __user *, fd_set __user *,
+ fd_set __user *, struct old_timespec32 __user *,
void __user *);
asmlinkage long sys_ppoll(struct pollfd __user *, unsigned int,
struct __kernel_timespec __user *, const sigset_t __user *,
--
2.17.1
--
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 v3 3/5] ppoll: use __kernel_timespec
From: Deepa Dinamani @ 2018-09-17 1:04 UTC (permalink / raw)
To: viro, tglx, linux-kernel; +Cc: arnd, y2038, linux-fsdevel, linux-api, linux-aio
In-Reply-To: <20180917010458.23159-1-deepa.kernel@gmail.com>
struct timespec is not y2038 safe.
struct __kernel_timespec is the new y2038 safe structure for all
syscalls that are using struct timespec.
Update ppoll interfaces to use struct __kernel_timespec.
sigset_t also has different representations on 32 bit and 64 bit
architectures. Hence, we need to support the following different
syscalls:
New y2038 safe syscalls:
(Controlled by CONFIG_64BIT_TIME for 32 bit ABIs)
Native 64 bit(unchanged) and native 32 bit : sys_ppoll
Compat : compat_sys_ppoll_time64
Older y2038 unsafe syscalls:
(Controlled by CONFIG_32BIT_COMPAT_TIME for 32 bit ABIs)
Native 32 bit : ppoll_time32
Compat : compat_sys_ppoll
Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
---
fs/select.c | 166 ++++++++++++++++++++++++++-------------
include/linux/compat.h | 5 ++
include/linux/syscalls.h | 5 +-
3 files changed, 120 insertions(+), 56 deletions(-)
diff --git a/fs/select.c b/fs/select.c
index eb9132520197..d332be059487 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -287,12 +287,18 @@ int poll_select_set_timeout(struct timespec64 *to, time64_t sec, long nsec)
return 0;
}
+enum poll_time_type {
+ PT_TIMEVAL = 0,
+ PT_OLD_TIMEVAL = 1,
+ PT_TIMESPEC = 2,
+ PT_OLD_TIMESPEC = 3,
+};
+
static int poll_select_copy_remaining(struct timespec64 *end_time,
void __user *p,
- int timeval, int ret)
+ enum poll_time_type pt_type, int ret)
{
struct timespec64 rts;
- struct timeval rtv;
if (!p)
return ret;
@@ -310,18 +316,40 @@ static int poll_select_copy_remaining(struct timespec64 *end_time,
rts.tv_sec = rts.tv_nsec = 0;
- if (timeval) {
- if (sizeof(rtv) > sizeof(rtv.tv_sec) + sizeof(rtv.tv_usec))
- memset(&rtv, 0, sizeof(rtv));
- rtv.tv_sec = rts.tv_sec;
- rtv.tv_usec = rts.tv_nsec / NSEC_PER_USEC;
+ switch (pt_type) {
+ case PT_TIMEVAL:
+ {
+ struct timeval rtv;
- if (!copy_to_user(p, &rtv, sizeof(rtv)))
+ if (sizeof(rtv) > sizeof(rtv.tv_sec) + sizeof(rtv.tv_usec))
+ memset(&rtv, 0, sizeof(rtv));
+ rtv.tv_sec = rts.tv_sec;
+ rtv.tv_usec = rts.tv_nsec / NSEC_PER_USEC;
+ if (!copy_to_user(p, &rtv, sizeof(rtv)))
+ return ret;
+ }
+ break;
+ case PT_OLD_TIMEVAL:
+ {
+ struct old_timeval32 rtv;
+
+ rtv.tv_sec = rts.tv_sec;
+ rtv.tv_usec = rts.tv_nsec / NSEC_PER_USEC;
+ if (!copy_to_user(p, &rtv, sizeof(rtv)))
+ return ret;
+ }
+ break;
+ case PT_TIMESPEC:
+ if (!put_timespec64(&rts, p))
return ret;
-
- } else if (!put_timespec64(&rts, p))
- return ret;
-
+ break;
+ case PT_OLD_TIMESPEC:
+ if (!put_old_timespec32(&rts, p))
+ return ret;
+ break;
+ default:
+ BUG();
+ }
/*
* If an application puts its timeval in read-only memory, we
* don't want the Linux-specific update to the timeval to
@@ -689,7 +717,7 @@ static int kern_select(int n, fd_set __user *inp, fd_set __user *outp,
}
ret = core_sys_select(n, inp, outp, exp, to);
- ret = poll_select_copy_remaining(&end_time, tvp, 1, ret);
+ ret = poll_select_copy_remaining(&end_time, tvp, PT_TIMEVAL, ret);
return ret;
}
@@ -722,7 +750,7 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
return ret;
ret = core_sys_select(n, inp, outp, exp, to);
- ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
+ ret = poll_select_copy_remaining(&end_time, tsp, PT_TIMESPEC, ret);
restore_user_sigmask(sigmask, &sigsaved);
@@ -1026,7 +1054,7 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,
}
SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
- struct timespec __user *, tsp, const sigset_t __user *, sigmask,
+ struct __kernel_timespec __user *, tsp, const sigset_t __user *, sigmask,
size_t, sigsetsize)
{
sigset_t ksigmask, sigsaved;
@@ -1054,60 +1082,50 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
if (ret == -EINTR)
ret = -ERESTARTNOHAND;
- ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
+ ret = poll_select_copy_remaining(&end_time, tsp, PT_TIMESPEC, ret);
return ret;
}
-#ifdef CONFIG_COMPAT
-#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t))
+#if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT)
-static
-int compat_poll_select_copy_remaining(struct timespec64 *end_time, void __user *p,
- int timeval, int ret)
+SYSCALL_DEFINE5(ppoll_time32, struct pollfd __user *, ufds, unsigned int, nfds,
+ struct old_timespec32 __user *, tsp, const sigset_t __user *, sigmask,
+ size_t, sigsetsize)
{
- struct timespec64 ts;
+ sigset_t ksigmask, sigsaved;
+ struct timespec64 ts, end_time, *to = NULL;
+ int ret;
- if (!p)
- return ret;
+ if (tsp) {
+ if (get_old_timespec32(&ts, tsp))
+ return -EFAULT;
- if (current->personality & STICKY_TIMEOUTS)
- goto sticky;
+ to = &end_time;
+ if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
+ return -EINVAL;
+ }
- /* No update for zero timeout */
- if (!end_time->tv_sec && !end_time->tv_nsec)
+ ret = set_user_sigmask(sigmask, &ksigmask, &sigsaved, sigsetsize);
+ if (ret)
return ret;
- ktime_get_ts64(&ts);
- ts = timespec64_sub(*end_time, ts);
- if (ts.tv_sec < 0)
- ts.tv_sec = ts.tv_nsec = 0;
+ ret = do_sys_poll(ufds, nfds, to);
- if (timeval) {
- struct old_timeval32 rtv;
+ restore_user_sigmask(sigmask, &sigsaved);
- rtv.tv_sec = ts.tv_sec;
- rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+ /* We can restart this syscall, usually */
+ if (ret == -EINTR)
+ ret = -ERESTARTNOHAND;
- if (!copy_to_user(p, &rtv, sizeof(rtv)))
- return ret;
- } else {
- if (!put_old_timespec32(&ts, p))
- return ret;
- }
- /*
- * If an application puts its timeval in read-only memory, we
- * don't want the Linux-specific update to the timeval to
- * cause a fault after the select has completed
- * successfully. However, because we're not updating the
- * timeval, we can't restart the system call.
- */
+ ret = poll_select_copy_remaining(&end_time, tsp, PT_OLD_TIMESPEC, ret);
-sticky:
- if (ret == -ERESTARTNOHAND)
- ret = -EINTR;
return ret;
}
+#endif
+
+#ifdef CONFIG_COMPAT
+#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t))
/*
* Ooo, nasty. We need here to frob 32-bit unsigned longs to
@@ -1239,7 +1257,7 @@ static int do_compat_select(int n, compat_ulong_t __user *inp,
}
ret = compat_core_sys_select(n, inp, outp, exp, to);
- ret = compat_poll_select_copy_remaining(&end_time, tvp, 1, ret);
+ ret = poll_select_copy_remaining(&end_time, tvp, PT_OLD_TIMEVAL, ret);
return ret;
}
@@ -1292,7 +1310,7 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp,
return ret;
ret = compat_core_sys_select(n, inp, outp, exp, to);
- ret = compat_poll_select_copy_remaining(&end_time, tsp, 0, ret);
+ ret = poll_select_copy_remaining(&end_time, tsp, PT_OLD_TIMESPEC, ret);
restore_user_sigmask(sigmask, &sigsaved);
@@ -1318,6 +1336,7 @@ COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp,
sigsetsize);
}
+#if defined(CONFIG_COMPAT_32BIT_TIME)
COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
unsigned int, nfds, struct old_timespec32 __user *, tsp,
const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)
@@ -1347,8 +1366,45 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
if (ret == -EINTR)
ret = -ERESTARTNOHAND;
- ret = compat_poll_select_copy_remaining(&end_time, tsp, 0, ret);
+ ret = poll_select_copy_remaining(&end_time, tsp, PT_OLD_TIMESPEC, ret);
return ret;
}
#endif
+
+/* New compat syscall for 64 bit time_t*/
+COMPAT_SYSCALL_DEFINE5(ppoll_time64, struct pollfd __user *, ufds,
+ unsigned int, nfds, struct __kernel_timespec __user *, tsp,
+ const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)
+{
+ sigset_t ksigmask, sigsaved;
+ struct timespec64 ts, end_time, *to = NULL;
+ int ret;
+
+ if (tsp) {
+ if (get_timespec64(&ts, tsp))
+ return -EFAULT;
+
+ to = &end_time;
+ if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
+ return -EINVAL;
+ }
+
+ ret = set_compat_user_sigmask(sigmask, &ksigmask, &sigsaved, sigsetsize);
+ if (ret)
+ return ret;
+
+ ret = do_sys_poll(ufds, nfds, to);
+
+ restore_user_sigmask(sigmask, &sigsaved);
+
+ /* We can restart this syscall, usually */
+ if (ret == -EINTR)
+ ret = -ERESTARTNOHAND;
+
+ ret = poll_select_copy_remaining(&end_time, tsp, PT_TIMESPEC, ret);
+
+ return ret;
+}
+
+#endif
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 03d65c509eeb..349a2d98e450 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -646,6 +646,11 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
struct old_timespec32 __user *tsp,
const compat_sigset_t __user *sigmask,
compat_size_t sigsetsize);
+asmlinkage long compat_sys_ppoll_time64(struct pollfd __user *ufds,
+ unsigned int nfds,
+ struct __kernel_timespec __user *tsp,
+ const compat_sigset_t __user *sigmask,
+ compat_size_t sigsetsize);
/* fs/signalfd.c */
asmlinkage long compat_sys_signalfd4(int ufd,
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 82682b69435e..9755e70cfbb0 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -470,7 +470,10 @@ asmlinkage long sys_pselect6(int, fd_set __user *, fd_set __user *,
fd_set __user *, struct timespec __user *,
void __user *);
asmlinkage long sys_ppoll(struct pollfd __user *, unsigned int,
- struct timespec __user *, const sigset_t __user *,
+ struct __kernel_timespec __user *, const sigset_t __user *,
+ size_t);
+asmlinkage long sys_ppoll_time32(struct pollfd __user *, unsigned int,
+ struct old_timespec32 __user *, const sigset_t __user *,
size_t);
/* fs/signalfd.c */
--
2.17.1
--
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 v3 2/5] signal: Add restore_user_sigmask()
From: Deepa Dinamani @ 2018-09-17 1:04 UTC (permalink / raw)
To: viro, tglx, linux-kernel; +Cc: arnd, y2038, linux-fsdevel, linux-api, linux-aio
In-Reply-To: <20180917010458.23159-1-deepa.kernel@gmail.com>
Refactor the logic to restore the sigmask before the syscall
returns into an api.
This is useful for versions of syscalls that pass in the
sigmask and expect the current->sigmask to be changed during
the execution and restored after the execution of the syscall.
With the advent of new y2038 syscalls in the subsequent patches,
we add 2 more new versions of the syscalls(for pselect, ppoll
and io_pgetevents) in addition to the existing native and compat
versions. Adding such an api reduces the logic that would need to
be replicated otherwise.
Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
---
fs/aio.c | 29 +++++---------------
fs/eventpoll.c | 30 ++-------------------
fs/select.c | 60 ++++++------------------------------------
include/linux/signal.h | 2 ++
kernel/signal.c | 33 +++++++++++++++++++++++
5 files changed, 51 insertions(+), 103 deletions(-)
diff --git a/fs/aio.c b/fs/aio.c
index 67e5b1f6fb0f..b81c216534d6 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -2111,18 +2111,9 @@ SYSCALL_DEFINE6(io_pgetevents,
return ret;
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL);
- if (signal_pending(current)) {
- if (ksig.sigmask) {
- current->saved_sigmask = sigsaved;
- set_restore_sigmask();
- }
-
- if (!ret)
- ret = -ERESTARTNOHAND;
- } else {
- if (ksig.sigmask)
- sigprocmask(SIG_SETMASK, &sigsaved, NULL);
- }
+ restore_user_sigmask(ksig.sigmask, &sigsaved);
+ if (signal_pending(current) && !ret)
+ ret = -ERESTARTNOHAND;
return ret;
}
@@ -2176,17 +2167,9 @@ COMPAT_SYSCALL_DEFINE6(io_pgetevents,
return ret;
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL);
- if (signal_pending(current)) {
- if (ksig.sigmask) {
- current->saved_sigmask = sigsaved;
- set_restore_sigmask();
- }
- if (!ret)
- ret = -ERESTARTNOHAND;
- } else {
- if (ksig.sigmask)
- sigprocmask(SIG_SETMASK, &sigsaved, NULL);
- }
+ restore_user_sigmask(ksig.sigmask, &sigsaved);
+ if (signal_pending(current) && !ret)
+ ret = -ERESTARTNOHAND;
return ret;
}
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 2d86eeba837b..8a5a1010886b 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -2229,20 +2229,7 @@ SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events,
error = do_epoll_wait(epfd, events, maxevents, timeout);
- /*
- * If we changed the signal mask, we need to restore the original one.
- * In case we've got a signal while waiting, we do not restore the
- * signal mask yet, and we allow do_signal() to deliver the signal on
- * the way back to userspace, before the signal mask is restored.
- */
- if (sigmask) {
- if (error == -EINTR) {
- memcpy(¤t->saved_sigmask, &sigsaved,
- sizeof(sigsaved));
- set_restore_sigmask();
- } else
- set_current_blocked(&sigsaved);
- }
+ restore_user_sigmask(sigmask, &sigsaved);
return error;
}
@@ -2267,20 +2254,7 @@ COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd,
err = do_epoll_wait(epfd, events, maxevents, timeout);
- /*
- * If we changed the signal mask, we need to restore the original one.
- * In case we've got a signal while waiting, we do not restore the
- * signal mask yet, and we allow do_signal() to deliver the signal on
- * the way back to userspace, before the signal mask is restored.
- */
- if (sigmask) {
- if (err == -EINTR) {
- memcpy(¤t->saved_sigmask, &sigsaved,
- sizeof(sigsaved));
- set_restore_sigmask();
- } else
- set_current_blocked(&sigsaved);
- }
+ restore_user_sigmask(sigmask, &sigsaved);
return err;
}
diff --git a/fs/select.c b/fs/select.c
index 65c78b4147a2..eb9132520197 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -724,19 +724,7 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
ret = core_sys_select(n, inp, outp, exp, to);
ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
- if (ret == -ERESTARTNOHAND) {
- /*
- * Don't restore the signal mask yet. Let do_signal() deliver
- * the signal on the way back to userspace, before the signal
- * mask is restored.
- */
- if (sigmask) {
- memcpy(¤t->saved_sigmask, &sigsaved,
- sizeof(sigsaved));
- set_restore_sigmask();
- }
- } else if (sigmask)
- sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+ restore_user_sigmask(sigmask, &sigsaved);
return ret;
}
@@ -1060,21 +1048,11 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
ret = do_sys_poll(ufds, nfds, to);
+ restore_user_sigmask(sigmask, &sigsaved);
+
/* We can restart this syscall, usually */
- if (ret == -EINTR) {
- /*
- * Don't restore the signal mask yet. Let do_signal() deliver
- * the signal on the way back to userspace, before the signal
- * mask is restored.
- */
- if (sigmask) {
- memcpy(¤t->saved_sigmask, &sigsaved,
- sizeof(sigsaved));
- set_restore_sigmask();
- }
+ if (ret == -EINTR)
ret = -ERESTARTNOHAND;
- } else if (sigmask)
- sigprocmask(SIG_SETMASK, &sigsaved, NULL);
ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
@@ -1316,19 +1294,7 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp,
ret = compat_core_sys_select(n, inp, outp, exp, to);
ret = compat_poll_select_copy_remaining(&end_time, tsp, 0, ret);
- if (ret == -ERESTARTNOHAND) {
- /*
- * Don't restore the signal mask yet. Let do_signal() deliver
- * the signal on the way back to userspace, before the signal
- * mask is restored.
- */
- if (sigmask) {
- memcpy(¤t->saved_sigmask, &sigsaved,
- sizeof(sigsaved));
- set_restore_sigmask();
- }
- } else if (sigmask)
- sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+ restore_user_sigmask(sigmask, &sigsaved);
return ret;
}
@@ -1375,21 +1341,11 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
ret = do_sys_poll(ufds, nfds, to);
+ restore_user_sigmask(sigmask, &sigsaved);
+
/* We can restart this syscall, usually */
- if (ret == -EINTR) {
- /*
- * Don't restore the signal mask yet. Let do_signal() deliver
- * the signal on the way back to userspace, before the signal
- * mask is restored.
- */
- if (sigmask) {
- memcpy(¤t->saved_sigmask, &sigsaved,
- sizeof(sigsaved));
- set_restore_sigmask();
- }
+ if (ret == -EINTR)
ret = -ERESTARTNOHAND;
- } else if (sigmask)
- sigprocmask(SIG_SETMASK, &sigsaved, NULL);
ret = compat_poll_select_copy_remaining(&end_time, tsp, 0, ret);
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 403e63d01bcf..ed8be17afe89 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -265,6 +265,8 @@ extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
extern int sigprocmask(int, sigset_t *, sigset_t *);
extern int set_user_sigmask(const sigset_t __user *usigmask, sigset_t *set,
sigset_t *oldset, size_t sigsetsize);
+extern void restore_user_sigmask(const void __user *usigmask,
+ sigset_t *sigsaved);
extern void set_current_blocked(sigset_t *);
extern void __set_current_blocked(const sigset_t *);
extern int show_unhandled_signals;
diff --git a/kernel/signal.c b/kernel/signal.c
index 1d72dcddcaaf..457d1abe62a4 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2783,6 +2783,39 @@ int set_compat_user_sigmask(const compat_sigset_t __user *usigmask,
EXPORT_SYMBOL(set_compat_user_sigmask);
#endif
+/*
+ * restore_user_sigmask:
+ * usigmask: sigmask passed in from userland.
+ * sigsaved: saved sigmask when the syscall started and changed the sigmask to
+ * usigmask.
+ *
+ * This is useful for syscalls such as ppoll, pselect, io_pgetevents and
+ * epoll_pwait where a new sigmask is passed in from userland for the syscalls.
+ */
+void restore_user_sigmask(const void __user *usigmask, sigset_t *sigsaved)
+{
+
+ if (!usigmask)
+ return;
+ /*
+ * When signals are pending, do not restore them here.
+ * Restoring sigmask here can lead to delivering signals that the above
+ * syscalls are intended to block because of the sigmask passed in.
+ */
+ if (signal_pending(current)) {
+ current->saved_sigmask = *sigsaved;
+ set_restore_sigmask();
+ return;
+ }
+
+ /*
+ * This is needed because the fast syscall return path does not restore
+ * saved_sigmask when signals are not pending.
+ */
+ set_current_blocked(sigsaved);
+}
+EXPORT_SYMBOL(restore_user_sigmask);
+
/**
* sys_rt_sigprocmask - change the list of currently blocked signals
* @how: whether to add, remove, or set signals
--
2.17.1
--
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 v3 1/5] signal: Add set_user_sigmask()
From: Deepa Dinamani @ 2018-09-17 1:04 UTC (permalink / raw)
To: viro, tglx, linux-kernel; +Cc: arnd, y2038, linux-fsdevel, linux-api, linux-aio
In-Reply-To: <20180917010458.23159-1-deepa.kernel@gmail.com>
Refactor reading sigset from userspace and updating sigmask
into an api.
This is useful for versions of syscalls that pass in the
sigmask and expect the current->sigmask to be changed during
the execution and restored after the execution of the syscall.
With the advent of new y2038 syscalls in the subsequent patches,
we add 2 more new versions of the syscalls(for pselect, ppoll
and io_pgetevents) in addition to the existing native and compat
versions. Adding such an api reduces the logic that would need to
be replicated otherwise.
Note that the calls to sigprocmask() ignored the return value
from the api as the function only returns an error on an invalid
first argument that is hardcoded at these call sites.
The updated logic uses set_current_blocked() instead.
Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
---
fs/aio.c | 23 ++++++-------------
fs/eventpoll.c | 22 +++++--------------
fs/select.c | 50 ++++++++++--------------------------------
include/linux/compat.h | 4 ++++
include/linux/signal.h | 2 ++
kernel/signal.c | 45 +++++++++++++++++++++++++++++++++++++
6 files changed, 76 insertions(+), 70 deletions(-)
diff --git a/fs/aio.c b/fs/aio.c
index 2914e8c1b3d2..67e5b1f6fb0f 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -2105,14 +2105,10 @@ SYSCALL_DEFINE6(io_pgetevents,
if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
return -EFAULT;
- if (ksig.sigmask) {
- if (ksig.sigsetsize != sizeof(sigset_t))
- return -EINVAL;
- if (copy_from_user(&ksigmask, ksig.sigmask, sizeof(ksigmask)))
- return -EFAULT;
- sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
- sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
- }
+
+ ret = set_user_sigmask(ksig.sigmask, &ksigmask, &sigsaved, ksig.sigsetsize);
+ if (ret)
+ return ret;
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL);
if (signal_pending(current)) {
@@ -2175,14 +2171,9 @@ COMPAT_SYSCALL_DEFINE6(io_pgetevents,
if (usig && copy_from_user(&ksig, usig, sizeof(ksig)))
return -EFAULT;
- if (ksig.sigmask) {
- if (ksig.sigsetsize != sizeof(compat_sigset_t))
- return -EINVAL;
- if (get_compat_sigset(&ksigmask, ksig.sigmask))
- return -EFAULT;
- sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
- sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
- }
+ ret = set_compat_user_sigmask(ksig.sigmask, &ksigmask, &sigsaved, ksig.sigsetsize);
+ if (ret)
+ return ret;
ret = do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL);
if (signal_pending(current)) {
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 42bbe6824b4b..2d86eeba837b 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -2223,14 +2223,9 @@ SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events,
* If the caller wants a certain signal mask to be set during the wait,
* we apply it here.
*/
- if (sigmask) {
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
- if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
- return -EFAULT;
- sigsaved = current->blocked;
- set_current_blocked(&ksigmask);
- }
+ error = set_user_sigmask(sigmask, &ksigmask, &sigsaved, sigsetsize);
+ if (error)
+ return error;
error = do_epoll_wait(epfd, events, maxevents, timeout);
@@ -2266,14 +2261,9 @@ COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd,
* If the caller wants a certain signal mask to be set during the wait,
* we apply it here.
*/
- if (sigmask) {
- if (sigsetsize != sizeof(compat_sigset_t))
- return -EINVAL;
- if (get_compat_sigset(&ksigmask, sigmask))
- return -EFAULT;
- sigsaved = current->blocked;
- set_current_blocked(&ksigmask);
- }
+ err = set_compat_user_sigmask(sigmask, &ksigmask, &sigsaved, sigsetsize);
+ if (err)
+ return err;
err = do_epoll_wait(epfd, events, maxevents, timeout);
diff --git a/fs/select.c b/fs/select.c
index 22b3bf89f051..65c78b4147a2 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -717,16 +717,9 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
return -EINVAL;
}
- if (sigmask) {
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
- if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
- return -EFAULT;
-
- sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
- sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
- }
+ ret = set_user_sigmask(sigmask, &ksigmask, &sigsaved, sigsetsize);
+ if (ret)
+ return ret;
ret = core_sys_select(n, inp, outp, exp, to);
ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
@@ -1061,16 +1054,9 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
return -EINVAL;
}
- if (sigmask) {
- /* XXX: Don't preclude handling different sized sigset_t's. */
- if (sigsetsize != sizeof(sigset_t))
- return -EINVAL;
- if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
- return -EFAULT;
-
- sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
- sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
- }
+ ret = set_user_sigmask(sigmask, &ksigmask, &sigsaved, sigsetsize);
+ if (ret)
+ return ret;
ret = do_sys_poll(ufds, nfds, to);
@@ -1323,15 +1309,9 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp,
return -EINVAL;
}
- if (sigmask) {
- if (sigsetsize != sizeof(compat_sigset_t))
- return -EINVAL;
- if (get_compat_sigset(&ksigmask, sigmask))
- return -EFAULT;
-
- sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
- sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
- }
+ ret = set_compat_user_sigmask(sigmask, &ksigmask, &sigsaved, sigsetsize);
+ if (ret)
+ return ret;
ret = compat_core_sys_select(n, inp, outp, exp, to);
ret = compat_poll_select_copy_remaining(&end_time, tsp, 0, ret);
@@ -1389,15 +1369,9 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
return -EINVAL;
}
- if (sigmask) {
- if (sigsetsize != sizeof(compat_sigset_t))
- return -EINVAL;
- if (get_compat_sigset(&ksigmask, sigmask))
- return -EFAULT;
-
- sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
- sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
- }
+ ret = set_compat_user_sigmask(sigmask, &ksigmask, &sigsaved, sigsetsize);
+ if (ret)
+ return ret;
ret = do_sys_poll(ufds, nfds, to);
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 6fb5abdb87be..03d65c509eeb 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -166,6 +166,10 @@ typedef struct {
compat_sigset_word sig[_COMPAT_NSIG_WORDS];
} compat_sigset_t;
+int set_compat_user_sigmask(const compat_sigset_t __user *usigmask,
+ sigset_t *set, sigset_t *oldset,
+ size_t sigsetsize);
+
struct compat_sigaction {
#ifndef __ARCH_HAS_IRIX_SIGACTION
compat_uptr_t sa_handler;
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 3d4cd5db30a9..403e63d01bcf 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -263,6 +263,8 @@ extern int group_send_sig_info(int sig, struct siginfo *info,
struct task_struct *p, enum pid_type type);
extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
extern int sigprocmask(int, sigset_t *, sigset_t *);
+extern int set_user_sigmask(const sigset_t __user *usigmask, sigset_t *set,
+ sigset_t *oldset, size_t sigsetsize);
extern void set_current_blocked(sigset_t *);
extern void __set_current_blocked(const sigset_t *);
extern int show_unhandled_signals;
diff --git a/kernel/signal.c b/kernel/signal.c
index 0831d56a731a..1d72dcddcaaf 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2738,6 +2738,51 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset)
return 0;
}
+/*
+ * The api helps set app-provided sigmasks.
+ *
+ * This is useful for syscalls such as ppoll, pselect, io_pgetevents and
+ * epoll_pwait where a new sigmask is passed from userland for the syscalls.
+ */
+int set_user_sigmask(const sigset_t __user *usigmask, sigset_t *set,
+ sigset_t *oldset, size_t sigsetsize)
+{
+ if (!usigmask)
+ return 0;
+
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+ if (copy_from_user(set, usigmask, sizeof(sigset_t)))
+ return -EFAULT;
+
+ *oldset = current->blocked;
+ set_current_blocked(set);
+
+ return 0;
+}
+EXPORT_SYMBOL(set_user_sigmask);
+
+#ifdef CONFIG_COMPAT
+int set_compat_user_sigmask(const compat_sigset_t __user *usigmask,
+ sigset_t *set, sigset_t *oldset,
+ size_t sigsetsize)
+{
+ if (!usigmask)
+ return 0;
+
+ if (sigsetsize != sizeof(compat_sigset_t))
+ return -EINVAL;
+ if (get_compat_sigset(set, usigmask))
+ return -EFAULT;
+
+ *oldset = current->blocked;
+ set_current_blocked(set);
+
+ return 0;
+}
+EXPORT_SYMBOL(set_compat_user_sigmask);
+#endif
+
/**
* sys_rt_sigprocmask - change the list of currently blocked signals
* @how: whether to add, remove, or set signals
--
2.17.1
--
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 v3 0/5] y2038: Make ppoll, io_pgetevents and pselect y2038 safe
From: Deepa Dinamani @ 2018-09-17 1:04 UTC (permalink / raw)
To: viro, tglx, linux-kernel; +Cc: arnd, y2038, linux-fsdevel, linux-api, linux-aio
The series transitions the ppoll, io_getevents, and pselect syscalls
to be y2038 safe.
This is part of the work proceeding for syscalls for y2038.
It is based on the series [1] from Arnd Bergmann.
The overview of the series is as below:
1. Refactor sigmask handling logic for the above syscalls.
2. Provide y2038 safe versions of syscalls for all ABIs.
[1] https://lkml.org/lkml/2018/8/27/651
Changes since v2:
* remove 64BIT_TIME conditional for ppoll, pselect,
io_getpevents as per review comments
Changes since v1:
* fixed bug pointed out by arnd
Deepa Dinamani (5):
signal: Add set_user_sigmask()
signal: Add restore_user_sigmask()
ppoll: use __kernel_timespec
pselect6: use __kernel_timespec
io_pgetevents: use __kernel_timespec
fs/aio.c | 135 ++++++++++-----
fs/eventpoll.c | 52 +-----
fs/select.c | 360 ++++++++++++++++++++++-----------------
include/linux/compat.h | 20 +++
include/linux/signal.h | 4 +
include/linux/syscalls.h | 20 ++-
kernel/signal.c | 78 +++++++++
7 files changed, 427 insertions(+), 242 deletions(-)
--
2.17.1
--
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
* Re: [GIT PULL] y2038: convert more syscalls
From: Arnd Bergmann @ 2018-09-15 20:35 UTC (permalink / raw)
To: Thomas Gleixner
Cc: y2038 Mailman List, Christoph Hellwig, Linux API, Deepa Dinamani,
Linux Kernel Mailing List
In-Reply-To: <CAK8P3a3dYscBOj-v+OJK6QJk_ruuhKO0GaXW1ZjXfjCqGAfJFA@mail.gmail.com>
Resent due to missing subject
On Sat, Sep 15, 2018 at 5:47 PM Arnd Bergmann <arnd@arndb.de> wrote:
>
> Hi Thomas,
>
> Please pull the system call changes into a branch of the tip tree.
> These are the ones I posted right after rc1, with the addition of
> two bug fixes that were contributed by Guenther and the kbuild test
> robot.
>
> I've had the changes in linux-next since then and not received
> any other bug reports or feedback.
>
> I panicked a little at one point when I realized that there is
> a sparc64 specific bug in some of my patches, but I then
> found that at least this series is not affected at all.
>
> Arnd
>
> The following changes since commit 5b394b2ddf0347bef56e50c69a58773c94343ff3:
>
> Linux 4.19-rc1 (2018-08-26 14:11:59 -0700)
>
> are available in the Git repository at:
>
> git+ssh://git@ra.kernel.org:/pub/scm/linux/kernel/git/arnd/playground.git
> tags/y2038
>
> for you to fetch changes up to 67314ec7b0250290cc85eaa7a2f88a8ddb9e8547:
>
> RISC-V: Request newstat syscalls (2018-09-05 22:44:21 +0200)
>
> ----------------------------------------------------------------
> y2038: convert more syscalls
>
> Here is another set of system call changes to prepare the change over to
> 64-bit time_t. As before, the strategy is to change system calls that
> take a 'struct timespec' argument over to 'struct __kernel_timespec',
> which for now is defined to be the same but will get redefined to use a
> 64-bit time_t argument once we are ready to modify the system call tables.
>
> The major change from previous patches is that the plan is no longer
> to directly use the 'compat' system calls for providing compatibility
> with the existing 32-bit time_t based entry points. Instead, we rename
> the compat code to something that makes more sense on 32-bit architectures,
> e.g. compat_timespec becomes old_timespec32.
>
> With the renamed types in place, we change over the 'stat' and 'utimes'
> families of system calls, sched_rr_get_interval, recvmmsg and
> rt_sigtimedwait. Another series for poll, select and io_pgetevents is
> currently being tested.
>
> ----------------------------------------------------------------
> Arnd Bergmann (14):
> y2038: remove unused time interfaces
> y2038: make do_gettimeofday() and get_seconds() inline
> y2038: globally rename compat_time to old_time32
> y2038: Remove newstat family from default syscall set
> y2038: Remove stat64 family from default syscall set
> asm-generic: Move common compat types to asm-generic/compat.h
> asm-generic: Remove unneeded __ARCH_WANT_SYS_LLSEEK macro
> asm-generic: Remove empty asm/unistd.h
> y2038: Change sys_utimensat() to use __kernel_timespec
> y2038: Compile utimes()/futimesat() conditionally
> y2038: utimes: Rework #ifdef guards for compat syscalls
> y2038: sched: Change sched_rr_get_interval to use __kernel_timespec
> y2038: socket: Change recvmmsg to use __kernel_timespec
> y2038: signal: Change rt_sigtimedwait to use __kernel_timespec
>
> Guenter Roeck (1):
> RISC-V: Request newstat syscalls
>
> kbuild test robot (1):
> y2038: __get_old_timespec32() can be static
>
> arch/alpha/include/asm/unistd.h | 2 ++
> arch/arc/include/uapi/asm/unistd.h | 1 +
> arch/arm/include/asm/unistd.h | 4 ++--
> arch/arm64/include/asm/compat.h | 26 +++++---------------------
> arch/arm64/include/asm/stat.h | 2 +-
> arch/arm64/include/asm/unistd.h | 2 +-
> arch/arm64/include/uapi/asm/unistd.h | 1 +
> arch/c6x/include/uapi/asm/unistd.h | 1 +
> arch/h8300/include/uapi/asm/unistd.h | 1 +
> arch/hexagon/include/uapi/asm/unistd.h | 1 +
> arch/ia64/include/asm/unistd.h | 3 +++
> arch/m68k/include/asm/unistd.h | 2 +-
> arch/microblaze/include/asm/unistd.h | 2 +-
> arch/mips/include/asm/compat.h | 28 +++++-----------------------
> arch/mips/include/asm/unistd.h | 3 ++-
> arch/mips/kernel/binfmt_elfn32.c | 14 +++++++-------
> arch/mips/kernel/binfmt_elfo32.c | 14 +++++++-------
> arch/nds32/include/uapi/asm/unistd.h | 1 +
> arch/nios2/include/uapi/asm/unistd.h | 1 +
> arch/openrisc/include/uapi/asm/unistd.h | 1 +
> arch/parisc/include/asm/compat.h | 24 +++++-------------------
> arch/parisc/include/asm/unistd.h | 3 ++-
> arch/powerpc/include/asm/compat.h | 24 +++++-------------------
> arch/powerpc/include/asm/unistd.h | 3 ++-
> arch/powerpc/kernel/asm-offsets.c | 8 ++++----
> arch/powerpc/oprofile/backtrace.c | 2 +-
> arch/riscv/include/asm/unistd.h | 1 +
> arch/s390/include/asm/compat.h | 18 ++----------------
> arch/s390/include/asm/unistd.h | 3 ++-
> arch/sh/include/asm/unistd.h | 2 +-
> arch/sparc/include/asm/compat.h | 25 +++++--------------------
> arch/sparc/include/asm/unistd.h | 3 ++-
> arch/unicore32/include/uapi/asm/unistd.h | 1 +
> arch/x86/include/asm/compat.h | 19 ++-----------------
> arch/x86/include/asm/unistd.h | 3 ++-
> arch/xtensa/include/asm/unistd.h | 2 +-
> fs/aio.c | 8 ++++----
> fs/compat_binfmt_elf.c | 2 +-
> fs/read_write.c | 2 +-
> fs/select.c | 20 ++++++++++----------
> fs/stat.c | 3 +++
> fs/timerfd.c | 12 ++++++------
> fs/utimes.c | 73
> +++++++++++++++++++++++++++++++++++--------------------------------------
> include/asm-generic/compat.h | 24 +++++++++++++++++++++++-
> include/asm-generic/unistd.h | 13 -------------
> include/linux/compat.h | 101
> +++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------
> include/linux/compat_time.h | 32 --------------------------------
> include/linux/elfcore-compat.h | 8 ++++----
> include/linux/restart_block.h | 4 ++--
> include/linux/socket.h | 4 ++--
> include/linux/syscalls.h | 21 ++++++++++++---------
> include/linux/time32.h | 78
> +++++++++++++++++++++++++++++++++++++++++-------------------------------------
> include/linux/timekeeping.h | 12 ------------
> include/linux/timekeeping32.h | 53
> +++++++----------------------------------------------
> include/uapi/asm-generic/unistd.h | 2 ++
> ipc/mqueue.c | 8 ++++----
> ipc/msg.c | 6 +++---
> ipc/sem.c | 10 +++++-----
> ipc/shm.c | 6 +++---
> ipc/syscall.c | 2 +-
> ipc/util.h | 2 +-
> kernel/compat.c | 8 ++++----
> kernel/futex_compat.c | 2 +-
> kernel/sched/core.c | 8 ++++----
> kernel/signal.c | 19 ++++++++++---------
> kernel/time/hrtimer.c | 8 ++++----
> kernel/time/posix-stubs.c | 18 +++++++++---------
> kernel/time/posix-timers.c | 30 +++++++++++++++---------------
> kernel/time/time.c | 97
> ++++++++++++++++++++++++++++++++++++++-----------------------------------------------------------
> kernel/time/timekeeping.c | 24 ------------------------
> net/compat.c | 10 +++++-----
> net/socket.c | 18 ++++++++----------
> 72 files changed, 398 insertions(+), 601 deletions(-)
> delete mode 100644 include/asm-generic/unistd.h
> delete mode 100644 include/linux/compat_time.h
>
> Reply
> Forward
> _______________________________________________
> Y2038 mailing list
> Y2038@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/y2038
^ permalink raw reply
* Re: [PATCH v2 4/5] pselect6: use __kernel_timespec
From: Deepa Dinamani @ 2018-09-15 19:04 UTC (permalink / raw)
To: Thomas Gleixner
Cc: Arnd Bergmann, Alexander Viro, Linux Kernel Mailing List,
y2038 Mailman List, Linux FS-devel Mailing List, Linux API,
linux-aio
In-Reply-To: <alpine.DEB.2.21.1809152039440.1650@nanos.tec.linutronix.de>
On Sat, Sep 15, 2018 at 11:42 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> On Sat, 15 Sep 2018, Deepa Dinamani wrote:
>
> > On Sat, Sep 15, 2018 at 8:28 AM Arnd Bergmann <arnd@arndb.de> wrote:
> > >
> > > On Sat, Sep 15, 2018 at 7:09 AM Deepa Dinamani <deepa.kernel@gmail.com> wrote:
> > >
> > > > +#if defined(CONFIG_64BIT_TIME)
> > > > +
> > > > +COMPAT_SYSCALL_DEFINE6(pselect6_time64, int, n, compat_ulong_t __user *, inp,
> > > > + compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
> > > > + struct __kernel_timespec __user *, tsp, void __user *, sig)
> > >
> > > I got a link error here since compat_sys_pselect6_time64 and
> > > compat_sys_ppoll_time64 are only defined when CONFIG_64BIT_TIME
> > > is set.
> > >
> > > I did not think we would select this symbol on arm64, is that a mistake
> > > on my side, or should the #ifdef check be removed?
> >
> > But, this is a compat syscall.
> > When we introduced this CONFIG_64BIT_TIME we planned to use it for
> > compat syscalls also is my understanding.
> >
> > config 64BIT_TIME
> > def_bool ARCH_HAS_64BIT_TIME
> > help
> > This should be selected by all architectures that need to support
> > new system calls with a 64-bit time_t. This is relevant on all 32-bit
> > architectures, and 64-bit architectures as part of compat syscall
> > handling.
> >
> > This means it should be set on 64 bit architechtures also right?
>
> It's only set when 32bit compat mode is enabled on the 64bit kernel.
Ok, then we could delete the #ifdef like Arnd suggested. So this will
be defined for all architectures that enable CONFIG_COMPAT
unconditionally.
I will post an updated version.
Thanks,
Deepa
--
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
* Re: [PATCH v2 4/5] pselect6: use __kernel_timespec
From: Thomas Gleixner @ 2018-09-15 18:42 UTC (permalink / raw)
To: Deepa Dinamani
Cc: linux-aio, Arnd Bergmann, y2038 Mailman List, Linux API,
Linux Kernel Mailing List, Alexander Viro,
Linux FS-devel Mailing List
In-Reply-To: <CABeXuvoOEW9+5BPiDN+2S1boyMSg+csvSAd4ue03TB+yEO6dLg@mail.gmail.com>
On Sat, 15 Sep 2018, Deepa Dinamani wrote:
> On Sat, Sep 15, 2018 at 8:28 AM Arnd Bergmann <arnd@arndb.de> wrote:
> >
> > On Sat, Sep 15, 2018 at 7:09 AM Deepa Dinamani <deepa.kernel@gmail.com> wrote:
> >
> > > +#if defined(CONFIG_64BIT_TIME)
> > > +
> > > +COMPAT_SYSCALL_DEFINE6(pselect6_time64, int, n, compat_ulong_t __user *, inp,
> > > + compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
> > > + struct __kernel_timespec __user *, tsp, void __user *, sig)
> >
> > I got a link error here since compat_sys_pselect6_time64 and
> > compat_sys_ppoll_time64 are only defined when CONFIG_64BIT_TIME
> > is set.
> >
> > I did not think we would select this symbol on arm64, is that a mistake
> > on my side, or should the #ifdef check be removed?
>
> But, this is a compat syscall.
> When we introduced this CONFIG_64BIT_TIME we planned to use it for
> compat syscalls also is my understanding.
>
> config 64BIT_TIME
> def_bool ARCH_HAS_64BIT_TIME
> help
> This should be selected by all architectures that need to support
> new system calls with a 64-bit time_t. This is relevant on all 32-bit
> architectures, and 64-bit architectures as part of compat syscall
> handling.
>
> This means it should be set on 64 bit architechtures also right?
It's only set when 32bit compat mode is enabled on the 64bit kernel.
Thanks,
tglx
_______________________________________________
Y2038 mailing list
Y2038@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/y2038
^ permalink raw reply
* Re: [PATCH v2 4/5] pselect6: use __kernel_timespec
From: Deepa Dinamani @ 2018-09-15 18:37 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Alexander Viro, Thomas Gleixner, Linux Kernel Mailing List,
y2038 Mailman List, Linux FS-devel Mailing List, Linux API,
linux-aio
In-Reply-To: <CAK8P3a2Kkm2ubg_MVN_BJL=s7qpUB1-np=9zVpcJ2U-aPAJswg@mail.gmail.com>
On Sat, Sep 15, 2018 at 8:28 AM Arnd Bergmann <arnd@arndb.de> wrote:
>
> On Sat, Sep 15, 2018 at 7:09 AM Deepa Dinamani <deepa.kernel@gmail.com> wrote:
>
> > +#if defined(CONFIG_64BIT_TIME)
> > +
> > +COMPAT_SYSCALL_DEFINE6(pselect6_time64, int, n, compat_ulong_t __user *, inp,
> > + compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
> > + struct __kernel_timespec __user *, tsp, void __user *, sig)
>
> I got a link error here since compat_sys_pselect6_time64 and
> compat_sys_ppoll_time64 are only defined when CONFIG_64BIT_TIME
> is set.
>
> I did not think we would select this symbol on arm64, is that a mistake
> on my side, or should the #ifdef check be removed?
But, this is a compat syscall.
When we introduced this CONFIG_64BIT_TIME we planned to use it for
compat syscalls also is my understanding.
config 64BIT_TIME
def_bool ARCH_HAS_64BIT_TIME
help
This should be selected by all architectures that need to support
new system calls with a 64-bit time_t. This is relevant on all 32-bit
architectures, and 64-bit architectures as part of compat syscall
handling.
This means it should be set on 64 bit architechtures also right?
If we don't have the #ifdef here then we have an entry point from
userspace defined and Thomas had pointed out that it was a security
hole.
-Deepa
--
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
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