dom0: implement size/file-count limit of downloaded updates (#198)
Currently limit is 2GB and 2048 files, but can be adjusted by env variables (UPDATES_MAX_BYTES, UPDATES_MAX_FILES).
This commit is contained in:
		
							parent
							
								
									60d14758d6
								
							
						
					
					
						commit
						977b058395
					
				| @ -29,3 +29,4 @@ enum { | |||||||
| 
 | 
 | ||||||
| int copy_file(int outfd, int infd, long long size, unsigned long *crc32); | int copy_file(int outfd, int infd, long long size, unsigned long *crc32); | ||||||
| char *copy_file_status_to_str(int status); | char *copy_file_status_to_str(int status); | ||||||
|  | void set_size_limit(long long new_bytes_limit, long long new_files_limit); | ||||||
|  | |||||||
| @ -11,10 +11,21 @@ | |||||||
| #include "crc32.h" | #include "crc32.h" | ||||||
| 
 | 
 | ||||||
| char untrusted_namebuf[MAX_PATH_LENGTH]; | char untrusted_namebuf[MAX_PATH_LENGTH]; | ||||||
|  | long long bytes_limit = 0; | ||||||
|  | long long files_limit = 0; | ||||||
|  | long long total_bytes = 0; | ||||||
|  | long long total_files = 0; | ||||||
|  | 
 | ||||||
| void notify_progress(int p1, int p2) | void notify_progress(int p1, int p2) | ||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void set_size_limit(long long new_bytes_limit, long long new_files_limit) | ||||||
|  | { | ||||||
|  | 	bytes_limit = new_bytes_limit; | ||||||
|  | 	files_limit = new_files_limit; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| unsigned long crc32_sum = 0; | unsigned long crc32_sum = 0; | ||||||
| int read_all_with_crc(int fd, void *buf, int size) { | int read_all_with_crc(int fd, void *buf, int size) { | ||||||
| 	int ret; | 	int ret; | ||||||
| @ -56,6 +67,9 @@ void process_one_file_reg(struct file_header *untrusted_hdr, | |||||||
| 	int fdout = open(untrusted_name, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0700);	/* safe because of chroot */ | 	int fdout = open(untrusted_name, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0700);	/* safe because of chroot */ | ||||||
| 	if (fdout < 0) | 	if (fdout < 0) | ||||||
| 		do_exit(errno); | 		do_exit(errno); | ||||||
|  | 	total_bytes += untrusted_hdr->filelen; | ||||||
|  | 	if (bytes_limit && total_bytes > bytes_limit) | ||||||
|  | 		do_exit(EDQUOT); | ||||||
| 	ret = copy_file(fdout, 0, untrusted_hdr->filelen, &crc32_sum); | 	ret = copy_file(fdout, 0, untrusted_hdr->filelen, &crc32_sum); | ||||||
| 	if (ret != COPY_FILE_OK) { | 	if (ret != COPY_FILE_OK) { | ||||||
| 		if (ret == COPY_FILE_READ_EOF | 		if (ret == COPY_FILE_READ_EOF | ||||||
| @ -140,6 +154,9 @@ void do_unpack(int fd) | |||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		process_one_file(&untrusted_hdr); | 		process_one_file(&untrusted_hdr); | ||||||
|  | 		total_files++; | ||||||
|  | 		if (files_limit && total_files > files_limit) | ||||||
|  | 			do_exit(EDQUOT); | ||||||
| 	} | 	} | ||||||
| 	send_status_and_crc(); | 	send_status_and_crc(); | ||||||
| 	if (errno) | 	if (errno) | ||||||
|  | |||||||
| @ -12,6 +12,10 @@ | |||||||
| #include <gui-fatal.h> | #include <gui-fatal.h> | ||||||
| #include <errno.h> | #include <errno.h> | ||||||
| #include "filecopy.h" | #include "filecopy.h" | ||||||
|  | 
 | ||||||
|  | #define DEFAULT_MAX_UPDATES_BYTES (2L<<30) | ||||||
|  | #define DEFAULT_MAX_UPDATES_FILES 2048 | ||||||
|  | 
 | ||||||
| int prepare_creds_return_uid(char *username) | int prepare_creds_return_uid(char *username) | ||||||
| { | { | ||||||
| 	struct passwd *pwd; | 	struct passwd *pwd; | ||||||
| @ -50,12 +54,20 @@ int main(int argc, char ** argv) | |||||||
| 	char *incoming_dir; | 	char *incoming_dir; | ||||||
| 	int pipefds[2]; | 	int pipefds[2]; | ||||||
| 	int uid; | 	int uid; | ||||||
|  | 	char *var; | ||||||
|  | 	long long files_limit = DEFAULT_MAX_UPDATES_FILES; | ||||||
|  | 	long long bytes_limit = DEFAULT_MAX_UPDATES_BYTES; | ||||||
| 
 | 
 | ||||||
| 	if (argc < 3) { | 	if (argc < 3) { | ||||||
| 		fprintf(stderr, "Invalid parameters, usage: %s user dir\n", argv[0]); | 		fprintf(stderr, "Invalid parameters, usage: %s user dir\n", argv[0]); | ||||||
| 		exit(1); | 		exit(1); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if ((var=getenv("UPDATES_MAX_BYTES"))) | ||||||
|  | 		bytes_limit = atoll(var); | ||||||
|  | 	if ((var=getenv("UPDATES_MAX_FILES"))) | ||||||
|  | 		files_limit = atoll(var); | ||||||
|  | 
 | ||||||
| 	pipe(pipefds); | 	pipe(pipefds); | ||||||
| 
 | 
 | ||||||
| 	uid = prepare_creds_return_uid(argv[1]); | 	uid = prepare_creds_return_uid(argv[1]); | ||||||
| @ -73,6 +85,7 @@ int main(int argc, char ** argv) | |||||||
| 			gui_fatal("Error chroot to %s", incoming_dir); | 			gui_fatal("Error chroot to %s", incoming_dir); | ||||||
| 		setuid(uid); | 		setuid(uid); | ||||||
| 		close(pipefds[0]); | 		close(pipefds[0]); | ||||||
|  | 		set_size_limit(bytes_limit, files_limit); | ||||||
| 		do_unpack(pipefds[1]); | 		do_unpack(pipefds[1]); | ||||||
| 		exit(0); | 		exit(0); | ||||||
| 	default:; | 	default:; | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Marek Marczykowski
						Marek Marczykowski