Merge branch 'hvm-for-master'
Conflicts: dom0/qvm-core/qubes.py dom0/qvm-tools/qvm-sync-clock version_dom0 vm-systemd/qubes-sysinit.sh
This commit is contained in:
		
						commit
						a9fd8ec5dd
					
				| @ -32,6 +32,17 @@ void perror_wrapper(char * msg) | |||||||
| 	errno=prev; | 	errno=prev; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void set_nonblock(int fd) | ||||||
|  | { | ||||||
|  | 	int fl = fcntl(fd, F_GETFL, 0); | ||||||
|  | 	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 write_all(int fd, void *buf, int size) | int write_all(int fd, void *buf, int size) | ||||||
| { | { | ||||||
| @ -42,7 +53,6 @@ int write_all(int fd, void *buf, int size) | |||||||
| 		if (ret == -1 && errno == EINTR) | 		if (ret == -1 && errno == EINTR) | ||||||
| 			continue; | 			continue; | ||||||
| 		if (ret <= 0) { | 		if (ret <= 0) { | ||||||
| 			perror_wrapper("write"); |  | ||||||
| 			return 0; | 			return 0; | ||||||
| 		} | 		} | ||||||
| 		written += ret; | 		written += ret; | ||||||
| @ -65,9 +75,14 @@ int read_all(int fd, void *buf, int size) | |||||||
| 			return 0; | 			return 0; | ||||||
| 		} | 		} | ||||||
| 		if (ret < 0) { | 		if (ret < 0) { | ||||||
| 			perror_wrapper("read"); | 			if (errno != EAGAIN) | ||||||
|  | 				perror_wrapper("read"); | ||||||
| 			return 0; | 			return 0; | ||||||
| 		} | 		} | ||||||
|  | 		if (got_read == 0) { | ||||||
|  | 			// force blocking operation on further reads
 | ||||||
|  | 			set_block(fd); | ||||||
|  | 		} | ||||||
| 		got_read += ret; | 		got_read += ret; | ||||||
| 	} | 	} | ||||||
| //      fprintf(stderr, "read %d bytes\n", size);
 | //      fprintf(stderr, "read %d bytes\n", size);
 | ||||||
|  | |||||||
| @ -1,3 +1,5 @@ | |||||||
| int write_all(int fd, void *buf, int size); | int write_all(int fd, void *buf, int size); | ||||||
| int read_all(int fd, void *buf, int size); | int read_all(int fd, void *buf, int size); | ||||||
| int copy_fd_all(int fdout, int fdin); | int copy_fd_all(int fdout, int fdin); | ||||||
|  | void set_nonblock(int fd); | ||||||
|  | void set_block(int fd); | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ | |||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #include <ioall.h> | #include <ioall.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
|  | #include <errno.h> | ||||||
| #include <gui-fatal.h> | #include <gui-fatal.h> | ||||||
| #include "filecopy.h" | #include "filecopy.h" | ||||||
| #include "crc32.h" | #include "crc32.h" | ||||||
| @ -49,6 +50,37 @@ void do_notify_progress(long long total, int flag) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void wait_for_result() | ||||||
|  | { | ||||||
|  | 	struct result_header hdr; | ||||||
|  | 
 | ||||||
|  | 	if (!read_all(0, &hdr, sizeof(hdr))) { | ||||||
|  | 		if (errno == EAGAIN) { | ||||||
|  | 			// no result sent and stdin still open
 | ||||||
|  | 			return; | ||||||
|  | 		} else { | ||||||
|  | 			// other read error or EOF
 | ||||||
|  | 			exit(1);	// hopefully remote has produced error message
 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (hdr.error_code != 0) { | ||||||
|  | 		switch (hdr.error_code) { | ||||||
|  | 			case EEXIST: | ||||||
|  | 				gui_fatal("File copy: not overwriting existing file. Clean incoming dir, and retry copy"); | ||||||
|  | 				break; | ||||||
|  | 			case EINVAL: | ||||||
|  | 				gui_fatal("File copy: Corrupted data from packer"); | ||||||
|  | 				break; | ||||||
|  | 			default: | ||||||
|  | 				gui_fatal("File copy: %s", | ||||||
|  | 						strerror(hdr.error_code)); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (hdr.crc32 != crc32_sum) { | ||||||
|  | 		gui_fatal("File transfer failed: checksum mismatch"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void notify_progress(int size, int flag) | void notify_progress(int size, int flag) | ||||||
| { | { | ||||||
| 	static long long total = 0; | 	static long long total = 0; | ||||||
| @ -56,6 +88,11 @@ void notify_progress(int size, int flag) | |||||||
| 	total += size; | 	total += size; | ||||||
| 	if (total > prev_total + PROGRESS_NOTIFY_DELTA | 	if (total > prev_total + PROGRESS_NOTIFY_DELTA | ||||||
| 	    || (flag != PROGRESS_FLAG_NORMAL)) { | 	    || (flag != PROGRESS_FLAG_NORMAL)) { | ||||||
|  | 		// check for possible error from qfile-unpacker; if error occured,
 | ||||||
|  | 		// exit() will be called, so don't bother with current state
 | ||||||
|  | 		// (notify_progress can be called as callback from copy_file())
 | ||||||
|  | 		if (flag == PROGRESS_FLAG_NORMAL) | ||||||
|  | 			wait_for_result(); | ||||||
| 		do_notify_progress(total, flag); | 		do_notify_progress(total, flag); | ||||||
| 		prev_total = total; | 		prev_total = total; | ||||||
| 	} | 	} | ||||||
| @ -64,8 +101,11 @@ void notify_progress(int size, int flag) | |||||||
| void write_headers(struct file_header *hdr, char *filename) | void write_headers(struct file_header *hdr, char *filename) | ||||||
| { | { | ||||||
| 	if (!write_all_with_crc(1, hdr, sizeof(*hdr)) | 	if (!write_all_with_crc(1, hdr, sizeof(*hdr)) | ||||||
| 	    || !write_all_with_crc(1, filename, hdr->namelen)) | 	    || !write_all_with_crc(1, filename, hdr->namelen)) { | ||||||
|  | 		set_block(0); | ||||||
|  | 		wait_for_result(); | ||||||
| 		exit(1); | 		exit(1); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int single_file_processor(char *filename, struct stat *st) | int single_file_processor(char *filename, struct stat *st) | ||||||
| @ -89,13 +129,15 @@ int single_file_processor(char *filename, struct stat *st) | |||||||
| 		hdr.filelen = st->st_size; | 		hdr.filelen = st->st_size; | ||||||
| 		write_headers(&hdr, filename); | 		write_headers(&hdr, filename); | ||||||
| 		ret = copy_file(1, fd, hdr.filelen, &crc32_sum); | 		ret = copy_file(1, fd, hdr.filelen, &crc32_sum); | ||||||
| 		// if COPY_FILE_WRITE_ERROR, hopefully remote will produce a message
 |  | ||||||
| 		if (ret != COPY_FILE_OK) { | 		if (ret != COPY_FILE_OK) { | ||||||
| 			if (ret != COPY_FILE_WRITE_ERROR) | 			if (ret != COPY_FILE_WRITE_ERROR) | ||||||
| 				gui_fatal("Copying file %s: %s", filename, | 				gui_fatal("Copying file %s: %s", filename, | ||||||
| 					  copy_file_status_to_str(ret)); | 					  copy_file_status_to_str(ret)); | ||||||
| 			else | 			else { | ||||||
|  | 				set_block(0); | ||||||
|  | 				wait_for_result(); | ||||||
| 				exit(1); | 				exit(1); | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		close(fd); | 		close(fd); | ||||||
| 	} | 	} | ||||||
| @ -109,9 +151,14 @@ int single_file_processor(char *filename, struct stat *st) | |||||||
| 			gui_fatal("readlink %s", filename); | 			gui_fatal("readlink %s", filename); | ||||||
| 		hdr.filelen = st->st_size + 1; | 		hdr.filelen = st->st_size + 1; | ||||||
| 		write_headers(&hdr, filename); | 		write_headers(&hdr, filename); | ||||||
| 		if (!write_all_with_crc(1, name, st->st_size + 1)) | 		if (!write_all_with_crc(1, name, st->st_size + 1)) { | ||||||
|  | 			set_block(0); | ||||||
|  | 			wait_for_result(); | ||||||
| 			exit(1); | 			exit(1); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  | 	// check for possible error from qfile-unpacker
 | ||||||
|  | 	wait_for_result(); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -147,7 +194,6 @@ int do_fs_walk(char *file) | |||||||
| 
 | 
 | ||||||
| void notify_end_and_wait_for_result() | void notify_end_and_wait_for_result() | ||||||
| { | { | ||||||
| 	struct result_header hdr; |  | ||||||
| 	struct file_header end_hdr; | 	struct file_header end_hdr; | ||||||
| 
 | 
 | ||||||
| 	/* nofity end of transfer */ | 	/* nofity end of transfer */ | ||||||
| @ -156,17 +202,8 @@ void notify_end_and_wait_for_result() | |||||||
| 	end_hdr.filelen = 0; | 	end_hdr.filelen = 0; | ||||||
| 	write_all_with_crc(1, &end_hdr, sizeof(end_hdr)); | 	write_all_with_crc(1, &end_hdr, sizeof(end_hdr)); | ||||||
| 
 | 
 | ||||||
| 	/* wait for result */ | 	set_block(0); | ||||||
| 	if (!read_all(0, &hdr, sizeof(hdr))) { | 	wait_for_result(); | ||||||
| 		exit(1);	// hopefully remote has produced error message
 |  | ||||||
| 	} |  | ||||||
| 	if (hdr.error_code != 0) { |  | ||||||
| 		gui_fatal("Error writing files: %s", |  | ||||||
| 			  strerror(hdr.error_code)); |  | ||||||
| 	} |  | ||||||
| 	if (hdr.crc32 != crc32_sum) { |  | ||||||
| 		gui_fatal("File transfer failed: checksum mismatch"); |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| char *get_abs_path(char *cwd, char *pathname) | char *get_abs_path(char *cwd, char *pathname) | ||||||
| @ -186,6 +223,8 @@ int main(int argc, char **argv) | |||||||
| 	char *sep; | 	char *sep; | ||||||
| 
 | 
 | ||||||
| 	signal(SIGPIPE, SIG_IGN); | 	signal(SIGPIPE, SIG_IGN); | ||||||
|  | 	// this will allow checking for possible feedback packet in the middle of transfer
 | ||||||
|  | 	set_nonblock(0); | ||||||
| 	notify_progress(0, PROGRESS_FLAG_INIT); | 	notify_progress(0, PROGRESS_FLAG_INIT); | ||||||
| 	crc32_sum = 0; | 	crc32_sum = 0; | ||||||
| 	cwd = getcwd(NULL, 0); | 	cwd = getcwd(NULL, 0); | ||||||
|  | |||||||
| @ -29,32 +29,14 @@ int prepare_creds_return_uid(char *username) | |||||||
| 	return pwd->pw_uid; | 	return pwd->pw_uid; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void wait_for_child(int statusfd) | extern int do_unpack(void); | ||||||
| { |  | ||||||
| 	int status; |  | ||||||
| 	if (read(statusfd, &status, sizeof status)!=sizeof status) |  | ||||||
| 		gui_fatal("File copy error: Internal error reading status from unpacker"); |  | ||||||
| 	errno = status; |  | ||||||
| 	switch (status) { |  | ||||||
| 	case LEGAL_EOF: break; |  | ||||||
| 	case 0: gui_fatal("File copy: Connection terminated unexpectedly"); break; |  | ||||||
| 	case EINVAL: gui_fatal("File copy: Corrupted data from packer"); break; |  | ||||||
| 	case EEXIST: gui_fatal("File copy: not overwriting existing file. Clean ~/incoming, and retry copy"); break; |  | ||||||
| 	default: gui_fatal("File copy");  |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| extern void do_unpack(int); |  | ||||||
| 
 | 
 | ||||||
| int main(int argc, char ** argv) | int main(int argc, char ** argv) | ||||||
| { | { | ||||||
| 	char *incoming_dir; | 	char *incoming_dir; | ||||||
| 	int pipefds[2]; |  | ||||||
| 	int uid; | 	int uid; | ||||||
| 	char *remote_domain; | 	char *remote_domain; | ||||||
| 
 | 
 | ||||||
| 	pipe(pipefds); |  | ||||||
| 
 |  | ||||||
| 	uid = prepare_creds_return_uid("user"); | 	uid = prepare_creds_return_uid("user"); | ||||||
| 
 | 
 | ||||||
| 	remote_domain = getenv("QREXEC_REMOTE_DOMAIN"); | 	remote_domain = getenv("QREXEC_REMOTE_DOMAIN"); | ||||||
| @ -67,23 +49,8 @@ int main(int argc, char ** argv) | |||||||
| 	mkdir(incoming_dir, 0700); | 	mkdir(incoming_dir, 0700); | ||||||
| 	if (chdir(incoming_dir)) | 	if (chdir(incoming_dir)) | ||||||
| 		gui_fatal("Error chdir to %s", incoming_dir);  | 		gui_fatal("Error chdir to %s", incoming_dir);  | ||||||
| 	switch (fork()) { | 	if (chroot(incoming_dir)) //impossible
 | ||||||
| 	case -1: | 		gui_fatal("Error chroot to %s", incoming_dir); | ||||||
| 		perror("fork"); |  | ||||||
| 		exit(1); |  | ||||||
| 	case 0: |  | ||||||
| 		if (chroot(incoming_dir)) //impossible
 |  | ||||||
| 			gui_fatal("Error chroot to %s", incoming_dir); |  | ||||||
| 		setuid(uid); |  | ||||||
| 		close(pipefds[0]); |  | ||||||
| 		do_unpack(pipefds[1]); |  | ||||||
| 		exit(0); |  | ||||||
| 	default:; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	setuid(uid); | 	setuid(uid); | ||||||
| 	close(pipefds[1]); | 	return do_unpack(); | ||||||
| 	wait_for_child(pipefds[0]); |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,4 +3,4 @@ | |||||||
| 
 | 
 | ||||||
| ## Please use a single # to start your custom comments | ## Please use a single # to start your custom comments | ||||||
| 
 | 
 | ||||||
| $anyvm	$anyvm	ask,user=root | $anyvm	$anyvm	ask | ||||||
|  | |||||||
| @ -35,14 +35,24 @@ int read_all_with_crc(int fd, void *buf, int size) { | |||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int global_status_fd; | void send_status_and_crc(int code) { | ||||||
| void do_exit(int code) | 	struct result_header hdr; | ||||||
| { | 	int saved_errno; | ||||||
| 	int codebuf = code; | 
 | ||||||
| 	write(global_status_fd, &codebuf, sizeof codebuf); | 	saved_errno = errno; | ||||||
| 	exit(0); | 	hdr.error_code = code; | ||||||
|  | 	hdr.crc32 = crc32_sum; | ||||||
|  | 	if (!write_all(1, &hdr, sizeof(hdr))) | ||||||
|  | 		perror("write status"); | ||||||
|  | 	errno = saved_errno; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void do_exit(int code) | ||||||
|  | { | ||||||
|  | 	close(0); | ||||||
|  | 	send_status_and_crc(code); | ||||||
|  | 	exit(code); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| void fix_times_and_perms(struct file_header *untrusted_hdr, | void fix_times_and_perms(struct file_header *untrusted_hdr, | ||||||
| 			 char *untrusted_name) | 			 char *untrusted_name) | ||||||
| @ -130,20 +140,8 @@ void process_one_file(struct file_header *untrusted_hdr) | |||||||
| 		do_exit(EINVAL); | 		do_exit(EINVAL); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void send_status_and_crc() { | int do_unpack() | ||||||
| 	struct result_header hdr; |  | ||||||
| 	int saved_errno; |  | ||||||
| 
 |  | ||||||
| 	saved_errno = errno; |  | ||||||
| 	hdr.error_code = errno; |  | ||||||
| 	hdr.crc32 = crc32_sum; |  | ||||||
| 	write_all(1, &hdr, sizeof(hdr)); |  | ||||||
| 	errno = saved_errno; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void do_unpack(int fd) |  | ||||||
| { | { | ||||||
| 	global_status_fd = fd; |  | ||||||
| 	struct file_header untrusted_hdr; | 	struct file_header untrusted_hdr; | ||||||
| 	/* initialize checksum */ | 	/* initialize checksum */ | ||||||
| 	crc32_sum = 0; | 	crc32_sum = 0; | ||||||
| @ -158,9 +156,6 @@ void do_unpack(int fd) | |||||||
| 		if (files_limit && total_files > files_limit) | 		if (files_limit && total_files > files_limit) | ||||||
| 			do_exit(EDQUOT); | 			do_exit(EDQUOT); | ||||||
| 	} | 	} | ||||||
| 	send_status_and_crc(); | 	send_status_and_crc(errno); | ||||||
| 	if (errno) | 	return errno; | ||||||
| 		do_exit(errno); |  | ||||||
| 	else |  | ||||||
| 		do_exit(LEGAL_EOF); |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -405,7 +405,7 @@ rm -rf $RPM_BUILD_ROOT | |||||||
| /usr/lib/qubes/meminfo-writer | /usr/lib/qubes/meminfo-writer | ||||||
| /usr/lib/qubes/network-manager-prepare-conf-dir | /usr/lib/qubes/network-manager-prepare-conf-dir | ||||||
| /usr/lib/qubes/qfile-agent | /usr/lib/qubes/qfile-agent | ||||||
| /usr/lib/qubes/qfile-unpacker | %attr(4755,root,root) /usr/lib/qubes/qfile-unpacker | ||||||
| /usr/lib/qubes/qopen-in-vm | /usr/lib/qubes/qopen-in-vm | ||||||
| /usr/lib/qubes/qrexec_agent | /usr/lib/qubes/qrexec_agent | ||||||
| /usr/lib/qubes/qrexec_client_vm | /usr/lib/qubes/qrexec_client_vm | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Marek Marczykowski
						Marek Marczykowski