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
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.
When SIGWINCH causes the window size to change, signal the replica's foreground
process group. This is similar to what Linux does.
Also implement TIOCSCTTY/TIOCNOTTY and SIGWINCH delivery on TIOCSWINSZ
for host-imported TTYs, which previously did not support controlling
terminals or window size change signals.
Add syscall tests in pty.cc and host_pty.cc to verify the behavior.
Co-authored-by: Skywalkr-dev <[email protected]>
Fixes#13317
PiperOrigin-RevId: 927482382
When the PTY master is closed, send SIGHUPto the foreground
process group of the session that has the slave as its controlling
terminal. This matches Linux's pty_close() -> tty_vhangup(tty->link)
behavior (drivers/tty/pty.c).
Without this, child processes spawned via PTY (e.g. by expect/telnet)
are never notified of the hangup and remain running indefinitely.
Signed-off-by: Tan Yifeng <[email protected]>
Linux PTYs accept TCSBRK as a no-op and implement TCFLSH by
flushing the input and/or output queues. gVisor returned ENOTTY,
which breaks programs such as pyserial during terminal setup.
Handle TCSBRK in the PTY ioctl paths and route TCFLSH through
lineDiscipline.tcFlush(), including packet mode flush notification
and queue wakeups, to match Linux PTY semantics.
Signed-off-by: Tan Yifeng <[email protected]>
Signal characters (Ctrl-C/Z/\) unconditionally generated signals
regardless of the ISIG flag. Linux only generates these signals when
L_ISIG(tty) is true (n_tty.c:n_tty_receive_char_special).
Also fix signal characters leaking into the read buffer — Linux
consumes them in n_tty_receive_signal_char() and never delivers
them to the reading process.
Signed-off-by: Tan Yifeng <[email protected]>
- Remove stale TCGETS, etc. cases from maybeEmitUnimplementedEvent
- Avoid test runner redundantly passing hostTTYFile in certain cases
PiperOrigin-RevId: 885097262
glibc 2.42 uses TCGETS2 in isatty, and fails to properly detect ttys
without TCGETS2 supported.
This commit also adds support for passing additional TTY file
descriptors (fd numbers > 2) from the host, which is needed by the
new host_pty test but may also be independently useful.
In line_discipline.go, ensure that termios state is not overwritten
on CopyIn failure (e.g. EFAULT). This was reported in review. A
regression test is added.
Move kernel_termios operators to pty_util for reuse.
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
The TTYOperations for a donated host TTY were on the TTYFileDescription, but
that scopes them per-FD, when they should be scoped per-inode.
This CL moves the TTYOperations logic to the host inode struct, rather than the
TTYFileDescription. It also renames TTYOperations.Open ->
TTYOperations.TTYOpen, to avoid a naming collision with kernfs.inodeOpen.
As a result, opening a TTY (like via /dev/tty) always goes through inode.open,
thus creating a new TTYFileDescrption every time, whereas previously we
incorrectly returned the same TTYFileDescription each time.
Fixes#11644
PiperOrigin-RevId: 752856291
From man TIOCPKT:
"""
In packet mode, each subsequent read(2) will return a packet that either
contains a single nonzero control byte, or has a single byte containing zero
('\0') followed by data written on the slave side of the pseudoterminal."
"""
This CL implements only the data portion of packet mode, not the control bytes,
but that seems to be enough to get xfce4-terminal to work.
PiperOrigin-RevId: 737175092
Previously, CheckChange (corresponding to Linux's tty/tty_check_change()) was
only used the host TTY implementation, not the devpts implementation.
Furthermore, ThreadGroup.SetForegroundProcessGroup() duplicated some of the
logic in CheckChange, notably sending SIGTTOU to background tasks. This means
that, for host TTYs, we could send SIGTTOU multiple times. In some
circumstances, this leads the ioctl returning ERESTARTSYS in an infinite loop.
PiperOrigin-RevId: 735934036
We used to track the foreground process group & session on the
TTYFileOperation, but these are already tracked in kernel.TTY.ThreadGroup.
So remove TTYFileOperations.fgProcessGroup and .session, and replace them with
a kernel.TTY.
This is analogous to how sentry-internal tty's already work.
Updates #10925
PiperOrigin-RevId: 681957240
The /dev/tty acts as a replica for the current thread group's controlling
terminal.
In a follow-up, I will make /dev/tty work for donated host ttys.
Updates #10925
PiperOrigin-RevId: 681629892
Adapted from cl/630063475.
This causes FUSE tests involving submounts to fail, because fuse.inode.Valid()
just returns false (fails revalidation) after the entry time expires, causing
all submounts to be unmounted; change it to perform revalidation instead, a la
Linux's fs/fuse/dir.c:fuse_dentry_revalidate(). This in turn requires that we
plumb the dentry's parent and name through kernfs.Inode.Valid().
PiperOrigin-RevId: 630476483
Previously, writing an empty string to the PTY replica output queue
would return linux.ErrWouldBlock. This PR fixes this behavior to
not return an error.
This applies a similar limit as `inputQueueTransformer.transform`.
The goal is to avoid large allocations of memory.
I'm not sure if this is the right thing to do, but it seems better than the
status quo of not having any limits.
PiperOrigin-RevId: 581034478
While there is a difference between flavors of this ioctl (`TCSETS`,
`TCSETSF`, `TCSETSW`), in practice it seems not to matter. We should let
users call `TCSETSF` and can implement those differences if necessary.
These inodes can never be part of a filesystem tree. They are nameless and
never have a parent.
This allows us to avoid taking a lock in kernfs.InotifyWithParent for such
anonymous inodes.
PiperOrigin-RevId: 538823227
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
We no longer store the foreground process directly in the terminal. Instead, we
get it from the terminal TTY's ThreadGroup. Added a new method:
tty.SignalForegroundProcessGroup to simplify this.
Cleaned up some things along the way:
* Terminal had a bunch of methods to get/set foreground process group and
controlling TTY, but those methods were only usable by Ioctl, since they
read/wrote to syscall arguments. I moved that logic to Ioctl, and deleted the
methods from Terminal, which is now a very simple type.
* Fixed a bug in ThreadGroud.SetForegroundProcessGroup where we were
overwriting the ID of an existing process group, rather than setting a new
process group on the session.
* Simplified the construction of lineDiscipline type.
Reported-by: [email protected]
PiperOrigin-RevId: 512330758
Some implementations handle more flags than others, so it doesn't
make sense to have one set of rules for all.
This change should functionally be a no-op.
PiperOrigin-RevId: 502712415
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 refsvfs2 are used in netstack, we should use atomicbitops to avoid
breaking 32-bit builds.
On 64-bit builds there is no performance difference.
PiperOrigin-RevId: 439687980
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
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