Skip to content

feat: cherry-pick 8 high-value upstream PRs (leak/memory/TTL/envd hardening) - #3

Merged
tiago-mitralab merged 17 commits into
mainfrom
feature/upstream-cherrypicks-2026-07-09
Jul 9, 2026
Merged

feat: cherry-pick 8 high-value upstream PRs (leak/memory/TTL/envd hardening)#3
tiago-mitralab merged 17 commits into
mainfrom
feature/upstream-cherrypicks-2026-07-09

Conversation

@tiago-mitralab

@tiago-mitralab tiago-mitralab commented Jul 9, 2026

Copy link
Copy Markdown

Cherry-picks de PRs abertos de alto valor do upstream e2b-dev/infra, empilhados sobre o rebase de 2026-07-09 (58 commits do upstream + ublk + max-starting).

Aplicados (9 PRs)

Tier 1:

Tier 2:

Ajustes locais (nao no upstream)

Status

Build OK nos 3 binarios no SF. Load test em andamento antes do merge.

adababys and others added 17 commits July 9, 2026 02:13
In Linux, the default route (0.0.0.0/0) has a nil Dst field in the
netlink.Route struct. The previous code called route.Dst.String() without
a nil check, which would panic on systems where the default route's Dst
is nil.

Fix by checking route.Dst == nil directly, which is the canonical way to
identify the default route.

(cherry picked from commit a2304dc)
Replace string inequality operator (!=) with crypto/subtle.ConstantTimeCompare
for signature validation in auth.go. The previous implementation was vulnerable
to timing attacks, where an attacker could potentially determine the correct
signature byte-by-byte by measuring response times.

This is a standard security best practice for comparing cryptographic values
such as HMAC signatures, tokens, and hashes.

(cherry picked from commit 85cce6c)
Add 6 test cases covering validateSigning:
- Accepts correct signature with expiration
- Rejects wrong signature
- Rejects expired signature
- Rejects missing signature parameter
- Accepts valid access token from header
- Rejects invalid access token from header

Also refactor existing tests to use a shared helper.

(cherry picked from commit 69cc233)
The UFFD handle goroutine had a TODO comment stating that the sandbox
should be killed when handle() fails. In fact, this is already
implemented: u.exit.SetError() triggers the sandbox exit watcher in
sandbox.go (line ~1093) which calls sbx.Stop().

- Remove the stale TODO comment
- Add error logging when handle() fails for better observability
- Add unit tests covering handle failure behavior (exit error
  propagation, readyCh closure, handler error state, initial state,
  socket creation)

(cherry picked from commit 3e30b03)
…up functions

There was a TOCTOU race between Add()/AddPriority() and run():

1. Add() checks hasRun (false) outside the lock
2. Add() blocks waiting for mu.Lock()
3. run() acquires lock, sets hasRun=true, executes all cleanups, unlocks
4. Add() acquires lock, appends f — but run() already finished

Result: f is never executed, potentially leaking resources (network
namespaces, cgroups, file descriptors, etc.).

Fix:
- Move hasRun.Store(true) inside the lock in run()
- Add double-checked locking in Add()/AddPriority(): re-check hasRun
  after acquiring the lock and execute f inline if cleanup already ran

Add race-condition tests that reliably reproduce the bug with -race.

(cherry picked from commit d7b2551)
Avoid holding the mutex while executing cleanup functions in the
double-check branch. This prevents potential deadlocks if a cleanup
function performs blocking operations or re-enters the lock.

(cherry picked from commit 97336fd)
…o template mmap cache

(cherry picked from commit 1f1a5a1)
…dd unit tests

- Replace unix.Sysinfo Freeram with /proc/meminfo MemAvailable to get
  true available memory (includes reclaimable page cache)
- Evict only one LRU entry per 1s tick instead of looping until threshold
  is met; mmap.Unmap is not instantaneous so the OS stats lag behind
- Add 6 unit tests covering WithCapacity LRU eviction, MemAvailable
  parser correctness/error handling, and pressure-eviction logic

(cherry picked from commit cab034c)
WaitForExit was defined but never called, leaving the API-layer evictor as
the sole mechanism to kill expired sandboxes.  If the API service restarts
the evictor goroutine stops and VMs accumulate indefinitely on nodes.

Two changes:

1. setupSandboxLifecycle (sandboxes.go): replace sbx.Wait with
   sbx.WaitForExit so the lifecycle goroutine races against the sandbox TTL.
   On timeout, Stop() is called explicitly before the normal Close/cleanup
   path runs.

2. WaitForExit (sandbox.go): replace the one-shot time.After with a
   time.NewTimer loop that re-checks endAt after each fire.  This means a
   KeepAlive that calls SetEndAt mid-flight correctly resets the node-side
   deadline instead of being silently ignored.

Fixes e2b-dev#3193

(cherry picked from commit 0a823f1)
5 cases covering the two code changes in the parent commit:

- AlreadyExpired: endAt in the past returns error immediately
- ExitBeforeTTL: clean FC exit before TTL returns nil
- ExitWithError: FC exits with error, error is wrapped and returned
- KeepAliveExtendsTTL: SetEndAt extension resets the timer loop;
  sandbox is NOT killed at the original deadline
- ContextCancelled: ctx cancel returns nil without killing

All pass with -race.

(cherry picked from commit 4826a8e)
When creating a sandbox, merge the template metadata's Context.EnvVars
(which contains Docker image ENV directives) into the sandbox config's
Envd.Vars before sending them to envd via POST /init.

User-provided env vars from the SDK create() call take precedence over
template defaults. Per-command env vars from process.start() still
override both.

This fixes both the standard resume path and the filesystem-only cold
boot (reboot) path, where DefaultUser and DefaultWorkdir were already
restored from template metadata but EnvVars was not.

Closes e2b-dev#2268

(cherry picked from commit 5bfd55e)
…0.6.9

e2b-dev#3146 as-is panics at boot on our host (default route has non-nil Dst=0.0.0.0/0). Bump envd for cherry-picked e2b-dev#3099/e2b-dev#3145 envd changes.
@tiago-mitralab
tiago-mitralab force-pushed the feature/upstream-cherrypicks-2026-07-09 branch from 00e5dc5 to 4fc7329 Compare July 9, 2026 05:17
@tiago-mitralab
tiago-mitralab merged commit 5f6d2c3 into main Jul 9, 2026
@tiago-mitralab
tiago-mitralab deleted the feature/upstream-cherrypicks-2026-07-09 branch July 9, 2026 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants