Luther Monson, Staff Software Engineer at SUSE

Luther Monson

Go by way of PHP · Containers · VMs · Windows · Kubernetes

Every Way a Tenant Escaped: A Cross-Tenant Breakout Field Guide

Eight ways one site broke out of its sandbox on a multi-tenant PHP server, all found by attacking it on purpose, all fixed.

10-Minute Read

Table of tenant isolation boundaries in ePHPm, how each was crossed, and the PR that fixed it

ePHPm can serve a directory full of sites out of one process. Point sites_dir at a folder and every subdirectory is a virtual host. The Host header decides which one you get. That’s how the PR preview environment runs. Every pull request gets a subdomain, and the code behind it is whatever somebody pushed. One process holding many tenants means ePHPm enforces every per-tenant boundary itself, in-process. There’s no container wall between site A and site B unless you add one.

We Disabled PHP's Stack Guard Ourselves: Containing Segfaults in a Single-Process PHP Server

How ePHPm went from dying silently on a segfault to containing stack overflows per thread. It also covers the linker flag that had turned off PHP's own guard.

12-Minute Read

Diagram of a PHP thread stack, the guard window below it, and which faults get contained versus which kill the process

php-fpm has a property nobody thinks about until they leave it. When a worker segfaults, you lose one request. The master forks a new child and life goes on. ePHPm runs every tenant’s PHP as threads inside one process. That’s where the memory and latency wins come from. It also means one tenant’s segfault takes down every other tenant on the box.

Per-Tenant Network Policy in One Process: ePHPm's eBPF Thread Tags

Every site on an ePHPm server runs inside the same process, so a normal firewall can't tell them apart. A small eBPF program tags each thread with its site. It keeps sites from reaching each other's local ports for under a microsecond per connection.

17-Minute Read

Flow from a PHP pool thread writing its vhost tag into a BPF map, through the bind and connect cgroup hooks, to allow, rewrite or EPERM

In multi-tenant mode ePHPm serves every site in sites_dir from one process. Every tenant’s PHP runs as the same OS user on the same pool of ZTS threads. A thread that just served blog.example will serve shop.example a few milliseconds later. That’s the density win. It also means the kernel has no idea which tenant is behind a given connect(). As far as Linux is concerned it’s all ephpm-web.

Recent Posts

Categories

About

Luther is a 20+ year software veteran specializing in backend APIs and architecting products. Employed at SUSE as the Team Lead for the Containers on Windows Team working on Rancher + Kubernetes