gvisor
gvisor copied to clipboard
ttyname: Inappropriate ioctl for device
Description
If I call ttyname(0) in C, it gives an Inappropriate ioctl for device error.
Steps to reproduce
If I compile this code to a.out:
#include <stdio.h>
#include <unistd.h>
int main() {
char *name = ttyname(0);
if (!name) {
perror("ttyname");
return 1;
}
printf("ttyname = %s\n", name);
return 0;
}
With runsc, it fails:
$ podman run --rm -ti -v $PWD/a.out:/a.out:ro --runtime=runsc --runtime-flag=ignore-cgroups --runtime-flag=network=none debian:testing /a.out
ttyname: Inappropriate ioctl for device
With runc, it works:
$ podman run --rm -ti -v $PWD/a.out:/a.out:ro --runtime=runc debian:testing /a.out
ttyname = /dev/pts/0
Note that in both cases, I gave it the -t flag.
runsc version
runsc version 0.0~20240729.0
spec: 1.2.0
docker version (if using docker)
$ podman version
Client: Podman Engine
Version: 5.4.0
API Version: 5.4.0
Go Version: go1.24.0
Built: Sun Feb 16 08:51:11 2025
OS/Arch: linux/amd64
uname
Linux solaria 6.12.12-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.12-1 (2025-02-02) x86_64 GNU/Linux
kubectl (if using Kubernetes)
repo state (if built from source)
No response
runsc debug logs (if available)
Interesting find!
This is a tricky one because when you pass -t into podman (or Docker), gvisor will "donate" the terminal FD from the host into the sandbox. The donated terminal FD does not have a corresponding file in /dev filesystem inside the sandbox.
I believe this is the error we are hitting: https://elixir.bootlin.com/glibc/glibc-2.41.9000/source/sysdeps/posix/ttyname_r.c#L89-L91
I'll have to think about how to handle this. Maybe we could populate something in /dev/ for the donated terminal FD.
Also, if you run a program that creates an in-sandbox PTY (like tmux), and run your repro inside that, it does work:
$ docker run --runtime=runsc -it --rm ubuntu
root@babd2660deaa:/# apt update && apt install tmux
root@babd2660deaa:/# tmux
# now inside tmux
root@babd2660deaa:/# ./a.out
ttyname = /dev/pts/1
I believe this is the error we are hitting: https://elixir.bootlin.com/glibc/glibc-2.41.9000/source/sysdeps/posix/ttyname_r.c#L89-L91
That doesn't involve ioctl, so I think it's somewhere else? I was looking at https://elixir.bootlin.com/glibc/glibc-2.41.9000/source/sysdeps/unix/sysv/linux/ptsname.c#L54 yesterday, but I'm not sure if or how that's called from ttyname.
I was able to reproduce the tty name part of https://github.com/tmux/tmux/issues/4421 outside of gvisor, so this ioctl error isn't actually relevant to any apps I'm using in gvisor anymore, as far as I know.
I believe this is the error we are hitting: https://elixir.bootlin.com/glibc/glibc-2.41.9000/source/sysdeps/posix/ttyname_r.c#L89-L91
That doesn't involve
ioctl, so I think it's somewhere else? I was looking at https://elixir.bootlin.com/glibc/glibc-2.41.9000/source/sysdeps/unix/sysv/linux/ptsname.c#L54 yesterday, but I'm not sure if or how that's called from ttyname.
The code I linked returns ENOTTY which is often stringified as "inappropriate ioctl for device", so it can occur even when there's no actual ioctl being made.
I looked at the strace logs from your repro, and all of the ioctl calls are handled correctly (none return errors).