Make qrexec_client wait for its local child before exiting
If we do not wait and exit imemdiately, qrexec_daemon will decrease the children count and continue spawning processes, while e.g. qfile-daemon still waits for kdialog - so dom0 will be DoSed by multiple processes.
This commit is contained in:
		
							parent
							
								
									27cfd6111a
								
							
						
					
					
						commit
						769eedd33a
					
				| @ -26,6 +26,7 @@ | |||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| #include <ioall.h> | #include <ioall.h> | ||||||
|  | #include <sys/wait.h> | ||||||
| #include "qrexec.h" | #include "qrexec.h" | ||||||
| #include "buffer.h" | #include "buffer.h" | ||||||
| #include "glue.h" | #include "glue.h" | ||||||
| @ -58,6 +59,18 @@ void do_exec(char *prog) | |||||||
| 
 | 
 | ||||||
| int local_stdin_fd, local_stdout_fd; | int local_stdin_fd, local_stdout_fd; | ||||||
| 
 | 
 | ||||||
|  | void do_exit(int code) | ||||||
|  | { | ||||||
|  | 	int status; | ||||||
|  | // sever communication lines; wait for child, if any
 | ||||||
|  | // so that qrexec-daemon can count (recursively) spawned processes correctly          
 | ||||||
|  | 	close(local_stdin_fd); | ||||||
|  | 	close(local_stdout_fd); | ||||||
|  | 	waitpid(-1, &status, 0); | ||||||
|  | 	exit(code); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| void prepare_local_fds(char *cmdline) | void prepare_local_fds(char *cmdline) | ||||||
| { | { | ||||||
| 	int pid; | 	int pid; | ||||||
| @ -79,7 +92,7 @@ void send_cmdline(int s, int type, char *cmdline) | |||||||
| 	if (!write_all(s, &hdr, sizeof(hdr)) | 	if (!write_all(s, &hdr, sizeof(hdr)) | ||||||
| 	    || !write_all(s, cmdline, hdr.len)) { | 	    || !write_all(s, cmdline, hdr.len)) { | ||||||
| 		perror("write daemon"); | 		perror("write daemon"); | ||||||
| 		exit(1); | 		do_exit(1); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -90,7 +103,7 @@ void handle_input(int s) | |||||||
| 	ret = read(local_stdout_fd, buf, sizeof(buf)); | 	ret = read(local_stdout_fd, buf, sizeof(buf)); | ||||||
| 	if (ret < 0) { | 	if (ret < 0) { | ||||||
| 		perror("read"); | 		perror("read"); | ||||||
| 		exit(1); | 		do_exit(1); | ||||||
| 	} | 	} | ||||||
| 	if (ret == 0) { | 	if (ret == 0) { | ||||||
| 		local_stdout_fd = -1; | 		local_stdout_fd = -1; | ||||||
| @ -98,7 +111,7 @@ void handle_input(int s) | |||||||
| 	} | 	} | ||||||
| 	if (!write_all(s, buf, ret)) { | 	if (!write_all(s, buf, ret)) { | ||||||
| 		perror("write daemon"); | 		perror("write daemon"); | ||||||
| 		exit(1); | 		do_exit(1); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -110,15 +123,15 @@ void handle_daemon_data(int s) | |||||||
| 
 | 
 | ||||||
| 	if (!read_all(s, &hdr, sizeof hdr)) { | 	if (!read_all(s, &hdr, sizeof hdr)) { | ||||||
| 		perror("read daemon"); | 		perror("read daemon"); | ||||||
| 		exit(1); | 		do_exit(1); | ||||||
| 	} | 	} | ||||||
| 	if (hdr.len > MAX_DATA_CHUNK) { | 	if (hdr.len > MAX_DATA_CHUNK) { | ||||||
| 		fprintf(stderr, "client_header.len=%d\n", hdr.len); | 		fprintf(stderr, "client_header.len=%d\n", hdr.len); | ||||||
| 		exit(1); | 		do_exit(1); | ||||||
| 	} | 	} | ||||||
| 	if (!read_all(s, buf, hdr.len)) { | 	if (!read_all(s, buf, hdr.len)) { | ||||||
| 		perror("read daemon"); | 		perror("read daemon"); | ||||||
| 		exit(1); | 		do_exit(1); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	switch (hdr.type) { | 	switch (hdr.type) { | ||||||
| @ -127,7 +140,7 @@ void handle_daemon_data(int s) | |||||||
| 			close(local_stdin_fd); | 			close(local_stdin_fd); | ||||||
| 		else if (!write_all(local_stdin_fd, buf, hdr.len)) { | 		else if (!write_all(local_stdin_fd, buf, hdr.len)) { | ||||||
| 			perror("write local stdout"); | 			perror("write local stdout"); | ||||||
| 			exit(1); | 			do_exit(1); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case MSG_SERVER_TO_CLIENT_STDERR: | 	case MSG_SERVER_TO_CLIENT_STDERR: | ||||||
| @ -136,13 +149,13 @@ void handle_daemon_data(int s) | |||||||
| 	case MSG_SERVER_TO_CLIENT_EXIT_CODE: | 	case MSG_SERVER_TO_CLIENT_EXIT_CODE: | ||||||
| 		status = *(unsigned int *) buf; | 		status = *(unsigned int *) buf; | ||||||
| 		if (WIFEXITED(status)) | 		if (WIFEXITED(status)) | ||||||
| 			exit(WEXITSTATUS(status)); | 			do_exit(WEXITSTATUS(status)); | ||||||
| 		else | 		else | ||||||
| 			exit(255); | 			do_exit(255); | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		fprintf(stderr, "unknown msg %d\n", hdr.type); | 		fprintf(stderr, "unknown msg %d\n", hdr.type); | ||||||
| 		exit(1); | 		do_exit(1); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -160,7 +173,7 @@ void handle_daemon_only_until_writable(s) | |||||||
| 
 | 
 | ||||||
| 		if (select(s + 1, &rdset, &wrset, NULL, NULL) < 0) { | 		if (select(s + 1, &rdset, &wrset, NULL, NULL) < 0) { | ||||||
| 			perror("select"); | 			perror("select"); | ||||||
| 			exit(1); | 			do_exit(1); | ||||||
| 		} | 		} | ||||||
| 		if (FD_ISSET(s, &rdset)) | 		if (FD_ISSET(s, &rdset)) | ||||||
| 			handle_daemon_data(s); | 			handle_daemon_data(s); | ||||||
| @ -183,7 +196,7 @@ void select_loop(int s) | |||||||
| 		} | 		} | ||||||
| 		if (select(max + 1, &select_set, NULL, NULL, NULL) < 0) { | 		if (select(max + 1, &select_set, NULL, NULL, NULL) < 0) { | ||||||
| 			perror("select"); | 			perror("select"); | ||||||
| 			exit(1); | 			do_exit(1); | ||||||
| 		} | 		} | ||||||
| 		if (FD_ISSET(s, &select_set)) | 		if (FD_ISSET(s, &select_set)) | ||||||
| 			handle_daemon_data(s); | 			handle_daemon_data(s); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Rafal Wojtczuk
						Rafal Wojtczuk