---
name: "pthread_jit_write_protect_np"
section: "3"
platform: "macos"
package: "libpthread"
version: "539.100.4"
release: "macOS 26.5"
platforms: ["macos"]
url: "https://new.carta.tech/pthread_jit_write_protect_np"
---

# pthread\_jit\_write\_protect\_np(3)

thread JIT region write protection settings

## NAME

**pthread\_jit\_write\_protect\_supported\_np**, **pthread\_jit\_write\_protect\_np**, **pthread\_jit\_write\_with\_callback\_np**, **pthread\_jit\_write\_freeze\_callbacks\_np** – thread JIT region write protection settings

## SYNOPSIS

**#include \<pthread.h\>**

*int*\

**pthread\_jit\_write\_protect\_supported\_np**(*void*);

*void*\

**pthread\_jit\_write\_protect\_np**(*int enabled*);

*typedef* *int \*pthread\_jit\_write\_callback\_tvoid \**;\

*int*\

**pthread\_jit\_write\_with\_callback\_np**(*pthread\_jit\_write\_callback\_t callback*, *void \*ctx*);

*void*\

**pthread\_jit\_write\_freeze\_callbacks\_np**(*void*);

## DESCRIPTION

The **pthread\_jit\_write\_protect\_supported\_np**() function returns whether per-thread write protection on the MAP\_JIT region is supported on this platform.

On platforms where **pthread\_jit\_write\_protect\_supported\_np**() is true, MAP\_JIT regions are never writeable and executable simultaneously. When write protection is enabled for the thread, writes by the thread to the MAP\_JIT region are denied and the MAP\_JIT region is executable. When write protection is disabled for the thread, writes by the thread to the MAP\_JIT region are allowed and the MAP\_JIT region is not executable.

The **pthread\_jit\_write\_protect\_np**() function sets whether MAP\_JIT region write protection is enabled for this thread. Pass a non-zero value for the *enabled* parameter to enable thread JIT region write protection and allow execution. Pass a zero value for the *enabled* parameter to disable thread JIT write protection and deny execution.

The **pthread\_jit\_write\_with\_callback\_np**() function disables write protection, calls the supplied *callback* with *ctx* to write to the JIT region after validating its input for safety according to application logic, and then re-enables write protection. That is, it's roughly equivalent to:

```
pthread_jit_write_protect_np(false);
int rc = callback(ctx);
pthread_jit_write_protect_np(true);
return rc;
```

However, **pthread\_jit\_write\_with\_callback\_np**() enforces that the *callback* function must have been previously enumerated in a static list of allowed JIT write callbacks declared using the **PTHREAD\_JIT\_WRITE\_ALLOW\_CALLBACKS\_NP** macro. Note that each image (i.e. main executable or framework/dylib) can specify its own list, and each image may specify at most one list. For example, an invocation of **PTHREAD\_JIT\_WRITE\_ALLOW\_CALLBACKS\_NP** to allow a JIT write callback **jit\_write\_cb()** would be:

```
static void *jit_region;
int
jit_write_cb(void *ctx)
{
	size_t len = 0;
	void *insns = validate_instructions(ctx, &len);
	if (!insns) {
		__builtin_trap();
	}
	memcpy(jit_region, insns, len);
	return 0;
}
PTHREAD_JIT_WRITE_ALLOW_CALLBACKS_NP(jit_write_cb);
```

By default, JIT write callbacks are not allowed in frameworks/dylibs dynamically loaded at runtime via [dlopen(3)](/dlopen/3.md). However, applications that need JIT write callbacks in dynamically loaded code can take an additional entitlement (see ENTITLEMENTS) to allow them in any code loaded up until the **pthread\_jit\_write\_freeze\_callbacks\_np**() function is called.

On platforms where **pthread\_jit\_write\_protect\_supported\_np**() is false, MAP\_JIT regions are simultaenously writeable and executable. Calls to **pthread\_jit\_write\_protect\_np**() are no-ops on unsupported platforms. Calls to **pthread\_jit\_write\_with\_callback\_np**() result in a direct call to *callback* on unsupported platforms.

## RETURN VALUES

If supported, the **pthread\_jit\_write\_protect\_supported\_np**() function will return one. Otherwise the function will return zero.

**pthread\_jit\_write\_with\_callback\_np**() returns the result returned by the *callback* function.

## SECURITY CONSIDERATIONS

The purpose of per-thread JIT region write protection is to serve as a hardening measure against attacks that attempt to gain code execution by exploiting vulnerabilities to write unintended code into the JIT region.

Some attacks may attempt to defeat JIT write protection by inducing unexpected/unintended calls to **pthread\_jit\_write\_protect\_np**(), e.g. dynamically via **dlsym**(). To further harden against such attacks, the **pthread\_jit\_write\_with\_callback\_np**() interface is intended to allow even tighter control over code permitted to write to the JIT region; in applications that adopt the **com.apple.security.cs.jit-write-allowlist** entitlement, only callbacks specifically enumerated in an invocation of **PTHREAD\_JIT\_WRITE\_ALLOW\_CALLBACKS\_NP** can do so, and **pthread\_jit\_write\_protect\_np**() is disabled.

Applications and frameworks should prefer to use **pthread\_jit\_write\_with\_callback\_np**() as a defense-in-depth hardening if relevant for their threat model.

Allowed callbacks should assume that their input is attacker-controlled and make an effort to validate that the instructions to be written should be permitted.

## ENTITLEMENTS

- com.apple.security.cs.jit-write-allowlist

  A Boolean value that indicates whether **pthread\_jit\_write\_protect\_np**() should be disabled and **pthread\_jit\_write\_with\_callback\_np**() must be used instead to write to the JIT region.

- com.apple.security.cs.jit-write-allowlist-freeze-late

  A Boolean value that indicates whether the runtime should wait for an explicit call to **pthread\_jit\_write\_freeze\_callbacks\_np**() before "freezing" the set of allowed JIT write callbacks, to allow the application to dynamically load code containing JIT write callbacks that should be allowed.

## SEE ALSO

[mmap(2)](/mmap/2.md)
