Skip to content

UNIX user namespacing

What is UNIX user namespacing, and why is it the default?

This article explains what namespacing is, the two effects it has, and the one case in which you may want to opt out.


What it is

By default, Cyberfusion runs each UNIX user — and each FPM pool — inside its own Linux namespace. A namespace is an isolated execution environment: processes inside it see a restricted view of the system.

Namespacing has two distinct effects, and both are relied on across Cyberfusion:

  1. Per-user PHP and Node.js versions — the user's selected default version is always what runs.
  2. Protection against Local Privilege Escalation — SUID binaries don't work, which blocks most LPE exploits.

Per-user PHP and Node.js versions

Inside a namespaced UNIX user, calls to php or node always run the version set as the default for that UNIX user.

To change the version used, update the default for the UNIX user:

How it works

On Linux, there is normally one system-wide default version of binaries such as php and node, which all users share. Cyberfusion uses the namespacing facilities to mount the UNIX user's selected default version over those default binaries.

As a result, the user's chosen default is always what gets invoked, regardless of how many other versions are installed on the cluster.

Why a daemon's PHP version can look wrong

After you set the default PHP version, running php -v shows the version you chose. But some programs don't run php directly — they read the path of the PHP interpreter that is currently running (PHP exposes this path as PHP_BINARY) and use that exact path to start more PHP processes. Laravel Horizon works this way: it starts its worker sub-processes from PHP_BINARY.

When such a program reports that path, you may see an older version number than the one you selected — for example php8.3 in the command line, while your default is PHP 8.5. This is expected, and PHP 8.5 is still the version actually running.

The reason: to make your selected version the one that runs, the cluster mounts that version's program over the shared php path (this is the mounting described above). The path keeps the name of the cluster's system-wide default version (here, php8.3), but the program running at that path is your selected version (8.5). So the version number in the path is misleading — the program behind it is the version you chose.

A plain php command is not affected — only a program that spawns a sub-process from the interpreter's own path sees the older-looking name. To confirm which version is really running, don't read the path: check the version the worker processes report (for example in phpinfo() or the application's own version output).

Protection against Local Privilege Escalation

Inside a namespace, SUID binaries (such as sudo) do not function. Attempting to use sudo simply fails.

This blocks Local Privilege Escalation (LPE) vulnerabilities — bugs that let a regular user elevate to root. Most LPE exploits depend on a SUID binary to perform the escalation. With SUID binaries disabled, the exploit cannot run even if the underlying bug is present.

Publicly known LPE exploits (Copy Fail, Dirty Frag, Fragnesia, and similar) do not work against namespaced UNIX users on Cyberfusion, regardless of patch state.

When to opt out

There is essentially one reason not to use namespacing: you need SUID binaries to work, typically because a legacy application depends on sudo or a similar SUID binary.

When namespacing is disabled, both effects above are lost:

  • Per-user versions — to approximate per-user defaults, Cyberfusion sets up shell aliases for php and node that point to the user's selected version. The aliases don't cover every case: they don't apply in non-interactive shells, in scripts that invoke the binary indirectly, or when the caller uses a full path. When the alias doesn't apply, the cluster's system-wide default version is used instead — which may not be the version you expected. To guarantee a specific version, call it by its full path. For example:

    /usr/bin/php7.4 /usr/bin/composer
    
  • LPE protection — SUID binaries function normally, so LPE exploits against unpatched bugs become possible.

Most projects do not need to opt out. Leave namespacing enabled unless a SUID-dependent legacy setup forces you to disable it.