google / gvisor

Application Kernel for Containers

Home Page:https://gvisor.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.