[03/13] posix: Consolidate Linux nanosleep syscall

Message ID 1494611894-9282-3-git-send-email-adhemerval.zanella@linaro.org
State Dropped
Headers

Commit Message

Adhemerval Zanella May 12, 2017, 5:58 p.m. UTC
  This patch consolidates the nanosleep Linux syscall generation on
sysdeps/unix/sysv/linux/nanosleep.c.  It basically removes it from
architectures auto-generation list.

Checked on i686-linux-gnu, x86_64-linux-gnu, x86_64-linux-gnux32,
arch64-linux-gnu, arm-linux-gnueabihf, powerpc64le-linux-gnu,
sparc64-linux-gnu, and sparcv9-linux-gnu.

	* nptl/Makefile (CFLAGS-nanosleep.c): New rule.
	* posix/Makefile (CFLAGS-nanosleep.c): Likewise.
	* sysdeps/unix/sysv/linux/nanosleep.c: New file.
	* sysdeps/unix/sysv/linux/syscalls.list: Remove nanosleep from
	auto-generated list.
---
 ChangeLog                             |  6 ++++++
 nptl/Makefile                         |  1 +
 posix/Makefile                        |  1 +
 sysdeps/unix/sysv/linux/nanosleep.c   | 30 ++++++++++++++++++++++++++++++
 sysdeps/unix/sysv/linux/syscalls.list |  1 -
 5 files changed, 38 insertions(+), 1 deletion(-)
 create mode 100644 sysdeps/unix/sysv/linux/nanosleep.c
  

Comments

Florian Weimer May 12, 2017, 6:21 p.m. UTC | #1
On 05/12/2017 07:58 PM, Adhemerval Zanella wrote:
> +++ b/nptl/Makefile

> +CFLAGS-nanosleep.c = -fexceptions -fasynchronous-unwind-tables


> +++ b/posix/Makefile

> +CFLAGS-nanosleep.c = -fexceptions

Why the discrepancy?  I suppose both implementations could be called in 
a multi-threaded program.

Thanks,
Florian
  
Adhemerval Zanella May 12, 2017, 6:30 p.m. UTC | #2
On 12/05/2017 15:21, Florian Weimer wrote:
> On 05/12/2017 07:58 PM, Adhemerval Zanella wrote:
>> +++ b/nptl/Makefile
> 
>> +CFLAGS-nanosleep.c = -fexceptions -fasynchronous-unwind-tables
> 
> 
>> +++ b/posix/Makefile
> 
>> +CFLAGS-nanosleep.c = -fexceptions
> 
> Why the discrepancy?  I suppose both implementations could be called in a multi-threaded program.

I do not recall a reason why these are different, I will set both to
-fexceptions -fasynchronous-unwind-tables.  AFAIK -fexception is the
required flag for cancelable syscall to work correctly, while 
-fasynchronous-unwind-tables is make it work also through signals
(not really sure though).  So I would say to be safe we should set
both.
  
Florian Weimer May 15, 2017, 9:43 a.m. UTC | #3
On 05/12/2017 08:30 PM, Adhemerval Zanella wrote:
> 
> 
> On 12/05/2017 15:21, Florian Weimer wrote:
>> On 05/12/2017 07:58 PM, Adhemerval Zanella wrote:
>>> +++ b/nptl/Makefile
>>
>>> +CFLAGS-nanosleep.c = -fexceptions -fasynchronous-unwind-tables
>>
>>
>>> +++ b/posix/Makefile
>>
>>> +CFLAGS-nanosleep.c = -fexceptions
>>
>> Why the discrepancy?  I suppose both implementations could be called in a multi-threaded program.
> 
> I do not recall a reason why these are different, I will set both to
> -fexceptions -fasynchronous-unwind-tables.  AFAIK -fexception is the
> required flag for cancelable syscall to work correctly, while
> -fasynchronous-unwind-tables is make it work also through signals
> (not really sure though).  So I would say to be safe we should set
> both.

glibc itself no longer uses the libgcc unwinder and the 
__gcc_personality_v0 personality routine.  As far as I know, the C front 
end never supported exceptions in this way, and we have since removed 
all assembly routines which used this functionality.

The replacement is a chain list of cleanup routines, rooted in a 
thread-local variable.  Cleanup code is specified by function pointers 
on the stack.  From a security perspective, this is far worse than 
unwinding based on tables stored in read-only memory.  We can likely 
obfuscate the function pointers (like we do for setjmp buffers), but 
that's it.

Technically, __gcc_personality_v0 is part of the ABI, so there could 
still be user code out there that uses it.  And of course, Ada and C++ 
code which is called from glibc code (or which runs from a signal 
handler that interrupts glibc code) could have stack frames with crucial 
unwinding information when thread cancellation happens.

In order to reach those stack frames, the cancellation code needs to 
unwind through glibc code.  This could be any code in glibc which calls 
a function which is a cancellation point.

Based on that, I think we should compile all of glibc with unwinding 
support, and considering that asynchronous cancellation can happen 
through synchronous cancellation within signal handlers, we need both 
-fexceptions *and* -fasynchronous-unwind-tables.

Comments?

Thanks,
Florian
  
Joseph Myers May 15, 2017, 11:36 a.m. UTC | #4
On Mon, 15 May 2017, Florian Weimer wrote:

> Technically, __gcc_personality_v0 is part of the ABI, so there could still be
> user code out there that uses it.  And of course, Ada and C++ code which is
> called from glibc code (or which runs from a signal handler that interrupts
> glibc code) could have stack frames with crucial unwinding information when
> thread cancellation happens.
> 
> In order to reach those stack frames, the cancellation code needs to unwind
> through glibc code.  This could be any code in glibc which calls a function
> which is a cancellation point.
> 
> Based on that, I think we should compile all of glibc with unwinding support,
> and considering that asynchronous cancellation can happen through synchronous
> cancellation within signal handlers, we need both -fexceptions *and*
> -fasynchronous-unwind-tables.

See <https://sourceware.org/ml/libc-alpha/2015-10/msg00569.html> and 
followups for discussion of the circumstances when those options may be 
needed.
  
Florian Weimer May 15, 2017, 11:46 a.m. UTC | #5
On 05/15/2017 01:36 PM, Joseph Myers wrote:

> See <https://sourceware.org/ml/libc-alpha/2015-10/msg00569.html> and
> followups for discussion of the circumstances when those options may be
> needed.

Interesting.  So the C frontend can actually generate code which invokes 
the personality routine (via the cleanup attribute).

I wonder if we can use this to make cancellation safer, at least within 
glibc.

Florian
  

Patch

diff --git a/nptl/Makefile b/nptl/Makefile
index d39bb50..cdf69bd 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -216,6 +216,7 @@  CFLAGS-sendmsg.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-close.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-read.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-write.c = -fexceptions -fasynchronous-unwind-tables
+CFLAGS-nanosleep.c = -fexceptions -fasynchronous-unwind-tables
 
 CFLAGS-pt-system.c = -fexceptions
 
diff --git a/posix/Makefile b/posix/Makefile
index 0025d8a..9f186cd 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -232,6 +232,7 @@  CFLAGS-execle.os = -fomit-frame-pointer
 CFLAGS-execl.os = -fomit-frame-pointer
 CFLAGS-execvp.os = -fomit-frame-pointer
 CFLAGS-execlp.os = -fomit-frame-pointer
+CFLAGS-nanosleep.c = -fexceptions
 
 tstgetopt-ARGS = -a -b -cfoobar --required foobar --optional=bazbug \
 		--none random --col --color --colour
diff --git a/sysdeps/unix/sysv/linux/nanosleep.c b/sysdeps/unix/sysv/linux/nanosleep.c
new file mode 100644
index 0000000..b352f84
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/nanosleep.c
@@ -0,0 +1,30 @@ 
+/* Linux high resolution nanosleep implementation.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <time.h>
+#include <sysdep-cancel.h>
+
+/* Pause execution for a number of nanoseconds.  */
+int
+__nanosleep (const struct timespec *requested_time,
+	     struct timespec *remaining)
+{
+  return SYSCALL_CANCEL (nanosleep, requested_time, remaining);
+}
+libc_hidden_def (__nanosleep)
+weak_alias (__nanosleep, nanosleep)
diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list
index eab30dd..7fca6f8 100644
--- a/sysdeps/unix/sysv/linux/syscalls.list
+++ b/sysdeps/unix/sysv/linux/syscalls.list
@@ -42,7 +42,6 @@  mount		EXTRA	mount		i:sssip	__mount	mount
 mremap		EXTRA	mremap		b:ainip	__mremap	mremap
 munlock		-	munlock		i:ai	munlock
 munlockall	-	munlockall	i:	munlockall
-nanosleep	-	nanosleep	Ci:pp	__nanosleep	nanosleep
 nfsservctl	EXTRA	nfsservctl	i:ipp	nfsservctl
 pipe		-	pipe		i:f	__pipe		pipe
 pipe2		-	pipe2		i:fi	__pipe2		pipe2