Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

builtin port forwarder cannot handle oob data #363

Open
Luap99 opened this issue Apr 27, 2023 · 0 comments
Open

builtin port forwarder cannot handle oob data #363

Luap99 opened this issue Apr 27, 2023 · 0 comments
Labels
enhancement New feature or request

Comments

@Luap99
Copy link
Contributor

Luap99 commented Apr 27, 2023

A podman user reported that a server hangs when receiving oob data. containers/podman#18161

It works as root and via slirp4netns port handler. I suspect that this is simply not implemented in the builtin port forwarder?
I haven't looked closely at the code here but it seems like we already use oob data to forward fds between child and parent process? I am not sure if this is causing the issues here.

I am forwarding the report from @pushpi55 here because I think this must be fixed here and there isn't really anything podman could do about that.


Podman is running in rootless mode and a server is listening on a port and using splice call to read the message.
When OOB message is being received the process inside the container is stuck forever in splice call.
Attached the strace of the container running the process
strace_podman_linux_image.txt

Steps to reproduce:

  • Pull a RHEL8 image from repo.
  • Install gcc and run the following program to start the server and start a client to send OOB message
  • Run the server program inside container which is using splice system call
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>

main() {
struct sockaddr_in sockaddr_serv;
int pipefd[2];
int sock=0;
int sockfd = 0;
socklen_t size_addr = 0;
char buf[1024];
 sock = socket(PF_INET, SOCK_STREAM, 0);
memset(&sockaddr_serv, 0, sizeof(sockaddr_serv));
sockaddr_serv.sin_family = PF_INET;
sockaddr_serv.sin_addr.s_addr = htonl(INADDR_ANY);
sockaddr_serv.sin_port = htons(9999);

if(bind(sock, (struct sockaddr*) &sockaddr_serv, sizeof(sockaddr_serv))<0) {
  printf("error in binding \n");
 return 1;
}
listen(sock, 5);
pipe(pipefd);
 sockfd = accept(sock, (struct sockaddr*) &sockaddr_serv, &size_addr);
  if(splice(sockfd,0, pipefd[1],0,100,SPLICE_F_MOVE | SPLICE_F_MORE) <0) {
    perror("Error in splice");
    close(sockfd);
    close(sock);
}
 printf("return from recv is %d\n",read(pipefd[0], buf, 50 ));
}
  • Start the client and send OOB message
import socket

HOST='127.0.0.1'
PORT=44957
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.send(b'!',socket.MSG_OOB)
    s.sendall(b'Hello, world')
    data = s.recv(1024)

print('Received', repr(data))

Started a server inside container and it is stuck in splice system call

(gdb) bt
#0  0x00007f30452764e8 in accept () from /lib64/libc.so.6
#1  0x0000000000400a28 in main () at serv.c:30
(gdb) n
Single stepping until exit from function accept,
which has no line number information.
main () at serv.c:31
31	  if(splice(sockfd,0, pipefd[1],0,100,SPLICE_F_MOVE | SPLICE_F_MORE) <0) {
(gdb)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants