google / google/gvisor

Running with fully `mlock`ed memory

Open
#10,530 2 comments 1 reaction 0 assignees View on GitHub
type: enhancement
Dominant language
Go
Stars
19.3k
Forks
2k
Avg merge
3d 5h
Merged PRs (30d)
264

Description

### Description

Add a mode whereby all gVisor memory pages, including those of the sandboxed application, are `mlock`ed (i.e. they cannot be paged out to swap).

This is useful for situations where it is desirable to leave no trace of the sandboxed workload on the host system.

### Is this feature related to a specific bug?

See [discussion here](https://github.com/freedomofpress/dangerzone/issues/633). Dangerzone is a project from the Freedom of the Press Foundation which handles potentially-dangerous, potentially-sensitive/confidential documents. As part of its document processing, it needs to run several applications and libraries (LibreOffice, PyMuPDF, etc.) which don't all support such a "traceless" mode. However, these applications run within gVisor, with all data only written to `tmpfs` mounts (which are backed by gVisor memory). Therefore, if we can `mlock` all gVisor memory pages, we can systematically guarantee that no traces of the document will be left on the host system.

### Do you have a specific solution in mind?

Per @nixprime (thanks!), there are two possible solutions:

- Use `mlockall(MCL_CURRENT|MCL_FUTURE|MCL_ONFAULT)` during boot. This works naturally for the KVM platform, but for Systrap we need to also call this for subprocesses, as it is not inherited across `fork()`. Because of the platform-specificity of this solution, this also requires adding some platform method to indicate whether it supports this feature. This solution also requires some hook in `pgalloc`'s `mlockDisabled` to always be `false` in such a mode, such that `tryPopulateMlock` (which calls `munlock`) is skipped.
- Add a `pgalloc.MemoryFile.MlockAllocated`, which causes `MemoryFile.Allocate` to ignore `AllocOpts.Mode` and always `mlock` the allocated range, and causes `MemoryFile.runReclaim` to `munlock` the range. Need to confirm that `fallocate(..., FALLOC_FL_PUNCH_HOLE, ...)` works on `mlock`'d memory (so that `MemoryFile.decommitFile` still works), and still need to call `mlock(MCL_CURRENT|MCL_FUTURE|MCL_ONFAULT)` during boot if we want to `mlock` the Go heap/stack data (which could contain sensitive things like filenames, env variables etc.)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.