From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/10955 Path: news.gmane.org!.POSTED!not-for-mail From: Eric Hassold Newsgroups: gmane.linux.lib.musl.general Subject: Fix pthread_create on some devices failing to initialize guard area Date: Fri, 20 Jan 2017 11:45:09 -0800 Message-ID: Reply-To: musl@lists.openwall.com NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Trace: blaine.gmane.org 1484941532 2298 195.159.176.226 (20 Jan 2017 19:45:32 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Fri, 20 Jan 2017 19:45:32 +0000 (UTC) User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:45.0) Gecko/20100101 Thunderbird/45.6.0 To: "musl@lists.openwall.com" Original-X-From: musl-return-10970-gllmg-musl=m.gmane.org@lists.openwall.com Fri Jan 20 20:45:27 2017 Return-path: Envelope-to: gllmg-musl@m.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by blaine.gmane.org with smtp (Exim 4.84_2) (envelope-from ) id 1cUf7h-0008A8-VS for gllmg-musl@m.gmane.org; Fri, 20 Jan 2017 20:45:22 +0100 Original-Received: (qmail 9353 invoked by uid 550); 20 Jan 2017 19:45:25 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Original-Received: (qmail 9306 invoked from network); 20 Jan 2017 19:45:23 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=to:from:subject:message-id:date:user-agent:mime-version :content-transfer-encoding; bh=PCkthqWeP9PEuCz00aD6D2k6RsbdeOE3QYFHLWlBu1E=; b=MadTlgW3RYe9i+tFUbFAgq3rg1ZhLpMEju1BTp13j7QNcpFqsR/n6x8ZQzyPaOBcJB bKVFYwSRdwqjiIb7NuZ+NMqzpuYJhuA4CGYFmcgeRwGARFDkvBBdfd4+9sLR3oMtManM b0wz7WHHBBjmU9p63/VqmZlQmIbAtAGCcamCRKI4XLC9FmCltXGvTfdgYSmcVvIxH62o u/rfu58g/ARQyMlj7nZXcNyiesD/EhOH0wJcJRRFWSX9nYui8n+EkFwLGknfBz9Qg5qP QsBvgOmOXBUzzk2lr10ZU92glER7SyiUUxEa5n+eHDSmKoJtp6v4/mePXNAWcFWhLlk9 ZXxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-transfer-encoding; bh=PCkthqWeP9PEuCz00aD6D2k6RsbdeOE3QYFHLWlBu1E=; b=Dz6i6A+i09G7OBAC4xoKE8M35UdnbkXNHNo1VIXrkLM/ZZcqX/WXekqcVcl+Wd7Lk0 1QxTf8JWkAXML48jeZvSR7LvYljnooFzV8neIjE8E773HfFQUwQjfGkDOJx3jffTZZNU 3iEuWL0YX1H/g3J+Vunb7KxTr4d111dkdhLHVofqLFRJBy7VhHVX8m1XyfUZ4asL+Kah y9Tgk2s9GiqO7/C7boMLh6QipMkcv4rlmeu5yt+kX+yFWw0CdSvtRVB3jRVsRDIwD3yB PUhVAhWx9JagVKtBuGEZPmeILbUnKhhFC1/AGoZD81uX5AGJ+amE08UCuk5nLrFfxixA YLSg== X-Gm-Message-State: AIkVDXL+bANugUa1eYrtEI8OWa12l1JJqBmNZb6SpFpQqr0ZC/6RW52qRRgyM+ujE9p2vA== X-Received: by 10.99.237.17 with SMTP id d17mr19021732pgi.82.1484941510978; Fri, 20 Jan 2017 11:45:10 -0800 (PST) Xref: news.gmane.org gmane.linux.lib.musl.general:10955 Archived-At: 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