mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Eric Hassold <hassold@gmail.com>
To: "musl@lists.openwall.com" <musl@lists.openwall.com>
Subject: Fix pthread_create on some devices failing to initialize guard area
Date: Fri, 20 Jan 2017 11:45:09 -0800	[thread overview]
Message-ID: <dc9ff861-1893-10fe-07d9-333310fc56bc@gmail.com> (raw)

Hi All,

While deploying test static executable across farm of different embedded systems, found out that pthread_create() is failing systematically on some (very few) arm-linux devices whenever non null stack guard is enabled (that is, also when calling pthread_create with default - i.e. null - attributes since default is a one page of guard). One of those device is for example a Marvell Armada 375 running Linux 3.10.39. Same test code, built with alternative libc implementations (glibc, uClibc) works as expected on those devices.


Issue

This occurs because of call to mprotect() in pthread_create fails. In current implementation, if guard size is non null, memory for (guard + stack + ...) is first allocated (mmap'ed) with no accessibility (PROT_NONE), then mprotect() is called to re-enable read/write access to (memory + guardsize). Since call to mprotect() systematically fails in this scenario (returning error code EINVAL), it is impossible to create thread.


Patch

In proposed patch (attached below), memory for (guard + stack + ...) is first mmap'ed with read/write accessibility, then guard area is protected by calling mprotect() with PROT_NONE on guardsize first bytes of returned memory. This call to mprotect() to remove all accessibility on guard area, with guard area being at beginning of previously mmap'ed memory, works correctly on those platforms having issue with current implementation. Incidentally, this makes the logic more concise to handle both cases (with or without guard) is a more consistent way, and handle systems with partial/invalid page protection implementation (e.g. mprotect() returning ENOSYS) more gracefully since the stack is explicitly created with read/write access.

-Eric.

---

Subject: [PATCH] set up guard protection after stack is mapped

calling mprotect beyond the guard page of PROT_NONE mmap-ed stack fails on
some devices, making it impossible to create thread. instead, allocate memory
for stack and guard first, with read and write permission, then protect guard
area.
---
  src/thread/pthread_create.c | 11 ++++-------
  1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
index 49f2f72..f846bec 100644
--- a/src/thread/pthread_create.c
+++ b/src/thread/pthread_create.c
@@ -232,21 +232,18 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
  	} else {
  		guard = ROUND(attr._a_guardsize);
  		size = guard + ROUND(attr._a_stacksize
-			+ libc.tls_size +  __pthread_tsd_size);
+			+ libc.tls_size + __pthread_tsd_size);
  	}
  
  	if (!tsd) {
+		map = __mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
+		if (map == MAP_FAILED) goto fail;
  		if (guard) {
-			map = __mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANON, -1, 0);
-			if (map == MAP_FAILED) goto fail;
-			if (__mprotect(map+guard, size-guard, PROT_READ|PROT_WRITE)
+			if (__mprotect(map, guard, PROT_NONE)
  			    && errno != ENOSYS) {
  				__munmap(map, size);
  				goto fail;
  			}
-		} else {
-			map = __mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
-			if (map == MAP_FAILED) goto fail;
  		}
  		tsd = map + size - __pthread_tsd_size;
  		if (!stack) {
-- 
2.7.4



             reply	other threads:[~2017-01-20 19:45 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-01-20 19:45 Eric Hassold [this message]
2017-01-20 19:56 ` Rich Felker
2017-01-20 21:04   ` Eric Hassold
2017-01-20 21:29     ` Rich Felker
2017-01-20 22:42       ` Eric Hassold
2017-01-30 21:30         ` Eric Hassold
2017-01-30 23:13           ` Rich Felker
2017-01-31  2:52             ` Eric Hassold
2017-01-31  3:58         ` Rich Felker
2017-01-31 21:18           ` Eric Hassold
2017-01-31 22:44             ` Eric Hassold
2017-02-01  9:52               ` Szabolcs Nagy
2017-02-01 18:21                 ` Eric Hassold
2017-02-01 18:35                   ` Rich Felker
2017-02-01 18:52                     ` Eric Hassold

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=dc9ff861-1893-10fe-07d9-333310fc56bc@gmail.com \
    --to=hassold@gmail.com \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).