For example, docker specifies a directory descriptor via /proc/self/fd:
mount(/sys/fs/cgroup/...", "/proc/self/fd/6", MS_BIND, 0x502f, <null>)
PiperOrigin-RevId: 557312955
This refactor changes the "shared list" from being a list pointer that's
shared among all the peers, to a circularly linked list that links all the
mounts together. This is generally safer (no shared pointer) and easier
to understand and work with. It's also closer to how linux implements this
feature.
The propagationType is also removed in favor of just using the propagation
flags from linux. This makes more sense as mounts can have two types at once
(shared+slave).
PiperOrigin-RevId: 556906544
This change introduces the nsfs file system. Each new namespace allocates
a new nsfs inode.
Here are reasons why we need these inodes:
* each namespace has to have an unique id.
* proc/pid/ns/ contains one entry for each namespace. Bind mounting one of
the files in this directory to somewhere else in the filesystem keeps the
corresponding namespace alive even if all processes currently in
the namespace terminate.
* setns() allows the calling process to join an existing namespace specified
by a file descriptor.
PiperOrigin-RevId: 550694515
Fixes https://github.com/google/gvisor/issues/6015 | Added EventRdHUp to waiter events | Added POLLRDHUP delivery on half-closed connection detection | Added POLLRDHUP delivery on local read end shutdown
This introduces a `metric.FieldValue` struct type that wraps a string.
All metric interfaces that deal with field values have been updated to use
pointers to this type instead of strings.
The intent of this change is to make it more obvious that field values must
be passed using references. Prior to this change, this was done using string
pointer comparisons. Now this must be done by using a pointer to the same
`metric.FieldValue` struct.
The struct type still externally exposes its string so that it can be referred
to in value function callbacks by "custom" metrics. (Though there are no
current uses of callback metrics with fields.)
PiperOrigin-RevId: 527030738
This optimizes both increments and lookup operations.
It does so using the following:
- For metrics of potential cardinality larger than 48, it will switch to using
a map rather than linear search for mapping field value combinations to the
index that combination corresponds to in the flattened list of values.
For metrics of cardinality 48 or smaller, linear search is still used as it
is still faster (and also still faster than binary search), as determined by
benchmarks.
- All field values are checked for pointer uniqueness (i.e. the pointer to the
start of each field value string must be unique). This is then used for
faster matching: instead of comparing whole strings (and needing to hash
them, in the case of doing map-based lookups), it compares pointer values.
In the context of this metric library, because all field values must be
pre-declared ahead of time, keeping references to these pre-declared strings
should always be possible. This is enforced: it will `panic` if the metric
user does not do this. In practice, this is easy to do by using `const`
strings for all metric values. This change does just that for existing
metrics with string fields.
From benchmarks, this speeds up the time to take a snapshot of existing
metrics by -8.35%. With the unimplemented syscall counter metric, this
optimization reduces the slowdown of adding this metric from +4,250% to
a still-large but much more manageable +290%. A further optimization
(cl/524419591) will reduce this overhead further before re-introducing the
unimplemented syscall counter metric.
PiperOrigin-RevId: 526134756
This catches up the interface to the `EmitUnimplementedEvent` method signature
on `kernel.Kernel`.
Also add build-time test to verify that `kernel.Kernel` implements this
interface, in order to catch such breakages at build time in the future.
PiperOrigin-RevId: 519000411
This will be used to plumb the syscall number through to a counter metric that
exports the number of times an unimplemented syscall has been called.
Plenty of syscall implementations call `EmitUnimplementedEvent` for flags and
settings that are not implemented. With `sysno` available, they will be able
to plumb that bit of information through.
PiperOrigin-RevId: 518635831
This moves the initialization of `seccheck.Points` out of package-level
`init` and instead moves it to an explicit `seccheck.Initialize()` function.
On AMD64, this saves about 614KiB of heap memory that would otherwise always
be live.
PiperOrigin-RevId: 514813332
This change also switches lock EOF to be MaxInt instead of MaxUint,
since the lock length can be a negative value.
Fixes#5264
PiperOrigin-RevId: 513571374
This flag is added for tests that need to trigger a panic in the sentry
kernel. Only done for x86_64 which does have a dedicated syscall number for
afs_syscall; ARM does not.
PiperOrigin-RevId: 512731631
gVisor does not support automount, so this flag is a no-op.
Confirmed that this fixes recent versions of 'ls':
$ docker run -ti --runtime=fig rockylinux:8.7 /bin/bash
[root@c6c749af0a7a /]# ls /
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
PiperOrigin-RevId: 511376385
Now that hostinet is enabled, we sometimes get EAGAIN which is not equal to
ErrWouldBlock, so we must use linuxerr.Equals to compare them.
PiperOrigin-RevId: 508501889
A few fixes in here:
* Linux does not transition the state of a non-blocking socket to SS_CONNECTED
when the connect happens asynchronously. Instead, it leaves the state as
SS_CONNECTING (seems like a Linux bug, but OK). This can introduce weird
behavior for subsequent connect() calls. gVisor now forces the state to
update to SS_CONNECTED by calling connect() twice.
* Socket shutdown events are slightly different between gVisor and linux. We
already assert different behavior between the two environments, and now we
also have to check for gVisor+hostinet instead of just gvisor.
* Handle send/recv timeouts, which fixes blocking for read()/write() syscalls.
* Handle cases like MSG_PEEK where the senderAddress is not returned.
* Pass through some more socketopts, and allow them in the syscall filters.
Something is still wrong with shutdown() and poll() calls, so those tests are
temporarily disabled. I'm looking at those next.
This also fixes a number of other syscall test suites, so those are enabled as
well.
PiperOrigin-RevId: 508397317
The current io_uring support is very limited and experimental. Disable
it by default, and add a flag to enable it for testing.
PiperOrigin-RevId: 500760451
Syzkaller has found several issues with the two syscalls and a rework is
required. Disable tests and the syscall until issues can be fixed.
PiperOrigin-RevId: 491716795
If we use the remote process's scratch buffer in process_vm_readv|writev
calls, we will get data races. Use the local task's scratch buffer always.
PiperOrigin-RevId: 491468904
Handling NOP operations helped us to introduce facilities to process submission
requests. Now we can proceed to adding more meaningful operations. The logical
choice for the first one is the READV operation as it is a next operation after
NOP and it is also used for the cat-like application example based of IO_URING.
PiperOrigin-RevId: 487615618
With io_uring_setup() and mmap() we can proceed with implementing a simplest
operation, namely, NOP. Once we make sure that we can send this command and
receive a response from the gVisor, we can move forward to read operation.
PiperOrigin-RevId: 485106019
This is the first in a series of changes that will enabled shared mount
subtrees. This will emulate the Linux kernel implementation described here:
https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt
Mounts can now a be part of a mount groups. These groups are
identified by ids assigned by the VFS. Group IDs can be reused after all
mounts that are a member of that group are destroyed.
Newly created mounts inherit the propagation type of their parent mount. A
mount created on a shared mount will also be a shared mount, though it will
be part of a different group. A shared mount 'A' bound to a shared mount 'B'
will replicate that bind to all of 'B's peers. These new mounts will all be
part of a new shared peer group.
Unmounting a mount 'A' that is a direct child of a shared mount 'B' mounted
at dentry 'b' will propagate that event to all its peers. So peers B1, B2,
B3, etc will all unmount the mounts (A1, A2...) located at 'b'. However, if
any of peers of A have children, they are skipped. If the original mount A
has children, the mount is failed entirely.
The initial root mount has propagation type MS_PRIVATE.
This change only implements a basic version of mount groups. Notably it does
not implement MS_SLAVE, MS_UNBINDABLE, or MS_REC.
PiperOrigin-RevId: 483792757
Once the user receives a file descriptor from `io_uring_setup()`, it will be
used for the subsequent `mmap()` calls. Thus, we need to add support for it in
our iouringfs.
PiperOrigin-RevId: 477318038
Similar to Linux, we should add pseudo-filesystem iouringfs in gVisor to back
IO_URING's file descriptors. We start with stubbing `io_uring_setup(2)` so it
provides a file descriptor backed by anonfs.
PiperOrigin-RevId: 473384042
ProcessVM readv/writev needs some work due to lock ordering issues
with locking MM between tasks. So disable the call until it
can be fixed.
Also add a test from one of the identified bugs from syzcaller.
PiperOrigin-RevId: 467085160
This is consistent with Linux. Some applications recursively add
files to inotify FD. They fail if they run into kernfs files
because inotify_add_watch(2) returns EPERM in that case.
PiperOrigin-RevId: 462642204
Since `arch.Context64` is the only concrete implementation of
`arch.Context`, this does not functionally change anything.
While `arch.Context64` *can* mean multiple things in the codebase, since
the `arch` module uses conditional compilation to create different builds
for AMD64 vs ARM64, the `Context64` type is still singular within each
possible version this can compile to.
This avoids the overhead involved in calling interface
functions in Go:
https://github.com/teh-cmc/go-internals/blob/master/chapter2_interfaces/README.md#dynamic-dispatch
This overhead is particularly painful for functions like `SyscallSaveOrig`
which is a no-op on AMD64.
On KVM, this reduces syscall latency by 4~5%:
```
name old wall_ns/op new wall_ns/op delta
Getpid 602 ± 4% 579 ± 3% -3.94% (p=0.000 n=66+195)
GetpidOpt 604 ± 3% 573 ± 3% -5.10% (p=0.000 n=71+194)
name old cpu_ns/op new cpu_ns/op delta
Getpid 604 ± 5% 581 ± 0% -3.81% (p=0.000 n=75+130)
GetpidOpt 604 ± 2% 574 ± 3% -4.95% (p=0.000 n=71+196)
```
PiperOrigin-RevId: 461742893
After 7858d7bca7fb ("mm/mempolicy: don't handle MPOL_LOCAL like a
fake MPOL_PREFERRED policy"), MPOL_PREFERRED is implemented as
MPOL_LOCAL when nodeset is empty.
Earlier, MPOL_LOCAL was implemented as MPOL_PREFERRED and kernel
checked that nodeset was empty.
Fixed the syscall test to avoid this conversion process. We don't
know which machine our native tests will run on, so it is hard to
test for either of these conversions of MPOL modes. In this state
the syscall test passes on newer and older kernels.
PiperOrigin-RevId: 460560999