Select on stdin broken unless running interactively
crappycrypto opened this issue · comments
Description
Since commit 9768009 select has been broken for STDIN. Since that commit select on STDIN returns EPERM instead of the expected response that STDIN is readable.
NOTE: This only occurs in containers that are started without an interactive stdin/stdout.
Steps to reproduce
Compile the program below and run it inside gvisor
$ ./a.out </dev/null; echo $?
0
$ docker run --rm --runtime=runc debian_test /a.out; echo $?
0
$ docker run --rm --runtime=runsc debian_test /a.out; echo $?
a.out: select(1, [STDIN], NULL, NULL) returned error: Operation not permitted
1
Test program
#include <sys/select.h>
#include <stddef.h>
#include <err.h>
void testSelect() {
fd_set rfds;
struct timeval tv;
int res;
FD_ZERO(&rfds);
FD_SET(0, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 1;
res = select(1, &rfds, NULL, NULL, &tv);
if (res == -1)
err(1, "select(1, [STDIN], NULL, NULL) returned error");
}
int main(int argc, char **argv, char**envp){
testSelect();
return 0;
}
The test function could be added to
https://github.com/google/gvisor/blob/master/images/basic/integrationtest/host_fd.c to avoid regressions.
runsc version
runsc version release-20220131.0
spec: 1.0.2-dev
docker version (if using docker)
Client: Docker Engine - Community
Version: 20.10.12
API version: 1.41
Go version: go1.16.12
Git commit: e91ed57
Built: Mon Dec 13 11:45:48 2021
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.12
API version: 1.41 (minimum version 1.12)
Go version: go1.16.12
Git commit: 459d0df
Built: Mon Dec 13 11:43:56 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.4.12
GitCommit: 7b11cfaabd73bb80907dd23182b9347b4245eb5d
runc:
Version: 1.0.2
GitCommit: v1.0.2-0-g52b36a2
docker-init:
Version: 0.19.0
GitCommit: de40ad0
uname
No response
kubectl (if using Kubernetes)
No response
repo state (if built from source)
No response
runsc debug logs (if available)
No response
When the container start non-interactively, stdin is set to /dev/null
which is not epoll-able. gVisor uses epoll as the underlying infrastructure to get notifications about host FDs to implement syscalls like epoll(2)
and select(2)
. Unfortunately, select(2)
allows /dev/null
to be passed in, which makes no send since it will never trigger. We would need to distinguish these 2 cases and eat up the error for select.