microsoft / microsoft/litebox

Broker resource limits are global, letting one session exhaust the budget for all others

Open
#1,084 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
2.7k
Forks
144
Avg merge
12h 21m
Merged PRs (30d)
146

Description

## Summary

`BrokerCoreLimits` are global to the broker core, but a single broker process serves every client association. One malicious or buggy local can therefore exhaust the shared budget and permanently deny object and pipe creation to all other sessions.

This is an availability issue only. Per-session ownership is enforced correctly on lookup, so there is no cross-session disclosure or confused-deputy exposure.

## Details

The limits are explicitly documented as shared:

https://github.com/microsoft/litebox/blob/ulitebox/litebox_broker_core/src/lib.rs#L42-L45

```rust
/// Resource limits for broker-owned authority state.
///
/// These limits are global to the broker core, not per session.
pub struct BrokerCoreLimits {
pub max_references: usize, // DEFAULT: 4096
pub max_total_pipe_capacity: usize, // DEFAULT: 64 MiB
}
```

`BrokerCore` is a process singleton (`BROKER_CORE_CREATED.compare_exchange`) that hands out sessions via `create_session()`, and both budgets are enforced against process-wide state:

- `create_object_reference` / `create_object_reference_pair` check `references.len()` against `max_references` on the shared `references` map (`litebox_broker_core/src/session.rs:82-101`, `:104-133`).
- Pipe capacity is reserved from the shared `reserved_pipe_capacity: AtomicUsize` against `max_total_pipe_capacity` (`litebox_broker_core/src/pipe.rs:193-201`).

Ownership enforcement itself is sound — `with_authorized_object` rejects handles whose `session_id` does not match the caller (`litebox_broker_core/src/session.rs:173-188`) — so this is strictly a shared-budget problem.

## Impact

A local that creates 4096 object references, or reserves 64 MiB of pipe capacity, causes every subsequent `create_*` from **any** session to fail with `ResourceExhausted`. The attacker does not need to be clever; ordinary buggy behavior in one sandbox produces the same result.

Two properties make it worse:

1. The budget is only released when the offending objects are closed or the session is torn down, so a local that simply stops making progress pins the budget indefinitely.
2. The host's ring capacity waits (`ControlRingProducer::wait_for_capacity`, reached from `UnixControlRingHostResponseSink::send_response`) have no timeout. They are interruptible by shutdown or peer close, but a local that stays alive and refuses to drain its response ring holds its association — and its share of the global budget — indefinitely with nothing to evict it.

## Suggested direction

Add per-session quotas alongside the existing global ceilings, so the global limit remains a backstop while no single session can consume all of it. Roughly:

- Track live reference count and reserved pipe capacity per `SessionId`.
- Enforce a per-session cap in `create_object_reference`, `create_object_reference_pair`, and the pipe capacity reservation path.
- Release the per-session accounting on object close and on session teardown.

Bounding or timing out `wait_for_capacity` is *not* the right fix on its own: any threshold that evicts a malicious local will eventually evict a legitimately slow one. It is only relevant as a way to reclaim a pinned budget, which per-session quotas address more directly.

## Notes

Pre-existing; not introduced by any current PR. Surfaced while auditing the broker trust boundary during review of #1083, which does not touch `litebox_broker_core`.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with BrokerCoreLimits in litebox_broker_core/src/lib.rs, then trace create_object_reference and create_object_reference_pair in session.rs and the reservation path in pipe.rs. Add per-session reference and pipe-capacity accounting while retaining global ceilings, and ensure both counts are released on close and session teardown.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.