1236 Commits
Author SHA1 Message Date
Shailend ChandandgVisor bot 46e35291a0 Support writing to cgroup v2 control files without an open file descriptor
Fix a panic when writing to cgroup v2 control files from outside the sandbox
(e.g., via Cgroups.WriteControlFiles / WriteControl), where writes occur
without an open in-sandbox VFS file descriptor (fd == nil). cgroup.procs now
safely falls back to context credentials with unconfined namespace migration,
and checkNSDelegateWrite skips namespace delegation checks. Add an integration
test for runsc cgroup v2 control file writes.

Also:
- Export cgroup2fs.InitHierarchy to initialize sandbox-wide cgroup2 state
  and root controller enablement.
- Plumb CgroupNamespace through sentry lifecycle and task context to derive
  initial container cgroup2 placements.
PiperOrigin-RevId: 978087817
2026-09-08 13:36:37 -07:00
gVisor bot 801e21b1df Merge pull request #14221 from ayushr2:rename
PiperOrigin-RevId: 976605832
2026-09-04 19:52:38 -07:00
Shailend ChandandgVisor bot 2842fb3414 cgroup2fs: DecRef inodes returned by Lookup for consistency
OrderedChildren.Lookup returns the inode with a ref that the caller is
expected to release (normally by handing it to a dentry via Init). Five
cgroup2fs call sites that look an inode up for a transient purpose
(permission checks, control-file read/write, interface-file removal)
never released that ref.

This is NOT a bug fix: every inode these sites can return
(cgroupInterfaceFile and eventFile, both via kernfs.DynamicBytesFile,
and cgroup directories themselves) embeds kernfs.InodeNoopRefCount, so
IncRef/DecRef are no-ops and nothing leaks today. The change only makes
the ref discipline explicit and correct, so these sites stay safe if a
lookup ever returns a genuinely refcounted inode.

PiperOrigin-RevId: 976563179
2026-09-04 17:16:35 -07:00
Shailend ChandandgVisor bot 32a2dc9364 cgroup2fs: Turn the cpuset mu into a lockdep mutex
PiperOrigin-RevId: 976537118
2026-09-04 16:05:04 -07:00
Ayush Ranjan 191f10948f Support RENAME_EXCHANGE in tmpfs and overlayfs
renameat2(2) support was added in 61f761343f ("Implement renameat2."),
but only for the gofer filesystem; tmpfs and overlayfs still return
EINVAL for RENAME_EXCHANGE.

Implement RENAME_EXCHANGE in tmpfs by swapping the two dentries between
their parent directories. When the exchanged files differ in type, the
parents' link counts (for "..") and the exchanged directory's reference
on its parent are transferred.

Implement RENAME_EXCHANGE in overlayfs by copying up the destination
file (and its descendants, if it is a directory) in addition to the
source, and then exchanging both files on the upper layer. Unlike a
regular rename, no whiteout is created at the source location, since
both locations remain occupied. Exchanged directories are marked opaque
at their new locations to prevent merging with lower layer directories
there.

RENAME_EXCHANGE permits the two files to differ in type and does not
require a directory being exchanged to be empty, but exchanging a file
with an ancestor directory must fail with EINVAL; see Linux's
fs/namei.c:__start_renaming(). The gofer filesystem previously required
both files to have the same type; lift that restriction, and update
parent link counts when files of different types are exchanged across
directories.

The RENAME_EXCHANGE syscall tests no longer accept EINVAL; they are
skipped where the flag remains unsupported, i.e. on FUSE and on gVisor
kernels other than runsc. New tests cover mixed-type exchanges and
exchanges with ancestor directories.

Fixes #7895
2026-09-02 17:49:31 +00:00
Shailend ChandandgVisor bot a43cece85a cgroup2fs: fix cpu controller accounting
The cpu controller tracks each task's CPU via a per-instance baseline
snapshot plus a cumulative total for exited tasks, but it never walked
the whole accounting domain when reporting cpu.stat and never reconciled
that state when a controller was disabled or when a task migrated within
a single controller's domain. This caused three accounting errors, each
covered by a new test:

  - Live tasks in descendant cgroups that had not enabled their own cpu
    controller were absent from the ancestor's cpu.stat until they
    exited, even though Linux aggregates descendant usage into the
    ancestor continuously.
  - Migrating a task between two cgroups sharing the same nearest cpu
    controller reset its baseline, discarding the pre-migration CPU.
  - Disabling +cpu discarded the controller's accumulated usage instead
    of reparenting it (Linux folds an offlined css's stats into parent).

Sum the whole domain (the controller's cgroup plus every descendant
without its own cpu controller, recursing into descendants that do) when
reading cpu.stat; leave the baseline untouched on same-instance
migration; and on disable, migrate the domain's tasks to the parent's
nearest cpu controller and fold the accumulated total into it.

PiperOrigin-RevId: 974821312
2026-09-01 18:35:58 -07:00
Shailend ChandandgVisor bot 4a2431a813 cgroup2fs: charge existing tasks on pids controller enablement
Enabling +pids in cgroup.subtree_control creates child pids controllers
with committed = 0, ignoring tasks already present in those cgroups.
pids.current then underreports, and migrating such a task away drives
it negative, since attach() applies deltas unguarded.

Charge a newly instantiated pids controller for the tasks already in
its subtree, both when a parent enables it (rebuildCtrlsLocked) and
when it is returned to the root (returnController). Adds a regression
test.

PiperOrigin-RevId: 974763124
2026-09-01 16:17:01 -07:00
gVisor bot 84e2a9076c Merge pull request #14103 from relkochta:relkochta/openat2
PiperOrigin-RevId: 974743571
2026-09-01 15:37:45 -07:00
Shailend ChandandgVisor bot 30d170b105 cgroup2fs: fix populated accounting when a mid-level cgroup drains
updatePopulated is called when a cgroup's own tasksCount crosses the
0<->1 boundary, but propagated the change to ancestor
nrPopulatedChildren counters even when the cgroup stayed populated
through a child. Draining a mid-level cgroup then made ancestors report
"populated 0" with live tasks below, and the child's later drain
decremented ancestors a second time, leaving the counter permanently
negative.

Skip the notification/propagation walk when the cgroup still has
populated children. Adds a regression test covering both the false
"populated 0" and the stuck-negative counter.

PiperOrigin-RevId: 974662615
2026-09-01 13:09:21 -07:00
Konstantin BogomolovandgVisor bot 58e263886b Implement /proc/sys/fs/mount-max.
It's just a matter of exposing the option via sysfs. Capped to same max as
Linux, to follow convention of what we're already doing with nr_open.

PiperOrigin-RevId: 972901017
2026-08-28 19:02:13 -07:00
gVisor bot d24336b6ce Merge pull request #13199 from ildar-safarov:erofs-dentry-lru-cache-v2
PiperOrigin-RevId: 972900915
2026-08-28 18:56:25 -07:00
gVisor bot 9ac3aa6e26 Merge pull request #13882 from ayushr2:rdma-efa
PiperOrigin-RevId: 970185578
2026-08-24 17:31:24 -07:00
gVisor bot d6dfe2252f Merge pull request #14369 from tamird:checklocks-proc-sysctl-fixes
PiperOrigin-RevId: 970145430
2026-08-24 16:17:28 -07:00
Shailend ChandandgVisor bot f30d796f52 Show NoNewPrivs in /proc/[pid]/status.
Linux prints the per-thread no_new_privs bit right before the seccomp
line, gVisor tracks the bit but did not surface it.

PiperOrigin-RevId: 969969482
2026-08-24 11:28:28 -07:00
Tamir DubersteinandHanzo Dev da02c90fb2 checklocks: synchronize proc network sysctls
Read SACK and ephemeral port ranges from the owning stack instead of
per-file caches. Separate proc mounts can cache different values, and a
rejected SACK write can change its cache. The saved stack already
preserves these settings.

Keep the last successfully written forwarding value, since individual
interfaces may have different forwarding settings. Guard it with a mutex
and publish updates only after the stack setter succeeds, leaving failed
writes out of subsequent readback.

Also make the existing TCP buffer-size helper contracts checkable. Their
mutex still serializes requests through the same byte source.

Cover shared readback, rejected SACK and forwarding writes, and
concurrent forwarding readback in the existing proc test target.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-24 13:58:53 -04:00
Ryan El KochtaandgVisor bot e033e1be16 overlayfs: panic on increment of non-positive refcount
Analogous to the check in pkg/refs/refs_template.go:IncRef().

PiperOrigin-RevId: 968708526
2026-08-21 15:07:11 -07:00
gVisor bot 0a922eea81 Merge pull request #14002 from luiscape:luis/allign-clocks-in-capprofiling
PiperOrigin-RevId: 968200399
2026-08-20 19:33:48 -07:00
AnilAltinayandgVisor bot 5c07de2296 Share dynamic char dev major for /proc/gvisor/{checkpoint,fscheckpoint}
Procfs mounts used a per-mount major number for /proc/gvisor/checkpoint.
Since Linux reserves a limited number of dynamic major numbers, running
many isolated container actions concurrently would exhaust the pool and
crash the sentry with EBUSY.

This adds VFS.GetSharedDynamicCharDevMajor(key) to allocate a major on
first use and share it across all subsequent mounts for that key.
The sentry now consumes exactly two majors for these devices regardless
of how many procfs instances are mounted.

PiperOrigin-RevId: 967985107
2026-08-20 12:34:38 -07:00
gVisor bot 6f73fb10c0 Merge pull request #14134 from luiscape:luis/expose-empty-proc-modules
PiperOrigin-RevId: 967601126
2026-08-19 23:03:04 -07:00
Nayana BidariandgVisor bot 690c579cdc Automated rollback of changelist 964380388
PiperOrigin-RevId: 967439753
2026-08-19 15:37:46 -07:00
Shailend ChandandgVisor bot f739fd243b Rename unix transport identifiers to demystify the package
Three nearly identical names covered three unrelated concepts
(ConnectedEndpoint, connectedEndpoint, connectionedEndpoint), and the
notification callbacks were named for the opposite of what they do
(RecvNotify woke writers, SendNotify woke readers).

- ConnectedEndpoint -> Sender, the write half of a connection
  (implementations queueSender, HostSender, SCMSender); the
  baseEndpoint field becomes connected -> peer: the type is named for
  what you do with it, the field for its role to the holder.
- SendNotify -> NotifyDataReady, RecvNotify -> NotifyWriteSpace,
  CloseNotify -> NotifyStateChange; each named for the wakeup it
  delivers. NotifyStateChange must wake hangup-only pollers.
- queue's embedded waiter queues become readerWaiters/writerWaiters,
  and baseEndpoint's embedded *waiter.Queue becomes a named field,
  WaitQueue, so wakeup call sites name their target.
- writeShutdown and wrShutdown/rdShutdown ->
  sendShutdown/recvShutdown, the shutdown(2) directions they track.
- A package doc block describes how the pieces fit together.

No behavior change.

PiperOrigin-RevId: 966732452
2026-08-18 12:14:22 -07:00
Nayana BidariandgVisor bot 021a58b69d Automated rollback of changelist 964518735
PiperOrigin-RevId: 966690028
2026-08-18 11:04:14 -07:00
Shailend ChandandgVisor bot 0a789f7147 gofer: dispatch device special file opens to the sentry
A new runsc flag controls the dispatch with the default being to
use sentry implementations alone.

PiperOrigin-RevId: 966266713
2026-08-17 17:17:02 -07:00
gVisor bot 7b85be74c3 Merge pull request #13609 from SamarthBagga:ipv6-addition
PiperOrigin-RevId: 966209546
2026-08-17 15:20:21 -07:00
Shailend ChandandgVisor bot d3bcea91b0 gofer: Take refs when adopting a cached endpoint-bearing inode
When an AF_UNIX socket is bound to a path, the resulting BoundEndpoint is
stored on the gofer inode, and other processes reach it by path: they walk
to the dentry, then pull the endpoint off its inode and connect. Crucially,
a bound socket stays connectable even when no file descriptor is holding
that path open.

The gofer refcounting invariant is: "An additional reference is held on all
synthetic dentries, and on all dentries for which endpoint is non-nil, until
they are unlinked or invalidated."

This purpose of this invariant is for a host-backed bound UDS to stay
resolvable by path even when no FD holds it. A gofer dentry at refs == 0 is
eligible for reclaim; reclaiming it tears down the inode and drops the
HostBoundEndpoint (and its host FD). So the filesystem pins every endpoint-
bearing dentry with one extra ref, held from bind until the name goes away.

This extra ref is dropped unconditionally, guarded only by `endpoint != nil`
in many places: unlinkAt, RenameAt, revalidation/invalidation, filesystem
teardown etc. (These drop paths assume that the invariant holds.)

To establish the invariant the extra ref is taken in the bind paths sure, but
we were missing a reference increment for a dentry that later comes to point
at the same endpoint-bearing inode. This can happen either due to a hard link
or another walk that lands on the same inode.

PiperOrigin-RevId: 966116353
2026-08-17 12:28:06 -07:00
Ayush RanjanandAlessio Ricci Toniolo be94182107 Add AWS EFA support to rdmaproxy
Add an efaproxy driver plug-in for AWS Elastic Fabric Adapter (EFA) devices
bound to the host `efa` driver. EFA's driver-private uverbs ABI carries no
userspace buffer pointers on CQ/QP CREATE: queue memory is kernel-allocated
and handed back via mmap keys in the CREATE response, which the core already
forwards to the host FD verbatim. PrepareCreateDMA is therefore a no-op; the
plug-in exists to register the "efa" driver name and to model EFA's MR_QUERY
driver-namespace method (used by libfabric to fetch RDMA read/write
interconnect IDs).

Model the standard AH object's destroy method (UVERBS_OBJECT_AH): EFA (SRD)
creates address handles via the legacy write path and destroys them through
the modern object, which the core must allow.

Extend the virtual RDMA sysfs for libfabric/hwloc topology discovery:
  - device/driver symlink and /sys/bus/pci/drivers/<driver> tree, which
    libfabric's EFA provider resolves during device discovery.
  - Mirror each PCI node's raw config space ("config" file). hwloc (used by
    aws-ofi-nccl to build the NCCL topology) reads it to recover the PCI
    bridge bus-number registers; without it hwloc cannot reconstruct the
    bridge hierarchy and aws-ofi-nccl aborts its topology write.
  - Serve the per-port lid_mask_count attribute alongside the other port
    attributes libibverbs reads from sysfs; ib_core creates it on every
    port.
The sysfs integration tests cover the new driver tree and config mirroring.

Advertise a >= 5.12 kernel release in RDMA-enabled sandboxes so aws-ofi-nccl
enables dmabuf-based GPU memory registration (ibv_reg_dmabuf_mr), which the
proxy handles via the existing REG_DMABUF_MR path. Sandboxes without RDMA
keep the current 4.19 release to limit the bump's blast radius; a later
change can make the newer release the default.

Co-authored-by: Alessio Ricci Toniolo <[email protected]>
2026-08-15 01:24:30 +00:00
Luis Capelo b6a86c4b61 Add an empty /proc/modules to procfs.
It's my understanding that Linux exposes `/proc/modules` empty in most
configurations (it's possible to not expose modules but that seems rare; only if the kernel is compile with that configuration).

Some applications like NVIDIA's GPUDirect Storage libraries (libcufile)
will scan `/proc/modules`. However, under gVisor, the scan never
succeeds and will hang forever.
2026-08-14 23:34:29 +00:00
Luis Capelo aa9030c7fe nvproxy: expose CLOCK_MONOTONIC_RAW as a distinct clock for capProfiling
GPU profilers (Nsight Systems/CUPTI) build their trace timeline from
CLOCK_MONOTONIC_RAW. gVisor serves CLOCK_MONOTONIC_RAW as an alias of
CLOCK_MONOTONIC, this will drift from CLOCK_MONOTONIC_RAW breaking profiling.

When nvproxy is enabled with `capProfiling`, this change exposes
CLOCK_MONOTONIC_RAW as a clock distinct from CLOCK_MONOTONIC that tracks the
host's CLOCK_MONOTONIC_RAW (absolute, unadjusted). CLOCK_MONOTONIC is
unchanged. When profiling is disabled, CLOCK_MONOTONIC_RAW continues to alias
CLOCK_MONOTONIC as before.
2026-08-14 19:42:03 +00:00
Nayana BidariandgVisor bot 0890b4de46 Support combined restore of full snapshot and filesystem snapshot.
This change extends the split filesystem checkpoint/restore feature to support
saving and restoring only a subset of filesystems (specified by paths). This
supports a "combined restore" mechanism where some memory files (tmpfs backings)
are restored from the filesystem checkpoint, while others are restored from the
main sentry checkpoint.
- Added `SplitFSCheckpointPaths` to `SaveOpts` to allow specifying paths for
  partial FS checkpoints.
- Updated `createPrivateMemoryFile` to return whether it successfully loaded
  state from the filesystem checkpoint.
- Track which memory files were loaded from the FS checkpoint during restore
  (`fsCheckpointedMfs`) and pass this information to the kernel via context
  (`CtxFSCheckpointedMemoryFiles`).
- In `loadPrivateMemoryFiles` (during sentry restore), only load memory files
  from the sentry checkpoint if they were not already loaded from the FS
  checkpoint.
- Added validation to ensure each memory file is restored from exactly one
  source (no duplicates, and none are missed).

PiperOrigin-RevId: 964518735
2026-08-13 23:52:38 -07:00
Ildar SafarovandAyush Ranjan 236bc0f60a erofs: add LRU dentry cache to bound memory usage
Mirrors fsimpl/gofer's caching model: each dentry holds one ref on its
parent; childMap is a weak map. refs == 0 means cache-eligible; refs
== -1 means destroyed. Cached children still hold their parent's ref,
so a parent only enters the cache after all its children are gone.

Per-dentry cachingMu serializes caching state; fs.cacheMu is held only
for LRU list mutations. Eviction re-checks under parent.dirMu, severs
from childMap, then destroys, cascading checkCaching up the tree.

Cache limit is 1000.

Co-authored-by: Ayush Ranjan <[email protected]>
2026-08-14 02:40:43 +02:00
Nayana BidariandgVisor bot 57a26ce22a Support checkpoint and restore to have separate pages for filesystem.
This change implements split filesystem checkpoint and restore, allowing the
filesystem state to be saved and restored separately from the sentry state.
- Added `--split-fscheckpoint` flag to the `checkpoint` command to trigger
saving filesystem state separately. Added `--split-fsrestore` and
`--fs-restore-image-path` flags to `restore` and `create` commands to support
restoring from split files.
- Added `FSSave` and restore code for split filesystems.
- Implemented saving/restoring tmpfs state (MemoryFile pages and directory
structure) to/from a tar-like format.
- Refactored tar read/write path to support merging filesystem state in tar.go
- Implemented donating filesystem checkpoint FDs to the sandbox during
creation/restore.
- Added test to verify split checkpoint and restore.

PiperOrigin-RevId: 964380388
2026-08-13 17:24:44 -07:00
gVisor bot d93cb4676b Merge pull request #14000 from ayushr2:dev-char
PiperOrigin-RevId: 964365188
2026-08-13 16:49:11 -07:00
gVisor bot e7d3eefca6 Merge pull request #14035 from ayushr2:erofs
PiperOrigin-RevId: 963785210
2026-08-12 19:05:22 -07:00
Ayush Ranjan 3358345b71 fsimpl/erofs: read regular file data from the image FD on FUSE
Regular file reads copy data out of the image's shared mapping. When the
image is backed by slow storage such as a FUSE mount, walking the mapping
faults it in one page at a time, turning a large read into many small,
largely serialized requests to the FUSE server. This makes erofs much
slower than fsimpl/gofer for large reads on such backends.

On those filesystems, read the data directly from the image file
descriptor with preadv2(2) instead, so the host serves a large read with a
single syscall and its own readahead, matching how fsimpl/gofer reads from
host FDs. The mapping copy is kept everywhere else, since it avoids a
syscall and is faster when the page cache is warm. The backing filesystem
is detected at mount time via fstatfs(2); currently only FUSE opts into FD
reads.

Inode.Data, which returned the data as a mapping-backed BlockSeq, is
replaced by Inode.DataRanges, which returns the image byte ranges that
hold the inode's data.
2026-08-12 21:10:59 +00:00
gVisor bot 35c5620e63 Merge pull request #13909 from relkochta:relkochta/overlayfs-posix-acls
PiperOrigin-RevId: 962838830
2026-08-11 09:56:10 -07:00
Shailend ChandandgVisor bot b943164ed6 Make every user of a tty also refcount
A tty inode was kept alive by a single ownership chain: the stdio file
description's reference on the import-time dentry. Everything else that used
the inode referred to it uncounted: a file description opened via /dev/tty
pins only the devtmpfs dentry, and the controlling-terminal association
(ThreadGroup.tty) is a bare pointer.

PiperOrigin-RevId: 962479941
2026-08-10 18:19:56 -07:00
Ayush Ranjan 19fbea7bb8 Create /dev/char and /dev/block symlinks in devtmpfs
On Linux, udev maintains /dev/char/<major>:<minor> and
/dev/block/<major>:<minor> symlinks to all device nodes it manages.
Applications open devices by device number through these symlinks; e.g.
rdma-core uses /dev/char to locate uverbs device nodes from the device
numbers advertised in sysfs.

There is no udev in the sandbox, so create these symlinks when device
files are created in devtmpfs. This covers both sentry-registered
devices and devices injected via the OCI runtime spec.
2026-08-06 21:37:11 +00:00
Shailend ChandandgVisor bot 0e33c409f1 Create per-container cgroup2 dirs and honor spec cgroupns
When --mount-cgroup-v2 is enabled, a container whose spec includes a
cgroup mount is now given its own cgroup "/<cid>" in the cgroup2
hierarchy, with its init process placed there.

Cgroup namespaces from the spec are now honored, mirroring PID
namespace policy: no entry means the root namespace, an entry with a
path joins the container that declared the same path, and an entry
without a path gets a new namespace rooted at the container's cgroup.
Since a fresh cgroup2 mount is rooted at the mounting namespace's
root, a private-namespace container's /sys/fs/cgroup shows only its
own subtree, as on Linux, with no need for bind mounts.

At boot the sentry now enables nsdelegate and delegates controllers
to per-container cgroups via the root cgroup.subtree_control. Exec
sessions join the container's cgroup and cgroup namespace, like
runc exec. Per-container "runsc events" and read-control queries
now resolve for any container with a cgroup mount.

Note two differences from the existing v1 support. In v1 we bind mount:
the per-container dir "/$cid" of each controller hierarchy appears as
/sys/fs/cgroup/<controller>. With v2 no bind mounts are needed: a fresh
cgroup2 mount is rooted at the mounting namespace's root, so honoring
the spec's cgroupns request yields the scoped view naturally. (Binding
a subtree a la v1 was not an option anyway: systemd explicitly rejects
a sub-hierarchy mounted without a matching cgroup namespace.) Second,
on container destroy we now make a best-effort, recursive attempt to
remove the container's cgroup subtree; v1 leaves its per-container
dirs behind.

The root container is not special-cased. As with v1, where even the
root container gets container-id-stamped cgroup dirs and the stats
queries they enable, it gets its own "/$root_cid", and its cgroup
namespace comes from the spec like everyone else's. Docker and
Kubernetes both request a private cgroup namespace for every container
on cgroup2 hosts, so in practice the root container sees its cgroup as
a pleasing "/" rather than "/$root_cid"; a spec with no cgroupns entry
(e.g. docker run --cgroupns=host) instead sees the full sandbox
hierarchy, as on Linux. One consequence of the private default: in a
multi-container sandbox the root container cannot see the other
containers' cgroups (namespace roots are not hierarchical). I don't
expect that to be problematic, and a spec without a cgroupns entry
regains the full view if ever needed.

PiperOrigin-RevId: 960153510
2026-08-06 01:57:42 -07:00
gVisor bot f5233ba717 Merge pull request #13149 from shayonj:fix-special-file-rofs
PiperOrigin-RevId: 959878764
2026-08-05 14:45:23 -07:00
Caroline ZhuandgVisor bot 916a5ecf6d Expose read-only /proc/gvisor/checkpoint file for Manual Trigger.
Default behavior change: /proc/gvisor/checkpoint will now always be available.

PiperOrigin-RevId: 959781433
2026-08-05 11:45:27 -07:00
Jing ChenandgVisor bot c5c379f9ba Implement O_DSYNC and fdatasync(2)
The goal is to differentiate O_DSYNC and O_SYNC, O_DSYNC behaves same
as O_SYNC today in gVisor.

assisted-by: agy
Fix #1897
PiperOrigin-RevId: 958610974
2026-08-03 15:38:06 -07:00
gVisor bot 85b6140ccc Merge pull request #13850 from relkochta:relkochta/cgroup-device-ebpf
PiperOrigin-RevId: 957442241
2026-07-31 19:14:59 -07:00
Ryan El Kochta 00d76e630f Add stub for the bpf(2) syscall and cgroup eBPF programs.
Adds initial scaffolding for eBPF in gVisor. It implements the bpf(2) syscall
with support for BPF_PROG_LOAD, BPF_PROG_QUERY, and BPF_PROG_ATTACH.

Necessary for the cgroups v2 flag to be enabled by default, as this fixes
Docker-in-gVisor with cgroups v2.
2026-07-31 15:55:57 -07:00
Ayush RanjanandAlessio Ricci Toniolo 1f926a2ab7 Add RDMA sysfs topology construction for gVisor sandboxes
Containers with /dev/infiniband/uverbs* devices need a sysfs surface for
device discovery: libibverbs enumerates /sys/class/infiniband_verbs, and
NCCL builds its hardware topology by resolving /sys/class symlinks with
realpath() and walking the PCI hierarchy.

This adds a --rdmaproxy flag which will gate all RDMA support. For now it
only wires up the sysfs topology: runsc snapshots the host sysfs closure
derived from the spec's uverbs devices (ibdevs, netdevs, PCI ancestor
chains, GPU functions, NUMA nodes) before pivot_root, and the sentry
constructs a path-identical virtual tree: one canonical /sys/devices/pci...
subtree per device, with /sys/class/* and /sys/bus/pci/devices as symlink
farms matching the kernel layout. Per-port dynamic state (RoCE GID tables,
link state, counters) is served live through targeted read-only bind mounts
of the per-ibdev ports subtrees; identity and PCI attributes are a static
snapshot, since the collecting process and the constructed sandbox tree do
not observe the same sysfs mount (the RDMA netdevs move into the sandbox
network namespace only after the sandbox is created).

Each PCI function directory also gets a subsystem symlink into a
synthesized /sys/bus/pci, and every node's bus gets a pci_bus entry: NCCL
classifies a directory as a PCI device by following its subsystem symlink,
and aborts topology discovery without it.

The NUMA topology is not mirrored: the sentry advertises a single node
holding every sandbox CPU, consistent with its single-node memory model
(set_mempolicy's maxNodes == 1) and its single-socket /proc/cpuinfo view.
Host node cpumasks name CPUs the sandbox does not have, which breaks
libnuma/hwloc consumers whenever the sandbox CPU count is below the
host's (numactl node binding, which NUMA-aware stacks exec in front of
worker subprocesses, kills the child). The PCI numa_node, local_cpus and
local_cpulist attributes are rewritten to match the single-node view.

The verbs device proxy that makes RDMA usable end-to-end is not part of
this change; --rdmaproxy is a work in progress and RDMA is not yet
functional.

Co-authored-by: Alessio Ricci Toniolo <[email protected]>
2026-07-30 06:50:18 +00:00
Ryan El Kochta 5a965ab528 overlayfs: implement POSIX ACLs
Implements POSIX ACLs for gVisor's overlayfs.

- Adds plumbing to keep access and default ACLs in sync with the underlying filesystems, simliar to mode
- Moves permission/filetype checking into helpers in posix_acl.go, used by both tmpfs and overlayfs
- Updates the POSIX ACL tests to be parametrized by filesystem. The existing acl test suite runs both on overlayfs and on tmpfs

This fixes journald not working for systemd user services.
2026-07-29 16:13:27 -07:00
gVisor bot 9f1306408c Merge pull request #13693 from relkochta:relkochta/posix-acls-tmpfs
PiperOrigin-RevId: 955521397
2026-07-29 10:11:40 -07:00
Shayon Mukherjee 5b002692af vfs: skip write tracking for special files on open
Linux skips the mount-level write check when opening a character device, block device, FIFO, or socket, so write-opening /dev/null on a read-only bind mount succeeds.

Mark the remaining FileDescriptions backed by special-file inodes. Also skip overlay copy-up for writable opens of special files; Linux overlayfs applies the same special_file() exception before deciding whether copy-up is required.

Add regression coverage for character devices and FIFOs through read-only bind mounts.
2026-07-28 06:47:46 -04:00
Shailend ChandandgVisor bot c8a8d4a815 cgroup2: Support the nsdelegate mount option
This mount option turns cgroup namespaces into delegation boundaries,
which results in the following two behaviors:

First, resource control. A cgroup's resource-control files carve out
the parent's resources, so they belong to the delegater, not to the
subtree's occupants. Accordingly, tasks in a non-init cgroup namespace
may no longer write to interface files of their own namespace root.
The delegatable files (cgroup.procs, cgroup.subtree_control) are exempt.
Subtree tasks cannot change what share of resources the subtree receives,
but remain free to organize processes and distribute that share within it.

Second, containment. Migration (including via CLONE_INTO_CGROUP) now
requires that both the source and destination cgroups be descendants of
the cgroupns root of the task performing the migration, failing with
ENOENT otherwise (actually it is the cgroupns of the task that opened the
fd for the migration file: this detail forces me to snapshot the cgroupns
against the fd, increasing the size of this patch).

PiperOrigin-RevId: 954892289
2026-07-27 16:30:46 -07:00
Xin ZhongandgVisor bot 1f06584417 seccheck: add binary_in_memfd to ExecveInfo
PiperOrigin-RevId: 953601428
2026-07-24 16:22:41 -07:00
Lucas ManningandgVisor bot 306b07a2e6 Fix FUSE directory listing boundary issues and implement directory seek.
This change fixes a bug in FUSE getdents where directory entries that straddle
the readdir boundary could be dropped or parsed incorrectly. It adds validation
to reject empty-name directory entries with EIO and implements the Seek method
for FUSE directory file descriptors.

Fixes #13721

PiperOrigin-RevId: 952998757
2026-07-23 15:51:53 -07:00