qrexec: when forgetting about a client/process, flush buffered data
We need to spawn a child to take care of buffered data flushing, if there is any. Expensive, but should be needed rarely.
This commit is contained in:
		
							parent
							
								
									53b517f6a5
								
							
						
					
					
						commit
						1d24ef9d1a
					
				@ -6,8 +6,8 @@ COMMONIOALL=../common/ioall.o
 | 
				
			|||||||
all: qrexec_daemon qrexec_agent qrexec_client
 | 
					all: qrexec_daemon qrexec_agent qrexec_client
 | 
				
			||||||
qrexec_daemon: qrexec_daemon.o unix_server.o $(COMMONIOALL) txrx-vchan.o buffer.o write_stdin.o
 | 
					qrexec_daemon: qrexec_daemon.o unix_server.o $(COMMONIOALL) txrx-vchan.o buffer.o write_stdin.o
 | 
				
			||||||
	$(CC) -g -o qrexec_daemon qrexec_daemon.o unix_server.o $(COMMONIOALL) txrx-vchan.o write_stdin.o buffer.o $(XENLIBS)
 | 
						$(CC) -g -o qrexec_daemon qrexec_daemon.o unix_server.o $(COMMONIOALL) txrx-vchan.o write_stdin.o buffer.o $(XENLIBS)
 | 
				
			||||||
qrexec_agent: qrexec_agent.o exec.o txrx-vchan.o write_stdin.o buffer.o
 | 
					qrexec_agent: qrexec_agent.o exec.o txrx-vchan.o write_stdin.o buffer.o $(COMMONIOALL)
 | 
				
			||||||
	$(CC) -g -o qrexec_agent qrexec_agent.o exec.o txrx-vchan.o write_stdin.o buffer.o $(XENLIBS)
 | 
						$(CC) -g -o qrexec_agent qrexec_agent.o exec.o txrx-vchan.o write_stdin.o buffer.o $(COMMONIOALL) $(XENLIBS)
 | 
				
			||||||
qrexec_client: qrexec_client.o $(COMMONIOALL) exec.o
 | 
					qrexec_client: qrexec_client.o $(COMMONIOALL) exec.o
 | 
				
			||||||
	$(CC) -g -o qrexec_client qrexec_client.o $(COMMONIOALL) exec.o
 | 
						$(CC) -g -o qrexec_client qrexec_client.o $(COMMONIOALL) exec.o
 | 
				
			||||||
clean:
 | 
					clean:
 | 
				
			||||||
 | 
				
			|||||||
@ -45,3 +45,4 @@ int flush_client_data(int fd, int clid, struct buffer *buffer);
 | 
				
			|||||||
int write_stdin(int fd, int clid, char *data, int len,
 | 
					int write_stdin(int fd, int clid, char *data, int len,
 | 
				
			||||||
		struct buffer *buffer);
 | 
							struct buffer *buffer);
 | 
				
			||||||
void set_nonblock(int fd);
 | 
					void set_nonblock(int fd);
 | 
				
			||||||
 | 
					int fork_and_flush_stdin(int fd, struct buffer *buffer);
 | 
				
			||||||
 | 
				
			|||||||
@ -206,8 +206,11 @@ void remove_process(int clid, int status)
 | 
				
			|||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	if (!client_info[clid].pid)
 | 
						if (!client_info[clid].pid)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					        fork_and_flush_stdin(client_info[clid].stdin_fd, &client_info[clid].buffer); 
 | 
				
			||||||
 | 
					#if 0 
 | 
				
			||||||
 | 
					//      let's let it die by itself, possibly after it has received buffered stdin
 | 
				
			||||||
	kill(client_info[clid].pid, SIGKILL);
 | 
						kill(client_info[clid].pid, SIGKILL);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	if (status != -1)
 | 
						if (status != -1)
 | 
				
			||||||
		send_exit_code(clid, status);
 | 
							send_exit_code(clid, status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -118,10 +118,15 @@ void handle_new_client()
 | 
				
			|||||||
		max_client_fd = fd;
 | 
							max_client_fd = fd;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int children_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void flush_client(int fd)
 | 
					void flush_client(int fd)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
	struct server_header s_hdr;
 | 
						struct server_header s_hdr;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						if (fork_and_flush_stdin(fd, &clients[fd].buffer))
 | 
				
			||||||
 | 
						        children_count++;
 | 
				
			||||||
	close(fd);
 | 
						close(fd);
 | 
				
			||||||
	clients[fd].state = CLIENT_INVALID;
 | 
						clients[fd].state = CLIENT_INVALID;
 | 
				
			||||||
	buffer_free(&clients[fd].buffer);
 | 
						buffer_free(&clients[fd].buffer);
 | 
				
			||||||
@ -249,7 +254,6 @@ void pass_to_client(int clid, struct client_header *hdr)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int children_count;
 | 
					 | 
				
			||||||
int child_exited;
 | 
					int child_exited;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void sigchld_handler(int x)
 | 
					void sigchld_handler(int x)
 | 
				
			||||||
 | 
				
			|||||||
@ -23,6 +23,8 @@
 | 
				
			|||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <ioall.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include "qrexec.h"
 | 
					#include "qrexec.h"
 | 
				
			||||||
#include "buffer.h"
 | 
					#include "buffer.h"
 | 
				
			||||||
#include "glue.h"
 | 
					#include "glue.h"
 | 
				
			||||||
@ -96,3 +98,31 @@ void set_nonblock(int fd)
 | 
				
			|||||||
	int fl = fcntl(fd, F_GETFL, 0);
 | 
						int fl = fcntl(fd, F_GETFL, 0);
 | 
				
			||||||
	fcntl(fd, F_SETFL, fl | O_NONBLOCK);
 | 
						fcntl(fd, F_SETFL, fl | O_NONBLOCK);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void set_block(int fd)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int fl = fcntl(fd, F_GETFL, 0);
 | 
				
			||||||
 | 
						fcntl(fd, F_SETFL, fl & ~O_NONBLOCK);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int fork_and_flush_stdin(int fd, struct buffer *buffer)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						if (!buffer_len(buffer))
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						switch (fork()) {
 | 
				
			||||||
 | 
						case -1:
 | 
				
			||||||
 | 
							perror("fork");
 | 
				
			||||||
 | 
							exit(1);
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for (i = 0; i < MAX_FDS; i++)
 | 
				
			||||||
 | 
							if (i != fd && i != 2)
 | 
				
			||||||
 | 
								close(i);
 | 
				
			||||||
 | 
						set_block(fd);
 | 
				
			||||||
 | 
						write_all(fd, buffer_data(buffer), buffer_len(buffer));
 | 
				
			||||||
 | 
						exit(0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user