Skip to content

Commit 10893f6

Browse files
committed
Rewrite and simplify thread support for upstream OpenBSD code.
Clean up uses of "thread_private.h", which is an OpenBSD implementation detail that doesn't belong in libc/private/. Our arc4random() can be more like upstream OpenBSD by using MADV_WIPEONFORK. Also prefer to die via async_safe_fatal() rather than returning and relying on the caller (which is OpenBSD code that just calls abort() without a message). Change-Id: I3804a648414b222ad752ab4b6b940d54fd7dd16f
1 parent fff0acd commit 10893f6

7 files changed

Lines changed: 71 additions & 135 deletions

File tree

libc/Android.bp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -998,7 +998,6 @@ cc_library_static {
998998
"bionic/system_property_set.cpp",
999999
"bionic/tdestroy.cpp",
10001000
"bionic/termios.cpp",
1001-
"bionic/thread_private.cpp",
10021001
"bionic/threads.cpp",
10031002
"bionic/time.cpp",
10041003
"bionic/tmpfile.cpp",

libc/bionic/libc_init_common.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
#include "private/bionic_defs.h"
5050
#include "private/bionic_globals.h"
5151
#include "private/bionic_tls.h"
52-
#include "private/thread_private.h"
5352
#include "pthread_internal.h"
5453

5554
extern "C" int __system_properties_init(void);
@@ -108,11 +107,6 @@ static void __check_max_thread_id() {
108107
}
109108
#endif
110109

111-
static void arc4random_fork_handler() {
112-
_rs_forked = 1;
113-
_thread_arc4_lock();
114-
}
115-
116110
__BIONIC_WEAK_FOR_NATIVE_BRIDGE
117111
void __libc_init_scudo() {
118112
// Heap tagging level *must* be set before interacting with Scudo, otherwise
@@ -203,9 +197,12 @@ void __libc_init_common() {
203197
#endif
204198
}
205199

200+
extern "C" void arc4random_mutex_lock();
201+
extern "C" void arc4random_mutex_unlock();
202+
206203
void __libc_init_fork_handler() {
207204
// Register atfork handlers to take and release the arc4random lock.
208-
pthread_atfork(arc4random_fork_handler, _thread_arc4_unlock, _thread_arc4_unlock);
205+
pthread_atfork(arc4random_mutex_lock, arc4random_mutex_unlock, arc4random_mutex_unlock);
209206
}
210207

211208
extern "C" void scudo_malloc_set_add_large_allocation_slack(int add_slack);

libc/bionic/thread_private.cpp

Lines changed: 0 additions & 42 deletions
This file was deleted.

libc/private/thread_private.h

Lines changed: 0 additions & 37 deletions
This file was deleted.

libc/stdio/stdio.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
#include "private/FdPath.h"
5757
#include "private/__bionic_get_shell_path.h"
5858
#include "private/bionic_fortify.h"
59-
#include "private/thread_private.h"
6059

6160
#define NDYNAMIC 10 /* add ten more whenever necessary */
6261

Lines changed: 36 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: arc4random_linux.h,v 1.7 2014/07/20 20:51:13 bcook Exp $ */
1+
/* $OpenBSD: arc4random_linux.h,v 1.7 2014/07/20 20:51:13 bcook Exp $ */
22

33
/*
44
* Copyright (c) 1996, David Mazieres <dm@uun.org>
@@ -18,67 +18,56 @@
1818
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1919
*/
2020

21-
/*
22-
* Stub functions for portability.
23-
*/
24-
25-
#include <errno.h>
2621
#include <pthread.h>
27-
#include <signal.h>
2822
#include <sys/mman.h>
2923
#include <sys/prctl.h>
3024

3125
#include <async_safe/log.h>
3226

33-
// Android gets these from "thread_private.h" so we can set an atfork handler.
34-
// TODO: we should investigate MADV_WIPEONFORK for the structs allocated
35-
// by _rs_allocate() [where OpenBSD uses their MAP_INHERIT_ZERO and has an
36-
// empty _rs_forkdetect()], but because the mutex guards the creation of that
37-
// VMA, we'd still need an external mutex, and we'd still want some way to
38-
// lock/unlock around a fork().
39-
#include "thread_private.h"
40-
//static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
41-
//#define _ARC4_LOCK() pthread_mutex_lock(&arc4random_mtx)
42-
//#define _ARC4_UNLOCK() pthread_mutex_unlock(&arc4random_mtx)
27+
static pthread_mutex_t g_arc4random_mutex = PTHREAD_MUTEX_INITIALIZER;
4328

44-
static inline void _getentropy_fail(void) {
45-
async_safe_fatal("getentropy failed: %s", strerror(errno));
29+
void arc4random_mutex_lock() {
30+
pthread_mutex_lock(&g_arc4random_mutex);
4631
}
4732

48-
volatile sig_atomic_t _rs_forked;
33+
void arc4random_mutex_unlock() {
34+
pthread_mutex_unlock(&g_arc4random_mutex);
35+
}
36+
37+
#define _ARC4_LOCK() arc4random_mutex_lock()
38+
#define _ARC4_UNLOCK() arc4random_mutex_unlock()
4939

50-
static inline void
51-
_rs_forkdetect(void)
52-
{
53-
static pid_t _rs_pid = 0;
54-
pid_t pid = getpid();
40+
static inline void _getentropy_fail(void) {
41+
async_safe_fatal("getentropy failed: %m");
42+
}
5543

56-
if (_rs_pid == 0 || _rs_pid != pid || _rs_forked) {
57-
_rs_pid = pid;
58-
_rs_forked = 0;
59-
if (rs)
60-
memset(rs, 0, sizeof(*rs));
61-
}
44+
static inline void _rs_forkdetect(void) {
45+
// Not needed thanks to the MADV_WIPEONFORK below.
6246
}
6347

64-
static inline int
65-
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
66-
{
67-
// OpenBSD's arc4random_linux.h allocates two separate mappings, but for
68-
// themselves they just allocate both structs into one mapping like this.
69-
struct {
70-
struct _rs rs;
71-
struct _rsx rsx;
72-
} *p;
48+
static inline int _rs_allocate(struct _rs** rsp, struct _rsx** rsxp) {
49+
// OpenBSD's arc4random_linux.h allocates two separate mappings, but for
50+
// themselves they just allocate both structs into one mapping like this.
51+
struct data {
52+
struct _rs rs;
53+
struct _rsx rsx;
54+
};
55+
const size_t size = sizeof(struct data);
7356

74-
if ((p = mmap(NULL, sizeof(*p), PROT_READ|PROT_WRITE,
75-
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
76-
return (-1);
57+
struct data* p = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
58+
if (p == MAP_FAILED) {
59+
async_safe_fatal("arc4random data allocation failed: %m");
60+
}
7761

78-
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, sizeof(*p), "arc4random data");
62+
// Equivalent to OpenBSD's minherit(MAP_INHERIT_ZERO).
63+
if (madvise(p, size, MADV_WIPEONFORK) == -1) {
64+
async_safe_fatal("arc4random data MADV_WIPEONFORK failed: %m");
65+
}
7966

80-
*rsp = &p->rs;
81-
*rsxp = &p->rsx;
67+
// Give the allocation a name to make tombstones more intelligible.
68+
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, size, "arc4random data");
8269

83-
return (0);
70+
*rsp = &p->rs;
71+
*rsxp = &p->rsx;
72+
return 0;
8473
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (C) 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include <pthread.h>
20+
#include <time.h>
21+
22+
// An internal OpenBSD interface, used by res_randomid() only.
23+
#define __MUTEX_NAME(name) __CONCAT(__libc_mutex_,name)
24+
#define _THREAD_PRIVATE_MUTEX(name) static pthread_mutex_t __MUTEX_NAME(name) = PTHREAD_MUTEX_INITIALIZER
25+
#define _THREAD_PRIVATE_MUTEX_LOCK(name) pthread_mutex_lock(&__MUTEX_NAME(name))
26+
#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) pthread_mutex_unlock(&__MUTEX_NAME(name))
27+
28+
// An internal OpenBSD interface, used by gdtoa only.
29+
// Note that these aren't exactly the usual OpenBSD ones which lazy-initialize!
30+
#define _MUTEX_LOCK(l) pthread_mutex_lock((pthread_mutex_t*) l)
31+
#define _MUTEX_UNLOCK(l) pthread_mutex_unlock((pthread_mutex_t*) l)

0 commit comments

Comments
 (0)