98 Commits
Author SHA1 Message Date
Xin ZhongandgVisor bot 488d530e97 seccheck: Trace sibling pipe processes in a client lib
PiperOrigin-RevId: 964771164
2026-08-14 10:39:17 -07:00
Ryan El Kochta 1ecb88b2b4 Allow writing to special files on read-only mounts.
On Linux, mount writability checks are skipped for special devices
(char, fifo, socket, blockdevice) when opening a file with write access.
gVisor currently does not handle this correctly.

This is an issue because some systemd unit files specify
PrivateDevices=yes, one of the effects of which is to make /dev appear
read-only to the service. For these services, writing to (for example)
/dev/null gives EROFS. Apache2 in particular runs into this issue.
2026-06-24 15:45:01 -07:00
gVisor bot 7465eeb020 Merge pull request #12598 from tamird:nogo-more-checks
PiperOrigin-RevId: 873002517
2026-02-20 11:35:37 -08:00
Jamie LiuandgVisor bot d7996a5d9b Remove "AddressSpace activation".
PiperOrigin-RevId: 869302553
2026-02-12 14:55:06 -08:00
Tamir Duberstein 50e6d6f796 Fix S1019 violations and drop suppression 2026-02-10 11:56:13 -08:00
Shailend ChandandgVisor bot e428bbea51 Fix creds check in linkat(AT_EMPTY_PATH)
linkat(AT_EMPTY_PATH) needs to check for CAP_DAC_READ_SEARCH in the userns in
which the fd was opened, not the userns of the task running linkat().

To get at that userns, vfs.FileDescription now saves a pointer to the creds
at the time of its creation: plumbing these creds in accounts for much of the
diff. This is similar to how `struct file` stores creds in `f_cred` in Linux.

Moreover, since the Linux patch "vfs: relax linkat() AT_EMPTY_PATH..." [1], the
need for this cap is excused if the creds of the calling task are literally
the same as the one stored in the fd.

[1] https://github.com/torvalds/linux/commit/42bd2af5950456d

PiperOrigin-RevId: 853374474
2026-01-07 12:48:17 -08:00
Andrei VaginandgVisor bot 6c816f42d1 kernel/pipe: trigger EPOLLERR on a write end if all readers has been closed
Fixes #10066

PiperOrigin-RevId: 612838688
2024-03-05 07:48:01 -08:00
Fabricio VoznikaandgVisor bot a9af2d309b Plumb restore context to afterLoad()
This allows for external information to be passed to restore code, like
host FDs to be remapped.

Updates #1956

PiperOrigin-RevId: 612540749
2024-03-04 12:21:50 -08:00
Jamie LiuandgVisor bot 28416cfd5c Fix #10046
See updated comment in sentry/kernel/pipe/vfs.go.

PiperOrigin-RevId: 610516821
2024-02-26 13:56:42 -08:00
Jamie LiuandgVisor bot 53330553f3 Fix splices to FDs that call usermem.IO.CopyIn/CopyInTo more than once.
Fixes #9932.

When Go is able to detect `io.Copy()` from a TCP socket or `AF_UNIX` stream
socket to a TCP socket, it attempts to implement the copy as a `splice(2)` from
the source to a pipe, followed by a `splice(2)` from the pipe to the
destination [1] (since `splice(2)` requires that one of the endpoints be a
pipe); the size of the pipe is set to 1 MB [2] (from a default of 64 KB [3]) to
reduce the number of splice syscalls required. In gVisor, a bug causes each
splice syscall from pipe to TCP socket to repeatedly read the *first* 64 KB [4]
of the pipe's data (when it contains more than 64 KB of data) rather than
*successive* chunks of 64 KB.

To fix this, advance pipe state by calling `Pipe.consumeLocked()` immediately
after `Pipe.peekLocked()`. Also defensively check that such FDs call
`Pipe.(usermem.IO)` methods on sequential addresses, and change
`fuse.deviceFD.Write()` to have this property.

[1] Go: `net/tcpsock_posix.go:TCPConn.readFrom()` =>
`net/splice_linux.go:splice()` => `internal/poll/splice_linux.go:Splice()`

[2] Go: `internal/poll/splice_linux.go:newPipe()` => `maxSpliceSize`

[3] `pkg/kernel/pipe/pipe.go:DefaultPipeSize`

[4] `pkg/tcpip/transport/tcp/endpoint.go:endpoint.Write()` =>
`endpoint.queueSegment()` => `endpoint.readFromPayloader()` =>
`pkg/buffer/buffer.go:Buffer.WriteFromReader()` =>
`pkg/buffer/chunk.go:MaxChunkSize`

PiperOrigin-RevId: 603151951
2024-01-31 14:02:18 -08:00
Jing ChenandgVisor bot 70ce036c8a Re-order loads in BUILD files to make transformations reversible in Copybara.
PiperOrigin-RevId: 598898756
2024-01-16 11:21:40 -08:00
Jamie LiuandgVisor bot 54e903b27d Ensure empty VFSPipeFD.SpliceToNonPipe(/dev/null) returns ErrWouldBlock.
When grep's stdout is /dev/null (so printed matches are discarded), its outcome
is only observable in its exit code, which is binary (0 for matches, 1 for no
matches). When grep's stdin is additionally a pipe, GNU grep optimizes for this
specific case by switching from reading input to splicing it directly to stdout
after the first match:

```
  if (exit_on_match | dev_null_output)
    list_files = LISTFILES_NONE;
...
  if (list_files == LISTFILES_NONE)
    finalize_input (desc, &st, ineof);
...
static bool
drain_input (int fd, struct stat const *st)
{
  ssize_t nbytes;
  if (S_ISFIFO (st->st_mode) && dev_null_output)
    {
#ifdef SPLICE_F_MOVE
      /* Should be faster, since it need not copy data to user space.  */
      nbytes = splice (fd, NULL, STDOUT_FILENO, NULL,
                       INITIAL_BUFSIZE, SPLICE_F_MOVE);
```

This triggers a bug in our splice implementation: since memdev.nullFD.Write()
never calls back into pipe.Pipe.peekLocked() to get ErrWouldBlock, this is
never propagated up to syscalls/linux.Splice(). Consequently, splice() returns
0 instead of blocking; grep interprets this as EOF from the pipe and exits.

We can't fix this by calling src.CopyInTo() in memdev.nullFD.Write() because
this would have the wrong behavior for `write(/dev/null, unmapped addr)`, which
should succeed because `drivers/char/mem.c:null_write()` also ignores the
application-provided pointer. Instead, handle this in
VFSPipeFD.SpliceToNonPipe(). (Linux instead avoids this problem by
distinguishing file_operations::write and file_operations::splice_write, which
we would prefer to avoid if possible.)

Fixes #9736

PiperOrigin-RevId: 584091971
2023-11-20 12:04:52 -08:00
Andrei Vagin 43bd258fcf Fix a few typos
It is an idea of running codespell as part of our presubmit checks.
Before enabling it for new changes, let's fix what it has found.

Signed-off-by: Andrei Vagin <[email protected]>
2023-10-25 12:13:42 -07:00
Jamie LiuandgVisor bot d627289f13 Remove //pkg/sentry/device.
This package was used for VFS1 device number assignment.

PiperOrigin-RevId: 538918926
2023-06-08 16:21:04 -07:00
Etienne PerotandgVisor bot c6d19db4e4 Update unimpl.EmitUnimplementedEvent interface to add the syscall number.
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
2023-03-23 17:01:37 -07:00
Adin ScannellandgVisor bot 2911d8c3b8 Add default_applicable_licenses rules to packages.
PiperOrigin-RevId: 513581243
2023-03-02 10:50:04 -08:00
Etienne PerotandgVisor bot 5f9231cd71 Lockdep: Print more info in the "unbalanced unlock" case.
This CL does the following:

- Add the ability for nested locks to have names.
- Give names to all current uses of nested locks in the codebase.
- Truncate `lockdep` debug stack traces to avoid the clutter from the
  `lockdep` code itself
- Simplify `lockdep` to not longer require `classMap`.

PiperOrigin-RevId: 491486620
2022-11-28 17:53:09 -08:00
Ayush RanjanandgVisor bot 1003ae8e93 Delete VFS1 completely.
- Delete pkg/sentry/fs/*.
- Move pkg/sentry/fs/fsutil out of VFS1 directory and remove VFS1 components.
- Remove remaining unused references to VFS1 from remaining codebase.
- Rename/refactor code to avoid even referencing VFS2, unless necessary.
- Rewrite VFS1-only tests to VFS2.

Updates #1624

PiperOrigin-RevId: 490064269
2022-11-21 13:57:52 -08:00
Andrei VaginandgVisor bot e7e65a9436 kernel: use lockdep mutexes
PiperOrigin-RevId: 449877248
2022-05-19 18:33:59 -07:00
Ayush RanjanandgVisor bot 2026e1f078 Reformat codebase.
PiperOrigin-RevId: 449358041
2022-05-17 17:48:35 -07:00
Kevin KrakauerandgVisor bot 3e7fcef1df switch fsimpl/ from sync/atomic to atomicbitops for 32 bit values
PiperOrigin-RevId: 443535714
2022-04-21 18:32:04 -07:00
Kevin KrakauerandgVisor bot b8dd528b97 prohibit direct use of sync/atomic (u)int64 functions
All atomic 64 bit ints are changed to atomicbitops.(Ui|I)nt64. A nogo checker
enforces that sync/atomic 64 bit functions are not called.

For reviewers: the interesting changes are in the atomicbitops and checkaligned
packages.

Why do this?
- It is very easy to accidentally use atomic values without sync/atomic funcs.
- We have checkatomics, but this is optional and is forgotten in several places.
  - Using a type+checker to enforce this seems less error prone and simpler.
- We get NoCopy protection.
- Use of 64 bit atomics can break 32 bit builds. We have types to handle this
  without any runtime cost, so we might as well use them.

PiperOrigin-RevId: 440473398
2022-04-08 16:06:26 -07:00
Fabricio VoznikaandgVisor bot 9725ff1d9b Fix epoll_ctl(2) regular files and dirs
Linux behaves differently for regular files and dirs for poll(2)/select(2)
compared to epoll_ctl(2). The latter returns EPERM for file and dirs.
I've also changed host FDs to behave like the underlying FD in regards
to epoll to keep it compatible with docker.

Fixes #7134

PiperOrigin-RevId: 429412692
2022-02-17 15:12:36 -08:00
Jamie LiuandgVisor bot 03b2ac845d Consistently order Pipe.mu before other file mutexes and MM.activeMu.
PiperOrigin-RevId: 422894869
2022-01-19 13:47:38 -08:00
Andrei VaginandgVisor bot d793894072 kernel/pipe: clean up unused fields from the Pipe structure
They have been added by mistake.

PiperOrigin-RevId: 417716586
2021-12-21 17:14:04 -08:00
Andrei VaginandgVisor bot 2be496d719 pipe: a reader has to wait when all writers will be notified
Otherwise, we can have a race when a reader cloes a pipe before
a write detects this reader.

PiperOrigin-RevId: 417645683
2021-12-21 10:19:23 -08:00
Andrei VaginandgVisor bot d3f84f62ec pipe: have separate notifiers for readers and writers
This change fixes a busy loop in the pipe code. VFSPipe.Open calls ctx.BlockOn
to wait an opposite side, but waitQueue.EventRegister always triggers
EventInternal, so we never block.

Reported-by: [email protected]
PiperOrigin-RevId: 415428542
2021-12-09 21:51:32 -08:00
Adin ScannellandgVisor bot 140b4e80f6 Align Context API with kernel internals.
This change adapts the existing context to use more suitable non-channel-based
methods. This is a requisite for migrating the kernel internals to a
sleeper-based notification mechanism.

The last uses of amutex outside those migrated as part of this change were
dropped in a previous change. Since amutex depends on the channel-based
implementation, this package is also deleted as part of this change.

PiperOrigin-RevId: 415189675
2021-12-08 23:51:37 -08:00
Fabricio VoznikaandgVisor bot cecd7315bc Don't eat error from epoll_ctl EPOLL_CTL_ADD
Docker maps stdin to `/dev/null` which doesn't support epoll. Host FD
was ignoring the error and suceeding the epoll_ctl call from the
container, giving false impressing that epoll would be notified.

This required plumbing failure to all waiter.Waitable.EventRegister
callers and implementers.

Closes #6795

PiperOrigin-RevId: 414797621
2021-12-07 12:36:00 -08:00
Adin ScannellandgVisor bot 4967b16af9 Update Waitable API.
Instead of passing the event mask at registratrion time, pass the mask as part
of the waiter. This makes the mask immutable and simplifies the architecture of
waiters. This is also necessary for a future fix that will allow the fdnotifier
to keep persistent entries, as opposed to requiring constant updates.

This change is intended to be a no-op in terms of function. The only exception
is signalfd, where this mask was abused. To handle this case, the operation of
signalfd changed to allow one layer of indirection.

PiperOrigin-RevId: 409702998
2021-11-13 12:54:39 -08:00
Jamie LiuandgVisor bot 319a5364e5 Remove state:"nosave"/"zerovalue" annotations from all waiter.Queues.
Prior to cl/318010298, //pkg/state couldn't handle pointers to struct fields,
which meant that it couldn't handle intrusive linked lists, which meant that it
couldn't handle waiter.Queue, which meant that it couldn't handle epoll. As a
result, VFS1 unregisters all epoll waiters before saving and re-registers them
after loading, and waitable VFS1 file implementations tag their waiter.Queues
state:"nosave" (causing them to be skipped by the save/restore machinery) or
state:"zerovalue" (causing them to only be checked for zero-value-equality on
save).

VFS2 required cl/318010298 to support save/restore (due to the Impl inheritance
pattern used by vfs.FileDescription, vfs.Dentry, etc.); correspondingly, VFS2
epoll assumes that waiter.Queues *will be* saved and loaded correctly, and VFS2
file implementations do not tag waiter.Queues.

Some waiter.Queues, e.g. pipe.Pipe.Queue and kernel.Task.signalQueue, are used
by both VFS1 and VFS2 (the latter via signalfd); as a result of the above,
tagging these Queues state:"nosave" or state:"zerovalue" breaks VFS2 epoll.
Remove VFS1 epoll unregistration before saving (bringing it in line with VFS2),
and remove these tags from all waiter.Queues.

Also clean up after the epoll test added by cl/402323053, which implied this
issue (by instantiating DisableSave in the new test) without reporting it.

PiperOrigin-RevId: 402596216
2021-10-12 10:25:30 -07:00
Zach KoopmansandgVisor bot 83bf514e27 [syserror] Remove pkg syserror.
Removes package syserror and moves still relevant code to either linuxerr
or to syserr (to be later removed).

Internal errors are converted from random types to *errors.Error types used
in linuxerr. Internal errors are in linuxerr/internal.go.

PiperOrigin-RevId: 390724202
2021-08-13 17:16:52 -07:00
Zach KoopmansandgVisor bot f26a93e634 [syserror] Convert remaining syserror definitions to linuxerr.
Convert remaining public errors (e.g. EINTR) from syserror to linuxerr.

PiperOrigin-RevId: 390471763
2021-08-12 15:19:12 -07:00
Adin ScannellandgVisor bot 0f15e2418e Mix checklocks and atomic analyzers.
This change makes the checklocks analyzer considerable more powerful, adding:
* The ability to traverse complex structures, e.g. to have multiple nested
  fields as part of the annotation.
* The ability to resolve simple anonymous functions and closures, and perform
  lock analysis across these invocations. This does not apply to closures that
  are passed elsewhere, since it is not possible to know the context in which
  they might be invoked.
* The ability to annotate return values in addition to receivers and other
  parameters, with the same complex structures noted above.
* Ignoring locking semantics for "fresh" objects, i.e. objects that are
  allocated in the local frame (typically a new-style function).
* Sanity checking of locking state across block transitions and returns, to
  ensure that no unexpected locks are held.

Note that initially, most of these findings are excluded by a comprehensive
nogo.yaml. The findings that are included are fundamental lock violations.
The changes here should be relatively low risk, minor refactorings to either
include necessary annotations to simplify the code structure (in general
removing closures in favor of methods) so that the analyzer can be easily
track the lock state.

This change additional includes two changes to nogo itself:
* Sanity checking of all types to ensure that the binary and ast-derived
  types have a consistent objectpath, to prevent the bug above from occurring
  silently (and causing much confusion). This also requires a trick in
  order to ensure that serialized facts are consumable downstream. This can
  be removed with https://go-review.googlesource.com/c/tools/+/331789 merged.
* A minor refactoring to isolation the objdump settings in its own package.
  This was originally used to implement the sanity check above, but this
  information is now being passed another way. The minor refactor is preserved
  however, since it cleans up the code slightly and is minimal risk.

PiperOrigin-RevId: 382613300
2021-07-01 15:07:56 -07:00
Zach KoopmansandgVisor bot f033577349 [syserror] Update several syserror errors to linuxerr equivalents.
Update/remove most syserror errors to linuxerr equivalents. For list
of removed errors, see //pkg/syserror/syserror.go.

PiperOrigin-RevId: 382574582
2021-07-01 12:05:19 -07:00
Zach KoopmansandgVisor bot 895c2eaa09 [syserror] Update syserror to linuxerr for EACCES, EBADF, and EPERM.
Update all instances of the above errors to the faster linuxerr implementation.
With the temporary linuxerr.Equals(), no logical changes are made.

PiperOrigin-RevId: 382306655
2021-06-30 08:18:59 -07:00
Zach KoopmansandgVisor bot cd84634cc0 [syserror] Change syserror to linuxerr for E2BIG, EADDRINUSE, and EINVAL
Remove three syserror entries duplicated in linuxerr. Because of the
linuxerr.Equals method, this is a mere change of return values from
syserror to linuxerr definitions.

Done with only these three errnos as CLs removing all grow to a significantly
large size.

PiperOrigin-RevId: 382173835
2021-06-29 15:08:46 -07:00
Zach KoopmansandgVisor bot 45b64220cb [syserror] Add conversions to linuxerr with temporary Equals method.
Add Equals method to compare syserror and unix.Errno errors to linuxerr errors.
This will facilitate removal of syserror definitions in a followup, and
finding needed conversions from unix.Errno to linuxerr.

PiperOrigin-RevId: 380909667
2021-06-22 15:53:32 -07:00
Ian LewisandgVisor bot d1ab856135 Remove usermem dependency from marshal
Both marshal and usermem are depended on by many packages and a dependency on
marshal can often create circular dependencies. marshal should consider adding
internal dependencies carefully moving forward.

Fixes #6160

PiperOrigin-RevId: 379199882
2021-06-13 19:23:55 -07:00
Ian LewisandgVisor bot 1025175a1c Send SIGPIPE for closed pipes.
Fixes #5974
Updates #161

PiperOrigin-RevId: 375024740
2021-05-20 23:44:41 -07:00
Zach KoopmansandgVisor bot d8f34027b3 [syserror] Split usermem package
Split usermem package to help remove syserror dependency in go_marshal.
New hostarch package contains code not dependent on syserror.

PiperOrigin-RevId: 365651233
2021-03-29 13:30:21 -07:00
Bhasker HariharanandgVisor bot cd96d40cf1 Add POLLRDNORM/POLLWRNORM support.
On Linux these are meant to be equivalent to POLLIN/POLLOUT. Rather
than hack these on in sys_poll etc it felt cleaner to just cleanup
the call sites to notify for both events. This is what linux does
as well.

Fixes #5544

PiperOrigin-RevId: 364859977
2021-03-24 12:11:44 -07:00
Ayush RanjanandgVisor bot c3ff9f93bc [op] Replace syscall package usage with golang.org/x/sys/unix in pkg/.
The syscall package has been deprecated in favor of golang.org/x/sys.

Note that syscall is still used in the following places:
- pkg/sentry/socket/hostinet/stack.go: some netlink related functionalities
  are not yet available in golang.org/x/sys.
- syscall.Stat_t is still used in some places because os.FileInfo.Sys() still
  returns it and not unix.Stat_t.

Updates #214

PiperOrigin-RevId: 360701387
2021-03-03 10:25:58 -08:00
Andrei VaginandgVisor bot a1ee9aca4c pipe: writeLocked has to return ErrWouldBlock if the pipe is full
PiperOrigin-RevId: 356450303
2021-02-09 01:34:45 -08:00
Jamie LiuandgVisor bot fedcd440a7 Remove call to Notify from pipe.VFSPipeFD.CopyOutFrom.
This was missed in cl/351911375; pipe.VFSPipeFD.SpliceFromNonPipe already calls
Notify.

PiperOrigin-RevId: 355246655
2021-02-02 14:01:22 -08:00
Dean DengandgVisor bot fe181d34f9 Move Lock/UnlockPOSIX into LockFD util.
PiperOrigin-RevId: 352904728
2021-01-20 16:55:07 -08:00
Jamie LiuandgVisor bot cc78e622c6 Simplify the pipe implementation.
- Remove the pipe package's dependence on the buffer package, which becomes
  unused as a result. The buffer package is currently intended to serve two use
  cases, pipes and temporary buffers, and does neither optimally as a result;
  this change facilitates retooling the buffer package to better serve the
  latter.

- Pass callbacks taking safemem.BlockSeq to the internal pipe I/O methods,
  which makes most callbacks trivial.

- Fix VFS1's splice() and tee() to immediately return if a pipe returns a
  partial write.

PiperOrigin-RevId: 351911375
2021-01-14 17:35:07 -08:00
Dean DengandgVisor bot c317e94de6 Add missing error checks for FileDescription.Init.
Syzkaller discovered this bug in pipefs by doing something quite strange:
creat(&(0x7f0000002a00)='./file1\x00', 0x0)
mount(&(0x7f0000000440)=ANY=[], &(0x7f00000002c0)='./file1\x00', &(0x7f0000000300)='devtmpfs\x00', 0x20000d, 0x0)
creat(&(0x7f0000000000)='./file1/file0\x00', 0x0)

This can be reproduced with:
touch mymount
mkfifo /dev/mypipe
mount -o ro -t devtmpfs devtmpfs mymount
echo 123 > mymount/mypipe

PiperOrigin-RevId: 349687714
2020-12-31 09:51:01 -08:00
Ting-Yu WangandgVisor bot ec5fb69513 Fix more nogo tests
PiperOrigin-RevId: 340536306
2020-11-03 15:23:32 -08:00
Nicolas LacasseandgVisor bot 90c5aab225 Make pipe min/max sizes match linux.
The default pipe size already matched linux, and is unchanged.

Furthermore `atomicIOBytes` is made a proper constant (as it is in Linux). We
were plumbing usermem.PageSize everywhere, so this is no functional change.

PiperOrigin-RevId: 340497006
2020-11-03 12:12:06 -08:00