• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2018 Google LLC
4  */
5 #define _GNU_SOURCE
6 
7 #include <alloca.h>
8 #include <dirent.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <lz4.h>
12 #include <poll.h>
13 #include <stdbool.h>
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <time.h>
19 #include <unistd.h>
20 #include <zstd.h>
21 
22 #include <sys/inotify.h>
23 #include <sys/mman.h>
24 #include <sys/mount.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <sys/xattr.h>
29 #include <sys/statvfs.h>
30 
31 #include <linux/random.h>
32 #include <linux/stat.h>
33 #include <linux/unistd.h>
34 
35 #include <openssl/pem.h>
36 #include <openssl/x509.h>
37 
38 #include <kselftest.h>
39 #include <include/uapi/linux/fsverity.h>
40 
41 #include "utils.h"
42 
43 /* Can't include uapi/linux/fs.h because it clashes with mount.h */
44 #define	FS_IOC_GETFLAGS			_IOR('f', 1, long)
45 #define FS_VERITY_FL			0x00100000 /* Verity protected inode */
46 
47 #define TEST_SKIP 2
48 #define TEST_FAILURE 1
49 #define TEST_SUCCESS 0
50 
51 #define INCFS_ROOT_INODE 0
52 
53 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
54 #define le16_to_cpu(x)          (x)
55 #define le32_to_cpu(x)          (x)
56 #define le64_to_cpu(x)          (x)
57 #else
58 #error Big endian not supported!
59 #endif
60 
61 struct {
62 	int file;
63 	int test;
64 	bool verbose;
65 } options;
66 
67 #define TESTCOND(condition)						\
68 	do {								\
69 		if (!(condition)) {					\
70 			ksft_print_msg("%s failed %d\n",		\
71 				       __func__, __LINE__);		\
72 			goto out;					\
73 		} else if (options.verbose)				\
74 			ksft_print_msg("%s succeeded %d\n",		\
75 				       __func__, __LINE__);		\
76 	} while (false)
77 
78 #define TEST(statement, condition)					\
79 	do {								\
80 		statement;						\
81 		TESTCOND(condition);					\
82 	} while (false)
83 
84 #define TESTEQUAL(statement, res)					\
85 	TESTCOND((statement) == (res))
86 
87 #define TESTNE(statement, res)					\
88 	TESTCOND((statement) != (res))
89 
90 #define TESTSYSCALL(statement)						\
91 	do {								\
92 		int res = statement;					\
93 									\
94 		if (res)						\
95 			ksft_print_msg("Failed: %s (%d)\n",		\
96 				       strerror(errno), errno);		\
97 		TESTEQUAL(res, 0);					\
98 	} while (false)
99 
print_bytes(const void * data,size_t size)100 void print_bytes(const void *data, size_t size)
101 {
102 	const uint8_t *bytes = data;
103 	int i;
104 
105 	for (i = 0; i < size; ++i) {
106 		if (i % 0x10 == 0)
107 			printf("%08x:", i);
108 		printf("%02x ", (unsigned int) bytes[i]);
109 		if (i % 0x10 == 0x0f)
110 			printf("\n");
111 	}
112 
113 	if (i % 0x10 != 0)
114 		printf("\n");
115 }
116 
117 struct hash_block {
118 	char data[INCFS_DATA_FILE_BLOCK_SIZE];
119 };
120 
121 struct test_signature {
122 	void *data;
123 	size_t size;
124 
125 	char add_data[100];
126 	size_t add_data_size;
127 };
128 
129 struct test_file {
130 	int index;
131 	incfs_uuid_t id;
132 	char *name;
133 	off_t size;
134 	char root_hash[INCFS_MAX_HASH_SIZE];
135 	struct hash_block *mtree;
136 	int mtree_block_count;
137 	struct test_signature sig;
138 	unsigned char *verity_sig;
139 	size_t verity_sig_size;
140 };
141 
142 struct test_files_set {
143 	struct test_file *files;
144 	int files_count;
145 };
146 
147 struct linux_dirent64 {
148 	uint64_t       d_ino;
149 	int64_t        d_off;
150 	unsigned short d_reclen;
151 	unsigned char  d_type;
152 	char	       d_name[0];
153 } __packed;
154 
get_test_files_set(void)155 struct test_files_set get_test_files_set(void)
156 {
157 	static struct test_file files[] = {
158 		{ .index = 0, .name = "file_one_byte", .size = 1 },
159 		{ .index = 1,
160 		  .name = "file_one_block",
161 		  .size = INCFS_DATA_FILE_BLOCK_SIZE },
162 		{ .index = 2,
163 		  .name = "file_one_and_a_half_blocks",
164 		  .size = INCFS_DATA_FILE_BLOCK_SIZE +
165 			  INCFS_DATA_FILE_BLOCK_SIZE / 2 },
166 		{ .index = 3,
167 		  .name = "file_three",
168 		  .size = 300 * INCFS_DATA_FILE_BLOCK_SIZE + 3 },
169 		{ .index = 4,
170 		  .name = "file_four",
171 		  .size = 400 * INCFS_DATA_FILE_BLOCK_SIZE + 7 },
172 		{ .index = 5,
173 		  .name = "file_five",
174 		  .size = 500 * INCFS_DATA_FILE_BLOCK_SIZE + 7 },
175 		{ .index = 6,
176 		  .name = "file_six",
177 		  .size = 600 * INCFS_DATA_FILE_BLOCK_SIZE + 7 },
178 		{ .index = 7,
179 		  .name = "file_seven",
180 		  .size = 700 * INCFS_DATA_FILE_BLOCK_SIZE + 7 },
181 		{ .index = 8,
182 		  .name = "file_eight",
183 		  .size = 800 * INCFS_DATA_FILE_BLOCK_SIZE + 7 },
184 		{ .index = 9,
185 		  .name = "file_nine",
186 		  .size = 900 * INCFS_DATA_FILE_BLOCK_SIZE + 7 },
187 		{ .index = 10, .name = "file_big", .size = 500 * 1024 * 1024 }
188 	};
189 
190 	if (options.file)
191 		return (struct test_files_set) {
192 			.files = files + options.file - 1,
193 			.files_count = 1,
194 		};
195 
196 	return (struct test_files_set){ .files = files,
197 					.files_count = ARRAY_SIZE(files) };
198 }
199 
get_small_test_files_set(void)200 struct test_files_set get_small_test_files_set(void)
201 {
202 	static struct test_file files[] = {
203 		{ .index = 0, .name = "file_one_byte", .size = 1 },
204 		{ .index = 1,
205 		  .name = "file_one_block",
206 		  .size = INCFS_DATA_FILE_BLOCK_SIZE },
207 		{ .index = 2,
208 		  .name = "file_one_and_a_half_blocks",
209 		  .size = INCFS_DATA_FILE_BLOCK_SIZE +
210 			  INCFS_DATA_FILE_BLOCK_SIZE / 2 },
211 		{ .index = 3,
212 		  .name = "file_three",
213 		  .size = 300 * INCFS_DATA_FILE_BLOCK_SIZE + 3 },
214 		{ .index = 4,
215 		  .name = "file_four",
216 		  .size = 400 * INCFS_DATA_FILE_BLOCK_SIZE + 7 }
217 	};
218 	return (struct test_files_set){ .files = files,
219 					.files_count = ARRAY_SIZE(files) };
220 }
221 
get_file_block_seed(int file,int block)222 static int get_file_block_seed(int file, int block)
223 {
224 	return 7919 * file + block;
225 }
226 
min(loff_t a,loff_t b)227 static loff_t min(loff_t a, loff_t b)
228 {
229 	return a < b ? a : b;
230 }
231 
ilog2(size_t n)232 static int ilog2(size_t n)
233 {
234 	int l = 0;
235 
236 	while (n > 1) {
237 		++l;
238 		n >>= 1;
239 	}
240 	return l;
241 }
242 
flush_and_fork(void)243 static pid_t flush_and_fork(void)
244 {
245 	fflush(stdout);
246 	return fork();
247 }
248 
print_error(char * msg)249 static void print_error(char *msg)
250 {
251 	ksft_print_msg("%s: %s\n", msg, strerror(errno));
252 }
253 
wait_for_process(pid_t pid)254 static int wait_for_process(pid_t pid)
255 {
256 	int status;
257 	int wait_res;
258 
259 	wait_res = waitpid(pid, &status, 0);
260 	if (wait_res <= 0) {
261 		print_error("Can't wait for the child");
262 		return -EINVAL;
263 	}
264 	if (!WIFEXITED(status)) {
265 		ksft_print_msg("Unexpected child status pid=%d\n", pid);
266 		return -EINVAL;
267 	}
268 	status = WEXITSTATUS(status);
269 	if (status != 0)
270 		return status;
271 	return 0;
272 }
273 
rnd_buf(uint8_t * data,size_t len,unsigned int seed)274 static void rnd_buf(uint8_t *data, size_t len, unsigned int seed)
275 {
276 	int i;
277 
278 	for (i = 0; i < len; i++) {
279 		seed = 1103515245 * seed + 12345;
280 		data[i] = (uint8_t)(seed >> (i % 13));
281 	}
282 }
283 
bin2hex(char * dst,const void * src,size_t count)284 char *bin2hex(char *dst, const void *src, size_t count)
285 {
286 	const unsigned char *_src = src;
287 	static const char hex_asc[] = "0123456789abcdef";
288 
289 	while (count--) {
290 		unsigned char x = *_src++;
291 
292 		*dst++ = hex_asc[(x & 0xf0) >> 4];
293 		*dst++ = hex_asc[(x & 0x0f)];
294 	}
295 	*dst = 0;
296 	return dst;
297 }
298 
get_index_filename(const char * mnt_dir,incfs_uuid_t id)299 static char *get_index_filename(const char *mnt_dir, incfs_uuid_t id)
300 {
301 	char path[FILENAME_MAX];
302 	char str_id[1 + 2 * sizeof(id)];
303 
304 	bin2hex(str_id, id.bytes, sizeof(id.bytes));
305 	snprintf(path, ARRAY_SIZE(path), "%s/.index/%s", mnt_dir, str_id);
306 
307 	return strdup(path);
308 }
309 
get_incomplete_filename(const char * mnt_dir,incfs_uuid_t id)310 static char *get_incomplete_filename(const char *mnt_dir, incfs_uuid_t id)
311 {
312 	char path[FILENAME_MAX];
313 	char str_id[1 + 2 * sizeof(id)];
314 
315 	bin2hex(str_id, id.bytes, sizeof(id.bytes));
316 	snprintf(path, ARRAY_SIZE(path), "%s/.incomplete/%s", mnt_dir, str_id);
317 
318 	return strdup(path);
319 }
320 
open_file_by_id(const char * mnt_dir,incfs_uuid_t id,bool use_ioctl)321 int open_file_by_id(const char *mnt_dir, incfs_uuid_t id, bool use_ioctl)
322 {
323 	char *path = get_index_filename(mnt_dir, id);
324 	int cmd_fd = open_commands_file(mnt_dir);
325 	int fd = open(path, O_RDWR | O_CLOEXEC);
326 	struct incfs_permit_fill permit_fill = {
327 		.file_descriptor = fd,
328 	};
329 	int error = 0;
330 
331 	if (fd < 0) {
332 		print_error("Can't open file by id.");
333 		error = -errno;
334 		goto out;
335 	}
336 
337 	if (use_ioctl && ioctl(cmd_fd, INCFS_IOC_PERMIT_FILL, &permit_fill)) {
338 		print_error("Failed to call PERMIT_FILL");
339 		error = -errno;
340 		goto out;
341 	}
342 
343 	if (ioctl(fd, INCFS_IOC_PERMIT_FILL, &permit_fill) != -1) {
344 		print_error(
345 			"Successfully called PERMIT_FILL on non pending_read file");
346 		return -errno;
347 		goto out;
348 	}
349 
350 out:
351 	free(path);
352 	close(cmd_fd);
353 
354 	if (error) {
355 		close(fd);
356 		return error;
357 	}
358 
359 	return fd;
360 }
361 
get_file_attr(const char * mnt_dir,incfs_uuid_t id,char * value,int size)362 int get_file_attr(const char *mnt_dir, incfs_uuid_t id, char *value, int size)
363 {
364 	char *path = get_index_filename(mnt_dir, id);
365 	int res;
366 
367 	res = getxattr(path, INCFS_XATTR_METADATA_NAME, value, size);
368 	if (res < 0)
369 		res = -errno;
370 
371 	free(path);
372 	return res;
373 }
374 
same_id(incfs_uuid_t * id1,incfs_uuid_t * id2)375 static bool same_id(incfs_uuid_t *id1, incfs_uuid_t *id2)
376 {
377 	return !memcmp(id1->bytes, id2->bytes, sizeof(id1->bytes));
378 }
379 
ZSTD_compress_default(char * data,char * comp_data,size_t data_size,size_t comp_size)380 ssize_t ZSTD_compress_default(char *data, char *comp_data, size_t data_size,
381 					size_t comp_size)
382 {
383 	return ZSTD_compress(comp_data, comp_size, data, data_size, 1);
384 }
385 
emit_test_blocks(const char * mnt_dir,struct test_file * file,int blocks[],int count)386 static int emit_test_blocks(const char *mnt_dir, struct test_file *file,
387 			int blocks[], int count)
388 {
389 	uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
390 	uint8_t comp_data[2 * INCFS_DATA_FILE_BLOCK_SIZE];
391 	int block_count = (count > 32) ? 32 : count;
392 	int data_buf_size = 2 * INCFS_DATA_FILE_BLOCK_SIZE * block_count;
393 	uint8_t *data_buf = malloc(data_buf_size);
394 	uint8_t *current_data = data_buf;
395 	uint8_t *data_end = data_buf + data_buf_size;
396 	struct incfs_fill_block *block_buf =
397 		calloc(block_count, sizeof(struct incfs_fill_block));
398 	struct incfs_fill_blocks fill_blocks = {
399 		.count = block_count,
400 		.fill_blocks = ptr_to_u64(block_buf),
401 	};
402 	ssize_t write_res = 0;
403 	int fd = -1;
404 	int error = 0;
405 	int i = 0;
406 	int blocks_written = 0;
407 
408 	for (i = 0; i < block_count; i++) {
409 		int block_index = blocks[i];
410 		bool compress_zstd = (file->index + block_index) % 4 == 2;
411 		bool compress_lz4 = (file->index + block_index) % 4 == 0;
412 		int seed = get_file_block_seed(file->index, block_index);
413 		off_t block_offset =
414 			((off_t)block_index) * INCFS_DATA_FILE_BLOCK_SIZE;
415 		size_t block_size = 0;
416 
417 		if (block_offset > file->size) {
418 			error = -EINVAL;
419 			break;
420 		}
421 		if (file->size - block_offset >
422 			INCFS_DATA_FILE_BLOCK_SIZE)
423 			block_size = INCFS_DATA_FILE_BLOCK_SIZE;
424 		else
425 			block_size = file->size - block_offset;
426 
427 		rnd_buf(data, block_size, seed);
428 		if (compress_lz4) {
429 			size_t comp_size = LZ4_compress_default((char *)data,
430 					(char *)comp_data, block_size,
431 					ARRAY_SIZE(comp_data));
432 
433 			if (comp_size <= 0) {
434 				error = -EBADMSG;
435 				break;
436 			}
437 			if (current_data + comp_size > data_end) {
438 				error = -ENOMEM;
439 				break;
440 			}
441 			memcpy(current_data, comp_data, comp_size);
442 			block_size = comp_size;
443 			block_buf[i].compression = COMPRESSION_LZ4;
444 		} else if (compress_zstd) {
445 			size_t comp_size = ZSTD_compress(comp_data,
446 					ARRAY_SIZE(comp_data), data, block_size,
447 					1);
448 
449 			if (comp_size <= 0) {
450 				error = -EBADMSG;
451 				break;
452 			}
453 			if (current_data + comp_size > data_end) {
454 				error = -ENOMEM;
455 				break;
456 			}
457 			memcpy(current_data, comp_data, comp_size);
458 			block_size = comp_size;
459 			block_buf[i].compression = COMPRESSION_ZSTD;
460 		} else {
461 			if (current_data + block_size > data_end) {
462 				error = -ENOMEM;
463 				break;
464 			}
465 			memcpy(current_data, data, block_size);
466 			block_buf[i].compression = COMPRESSION_NONE;
467 		}
468 
469 		block_buf[i].block_index = block_index;
470 		block_buf[i].data_len = block_size;
471 		block_buf[i].data = ptr_to_u64(current_data);
472 		current_data += block_size;
473 	}
474 
475 	if (!error) {
476 		fd = open_file_by_id(mnt_dir, file->id, false);
477 		if (fd < 0) {
478 			error = -errno;
479 			goto out;
480 		}
481 		write_res = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks);
482 		if (write_res >= 0) {
483 			ksft_print_msg("Wrote to file via normal fd error\n");
484 			error = -EPERM;
485 			goto out;
486 		}
487 
488 		close(fd);
489 		fd = open_file_by_id(mnt_dir, file->id, true);
490 		if (fd < 0) {
491 			error = -errno;
492 			goto out;
493 		}
494 		write_res = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks);
495 		if (write_res < 0)
496 			error = -errno;
497 		else
498 			blocks_written = write_res;
499 	}
500 	if (error) {
501 		ksft_print_msg(
502 			"Writing data block error. Write returned: %d. Error:%s\n",
503 			write_res, strerror(-error));
504 	}
505 
506 out:
507 	free(block_buf);
508 	free(data_buf);
509 	close(fd);
510 	return (error < 0) ? error : blocks_written;
511 }
512 
emit_test_block(const char * mnt_dir,struct test_file * file,int block_index)513 static int emit_test_block(const char *mnt_dir, struct test_file *file,
514 				int block_index)
515 {
516 	int res = emit_test_blocks(mnt_dir, file, &block_index, 1);
517 
518 	if (res == 0)
519 		return -EINVAL;
520 	if (res == 1)
521 		return 0;
522 	return res;
523 }
524 
shuffle(int array[],int count,unsigned int seed)525 static void shuffle(int array[], int count, unsigned int seed)
526 {
527 	int i;
528 
529 	for (i = 0; i < count - 1; i++) {
530 		int items_left = count - i;
531 		int shuffle_index;
532 		int v;
533 
534 		seed = 1103515245 * seed + 12345;
535 		shuffle_index = i + seed % items_left;
536 
537 		v = array[shuffle_index];
538 		array[shuffle_index] = array[i];
539 		array[i] = v;
540 	}
541 }
542 
emit_test_file_data(const char * mount_dir,struct test_file * file)543 static int emit_test_file_data(const char *mount_dir, struct test_file *file)
544 {
545 	int i;
546 	int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
547 	int *block_indexes = NULL;
548 	int result = 0;
549 	int blocks_written = 0;
550 
551 	if (file->size == 0)
552 		return 0;
553 
554 	block_indexes = calloc(block_cnt, sizeof(*block_indexes));
555 	for (i = 0; i < block_cnt; i++)
556 		block_indexes[i] = i;
557 	shuffle(block_indexes, block_cnt, file->index);
558 
559 	for (i = 0; i < block_cnt; i += blocks_written) {
560 		blocks_written = emit_test_blocks(mount_dir, file,
561 					block_indexes + i, block_cnt - i);
562 		if (blocks_written < 0) {
563 			result = blocks_written;
564 			goto out;
565 		}
566 		if (blocks_written == 0) {
567 			result = -EIO;
568 			goto out;
569 		}
570 	}
571 out:
572 	free(block_indexes);
573 	return result;
574 }
575 
read_whole_file(const char * filename)576 static loff_t read_whole_file(const char *filename)
577 {
578 	int fd = -1;
579 	loff_t result;
580 	loff_t bytes_read = 0;
581 	uint8_t buff[16 * 1024];
582 
583 	fd = open(filename, O_RDONLY | O_CLOEXEC);
584 	if (fd <= 0)
585 		return fd;
586 
587 	while (1) {
588 		int read_result = read(fd, buff, ARRAY_SIZE(buff));
589 
590 		if (read_result < 0) {
591 			print_error("Error during reading from a file.");
592 			result = -errno;
593 			goto cleanup;
594 		} else if (read_result == 0)
595 			break;
596 
597 		bytes_read += read_result;
598 	}
599 	result = bytes_read;
600 
601 cleanup:
602 	close(fd);
603 	return result;
604 }
605 
read_test_file(uint8_t * buf,size_t len,char * filename,int block_idx)606 static int read_test_file(uint8_t *buf, size_t len, char *filename,
607 			  int block_idx)
608 {
609 	int fd = -1;
610 	int result;
611 	int bytes_read = 0;
612 	size_t bytes_to_read = len;
613 	off_t offset = ((off_t)block_idx) * INCFS_DATA_FILE_BLOCK_SIZE;
614 
615 	fd = open(filename, O_RDONLY | O_CLOEXEC);
616 	if (fd <= 0)
617 		return fd;
618 
619 	if (lseek(fd, offset, SEEK_SET) != offset) {
620 		print_error("Seek error");
621 		return -errno;
622 	}
623 
624 	while (bytes_read < bytes_to_read) {
625 		int read_result =
626 			read(fd, buf + bytes_read, bytes_to_read - bytes_read);
627 		if (read_result < 0) {
628 			result = -errno;
629 			goto cleanup;
630 		} else if (read_result == 0)
631 			break;
632 
633 		bytes_read += read_result;
634 	}
635 	result = bytes_read;
636 
637 cleanup:
638 	close(fd);
639 	return result;
640 }
641 
create_backing_dir(const char * mount_dir)642 static char *create_backing_dir(const char *mount_dir)
643 {
644 	struct stat st;
645 	char backing_dir_name[255];
646 
647 	snprintf(backing_dir_name, ARRAY_SIZE(backing_dir_name), "%s-src",
648 		 mount_dir);
649 
650 	if (stat(backing_dir_name, &st) == 0) {
651 		if (S_ISDIR(st.st_mode)) {
652 			int error = delete_dir_tree(backing_dir_name);
653 
654 			if (error) {
655 				ksft_print_msg(
656 				      "Can't delete existing backing dir. %d\n",
657 				      error);
658 				return NULL;
659 			}
660 		} else {
661 			if (unlink(backing_dir_name)) {
662 				print_error("Can't clear backing dir");
663 				return NULL;
664 			}
665 		}
666 	}
667 
668 	if (mkdir(backing_dir_name, 0777)) {
669 		if (errno != EEXIST) {
670 			print_error("Can't open/create backing dir");
671 			return NULL;
672 		}
673 	}
674 
675 	return strdup(backing_dir_name);
676 }
677 
validate_test_file_content_with_seed(const char * mount_dir,struct test_file * file,unsigned int shuffle_seed)678 static int validate_test_file_content_with_seed(const char *mount_dir,
679 						struct test_file *file,
680 						unsigned int shuffle_seed)
681 {
682 	int error = -1;
683 	char *filename = concat_file_name(mount_dir, file->name);
684 	off_t size = file->size;
685 	loff_t actual_size = get_file_size(filename);
686 	int block_cnt = 1 + (size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
687 	int *block_indexes = NULL;
688 	int i;
689 
690 	block_indexes = alloca(sizeof(int) * block_cnt);
691 	for (i = 0; i < block_cnt; i++)
692 		block_indexes[i] = i;
693 
694 	if (shuffle_seed != 0)
695 		shuffle(block_indexes, block_cnt, shuffle_seed);
696 
697 	if (actual_size != size) {
698 		ksft_print_msg(
699 			"File size doesn't match. name: %s expected size:%ld actual size:%ld\n",
700 			filename, size, actual_size);
701 		error = -1;
702 		goto failure;
703 	}
704 
705 	for (i = 0; i < block_cnt; i++) {
706 		int block_idx = block_indexes[i];
707 		uint8_t expected_block[INCFS_DATA_FILE_BLOCK_SIZE];
708 		uint8_t actual_block[INCFS_DATA_FILE_BLOCK_SIZE];
709 		int seed = get_file_block_seed(file->index, block_idx);
710 		size_t bytes_to_compare = min(
711 			(off_t)INCFS_DATA_FILE_BLOCK_SIZE,
712 			size - ((off_t)block_idx) * INCFS_DATA_FILE_BLOCK_SIZE);
713 		int read_result =
714 			read_test_file(actual_block, INCFS_DATA_FILE_BLOCK_SIZE,
715 				       filename, block_idx);
716 		if (read_result < 0) {
717 			ksft_print_msg(
718 				"Error reading block %d from file %s. Error: %s\n",
719 				block_idx, filename, strerror(-read_result));
720 			error = read_result;
721 			goto failure;
722 		}
723 		rnd_buf(expected_block, INCFS_DATA_FILE_BLOCK_SIZE, seed);
724 		if (memcmp(expected_block, actual_block, bytes_to_compare)) {
725 			ksft_print_msg(
726 				"File contents don't match. name: %s block:%d\n",
727 				file->name, block_idx);
728 			error = -2;
729 			goto failure;
730 		}
731 	}
732 	free(filename);
733 	return 0;
734 
735 failure:
736 	free(filename);
737 	return error;
738 }
739 
validate_test_file_content(const char * mount_dir,struct test_file * file)740 static int validate_test_file_content(const char *mount_dir,
741 				      struct test_file *file)
742 {
743 	return validate_test_file_content_with_seed(mount_dir, file, 0);
744 }
745 
data_producer(const char * mount_dir,struct test_files_set * test_set)746 static int data_producer(const char *mount_dir, struct test_files_set *test_set)
747 {
748 	int ret = 0;
749 	int timeout_ms = 1000;
750 	struct incfs_pending_read_info prs[100] = {};
751 	int prs_size = ARRAY_SIZE(prs);
752 	int fd = open_commands_file(mount_dir);
753 
754 	if (fd < 0)
755 		return -errno;
756 
757 	while ((ret = wait_for_pending_reads(fd, timeout_ms, prs, prs_size)) >
758 	       0) {
759 		int read_count = ret;
760 		int i;
761 
762 		for (i = 0; i < read_count; i++) {
763 			int j = 0;
764 			struct test_file *file = NULL;
765 
766 			for (j = 0; j < test_set->files_count; j++) {
767 				bool same = same_id(&(test_set->files[j].id),
768 					&(prs[i].file_id));
769 
770 				if (same) {
771 					file = &test_set->files[j];
772 					break;
773 				}
774 			}
775 			if (!file) {
776 				ksft_print_msg(
777 					"Unknown file in pending reads.\n");
778 				break;
779 			}
780 
781 			ret = emit_test_block(mount_dir, file,
782 				prs[i].block_index);
783 			if (ret < 0) {
784 				ksft_print_msg("Emitting test data error: %s\n",
785 						strerror(-ret));
786 				break;
787 			}
788 		}
789 	}
790 	close(fd);
791 	return ret;
792 }
793 
data_producer2(const char * mount_dir,struct test_files_set * test_set)794 static int data_producer2(const char *mount_dir,
795 			  struct test_files_set *test_set)
796 {
797 	int ret = 0;
798 	int timeout_ms = 1000;
799 	struct incfs_pending_read_info2 prs[100] = {};
800 	int prs_size = ARRAY_SIZE(prs);
801 	int fd = open_commands_file(mount_dir);
802 
803 	if (fd < 0)
804 		return -errno;
805 
806 	while ((ret = wait_for_pending_reads2(fd, timeout_ms, prs, prs_size)) >
807 	       0) {
808 		int read_count = ret;
809 		int i;
810 
811 		for (i = 0; i < read_count; i++) {
812 			int j = 0;
813 			struct test_file *file = NULL;
814 
815 			for (j = 0; j < test_set->files_count; j++) {
816 				bool same = same_id(&(test_set->files[j].id),
817 					&(prs[i].file_id));
818 
819 				if (same) {
820 					file = &test_set->files[j];
821 					break;
822 				}
823 			}
824 			if (!file) {
825 				ksft_print_msg(
826 					"Unknown file in pending reads.\n");
827 				break;
828 			}
829 
830 			ret = emit_test_block(mount_dir, file,
831 				prs[i].block_index);
832 			if (ret < 0) {
833 				ksft_print_msg("Emitting test data error: %s\n",
834 						strerror(-ret));
835 				break;
836 			}
837 		}
838 	}
839 	close(fd);
840 	return ret;
841 }
842 
build_mtree(struct test_file * file)843 static int build_mtree(struct test_file *file)
844 {
845 	char data[INCFS_DATA_FILE_BLOCK_SIZE] = {};
846 	const int digest_size = SHA256_DIGEST_SIZE;
847 	const int hash_per_block = INCFS_DATA_FILE_BLOCK_SIZE / digest_size;
848 	int block_count = 0;
849 	int hash_block_count = 0;
850 	int total_tree_block_count = 0;
851 	int tree_lvl_index[INCFS_MAX_MTREE_LEVELS] = {};
852 	int tree_lvl_count[INCFS_MAX_MTREE_LEVELS] = {};
853 	int levels_count = 0;
854 	int i, level;
855 
856 	if (file->size == 0)
857 		return 0;
858 
859 	block_count = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
860 	hash_block_count = block_count;
861 	for (i = 0; hash_block_count > 1; i++) {
862 		hash_block_count = (hash_block_count + hash_per_block - 1)
863 			/ hash_per_block;
864 		tree_lvl_count[i] = hash_block_count;
865 		total_tree_block_count += hash_block_count;
866 	}
867 	levels_count = i;
868 
869 	for (i = 0; i < levels_count; i++) {
870 		int prev_lvl_base = (i == 0) ? total_tree_block_count :
871 			tree_lvl_index[i - 1];
872 
873 		tree_lvl_index[i] = prev_lvl_base - tree_lvl_count[i];
874 	}
875 
876 	file->mtree_block_count = total_tree_block_count;
877 	if (block_count == 1) {
878 		int seed = get_file_block_seed(file->index, 0);
879 
880 		memset(data, 0, INCFS_DATA_FILE_BLOCK_SIZE);
881 		rnd_buf((uint8_t *)data, file->size, seed);
882 		sha256(data, INCFS_DATA_FILE_BLOCK_SIZE, file->root_hash);
883 		return 0;
884 	}
885 
886 	file->mtree = calloc(total_tree_block_count, sizeof(*file->mtree));
887 	/* Build level 0 hashes. */
888 	for (i = 0; i < block_count; i++) {
889 		off_t offset = i * INCFS_DATA_FILE_BLOCK_SIZE;
890 		size_t block_size = INCFS_DATA_FILE_BLOCK_SIZE;
891 		int block_index = tree_lvl_index[0] +
892 					i / hash_per_block;
893 		int block_off = (i % hash_per_block) * digest_size;
894 		int seed = get_file_block_seed(file->index, i);
895 		char *hash_ptr = file->mtree[block_index].data + block_off;
896 
897 		if (file->size - offset < block_size) {
898 			block_size = file->size - offset;
899 			memset(data, 0, INCFS_DATA_FILE_BLOCK_SIZE);
900 		}
901 
902 		rnd_buf((uint8_t *)data, block_size, seed);
903 		sha256(data, INCFS_DATA_FILE_BLOCK_SIZE, hash_ptr);
904 	}
905 
906 	/* Build higher levels of hash tree. */
907 	for (level = 1; level < levels_count; level++) {
908 		int prev_lvl_base = tree_lvl_index[level - 1];
909 		int prev_lvl_count = tree_lvl_count[level - 1];
910 
911 		for (i = 0; i < prev_lvl_count; i++) {
912 			int block_index =
913 				i / hash_per_block + tree_lvl_index[level];
914 			int block_off = (i % hash_per_block) * digest_size;
915 			char *hash_ptr =
916 				file->mtree[block_index].data + block_off;
917 
918 			sha256(file->mtree[i + prev_lvl_base].data,
919 			       INCFS_DATA_FILE_BLOCK_SIZE, hash_ptr);
920 		}
921 	}
922 
923 	/* Calculate root hash from the top block */
924 	sha256(file->mtree[0].data,
925 		INCFS_DATA_FILE_BLOCK_SIZE, file->root_hash);
926 
927 	return 0;
928 }
929 
load_hash_tree(const char * mount_dir,struct test_file * file)930 static int load_hash_tree(const char *mount_dir, struct test_file *file)
931 {
932 	int err;
933 	int i;
934 	int fd;
935 	struct incfs_fill_blocks fill_blocks = {
936 		.count = file->mtree_block_count,
937 	};
938 	struct incfs_fill_block *fill_block_array =
939 		calloc(fill_blocks.count, sizeof(struct incfs_fill_block));
940 
941 	if (fill_blocks.count == 0)
942 		return 0;
943 
944 	if (!fill_block_array)
945 		return -ENOMEM;
946 	fill_blocks.fill_blocks = ptr_to_u64(fill_block_array);
947 
948 	for (i = 0; i < fill_blocks.count; i++) {
949 		fill_block_array[i] = (struct incfs_fill_block){
950 			.block_index = i,
951 			.data_len = INCFS_DATA_FILE_BLOCK_SIZE,
952 			.data = ptr_to_u64(file->mtree[i].data),
953 			.flags = INCFS_BLOCK_FLAGS_HASH
954 		};
955 	}
956 
957 	fd = open_file_by_id(mount_dir, file->id, false);
958 	if (fd < 0) {
959 		err = errno;
960 		goto failure;
961 	}
962 
963 	err = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks);
964 	close(fd);
965 	if (err >= 0) {
966 		err = -EPERM;
967 		goto failure;
968 	}
969 
970 	fd = open_file_by_id(mount_dir, file->id, true);
971 	if (fd < 0) {
972 		err = errno;
973 		goto failure;
974 	}
975 
976 	err = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks);
977 	close(fd);
978 	if (err < fill_blocks.count)
979 		err = errno;
980 	else
981 		err = 0;
982 
983 failure:
984 	free(fill_block_array);
985 	return err;
986 }
987 
cant_touch_index_test(const char * mount_dir)988 static int cant_touch_index_test(const char *mount_dir)
989 {
990 	char *file_name = "test_file";
991 	int file_size = 123;
992 	incfs_uuid_t file_id;
993 	char *index_path = concat_file_name(mount_dir, ".index");
994 	char *subdir = concat_file_name(index_path, "subdir");
995 	char *dst_name = concat_file_name(mount_dir, "something");
996 	char *filename_in_index = NULL;
997 	char *file_path = concat_file_name(mount_dir, file_name);
998 	char *backing_dir;
999 	int cmd_fd = -1;
1000 	int err;
1001 
1002 	backing_dir = create_backing_dir(mount_dir);
1003 	if (!backing_dir)
1004 		goto failure;
1005 
1006 	/* Mount FS and release the backing file. */
1007 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1008 		goto failure;
1009 	free(backing_dir);
1010 
1011 	cmd_fd = open_commands_file(mount_dir);
1012 	if (cmd_fd < 0)
1013 		goto failure;
1014 
1015 
1016 	err = mkdir(subdir, 0777);
1017 	if (err == 0 || errno != EBUSY) {
1018 		print_error("Shouldn't be able to crate subdir in index\n");
1019 		goto failure;
1020 	}
1021 
1022 	err = rmdir(index_path);
1023 	if (err == 0 || errno != EBUSY) {
1024 		print_error(".index directory should not be removed\n");
1025 		goto failure;
1026 	}
1027 
1028 	err = emit_file(cmd_fd, ".index", file_name, &file_id,
1029 				file_size, NULL);
1030 	if (err != -EBUSY) {
1031 		print_error("Shouldn't be able to crate a file in index\n");
1032 		goto failure;
1033 	}
1034 
1035 	err = emit_file(cmd_fd, NULL, file_name, &file_id,
1036 				file_size, NULL);
1037 	if (err < 0)
1038 		goto failure;
1039 	filename_in_index = get_index_filename(mount_dir, file_id);
1040 
1041 	err = unlink(filename_in_index);
1042 	if (err == 0 || errno != EBUSY) {
1043 		print_error("Shouldn't be delete from index\n");
1044 		goto failure;
1045 	}
1046 
1047 
1048 	err = rename(filename_in_index, dst_name);
1049 	if (err == 0 || errno != EBUSY) {
1050 		print_error("Shouldn't be able to move from index\n");
1051 		goto failure;
1052 	}
1053 
1054 	free(filename_in_index);
1055 	filename_in_index = concat_file_name(index_path, "abc");
1056 	err = link(file_path, filename_in_index);
1057 	if (err == 0 || errno != EBUSY) {
1058 		print_error("Shouldn't be able to link inside index\n");
1059 		goto failure;
1060 	}
1061 
1062 	err = rename(index_path, dst_name);
1063 	if (err == 0 || errno != EBUSY) {
1064 		print_error("Shouldn't rename .index directory\n");
1065 		goto failure;
1066 	}
1067 
1068 	close(cmd_fd);
1069 	free(subdir);
1070 	free(index_path);
1071 	free(dst_name);
1072 	free(filename_in_index);
1073 	if (umount(mount_dir) != 0) {
1074 		print_error("Can't unmout FS");
1075 		goto failure;
1076 	}
1077 
1078 	return TEST_SUCCESS;
1079 
1080 failure:
1081 	free(subdir);
1082 	free(dst_name);
1083 	free(index_path);
1084 	free(filename_in_index);
1085 	close(cmd_fd);
1086 	umount(mount_dir);
1087 	return TEST_FAILURE;
1088 }
1089 
iterate_directory(const char * dir_to_iterate,bool root,int file_count)1090 static bool iterate_directory(const char *dir_to_iterate, bool root,
1091 			      int file_count)
1092 {
1093 	struct expected_name {
1094 		const char *name;
1095 		bool root_only;
1096 		bool found;
1097 	} names[] = {
1098 		{INCFS_LOG_FILENAME, true, false},
1099 		{INCFS_PENDING_READS_FILENAME, true, false},
1100 		{INCFS_BLOCKS_WRITTEN_FILENAME, true, false},
1101 		{".index", true, false},
1102 		{".incomplete", true, false},
1103 		{"..", false, false},
1104 		{".", false, false},
1105 	};
1106 
1107 	bool pass = true, found;
1108 	int i;
1109 
1110 	/* Test directory iteration */
1111 	int fd = open(dir_to_iterate, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
1112 
1113 	if (fd < 0) {
1114 		print_error("Can't open directory\n");
1115 		return false;
1116 	}
1117 
1118 	for (;;) {
1119 		/* Enough space for one dirent - no name over 30 */
1120 		char buf[sizeof(struct linux_dirent64) + NAME_MAX];
1121 		struct linux_dirent64 *dirent = (struct linux_dirent64 *) buf;
1122 		int nread;
1123 		int i;
1124 
1125 		for (i = 0; i < NAME_MAX; ++i) {
1126 			nread = syscall(__NR_getdents64, fd, buf,
1127 					 sizeof(struct linux_dirent64) + i);
1128 
1129 			if (nread >= 0)
1130 				break;
1131 			if (errno != EINVAL)
1132 				break;
1133 		}
1134 
1135 		if (nread == 0)
1136 			break;
1137 		if (nread < 0) {
1138 			print_error("Error iterating directory\n");
1139 			pass = false;
1140 			goto failure;
1141 		}
1142 
1143 		/* Expected size is rounded up to 8 byte boundary. Not sure if
1144 		 * this is universal truth or just happenstance, but useful test
1145 		 * for the moment
1146 		 */
1147 		if (nread != (((sizeof(struct linux_dirent64)
1148 				+ strlen(dirent->d_name) + 1) + 7) & ~7)) {
1149 			print_error("Wrong dirent size");
1150 			pass = false;
1151 			goto failure;
1152 		}
1153 
1154 		found = false;
1155 		for (i = 0; i < sizeof(names) / sizeof(*names); ++i)
1156 			if (!strcmp(dirent->d_name, names[i].name)) {
1157 				if (names[i].root_only && !root) {
1158 					print_error("Root file error");
1159 					pass = false;
1160 					goto failure;
1161 				}
1162 
1163 				if (names[i].found) {
1164 					print_error("File appears twice");
1165 					pass = false;
1166 					goto failure;
1167 				}
1168 
1169 				names[i].found = true;
1170 				found = true;
1171 				break;
1172 			}
1173 
1174 		if (!found)
1175 			--file_count;
1176 	}
1177 
1178 	for (i = 0; i < sizeof(names) / sizeof(*names); ++i) {
1179 		if (!names[i].found)
1180 			if (root || !names[i].root_only) {
1181 				print_error("Expected file not present");
1182 				pass = false;
1183 				goto failure;
1184 			}
1185 	}
1186 
1187 	if (file_count) {
1188 		print_error("Wrong number of files\n");
1189 		pass = false;
1190 		goto failure;
1191 	}
1192 
1193 failure:
1194 	close(fd);
1195 	return pass;
1196 }
1197 
basic_file_ops_test(const char * mount_dir)1198 static int basic_file_ops_test(const char *mount_dir)
1199 {
1200 	struct test_files_set test = get_test_files_set();
1201 	const int file_num = test.files_count;
1202 	char *subdir1 = concat_file_name(mount_dir, "subdir1");
1203 	char *subdir2 = concat_file_name(mount_dir, "subdir2");
1204 	char *backing_dir;
1205 	int cmd_fd = -1;
1206 	int i, err;
1207 
1208 	backing_dir = create_backing_dir(mount_dir);
1209 	if (!backing_dir)
1210 		goto failure;
1211 
1212 	/* Mount FS and release the backing file. */
1213 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1214 		goto failure;
1215 	free(backing_dir);
1216 
1217 	cmd_fd = open_commands_file(mount_dir);
1218 	if (cmd_fd < 0)
1219 		goto failure;
1220 
1221 	err = mkdir(subdir1, 0777);
1222 	if (err < 0 && errno != EEXIST) {
1223 		print_error("Can't create subdir1\n");
1224 		goto failure;
1225 	}
1226 
1227 	err = mkdir(subdir2, 0777);
1228 	if (err < 0 && errno != EEXIST) {
1229 		print_error("Can't create subdir2\n");
1230 		goto failure;
1231 	}
1232 
1233 	/* Create all test files in subdir1 directory */
1234 	for (i = 0; i < file_num; i++) {
1235 		struct test_file *file = &test.files[i];
1236 		loff_t size;
1237 		char *file_path = concat_file_name(subdir1, file->name);
1238 
1239 		err = emit_file(cmd_fd, "subdir1", file->name, &file->id,
1240 				     file->size, NULL);
1241 		if (err < 0)
1242 			goto failure;
1243 
1244 		size = get_file_size(file_path);
1245 		free(file_path);
1246 		if (size != file->size) {
1247 			ksft_print_msg("Wrong size %lld of %s.\n",
1248 				size, file->name);
1249 			goto failure;
1250 		}
1251 	}
1252 
1253 	if (!iterate_directory(subdir1, false, file_num))
1254 		goto failure;
1255 
1256 	/* Link the files to subdir2 */
1257 	for (i = 0; i < file_num; i++) {
1258 		struct test_file *file = &test.files[i];
1259 		char *src_name = concat_file_name(subdir1, file->name);
1260 		char *dst_name = concat_file_name(subdir2, file->name);
1261 		loff_t size;
1262 
1263 		err = link(src_name, dst_name);
1264 		if (err < 0) {
1265 			print_error("Can't move file\n");
1266 			goto failure;
1267 		}
1268 
1269 		size = get_file_size(dst_name);
1270 		if (size != file->size) {
1271 			ksft_print_msg("Wrong size %lld of %s.\n",
1272 				size, file->name);
1273 			goto failure;
1274 		}
1275 		free(src_name);
1276 		free(dst_name);
1277 	}
1278 
1279 	/* Move the files from subdir2 to the mount dir */
1280 	for (i = 0; i < file_num; i++) {
1281 		struct test_file *file = &test.files[i];
1282 		char *src_name = concat_file_name(subdir2, file->name);
1283 		char *dst_name = concat_file_name(mount_dir, file->name);
1284 		loff_t size;
1285 
1286 		err = rename(src_name, dst_name);
1287 		if (err < 0) {
1288 			print_error("Can't move file\n");
1289 			goto failure;
1290 		}
1291 
1292 		size = get_file_size(dst_name);
1293 		if (size != file->size) {
1294 			ksft_print_msg("Wrong size %lld of %s.\n",
1295 				size, file->name);
1296 			goto failure;
1297 		}
1298 		free(src_name);
1299 		free(dst_name);
1300 	}
1301 
1302 	/* +2 because there are 2 subdirs */
1303 	if (!iterate_directory(mount_dir, true, file_num + 2))
1304 		goto failure;
1305 
1306 	/* Open and close all files from the mount dir */
1307 	for (i = 0; i < file_num; i++) {
1308 		struct test_file *file = &test.files[i];
1309 		char *path = concat_file_name(mount_dir, file->name);
1310 		int fd;
1311 
1312 		fd = open(path, O_RDWR | O_CLOEXEC);
1313 		free(path);
1314 		if (fd <= 0) {
1315 			print_error("Can't open file");
1316 			goto failure;
1317 		}
1318 		if (close(fd)) {
1319 			print_error("Can't close file");
1320 			goto failure;
1321 		}
1322 	}
1323 
1324 	/* Delete all files from the mount dir */
1325 	for (i = 0; i < file_num; i++) {
1326 		struct test_file *file = &test.files[i];
1327 		char *path = concat_file_name(mount_dir, file->name);
1328 
1329 		err = unlink(path);
1330 		free(path);
1331 		if (err < 0) {
1332 			print_error("Can't unlink file");
1333 			goto failure;
1334 		}
1335 	}
1336 
1337 	err = delete_dir_tree(subdir1);
1338 	if (err) {
1339 		ksft_print_msg("Error deleting subdir1 %d", err);
1340 		goto failure;
1341 	}
1342 
1343 	err = rmdir(subdir2);
1344 	if (err) {
1345 		print_error("Error deleting subdir2");
1346 		goto failure;
1347 	}
1348 
1349 	close(cmd_fd);
1350 	cmd_fd = -1;
1351 	if (umount(mount_dir) != 0) {
1352 		print_error("Can't unmout FS");
1353 		goto failure;
1354 	}
1355 
1356 	return TEST_SUCCESS;
1357 
1358 failure:
1359 	close(cmd_fd);
1360 	umount(mount_dir);
1361 	return TEST_FAILURE;
1362 }
1363 
dynamic_files_and_data_test(const char * mount_dir)1364 static int dynamic_files_and_data_test(const char *mount_dir)
1365 {
1366 	struct test_files_set test = get_test_files_set();
1367 	const int file_num = test.files_count;
1368 	const int missing_file_idx = 5;
1369 	int cmd_fd = -1;
1370 	char *backing_dir;
1371 	int i;
1372 
1373 	backing_dir = create_backing_dir(mount_dir);
1374 	if (!backing_dir)
1375 		goto failure;
1376 
1377 	/* Mount FS and release the backing file. */
1378 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1379 		goto failure;
1380 	free(backing_dir);
1381 
1382 	cmd_fd = open_commands_file(mount_dir);
1383 	if (cmd_fd < 0)
1384 		goto failure;
1385 
1386 	/* Check that test files don't exist in the filesystem. */
1387 	for (i = 0; i < file_num; i++) {
1388 		struct test_file *file = &test.files[i];
1389 		char *filename = concat_file_name(mount_dir, file->name);
1390 
1391 		if (access(filename, F_OK) != -1) {
1392 			ksft_print_msg(
1393 				"File %s somehow already exists in a clean FS.\n",
1394 				filename);
1395 			goto failure;
1396 		}
1397 		free(filename);
1398 	}
1399 
1400 	/* Write test data into the command file. */
1401 	for (i = 0; i < file_num; i++) {
1402 		struct test_file *file = &test.files[i];
1403 		int res;
1404 
1405 		res = emit_file(cmd_fd, NULL, file->name, &file->id,
1406 				     file->size, NULL);
1407 		if (res < 0) {
1408 			ksft_print_msg("Error %s emiting file %s.\n",
1409 				       strerror(-res), file->name);
1410 			goto failure;
1411 		}
1412 
1413 		/* Skip writing data to one file so we can check */
1414 		/* that it's missing later. */
1415 		if (i == missing_file_idx)
1416 			continue;
1417 
1418 		res = emit_test_file_data(mount_dir, file);
1419 		if (res) {
1420 			ksft_print_msg("Error %s emiting data for %s.\n",
1421 				       strerror(-res), file->name);
1422 			goto failure;
1423 		}
1424 	}
1425 
1426 	/* Validate contents of the FS */
1427 	for (i = 0; i < file_num; i++) {
1428 		struct test_file *file = &test.files[i];
1429 
1430 		if (i == missing_file_idx) {
1431 			/* No data has been written to this file. */
1432 			/* Check for read error; */
1433 			uint8_t buf;
1434 			char *filename =
1435 				concat_file_name(mount_dir, file->name);
1436 			int res = read_test_file(&buf, 1, filename, 0);
1437 
1438 			free(filename);
1439 			if (res > 0) {
1440 				ksft_print_msg(
1441 					"Data present, even though never writtern.\n");
1442 				goto failure;
1443 			}
1444 			if (res != -ETIME) {
1445 				ksft_print_msg("Wrong error code: %d.\n", res);
1446 				goto failure;
1447 			}
1448 		} else {
1449 			if (validate_test_file_content(mount_dir, file) < 0)
1450 				goto failure;
1451 		}
1452 	}
1453 
1454 	close(cmd_fd);
1455 	cmd_fd = -1;
1456 	if (umount(mount_dir) != 0) {
1457 		print_error("Can't unmout FS");
1458 		goto failure;
1459 	}
1460 
1461 	return TEST_SUCCESS;
1462 
1463 failure:
1464 	close(cmd_fd);
1465 	umount(mount_dir);
1466 	return TEST_FAILURE;
1467 }
1468 
concurrent_reads_and_writes_test(const char * mount_dir)1469 static int concurrent_reads_and_writes_test(const char *mount_dir)
1470 {
1471 	struct test_files_set test = get_test_files_set();
1472 	const int file_num = test.files_count;
1473 	/* Validate each file from that many child processes. */
1474 	const int child_multiplier = 3;
1475 	int cmd_fd = -1;
1476 	char *backing_dir;
1477 	int status;
1478 	int i;
1479 	pid_t producer_pid;
1480 	pid_t *child_pids = alloca(child_multiplier * file_num * sizeof(pid_t));
1481 
1482 	backing_dir = create_backing_dir(mount_dir);
1483 	if (!backing_dir)
1484 		goto failure;
1485 
1486 	/* Mount FS and release the backing file. */
1487 	if (mount_fs(mount_dir, backing_dir, 500) != 0)
1488 		goto failure;
1489 	free(backing_dir);
1490 
1491 	cmd_fd = open_commands_file(mount_dir);
1492 	if (cmd_fd < 0)
1493 		goto failure;
1494 
1495 	/* Tell FS about the files, without actually providing the data. */
1496 	for (i = 0; i < file_num; i++) {
1497 		struct test_file *file = &test.files[i];
1498 		int res;
1499 
1500 		res = emit_file(cmd_fd, NULL, file->name, &file->id,
1501 				     file->size, NULL);
1502 		if (res)
1503 			goto failure;
1504 	}
1505 
1506 	/* Start child processes acessing data in the files */
1507 	for (i = 0; i < file_num * child_multiplier; i++) {
1508 		struct test_file *file = &test.files[i / child_multiplier];
1509 		pid_t child_pid = flush_and_fork();
1510 
1511 		if (child_pid == 0) {
1512 			/* This is a child process, do the data validation. */
1513 			int ret = validate_test_file_content_with_seed(
1514 				mount_dir, file, i);
1515 			if (ret >= 0) {
1516 				/* Zero exit status if data is valid. */
1517 				exit(0);
1518 			}
1519 
1520 			/* Positive status if validation error found. */
1521 			exit(-ret);
1522 		} else if (child_pid > 0) {
1523 			child_pids[i] = child_pid;
1524 		} else {
1525 			print_error("Fork error");
1526 			goto failure;
1527 		}
1528 	}
1529 
1530 	producer_pid = flush_and_fork();
1531 	if (producer_pid == 0) {
1532 		int ret;
1533 		/*
1534 		 * This is a child that should provide data to
1535 		 * pending reads.
1536 		 */
1537 
1538 		ret = data_producer(mount_dir, &test);
1539 		exit(-ret);
1540 	} else {
1541 		status = wait_for_process(producer_pid);
1542 		if (status != 0) {
1543 			ksft_print_msg("Data produces failed. %d(%s) ", status,
1544 				       strerror(status));
1545 			goto failure;
1546 		}
1547 	}
1548 
1549 	/* Check that all children has finished with 0 exit status */
1550 	for (i = 0; i < file_num * child_multiplier; i++) {
1551 		struct test_file *file = &test.files[i / child_multiplier];
1552 
1553 		status = wait_for_process(child_pids[i]);
1554 		if (status != 0) {
1555 			ksft_print_msg(
1556 				"Validation for the file %s failed with code %d (%s)\n",
1557 				file->name, status, strerror(status));
1558 			goto failure;
1559 		}
1560 	}
1561 
1562 	/* Check that there are no pending reads left */
1563 	{
1564 		struct incfs_pending_read_info prs[1] = {};
1565 		int timeout = 0;
1566 		int read_count = wait_for_pending_reads(cmd_fd, timeout, prs,
1567 							ARRAY_SIZE(prs));
1568 
1569 		if (read_count) {
1570 			ksft_print_msg(
1571 				"Pending reads pending when all data written\n");
1572 			goto failure;
1573 		}
1574 	}
1575 
1576 	close(cmd_fd);
1577 	cmd_fd = -1;
1578 	if (umount(mount_dir) != 0) {
1579 		print_error("Can't unmout FS");
1580 		goto failure;
1581 	}
1582 
1583 	return TEST_SUCCESS;
1584 
1585 failure:
1586 	close(cmd_fd);
1587 	umount(mount_dir);
1588 	return TEST_FAILURE;
1589 }
1590 
work_after_remount_test(const char * mount_dir)1591 static int work_after_remount_test(const char *mount_dir)
1592 {
1593 	struct test_files_set test = get_test_files_set();
1594 	const int file_num = test.files_count;
1595 	const int file_num_stage1 = file_num / 2;
1596 	const int file_num_stage2 = file_num;
1597 	char *backing_dir = NULL;
1598 	int i = 0;
1599 	int cmd_fd = -1;
1600 
1601 	backing_dir = create_backing_dir(mount_dir);
1602 	if (!backing_dir)
1603 		goto failure;
1604 
1605 	/* Mount FS and release the backing file. */
1606 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1607 		goto failure;
1608 
1609 	cmd_fd = open_commands_file(mount_dir);
1610 	if (cmd_fd < 0)
1611 		goto failure;
1612 
1613 	/* Write first half of the data into the command file. (stage 1) */
1614 	for (i = 0; i < file_num_stage1; i++) {
1615 		struct test_file *file = &test.files[i];
1616 
1617 		if (emit_file(cmd_fd, NULL, file->name, &file->id,
1618 				     file->size, NULL))
1619 			goto failure;
1620 
1621 		if (emit_test_file_data(mount_dir, file))
1622 			goto failure;
1623 	}
1624 
1625 	/* Unmount and mount again, to see that data is persistent. */
1626 	close(cmd_fd);
1627 	cmd_fd = -1;
1628 	if (umount(mount_dir) != 0) {
1629 		print_error("Can't unmout FS");
1630 		goto failure;
1631 	}
1632 
1633 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1634 		goto failure;
1635 
1636 	cmd_fd = open_commands_file(mount_dir);
1637 	if (cmd_fd < 0)
1638 		goto failure;
1639 
1640 	/* Write the second half of the data into the command file. (stage 2) */
1641 	for (; i < file_num_stage2; i++) {
1642 		struct test_file *file = &test.files[i];
1643 		int res = emit_file(cmd_fd, NULL, file->name, &file->id,
1644 				     file->size, NULL);
1645 
1646 		if (res)
1647 			goto failure;
1648 
1649 		if (emit_test_file_data(mount_dir, file))
1650 			goto failure;
1651 	}
1652 
1653 	/* Validate contents of the FS */
1654 	for (i = 0; i < file_num_stage2; i++) {
1655 		struct test_file *file = &test.files[i];
1656 
1657 		if (validate_test_file_content(mount_dir, file) < 0)
1658 			goto failure;
1659 	}
1660 
1661 	/* Delete all files */
1662 	for (i = 0; i < file_num; i++) {
1663 		struct test_file *file = &test.files[i];
1664 		char *filename = concat_file_name(mount_dir, file->name);
1665 		char *filename_in_index = get_index_filename(mount_dir,
1666 							file->id);
1667 
1668 		if (access(filename, F_OK) != 0) {
1669 			ksft_print_msg("File %s is not visible.\n", filename);
1670 			goto failure;
1671 		}
1672 
1673 		if (access(filename_in_index, F_OK) != 0) {
1674 			ksft_print_msg("File %s is not visible.\n",
1675 				filename_in_index);
1676 			goto failure;
1677 		}
1678 
1679 		unlink(filename);
1680 
1681 		if (access(filename, F_OK) != -1) {
1682 			ksft_print_msg("File %s is still present.\n", filename);
1683 			goto failure;
1684 		}
1685 
1686 		if (access(filename_in_index, F_OK) != -1) {
1687 			ksft_print_msg("File %s is still present.\n",
1688 				filename_in_index);
1689 			goto failure;
1690 		}
1691 		free(filename);
1692 		free(filename_in_index);
1693 	}
1694 
1695 	/* Unmount and mount again, to see that deleted files stay deleted. */
1696 	close(cmd_fd);
1697 	cmd_fd = -1;
1698 	if (umount(mount_dir) != 0) {
1699 		print_error("Can't unmout FS");
1700 		goto failure;
1701 	}
1702 
1703 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1704 		goto failure;
1705 
1706 	cmd_fd = open_commands_file(mount_dir);
1707 	if (cmd_fd < 0)
1708 		goto failure;
1709 
1710 	/* Validate all deleted files are still deleted. */
1711 	for (i = 0; i < file_num; i++) {
1712 		struct test_file *file = &test.files[i];
1713 		char *filename = concat_file_name(mount_dir, file->name);
1714 
1715 		if (access(filename, F_OK) != -1) {
1716 			ksft_print_msg("File %s is still visible.\n", filename);
1717 			goto failure;
1718 		}
1719 		free(filename);
1720 	}
1721 
1722 	/* Final unmount */
1723 	close(cmd_fd);
1724 	free(backing_dir);
1725 	cmd_fd = -1;
1726 	if (umount(mount_dir) != 0) {
1727 		print_error("Can't unmout FS");
1728 		goto failure;
1729 	}
1730 
1731 	return TEST_SUCCESS;
1732 
1733 failure:
1734 	close(cmd_fd);
1735 	free(backing_dir);
1736 	umount(mount_dir);
1737 	return TEST_FAILURE;
1738 }
1739 
attribute_test(const char * mount_dir)1740 static int attribute_test(const char *mount_dir)
1741 {
1742 	char file_attr[] = "metadata123123";
1743 	char attr_buf[INCFS_MAX_FILE_ATTR_SIZE] = {};
1744 	int cmd_fd = -1;
1745 	incfs_uuid_t file_id;
1746 	int attr_res = 0;
1747 	char *backing_dir;
1748 
1749 
1750 	backing_dir = create_backing_dir(mount_dir);
1751 	if (!backing_dir)
1752 		goto failure;
1753 
1754 	/* Mount FS and release the backing file. */
1755 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1756 		goto failure;
1757 
1758 
1759 	cmd_fd = open_commands_file(mount_dir);
1760 	if (cmd_fd < 0)
1761 		goto failure;
1762 
1763 	if (emit_file(cmd_fd, NULL, "file", &file_id, 12, file_attr))
1764 		goto failure;
1765 
1766 	/* Test attribute values */
1767 	attr_res = get_file_attr(mount_dir, file_id, attr_buf,
1768 		ARRAY_SIZE(attr_buf));
1769 	if (attr_res != strlen(file_attr)) {
1770 		ksft_print_msg("Get file attr error: %d\n", attr_res);
1771 		goto failure;
1772 	}
1773 	if (strcmp(attr_buf, file_attr) != 0) {
1774 		ksft_print_msg("Incorrect file attr value: '%s'", attr_buf);
1775 		goto failure;
1776 	}
1777 
1778 	/* Unmount and mount again, to see that attributes are persistent. */
1779 	close(cmd_fd);
1780 	cmd_fd = -1;
1781 	if (umount(mount_dir) != 0) {
1782 		print_error("Can't unmout FS");
1783 		goto failure;
1784 	}
1785 
1786 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
1787 		goto failure;
1788 
1789 	cmd_fd = open_commands_file(mount_dir);
1790 	if (cmd_fd < 0)
1791 		goto failure;
1792 
1793 	/* Test attribute values again after remount*/
1794 	attr_res = get_file_attr(mount_dir, file_id, attr_buf,
1795 		ARRAY_SIZE(attr_buf));
1796 	if (attr_res != strlen(file_attr)) {
1797 		ksft_print_msg("Get dir attr error: %d\n", attr_res);
1798 		goto failure;
1799 	}
1800 	if (strcmp(attr_buf, file_attr) != 0) {
1801 		ksft_print_msg("Incorrect file attr value: '%s'", attr_buf);
1802 		goto failure;
1803 	}
1804 
1805 	/* Final unmount */
1806 	close(cmd_fd);
1807 	free(backing_dir);
1808 	cmd_fd = -1;
1809 	if (umount(mount_dir) != 0) {
1810 		print_error("Can't unmout FS");
1811 		goto failure;
1812 	}
1813 
1814 	return TEST_SUCCESS;
1815 
1816 failure:
1817 	close(cmd_fd);
1818 	free(backing_dir);
1819 	umount(mount_dir);
1820 	return TEST_FAILURE;
1821 }
1822 
child_procs_waiting_for_data_test(const char * mount_dir)1823 static int child_procs_waiting_for_data_test(const char *mount_dir)
1824 {
1825 	struct test_files_set test = get_test_files_set();
1826 	const int file_num = test.files_count;
1827 	int cmd_fd = -1;
1828 	int i;
1829 	pid_t *child_pids = alloca(file_num * sizeof(pid_t));
1830 	char *backing_dir;
1831 
1832 	backing_dir = create_backing_dir(mount_dir);
1833 	if (!backing_dir)
1834 		goto failure;
1835 
1836 	/* Mount FS and release the backing file.  (10s wait time) */
1837 	if (mount_fs(mount_dir, backing_dir, 10000) != 0)
1838 		goto failure;
1839 
1840 
1841 	cmd_fd = open_commands_file(mount_dir);
1842 	if (cmd_fd < 0)
1843 		goto failure;
1844 
1845 	/* Tell FS about the files, without actually providing the data. */
1846 	for (i = 0; i < file_num; i++) {
1847 		struct test_file *file = &test.files[i];
1848 
1849 		emit_file(cmd_fd, NULL, file->name, &file->id,
1850 				     file->size, NULL);
1851 	}
1852 
1853 	/* Start child processes acessing data in the files */
1854 	for (i = 0; i < file_num; i++) {
1855 		struct test_file *file = &test.files[i];
1856 		pid_t child_pid = flush_and_fork();
1857 
1858 		if (child_pid == 0) {
1859 			/* This is a child process, do the data validation. */
1860 			int ret = validate_test_file_content(mount_dir, file);
1861 
1862 			if (ret >= 0) {
1863 				/* Zero exit status if data is valid. */
1864 				exit(0);
1865 			}
1866 
1867 			/* Positive status if validation error found. */
1868 			exit(-ret);
1869 		} else if (child_pid > 0) {
1870 			child_pids[i] = child_pid;
1871 		} else {
1872 			print_error("Fork error");
1873 			goto failure;
1874 		}
1875 	}
1876 
1877 	/* Write test data into the command file. */
1878 	for (i = 0; i < file_num; i++) {
1879 		struct test_file *file = &test.files[i];
1880 
1881 		if (emit_test_file_data(mount_dir, file))
1882 			goto failure;
1883 	}
1884 
1885 	/* Check that all children has finished with 0 exit status */
1886 	for (i = 0; i < file_num; i++) {
1887 		struct test_file *file = &test.files[i];
1888 		int status = wait_for_process(child_pids[i]);
1889 
1890 		if (status != 0) {
1891 			ksft_print_msg(
1892 				"Validation for the file %s failed with code %d (%s)\n",
1893 				file->name, status, strerror(status));
1894 			goto failure;
1895 		}
1896 	}
1897 
1898 	close(cmd_fd);
1899 	free(backing_dir);
1900 	cmd_fd = -1;
1901 	if (umount(mount_dir) != 0) {
1902 		print_error("Can't unmout FS");
1903 		goto failure;
1904 	}
1905 
1906 	return TEST_SUCCESS;
1907 
1908 failure:
1909 	close(cmd_fd);
1910 	free(backing_dir);
1911 	umount(mount_dir);
1912 	return TEST_FAILURE;
1913 }
1914 
multiple_providers_test(const char * mount_dir)1915 static int multiple_providers_test(const char *mount_dir)
1916 {
1917 	struct test_files_set test = get_test_files_set();
1918 	const int file_num = test.files_count;
1919 	const int producer_count = 5;
1920 	int cmd_fd = -1;
1921 	int status;
1922 	int i;
1923 	pid_t *producer_pids = alloca(producer_count * sizeof(pid_t));
1924 	char *backing_dir;
1925 
1926 	backing_dir = create_backing_dir(mount_dir);
1927 	if (!backing_dir)
1928 		goto failure;
1929 
1930 	/* Mount FS and release the backing file.  (10s wait time) */
1931 	if (mount_fs_opt(mount_dir, backing_dir,
1932 			 "read_timeout_ms=10000,report_uid", false) != 0)
1933 		goto failure;
1934 
1935 	cmd_fd = open_commands_file(mount_dir);
1936 	if (cmd_fd < 0)
1937 		goto failure;
1938 
1939 	/* Tell FS about the files, without actually providing the data. */
1940 	for (i = 0; i < file_num; i++) {
1941 		struct test_file *file = &test.files[i];
1942 
1943 		if (emit_file(cmd_fd, NULL, file->name, &file->id,
1944 				     file->size, NULL) < 0)
1945 			goto failure;
1946 	}
1947 
1948 	/* Start producer processes */
1949 	for (i = 0; i < producer_count; i++) {
1950 		pid_t producer_pid = flush_and_fork();
1951 
1952 		if (producer_pid == 0) {
1953 			int ret;
1954 			/*
1955 			 * This is a child that should provide data to
1956 			 * pending reads.
1957 			 */
1958 
1959 			ret = data_producer2(mount_dir, &test);
1960 			exit(-ret);
1961 		} else if (producer_pid > 0) {
1962 			producer_pids[i] = producer_pid;
1963 		} else {
1964 			print_error("Fork error");
1965 			goto failure;
1966 		}
1967 	}
1968 
1969 	/* Validate FS content */
1970 	for (i = 0; i < file_num; i++) {
1971 		struct test_file *file = &test.files[i];
1972 		char *filename = concat_file_name(mount_dir, file->name);
1973 		loff_t read_result = read_whole_file(filename);
1974 
1975 		free(filename);
1976 		if (read_result != file->size) {
1977 			ksft_print_msg(
1978 				"Error validating file %s. Result: %ld\n",
1979 				file->name, read_result);
1980 			goto failure;
1981 		}
1982 	}
1983 
1984 	/* Check that all producers has finished with 0 exit status */
1985 	for (i = 0; i < producer_count; i++) {
1986 		status = wait_for_process(producer_pids[i]);
1987 		if (status != 0) {
1988 			ksft_print_msg("Producer %d failed with code (%s)\n", i,
1989 				       strerror(status));
1990 			goto failure;
1991 		}
1992 	}
1993 
1994 	close(cmd_fd);
1995 	free(backing_dir);
1996 	cmd_fd = -1;
1997 	if (umount(mount_dir) != 0) {
1998 		print_error("Can't unmout FS");
1999 		goto failure;
2000 	}
2001 
2002 	return TEST_SUCCESS;
2003 
2004 failure:
2005 	close(cmd_fd);
2006 	free(backing_dir);
2007 	umount(mount_dir);
2008 	return TEST_FAILURE;
2009 }
2010 
validate_hash_tree(const char * mount_dir,struct test_file * file)2011 static int validate_hash_tree(const char *mount_dir, struct test_file *file)
2012 {
2013 	int result = TEST_FAILURE;
2014 	char *filename = NULL;
2015 	int fd = -1;
2016 	unsigned char *buf;
2017 	int i, err;
2018 
2019 	TEST(filename = concat_file_name(mount_dir, file->name), filename);
2020 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
2021 	TEST(buf = malloc(INCFS_DATA_FILE_BLOCK_SIZE * 8), buf);
2022 
2023 	for (i = 0; i < file->mtree_block_count; ) {
2024 		int blocks_to_read = i % 7 + 1;
2025 		struct fsverity_read_metadata_arg args = {
2026 			.metadata_type = FS_VERITY_METADATA_TYPE_MERKLE_TREE,
2027 			.offset = i * INCFS_DATA_FILE_BLOCK_SIZE,
2028 			.length = blocks_to_read * INCFS_DATA_FILE_BLOCK_SIZE,
2029 			.buf_ptr = ptr_to_u64(buf),
2030 		};
2031 
2032 		TEST(err = ioctl(fd, FS_IOC_READ_VERITY_METADATA, &args),
2033 		     err == min(args.length, (file->mtree_block_count - i) *
2034 					     INCFS_DATA_FILE_BLOCK_SIZE));
2035 		TESTEQUAL(memcmp(buf, file->mtree[i].data, err), 0);
2036 
2037 		i += blocks_to_read;
2038 	}
2039 
2040 	result = TEST_SUCCESS;
2041 
2042 out:
2043 	free(buf);
2044 	close(fd);
2045 	free(filename);
2046 	return result;
2047 }
2048 
hash_tree_test(const char * mount_dir)2049 static int hash_tree_test(const char *mount_dir)
2050 {
2051 	int result = TEST_FAILURE;
2052 	char *backing_dir;
2053 	struct test_files_set test = get_test_files_set();
2054 	const int file_num = test.files_count;
2055 	const int corrupted_file_idx = 5;
2056 	int i = 0;
2057 	int cmd_fd = -1;
2058 
2059 	backing_dir = create_backing_dir(mount_dir);
2060 	if (!backing_dir)
2061 		goto failure;
2062 
2063 	/* Mount FS and release the backing file. */
2064 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
2065 		goto failure;
2066 
2067 	cmd_fd = open_commands_file(mount_dir);
2068 	if (cmd_fd < 0)
2069 		goto failure;
2070 
2071 	/* Write hashes and data. */
2072 	for (i = 0; i < file_num; i++) {
2073 		struct test_file *file = &test.files[i];
2074 		int res;
2075 
2076 		build_mtree(file);
2077 		res = crypto_emit_file(cmd_fd, NULL, file->name, &file->id,
2078 				       file->size, file->root_hash,
2079 				       file->sig.add_data);
2080 
2081 		if (i == corrupted_file_idx) {
2082 			/* Corrupt third blocks hash */
2083 			file->mtree[0].data[2 * SHA256_DIGEST_SIZE] ^= 0xff;
2084 		}
2085 		if (emit_test_file_data(mount_dir, file))
2086 			goto failure;
2087 
2088 		res = load_hash_tree(mount_dir, file);
2089 		if (res) {
2090 			ksft_print_msg("Can't load hashes for %s. error: %s\n",
2091 				file->name, strerror(-res));
2092 			goto failure;
2093 		}
2094 	}
2095 
2096 	/* Validate data */
2097 	for (i = 0; i < file_num; i++) {
2098 		struct test_file *file = &test.files[i];
2099 
2100 		if (i == corrupted_file_idx) {
2101 			uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
2102 			char *filename =
2103 				concat_file_name(mount_dir, file->name);
2104 			int res;
2105 
2106 			res = read_test_file(data, INCFS_DATA_FILE_BLOCK_SIZE,
2107 					     filename, 2);
2108 			free(filename);
2109 			if (res != -EBADMSG) {
2110 				ksft_print_msg("Hash violation missed1. %d\n",
2111 					       res);
2112 				goto failure;
2113 			}
2114 		} else if (validate_test_file_content(mount_dir, file) < 0)
2115 			goto failure;
2116 		else if (validate_hash_tree(mount_dir, file) < 0)
2117 			goto failure;
2118 	}
2119 
2120 	/* Unmount and mount again, to that hashes are persistent. */
2121 	close(cmd_fd);
2122 	cmd_fd = -1;
2123 	if (umount(mount_dir) != 0) {
2124 		print_error("Can't unmout FS");
2125 		goto failure;
2126 	}
2127 	if (mount_fs(mount_dir, backing_dir, 50) != 0)
2128 		goto failure;
2129 
2130 	cmd_fd = open_commands_file(mount_dir);
2131 	if (cmd_fd < 0)
2132 		goto failure;
2133 
2134 	/* Validate data again */
2135 	for (i = 0; i < file_num; i++) {
2136 		struct test_file *file = &test.files[i];
2137 
2138 		if (i == corrupted_file_idx) {
2139 			uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
2140 			char *filename =
2141 				concat_file_name(mount_dir, file->name);
2142 			int res;
2143 
2144 			res = read_test_file(data, INCFS_DATA_FILE_BLOCK_SIZE,
2145 					     filename, 2);
2146 			free(filename);
2147 			if (res != -EBADMSG) {
2148 				ksft_print_msg("Hash violation missed2. %d\n",
2149 					       res);
2150 				goto failure;
2151 			}
2152 		} else if (validate_test_file_content(mount_dir, file) < 0)
2153 			goto failure;
2154 	}
2155 	result = TEST_SUCCESS;
2156 
2157 failure:
2158 	for (i = 0; i < file_num; i++) {
2159 		struct test_file *file = &test.files[i];
2160 
2161 		free(file->mtree);
2162 	}
2163 
2164 	close(cmd_fd);
2165 	free(backing_dir);
2166 	umount(mount_dir);
2167 	return result;
2168 }
2169 
2170 enum expected_log { FULL_LOG, NO_LOG, PARTIAL_LOG };
2171 
validate_logs(const char * mount_dir,int log_fd,struct test_file * file,enum expected_log expected_log,bool report_uid,bool expect_data)2172 static int validate_logs(const char *mount_dir, int log_fd,
2173 			 struct test_file *file,
2174 			 enum expected_log expected_log,
2175 			 bool report_uid, bool expect_data)
2176 {
2177 	int result = TEST_FAILURE;
2178 	uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
2179 	struct incfs_pending_read_info prs[2048] = {};
2180 	struct incfs_pending_read_info2 prs2[2048] = {};
2181 	struct incfs_pending_read_info *previous_record = NULL;
2182 	int prs_size = ARRAY_SIZE(prs);
2183 	int block_count = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
2184 	int expected_read_count, read_count, block_index, read_index;
2185 	char *filename = NULL;
2186 	int fd = -1;
2187 
2188 	TEST(filename = concat_file_name(mount_dir, file->name), filename);
2189 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
2190 
2191 	if (block_count > prs_size)
2192 		block_count = prs_size;
2193 	expected_read_count = block_count;
2194 
2195 	for (block_index = 0; block_index < block_count; block_index++) {
2196 		int result = pread(fd, data, sizeof(data),
2197 			    INCFS_DATA_FILE_BLOCK_SIZE * block_index);
2198 
2199 		/* Make some read logs of type SAME_FILE_NEXT_BLOCK */
2200 		if (block_index % 100 == 10)
2201 			usleep(20000);
2202 
2203 		/* Skip some blocks to make logs of type SAME_FILE */
2204 		if (block_index % 10 == 5) {
2205 			++block_index;
2206 			--expected_read_count;
2207 		}
2208 
2209 		if (expect_data)
2210 			TESTCOND(result > 0);
2211 
2212 		if (!expect_data)
2213 			TESTEQUAL(result, -1);
2214 	}
2215 
2216 	if (report_uid)
2217 		read_count = wait_for_pending_reads2(log_fd,
2218 				expected_log == NO_LOG ? 10 : 0,
2219 				prs2, prs_size);
2220 	else
2221 		read_count = wait_for_pending_reads(log_fd,
2222 				expected_log == NO_LOG ? 10 : 0,
2223 				prs, prs_size);
2224 
2225 	if (expected_log == NO_LOG)
2226 		TESTEQUAL(read_count, 0);
2227 
2228 	if (expected_log == PARTIAL_LOG)
2229 		TESTCOND(read_count > 0 &&
2230 			 read_count <= expected_read_count);
2231 
2232 	if (expected_log == FULL_LOG)
2233 		TESTEQUAL(read_count, expected_read_count);
2234 
2235 	/* If read less than expected, advance block_index appropriately */
2236 	for (block_index = 0, read_index = 0;
2237 	     read_index < expected_read_count - read_count;
2238 	     block_index++, read_index++)
2239 		if (block_index % 10 == 5)
2240 			++block_index;
2241 
2242 	for (read_index = 0; read_index < read_count;
2243 	     block_index++, read_index++) {
2244 		struct incfs_pending_read_info *record = report_uid ?
2245 			(struct incfs_pending_read_info *) &prs2[read_index] :
2246 			&prs[read_index];
2247 
2248 		TESTCOND(same_id(&record->file_id, &file->id));
2249 		TESTEQUAL(record->block_index, block_index);
2250 		TESTNE(record->timestamp_us, 0);
2251 		if (previous_record)
2252 			TESTEQUAL(record->serial_number,
2253 				  previous_record->serial_number + 1);
2254 
2255 		previous_record = record;
2256 		if (block_index % 10 == 5)
2257 			++block_index;
2258 	}
2259 
2260 	result = TEST_SUCCESS;
2261 out:
2262 	close(fd);
2263 	free(filename);
2264 	return result;
2265 }
2266 
read_log_test(const char * mount_dir)2267 static int read_log_test(const char *mount_dir)
2268 {
2269 	int result = TEST_FAILURE;
2270 	struct test_files_set test = get_test_files_set();
2271 	const int file_num = test.files_count;
2272 	int i = 0;
2273 	int cmd_fd = -1, log_fd = -1;
2274 	char *backing_dir = NULL;
2275 
2276 	/* Create files */
2277 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
2278 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir,
2279 			       "readahead=0,report_uid,read_timeout_ms=0",
2280 				 false), 0);
2281 	TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
2282 	for (i = 0; i < file_num; i++) {
2283 		struct test_file *file = &test.files[i];
2284 
2285 		TESTEQUAL(emit_file(cmd_fd, NULL, file->name, &file->id,
2286 				    file->size, NULL), 0);
2287 	}
2288 	close(cmd_fd);
2289 	cmd_fd = -1;
2290 
2291 	/* Validate logs */
2292 	TEST(log_fd = open_log_file(mount_dir), log_fd != -1);
2293 	for (i = 0; i < file_num; i++)
2294 		TESTEQUAL(validate_logs(mount_dir, log_fd, &test.files[i],
2295 					FULL_LOG, true, false), 0);
2296 
2297 	/* Unmount and mount again without report_uid */
2298 	close(log_fd);
2299 	log_fd = -1;
2300 	TESTEQUAL(umount(mount_dir), 0);
2301 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir,
2302 			       "readahead=0,read_timeout_ms=0", false), 0);
2303 
2304 	TEST(log_fd = open_log_file(mount_dir), log_fd != -1);
2305 	for (i = 0; i < file_num; i++)
2306 		TESTEQUAL(validate_logs(mount_dir, log_fd, &test.files[i],
2307 					FULL_LOG, false, false), 0);
2308 
2309 	/* No read log to make sure poll doesn't crash */
2310 	close(log_fd);
2311 	log_fd = -1;
2312 	TESTEQUAL(umount(mount_dir), 0);
2313 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir,
2314 			       "readahead=0,rlog_pages=0,read_timeout_ms=0",
2315 			       false), 0);
2316 
2317 	TEST(log_fd = open_log_file(mount_dir), log_fd != -1);
2318 	for (i = 0; i < file_num; i++)
2319 		TESTEQUAL(validate_logs(mount_dir, log_fd, &test.files[i],
2320 					NO_LOG, false, false), 0);
2321 
2322 	/* Remount and check that logs start working again */
2323 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir,
2324 			       "readahead=0,rlog_pages=1,read_timeout_ms=0",
2325 			       true), 0);
2326 	for (i = 0; i < file_num; i++)
2327 		TESTEQUAL(validate_logs(mount_dir, log_fd, &test.files[i],
2328 					PARTIAL_LOG, false, false), 0);
2329 
2330 	/* Remount and check that logs continue working */
2331 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir,
2332 			       "readahead=0,rlog_pages=4,read_timeout_ms=0",
2333 			       true), 0);
2334 	for (i = 0; i < file_num; i++)
2335 		TESTEQUAL(validate_logs(mount_dir, log_fd, &test.files[i],
2336 					FULL_LOG, false, false), 0);
2337 
2338 	/* Check logs work with data */
2339 	for (i = 0; i < file_num; i++) {
2340 		TESTEQUAL(emit_test_file_data(mount_dir, &test.files[i]), 0);
2341 		TESTEQUAL(validate_logs(mount_dir, log_fd, &test.files[i],
2342 					FULL_LOG, false, true), 0);
2343 	}
2344 
2345 	/* Final unmount */
2346 	close(log_fd);
2347 	log_fd = -1;
2348 	TESTEQUAL(umount(mount_dir), 0);
2349 
2350 	result = TEST_SUCCESS;
2351 out:
2352 	close(cmd_fd);
2353 	close(log_fd);
2354 	free(backing_dir);
2355 	umount(mount_dir);
2356 	return result;
2357 }
2358 
emit_partial_test_file_data(const char * mount_dir,struct test_file * file)2359 static int emit_partial_test_file_data(const char *mount_dir,
2360 				       struct test_file *file)
2361 {
2362 	int i, j;
2363 	int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
2364 	int *block_indexes = NULL;
2365 	int result = 0;
2366 	int blocks_written = 0;
2367 	int bw_fd = -1;
2368 	char buffer[20];
2369 	struct pollfd pollfd;
2370 	long blocks_written_total, blocks_written_new_total;
2371 
2372 	if (file->size == 0)
2373 		return 0;
2374 
2375 	bw_fd = open_blocks_written_file(mount_dir);
2376 	if (bw_fd == -1)
2377 		return -errno;
2378 
2379 	result = read(bw_fd, buffer, sizeof(buffer));
2380 	if (result <= 0) {
2381 		result = -EIO;
2382 		goto out;
2383 	}
2384 
2385 	buffer[result] = 0;
2386 	blocks_written_total = strtol(buffer, NULL, 10);
2387 	result = 0;
2388 
2389 	pollfd = (struct pollfd) {
2390 		.fd = bw_fd,
2391 		.events = POLLIN,
2392 	};
2393 
2394 	result = poll(&pollfd, 1, 0);
2395 	if (result) {
2396 		result = -EIO;
2397 		goto out;
2398 	}
2399 
2400 	/* Emit 2 blocks, skip 2 blocks etc*/
2401 	block_indexes = calloc(block_cnt, sizeof(*block_indexes));
2402 	for (i = 0, j = 0; i < block_cnt; ++i)
2403 		if ((i & 2) == 0) {
2404 			block_indexes[j] = i;
2405 			++j;
2406 		}
2407 
2408 	for (i = 0; i < j; i += blocks_written) {
2409 		blocks_written = emit_test_blocks(mount_dir, file,
2410 						  block_indexes + i, j - i);
2411 		if (blocks_written < 0) {
2412 			result = blocks_written;
2413 			goto out;
2414 		}
2415 		if (blocks_written == 0) {
2416 			result = -EIO;
2417 			goto out;
2418 		}
2419 
2420 		result = poll(&pollfd, 1, 0);
2421 		if (result != 1 || pollfd.revents != POLLIN) {
2422 			result = -EIO;
2423 			goto out;
2424 		}
2425 
2426 		result = read(bw_fd, buffer, sizeof(buffer));
2427 		buffer[result] = 0;
2428 		blocks_written_new_total = strtol(buffer, NULL, 10);
2429 
2430 		if (blocks_written_new_total - blocks_written_total
2431 		    != blocks_written) {
2432 			result = -EIO;
2433 			goto out;
2434 		}
2435 
2436 		blocks_written_total = blocks_written_new_total;
2437 		result = 0;
2438 	}
2439 out:
2440 	free(block_indexes);
2441 	close(bw_fd);
2442 	return result;
2443 }
2444 
validate_ranges(const char * mount_dir,struct test_file * file)2445 static int validate_ranges(const char *mount_dir, struct test_file *file)
2446 {
2447 	int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
2448 	char *filename = concat_file_name(mount_dir, file->name);
2449 	int fd;
2450 	struct incfs_filled_range ranges[128];
2451 	struct incfs_get_filled_blocks_args fba = {
2452 		.range_buffer = ptr_to_u64(ranges),
2453 		.range_buffer_size = sizeof(ranges),
2454 	};
2455 	int error = TEST_SUCCESS;
2456 	int i;
2457 	int range_cnt;
2458 	int cmd_fd = -1;
2459 	struct incfs_permit_fill permit_fill;
2460 
2461 	fd = open(filename, O_RDONLY | O_CLOEXEC);
2462 	free(filename);
2463 	if (fd <= 0)
2464 		return TEST_FAILURE;
2465 
2466 	error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba);
2467 	if (error != -1 || errno != EPERM) {
2468 		ksft_print_msg("INCFS_IOC_GET_FILLED_BLOCKS not blocked\n");
2469 		error = -EPERM;
2470 		goto out;
2471 	}
2472 
2473 	cmd_fd = open_commands_file(mount_dir);
2474 	permit_fill.file_descriptor = fd;
2475 	if (ioctl(cmd_fd, INCFS_IOC_PERMIT_FILL, &permit_fill)) {
2476 		print_error("INCFS_IOC_PERMIT_FILL failed");
2477 		return -EPERM;
2478 		goto out;
2479 	}
2480 
2481 	error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba);
2482 	if (error && errno != ERANGE)
2483 		goto out;
2484 
2485 	if (error && errno == ERANGE && block_cnt < 509)
2486 		goto out;
2487 
2488 	if (!error && block_cnt >= 509) {
2489 		error = -ERANGE;
2490 		goto out;
2491 	}
2492 
2493 	if (fba.total_blocks_out != block_cnt) {
2494 		error = -EINVAL;
2495 		goto out;
2496 	}
2497 
2498 	if (fba.data_blocks_out != block_cnt) {
2499 		error = -EINVAL;
2500 		goto out;
2501 	}
2502 
2503 	range_cnt = (block_cnt + 3) / 4;
2504 	if (range_cnt > 128)
2505 		range_cnt = 128;
2506 	if (range_cnt != fba.range_buffer_size_out / sizeof(*ranges)) {
2507 		error = -ERANGE;
2508 		goto out;
2509 	}
2510 
2511 	error = TEST_SUCCESS;
2512 	for (i = 0; i < fba.range_buffer_size_out / sizeof(*ranges) - 1; ++i)
2513 		if (ranges[i].begin != i * 4 || ranges[i].end != i * 4 + 2) {
2514 			error = -EINVAL;
2515 			goto out;
2516 		}
2517 
2518 	if (ranges[i].begin != i * 4 ||
2519 	    (ranges[i].end != i * 4 + 1 && ranges[i].end != i * 4 + 2)) {
2520 		error = -EINVAL;
2521 		goto out;
2522 	}
2523 
2524 	for (i = 0; i < 64; ++i) {
2525 		fba.start_index = i * 2;
2526 		fba.end_index = i * 2 + 2;
2527 		error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba);
2528 		if (error)
2529 			goto out;
2530 
2531 		if (fba.total_blocks_out != block_cnt) {
2532 			error = -EINVAL;
2533 			goto out;
2534 		}
2535 
2536 		if (fba.start_index >= block_cnt) {
2537 			if (fba.index_out != fba.start_index) {
2538 				error = -EINVAL;
2539 				goto out;
2540 			}
2541 
2542 			break;
2543 		}
2544 
2545 		if (i % 2) {
2546 			if (fba.range_buffer_size_out != 0) {
2547 				error = -EINVAL;
2548 				goto out;
2549 			}
2550 		} else {
2551 			if (fba.range_buffer_size_out != sizeof(*ranges)) {
2552 				error = -EINVAL;
2553 				goto out;
2554 			}
2555 
2556 			if (ranges[0].begin != i * 2) {
2557 				error = -EINVAL;
2558 				goto out;
2559 			}
2560 
2561 			if (ranges[0].end != i * 2 + 1 &&
2562 			    ranges[0].end != i * 2 + 2) {
2563 				error = -EINVAL;
2564 				goto out;
2565 			}
2566 		}
2567 	}
2568 
2569 out:
2570 	close(fd);
2571 	close(cmd_fd);
2572 	return error;
2573 }
2574 
get_blocks_test(const char * mount_dir)2575 static int get_blocks_test(const char *mount_dir)
2576 {
2577 	char *backing_dir;
2578 	int cmd_fd = -1;
2579 	int i;
2580 	struct test_files_set test = get_test_files_set();
2581 	const int file_num = test.files_count;
2582 
2583 	backing_dir = create_backing_dir(mount_dir);
2584 	if (!backing_dir)
2585 		goto failure;
2586 
2587 	if (mount_fs_opt(mount_dir, backing_dir, "readahead=0", false) != 0)
2588 		goto failure;
2589 
2590 	cmd_fd = open_commands_file(mount_dir);
2591 	if (cmd_fd < 0)
2592 		goto failure;
2593 
2594 	/* Write data. */
2595 	for (i = 0; i < file_num; i++) {
2596 		struct test_file *file = &test.files[i];
2597 
2598 		if (emit_file(cmd_fd, NULL, file->name, &file->id, file->size,
2599 			      NULL))
2600 			goto failure;
2601 
2602 		if (emit_partial_test_file_data(mount_dir, file))
2603 			goto failure;
2604 	}
2605 
2606 	for (i = 0; i < file_num; i++) {
2607 		struct test_file *file = &test.files[i];
2608 
2609 		if (validate_ranges(mount_dir, file))
2610 			goto failure;
2611 
2612 		/*
2613 		 * The smallest files are filled completely, so this checks that
2614 		 * the fast get_filled_blocks path is not causing issues
2615 		 */
2616 		if (validate_ranges(mount_dir, file))
2617 			goto failure;
2618 	}
2619 
2620 	close(cmd_fd);
2621 	umount(mount_dir);
2622 	free(backing_dir);
2623 	return TEST_SUCCESS;
2624 
2625 failure:
2626 	close(cmd_fd);
2627 	umount(mount_dir);
2628 	free(backing_dir);
2629 	return TEST_FAILURE;
2630 }
2631 
emit_partial_test_file_hash(const char * mount_dir,struct test_file * file)2632 static int emit_partial_test_file_hash(const char *mount_dir,
2633 				       struct test_file *file)
2634 {
2635 	int err;
2636 	int fd;
2637 	struct incfs_fill_blocks fill_blocks = {
2638 		.count = 1,
2639 	};
2640 	struct incfs_fill_block *fill_block_array =
2641 		calloc(fill_blocks.count, sizeof(struct incfs_fill_block));
2642 	uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
2643 
2644 	if (file->size <= 4096 / 32 * 4096)
2645 		return 0;
2646 
2647 	if (!fill_block_array)
2648 		return -ENOMEM;
2649 	fill_blocks.fill_blocks = ptr_to_u64(fill_block_array);
2650 
2651 	rnd_buf(data, sizeof(data), 0);
2652 
2653 	fill_block_array[0] =
2654 		(struct incfs_fill_block){ .block_index = 1,
2655 					   .data_len =
2656 						   INCFS_DATA_FILE_BLOCK_SIZE,
2657 					   .data = ptr_to_u64(data),
2658 					   .flags = INCFS_BLOCK_FLAGS_HASH };
2659 
2660 	fd = open_file_by_id(mount_dir, file->id, true);
2661 	if (fd < 0) {
2662 		err = errno;
2663 		goto failure;
2664 	}
2665 
2666 	err = ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks);
2667 	close(fd);
2668 	if (err < fill_blocks.count)
2669 		err = errno;
2670 	else
2671 		err = 0;
2672 
2673 failure:
2674 	free(fill_block_array);
2675 	return err;
2676 }
2677 
validate_hash_ranges(const char * mount_dir,struct test_file * file)2678 static int validate_hash_ranges(const char *mount_dir, struct test_file *file)
2679 {
2680 	int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE;
2681 	char *filename = concat_file_name(mount_dir, file->name);
2682 	int fd;
2683 	struct incfs_filled_range ranges[128];
2684 	struct incfs_get_filled_blocks_args fba = {
2685 		.range_buffer = ptr_to_u64(ranges),
2686 		.range_buffer_size = sizeof(ranges),
2687 	};
2688 	int error = TEST_SUCCESS;
2689 	int file_blocks = (file->size + INCFS_DATA_FILE_BLOCK_SIZE - 1) /
2690 			  INCFS_DATA_FILE_BLOCK_SIZE;
2691 	int cmd_fd = -1;
2692 	struct incfs_permit_fill permit_fill;
2693 
2694 	if (file->size <= 4096 / 32 * 4096)
2695 		return 0;
2696 
2697 	fd = open(filename, O_RDONLY | O_CLOEXEC);
2698 	free(filename);
2699 	if (fd <= 0)
2700 		return TEST_FAILURE;
2701 
2702 	error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba);
2703 	if (error != -1 || errno != EPERM) {
2704 		ksft_print_msg("INCFS_IOC_GET_FILLED_BLOCKS not blocked\n");
2705 		error = -EPERM;
2706 		goto out;
2707 	}
2708 
2709 	cmd_fd = open_commands_file(mount_dir);
2710 	permit_fill.file_descriptor = fd;
2711 	if (ioctl(cmd_fd, INCFS_IOC_PERMIT_FILL, &permit_fill)) {
2712 		print_error("INCFS_IOC_PERMIT_FILL failed");
2713 		return -EPERM;
2714 		goto out;
2715 	}
2716 
2717 	error = ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba);
2718 	if (error)
2719 		goto out;
2720 
2721 	if (fba.total_blocks_out <= block_cnt) {
2722 		error = -EINVAL;
2723 		goto out;
2724 	}
2725 
2726 	if (fba.data_blocks_out != block_cnt) {
2727 		error = -EINVAL;
2728 		goto out;
2729 	}
2730 
2731 	if (fba.range_buffer_size_out != sizeof(struct incfs_filled_range)) {
2732 		error = -EINVAL;
2733 		goto out;
2734 	}
2735 
2736 	if (ranges[0].begin != file_blocks + 1 ||
2737 	    ranges[0].end != file_blocks + 2) {
2738 		error = -EINVAL;
2739 		goto out;
2740 	}
2741 
2742 out:
2743 	close(cmd_fd);
2744 	close(fd);
2745 	return error;
2746 }
2747 
get_hash_blocks_test(const char * mount_dir)2748 static int get_hash_blocks_test(const char *mount_dir)
2749 {
2750 	char *backing_dir;
2751 	int cmd_fd = -1;
2752 	int i;
2753 	struct test_files_set test = get_test_files_set();
2754 	const int file_num = test.files_count;
2755 
2756 	backing_dir = create_backing_dir(mount_dir);
2757 	if (!backing_dir)
2758 		goto failure;
2759 
2760 	if (mount_fs_opt(mount_dir, backing_dir, "readahead=0", false) != 0)
2761 		goto failure;
2762 
2763 	cmd_fd = open_commands_file(mount_dir);
2764 	if (cmd_fd < 0)
2765 		goto failure;
2766 
2767 	for (i = 0; i < file_num; i++) {
2768 		struct test_file *file = &test.files[i];
2769 
2770 		if (crypto_emit_file(cmd_fd, NULL, file->name, &file->id,
2771 				     file->size, file->root_hash,
2772 				     file->sig.add_data))
2773 			goto failure;
2774 
2775 		if (emit_partial_test_file_hash(mount_dir, file))
2776 			goto failure;
2777 	}
2778 
2779 	for (i = 0; i < file_num; i++) {
2780 		struct test_file *file = &test.files[i];
2781 
2782 		if (validate_hash_ranges(mount_dir, file))
2783 			goto failure;
2784 	}
2785 
2786 	close(cmd_fd);
2787 	umount(mount_dir);
2788 	free(backing_dir);
2789 	return TEST_SUCCESS;
2790 
2791 failure:
2792 	close(cmd_fd);
2793 	umount(mount_dir);
2794 	free(backing_dir);
2795 	return TEST_FAILURE;
2796 }
2797 
2798 #define THREE_GB (3LL * 1024 * 1024 * 1024)
2799 #define FOUR_GB (4LL * 1024 * 1024 * 1024) /* Have 1GB of margin */
large_file_test(const char * mount_dir)2800 static int large_file_test(const char *mount_dir)
2801 {
2802 	char *backing_dir;
2803 	int cmd_fd = -1;
2804 	int i;
2805 	int result = TEST_FAILURE, ret;
2806 	uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE] = {};
2807 	int block_count = THREE_GB / INCFS_DATA_FILE_BLOCK_SIZE;
2808 	struct incfs_fill_block *block_buf =
2809 		calloc(block_count, sizeof(struct incfs_fill_block));
2810 	struct incfs_fill_blocks fill_blocks = {
2811 		.count = block_count,
2812 		.fill_blocks = ptr_to_u64(block_buf),
2813 	};
2814 	incfs_uuid_t id;
2815 	int fd = -1;
2816 	struct statvfs svfs;
2817 	unsigned long long free_disksz;
2818 
2819 	ret = statvfs(mount_dir, &svfs);
2820 	if (ret) {
2821 		ksft_print_msg("Can't get disk size. Skipping %s...\n", __func__);
2822 		return TEST_SKIP;
2823 	}
2824 
2825 	free_disksz = (unsigned long long)svfs.f_bavail * svfs.f_bsize;
2826 
2827 	if (FOUR_GB > free_disksz) {
2828 		ksft_print_msg("Not enough free disk space (%lldMB). Skipping %s...\n",
2829 				free_disksz >> 20, __func__);
2830 		return TEST_SKIP;
2831 	}
2832 
2833 	backing_dir = create_backing_dir(mount_dir);
2834 	if (!backing_dir)
2835 		goto failure;
2836 
2837 	if (mount_fs_opt(mount_dir, backing_dir, "readahead=0", false) != 0)
2838 		goto failure;
2839 
2840 	cmd_fd = open_commands_file(mount_dir);
2841 	if (cmd_fd < 0)
2842 		goto failure;
2843 
2844 	if (emit_file(cmd_fd, NULL, "very_large_file", &id,
2845 		      (uint64_t)block_count * INCFS_DATA_FILE_BLOCK_SIZE,
2846 		      NULL) < 0)
2847 		goto failure;
2848 
2849 	for (i = 0; i < block_count; i++) {
2850 		block_buf[i].compression = COMPRESSION_NONE;
2851 		block_buf[i].block_index = i;
2852 		block_buf[i].data_len = INCFS_DATA_FILE_BLOCK_SIZE;
2853 		block_buf[i].data = ptr_to_u64(data);
2854 	}
2855 
2856 	fd = open_file_by_id(mount_dir, id, true);
2857 	if (fd < 0)
2858 		goto failure;
2859 
2860 	if (ioctl(fd, INCFS_IOC_FILL_BLOCKS, &fill_blocks) != block_count)
2861 		goto failure;
2862 
2863 	if (emit_file(cmd_fd, NULL, "very_very_large_file", &id, 1LL << 40,
2864 		      NULL) < 0)
2865 		goto failure;
2866 
2867 	result = TEST_SUCCESS;
2868 
2869 failure:
2870 	close(fd);
2871 	close(cmd_fd);
2872 	unlink("very_large_file");
2873 	umount(mount_dir);
2874 	free(backing_dir);
2875 	return result;
2876 }
2877 
validate_mapped_file(const char * orig_name,const char * name,size_t size,size_t offset)2878 static int validate_mapped_file(const char *orig_name, const char *name,
2879 				size_t size, size_t offset)
2880 {
2881 	struct stat st;
2882 	int orig_fd = -1, fd = -1;
2883 	size_t block;
2884 	int result = TEST_FAILURE;
2885 
2886 	if (stat(name, &st)) {
2887 		ksft_print_msg("Failed to stat %s with error %s\n",
2888 			       name, strerror(errno));
2889 		goto failure;
2890 	}
2891 
2892 	if (size != st.st_size) {
2893 		ksft_print_msg("Mismatched file sizes for file %s - expected %llu, got %llu\n",
2894 				   name, size, st.st_size);
2895 		goto failure;
2896 	}
2897 
2898 	fd = open(name, O_RDONLY | O_CLOEXEC);
2899 	if (fd == -1) {
2900 		ksft_print_msg("Failed to open %s with error %s\n", name,
2901 			       strerror(errno));
2902 		goto failure;
2903 	}
2904 
2905 	orig_fd = open(orig_name, O_RDONLY | O_CLOEXEC);
2906 	if (orig_fd == -1) {
2907 		ksft_print_msg("Failed to open %s with error %s\n", orig_name,
2908 			       strerror(errno));
2909 		goto failure;
2910 	}
2911 
2912 	for (block = 0; block < size; block += INCFS_DATA_FILE_BLOCK_SIZE) {
2913 		uint8_t orig_data[INCFS_DATA_FILE_BLOCK_SIZE];
2914 		uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE];
2915 		ssize_t orig_read, mapped_read;
2916 
2917 		orig_read = pread(orig_fd, orig_data,
2918 				 INCFS_DATA_FILE_BLOCK_SIZE, block + offset);
2919 		mapped_read = pread(fd, data, INCFS_DATA_FILE_BLOCK_SIZE,
2920 				    block);
2921 
2922 		if (orig_read < mapped_read ||
2923 		    mapped_read != min(size - block,
2924 				       INCFS_DATA_FILE_BLOCK_SIZE)) {
2925 			ksft_print_msg("Failed to read enough data: %llu %llu %llu %lld %lld\n",
2926 				       block, size, offset, orig_read,
2927 				       mapped_read);
2928 			goto failure;
2929 		}
2930 
2931 		if (memcmp(orig_data, data, mapped_read)) {
2932 			ksft_print_msg("Data doesn't match: %llu %llu %llu %lld %lld\n",
2933 				       block, size, offset, orig_read,
2934 				       mapped_read);
2935 			goto failure;
2936 		}
2937 	}
2938 
2939 	result = TEST_SUCCESS;
2940 
2941 failure:
2942 	close(orig_fd);
2943 	close(fd);
2944 	return result;
2945 }
2946 
mapped_file_test(const char * mount_dir)2947 static int mapped_file_test(const char *mount_dir)
2948 {
2949 	char *backing_dir;
2950 	int result = TEST_FAILURE;
2951 	int cmd_fd = -1;
2952 	int i;
2953 	struct test_files_set test = get_test_files_set();
2954 	const int file_num = test.files_count;
2955 
2956 	backing_dir = create_backing_dir(mount_dir);
2957 	if (!backing_dir)
2958 		goto failure;
2959 
2960 	if (mount_fs_opt(mount_dir, backing_dir, "readahead=0", false) != 0)
2961 		goto failure;
2962 
2963 	cmd_fd = open_commands_file(mount_dir);
2964 	if (cmd_fd < 0)
2965 		goto failure;
2966 
2967 	for (i = 0; i < file_num; ++i) {
2968 		struct test_file *file = &test.files[i];
2969 		size_t blocks = file->size / INCFS_DATA_FILE_BLOCK_SIZE;
2970 		size_t mapped_offset = blocks / 4 *
2971 			INCFS_DATA_FILE_BLOCK_SIZE;
2972 		size_t mapped_size = file->size / 4 * 3 - mapped_offset;
2973 		struct incfs_create_mapped_file_args mfa;
2974 		char mapped_file_name[FILENAME_MAX];
2975 		char orig_file_path[PATH_MAX];
2976 		char mapped_file_path[PATH_MAX];
2977 
2978 		if (emit_file(cmd_fd, NULL, file->name, &file->id, file->size,
2979 					NULL) < 0)
2980 			goto failure;
2981 
2982 		if (emit_test_file_data(mount_dir, file))
2983 			goto failure;
2984 
2985 		if (snprintf(mapped_file_name, ARRAY_SIZE(mapped_file_name),
2986 					"%s.mapped", file->name) < 0)
2987 			goto failure;
2988 
2989 		mfa = (struct incfs_create_mapped_file_args) {
2990 			.size = mapped_size,
2991 			.mode = 0664,
2992 			.file_name = ptr_to_u64(mapped_file_name),
2993 			.source_file_id = file->id,
2994 			.source_offset = mapped_offset,
2995 		};
2996 
2997 		result = ioctl(cmd_fd, INCFS_IOC_CREATE_MAPPED_FILE, &mfa);
2998 		if (result) {
2999 			ksft_print_msg(
3000 				"Failed to create mapped file with error %d\n",
3001 				result);
3002 			goto failure;
3003 		}
3004 
3005 		result = snprintf(orig_file_path,
3006 				  ARRAY_SIZE(orig_file_path), "%s/%s",
3007 				  mount_dir, file->name);
3008 
3009 		if (result < 0 || result >= ARRAY_SIZE(mapped_file_path)) {
3010 			result = TEST_FAILURE;
3011 			goto failure;
3012 		}
3013 
3014 		result = snprintf(mapped_file_path,
3015 				  ARRAY_SIZE(mapped_file_path), "%s/%s",
3016 				  mount_dir, mapped_file_name);
3017 
3018 		if (result < 0 || result >= ARRAY_SIZE(mapped_file_path)) {
3019 			result = TEST_FAILURE;
3020 			goto failure;
3021 		}
3022 
3023 		result = validate_mapped_file(orig_file_path, mapped_file_path,
3024 					      mapped_size, mapped_offset);
3025 		if (result)
3026 			goto failure;
3027 	}
3028 
3029 failure:
3030 	close(cmd_fd);
3031 	umount(mount_dir);
3032 	free(backing_dir);
3033 	return result;
3034 }
3035 
3036 static const char v1_file[] = {
3037 	/* Header */
3038 	/* 0x00: Magic number */
3039 	0x49, 0x4e, 0x43, 0x46, 0x53, 0x00, 0x00, 0x00,
3040 	/* 0x08: Version */
3041 	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3042 	/* 0x10: Header size */
3043 	0x38, 0x00,
3044 	/* 0x12: Block size */
3045 	0x00, 0x10,
3046 	/* 0x14: Flags */
3047 	0x00, 0x00, 0x00, 0x00,
3048 	/* 0x18: First md offset */
3049 	0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3050 	/* 0x20: File size */
3051 	0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3052 	/* 0x28: UUID */
3053 	0x8c, 0x7d, 0xd9, 0x22, 0xad, 0x47, 0x49, 0x4f,
3054 	0xc0, 0x2c, 0x38, 0x8e, 0x12, 0xc0, 0x0e, 0xac,
3055 
3056 	/* 0x38: Attribute */
3057 	0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
3058 	0x31, 0x32, 0x33, 0x31, 0x32, 0x33,
3059 
3060 	/* Attribute md record */
3061 	/* 0x46: Type */
3062 	0x02,
3063 	/* 0x47: Size */
3064 	0x25, 0x00,
3065 	/* 0x49: CRC */
3066 	0x9a, 0xef, 0xef, 0x72,
3067 	/* 0x4d: Next md offset */
3068 	0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3069 	/* 0x55: Prev md offset */
3070 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3071 	/* 0x5d: fa_offset */
3072 	0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3073 	/* 0x65: fa_size */
3074 	0x0e, 0x00,
3075 	/* 0x67: fa_crc */
3076 	0xfb, 0x5e, 0x72, 0x89,
3077 
3078 	/* Blockmap table */
3079 	/* 0x6b: First 10-byte entry */
3080 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3081 
3082 	/* Blockmap md record */
3083 	/* 0x75: Type */
3084 	0x01,
3085 	/* 0x76: Size */
3086 	0x23, 0x00,
3087 	/* 0x78: CRC */
3088 	0x74, 0x45, 0xd3, 0xb9,
3089 	/* 0x7c: Next md offset */
3090 	0x00, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00,
3091 	/* 0x84: Prev md offset */
3092 	0x46, 0x00, 0x00, 0x00,	0x00, 0x00, 0x00, 0x00,
3093 	/* 0x8c: blockmap offset */
3094 	0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3095 	/* 0x94: blockmap count */
3096 	0x01, 0x00, 0x00, 0x00,
3097 };
3098 
compatibility_test(const char * mount_dir)3099 static int compatibility_test(const char *mount_dir)
3100 {
3101 	static const char *name = "file";
3102 	int result = TEST_FAILURE;
3103 	char *backing_dir = NULL;
3104 	char *filename = NULL;
3105 	int fd = -1;
3106 	uint64_t size = 0x0c;
3107 
3108 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
3109 	TEST(filename = concat_file_name(backing_dir, name), filename);
3110 	TEST(fd = open(filename, O_CREAT | O_WRONLY | O_CLOEXEC, 0777),
3111 	     fd != -1);
3112 	TESTEQUAL(write(fd, v1_file, sizeof(v1_file)), sizeof(v1_file));
3113 	TESTEQUAL(fsetxattr(fd, INCFS_XATTR_SIZE_NAME, &size, sizeof(size), 0),
3114 		  0);
3115 	TESTEQUAL(mount_fs(mount_dir, backing_dir, 50), 0);
3116 	free(filename);
3117 	TEST(filename = concat_file_name(mount_dir, name), filename);
3118 	close(fd);
3119 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
3120 
3121 	result = TEST_SUCCESS;
3122 out:
3123 	close(fd);
3124 	umount(mount_dir);
3125 	free(backing_dir);
3126 	free(filename);
3127 	return result;
3128 }
3129 
zero_blocks_written_count(int fd,uint32_t data_blocks_written,uint32_t hash_blocks_written)3130 static int zero_blocks_written_count(int fd, uint32_t data_blocks_written,
3131 				     uint32_t hash_blocks_written)
3132 {
3133 	int test_result = TEST_FAILURE;
3134 	uint64_t offset;
3135 	uint8_t type;
3136 	uint32_t bw;
3137 
3138 	/* Get first md record */
3139 	TESTEQUAL(pread(fd, &offset, sizeof(offset), 24), sizeof(offset));
3140 
3141 	/* Find status md record */
3142 	for (;;) {
3143 		TESTNE(offset, 0);
3144 		TESTEQUAL(pread(fd, &type, sizeof(type), le64_to_cpu(offset)),
3145 			  sizeof(type));
3146 		if (type == 4)
3147 			break;
3148 		TESTEQUAL(pread(fd, &offset, sizeof(offset),
3149 				le64_to_cpu(offset) + 7),
3150 			  sizeof(offset));
3151 	}
3152 
3153 	/* Read blocks_written */
3154 	offset = le64_to_cpu(offset);
3155 	TESTEQUAL(pread(fd, &bw, sizeof(bw), offset + 23), sizeof(bw));
3156 	TESTEQUAL(le32_to_cpu(bw), data_blocks_written);
3157 	TESTEQUAL(pread(fd, &bw, sizeof(bw), offset + 27), sizeof(bw));
3158 	TESTEQUAL(le32_to_cpu(bw), hash_blocks_written);
3159 
3160 	/* Write out zero */
3161 	bw = 0;
3162 	TESTEQUAL(pwrite(fd, &bw, sizeof(bw), offset + 23), sizeof(bw));
3163 	TESTEQUAL(pwrite(fd, &bw, sizeof(bw), offset + 27), sizeof(bw));
3164 
3165 	test_result = TEST_SUCCESS;
3166 out:
3167 	return test_result;
3168 }
3169 
validate_block_count(const char * mount_dir,const char * backing_dir,struct test_file * file,int total_data_blocks,int filled_data_blocks,int total_hash_blocks,int filled_hash_blocks)3170 static int validate_block_count(const char *mount_dir, const char *backing_dir,
3171 				struct test_file *file,
3172 				int total_data_blocks, int filled_data_blocks,
3173 				int total_hash_blocks, int filled_hash_blocks)
3174 {
3175 	char *filename = NULL;
3176 	char *backing_filename = NULL;
3177 	int fd = -1;
3178 	struct incfs_get_block_count_args bca = {};
3179 	int test_result = TEST_FAILURE;
3180 	struct incfs_filled_range ranges[128];
3181 	struct incfs_get_filled_blocks_args fba = {
3182 		.range_buffer = ptr_to_u64(ranges),
3183 		.range_buffer_size = sizeof(ranges),
3184 	};
3185 	int cmd_fd = -1;
3186 	struct incfs_permit_fill permit_fill;
3187 
3188 	TEST(filename = concat_file_name(mount_dir, file->name), filename);
3189 	TEST(backing_filename = concat_file_name(backing_dir, file->name),
3190 	     backing_filename);
3191 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
3192 
3193 	TESTEQUAL(ioctl(fd, INCFS_IOC_GET_BLOCK_COUNT, &bca), 0);
3194 	TESTEQUAL(bca.total_data_blocks_out, total_data_blocks);
3195 	TESTEQUAL(bca.filled_data_blocks_out, filled_data_blocks);
3196 	TESTEQUAL(bca.total_hash_blocks_out, total_hash_blocks);
3197 	TESTEQUAL(bca.filled_hash_blocks_out, filled_hash_blocks);
3198 
3199 	close(fd);
3200 	TESTEQUAL(umount(mount_dir), 0);
3201 	TEST(fd = open(backing_filename, O_RDWR | O_CLOEXEC), fd != -1);
3202 	TESTEQUAL(zero_blocks_written_count(fd, filled_data_blocks,
3203 					    filled_hash_blocks),
3204 		  TEST_SUCCESS);
3205 	close(fd);
3206 	fd = -1;
3207 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir, "readahead=0", false),
3208 		  0);
3209 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
3210 
3211 	TESTEQUAL(ioctl(fd, INCFS_IOC_GET_BLOCK_COUNT, &bca), 0);
3212 	TESTEQUAL(bca.total_data_blocks_out, total_data_blocks);
3213 	TESTEQUAL(bca.filled_data_blocks_out, 0);
3214 	TESTEQUAL(bca.total_hash_blocks_out, total_hash_blocks);
3215 	TESTEQUAL(bca.filled_hash_blocks_out, 0);
3216 
3217 	TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
3218 	permit_fill.file_descriptor = fd;
3219 	TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_PERMIT_FILL, &permit_fill), 0);
3220 	do {
3221 		ioctl(fd, INCFS_IOC_GET_FILLED_BLOCKS, &fba);
3222 		fba.start_index = fba.index_out + 1;
3223 	} while (fba.index_out < fba.total_blocks_out);
3224 
3225 	TESTEQUAL(ioctl(fd, INCFS_IOC_GET_BLOCK_COUNT, &bca), 0);
3226 	TESTEQUAL(bca.total_data_blocks_out, total_data_blocks);
3227 	TESTEQUAL(bca.filled_data_blocks_out, filled_data_blocks);
3228 	TESTEQUAL(bca.total_hash_blocks_out, total_hash_blocks);
3229 	TESTEQUAL(bca.filled_hash_blocks_out, filled_hash_blocks);
3230 
3231 	test_result = TEST_SUCCESS;
3232 out:
3233 	close(cmd_fd);
3234 	close(fd);
3235 	free(filename);
3236 	free(backing_filename);
3237 	return test_result;
3238 }
3239 
3240 
3241 
validate_data_block_count(const char * mount_dir,const char * backing_dir,struct test_file * file)3242 static int validate_data_block_count(const char *mount_dir,
3243 				     const char *backing_dir,
3244 				     struct test_file *file)
3245 {
3246 	const int total_data_blocks = 1 + (file->size - 1) /
3247 						INCFS_DATA_FILE_BLOCK_SIZE;
3248 	const int filled_data_blocks = (total_data_blocks + 1) / 2;
3249 
3250 	int test_result = TEST_FAILURE;
3251 	char *filename = NULL;
3252 	char *incomplete_filename = NULL;
3253 	struct stat stat_buf_incomplete, stat_buf_file;
3254 	int fd = -1;
3255 	struct incfs_get_block_count_args bca = {};
3256 	int i;
3257 
3258 	TEST(filename = concat_file_name(mount_dir, file->name), filename);
3259 	TEST(incomplete_filename = get_incomplete_filename(mount_dir, file->id),
3260 	     incomplete_filename);
3261 
3262 	TESTEQUAL(stat(filename, &stat_buf_file), 0);
3263 	TESTEQUAL(stat(incomplete_filename, &stat_buf_incomplete), 0);
3264 	TESTEQUAL(stat_buf_file.st_ino, stat_buf_incomplete.st_ino);
3265 	TESTEQUAL(stat_buf_file.st_nlink, 3);
3266 
3267 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
3268 	TESTEQUAL(ioctl(fd, INCFS_IOC_GET_BLOCK_COUNT, &bca), 0);
3269 	TESTEQUAL(bca.total_data_blocks_out, total_data_blocks);
3270 	TESTEQUAL(bca.filled_data_blocks_out, 0);
3271 	TESTEQUAL(bca.total_hash_blocks_out, 0);
3272 	TESTEQUAL(bca.filled_hash_blocks_out, 0);
3273 
3274 	for (i = 0; i < total_data_blocks; i += 2)
3275 		TESTEQUAL(emit_test_block(mount_dir, file, i), 0);
3276 
3277 	TESTEQUAL(ioctl(fd, INCFS_IOC_GET_BLOCK_COUNT, &bca), 0);
3278 	TESTEQUAL(bca.total_data_blocks_out, total_data_blocks);
3279 	TESTEQUAL(bca.filled_data_blocks_out, filled_data_blocks);
3280 	TESTEQUAL(bca.total_hash_blocks_out, 0);
3281 	TESTEQUAL(bca.filled_hash_blocks_out, 0);
3282 	close(fd);
3283 	fd = -1;
3284 
3285 	TESTEQUAL(validate_block_count(mount_dir, backing_dir, file,
3286 				       total_data_blocks, filled_data_blocks,
3287 				       0, 0),
3288 		  0);
3289 
3290 	for (i = 1; i < total_data_blocks; i += 2)
3291 		TESTEQUAL(emit_test_block(mount_dir, file, i), 0);
3292 
3293 	TESTEQUAL(stat(incomplete_filename, &stat_buf_incomplete), -1);
3294 	TESTEQUAL(errno, ENOENT);
3295 
3296 	test_result = TEST_SUCCESS;
3297 out:
3298 	close(fd);
3299 	free(incomplete_filename);
3300 	free(filename);
3301 	return test_result;
3302 }
3303 
data_block_count_test(const char * mount_dir)3304 static int data_block_count_test(const char *mount_dir)
3305 {
3306 	int result = TEST_FAILURE;
3307 	char *backing_dir;
3308 	int cmd_fd = -1;
3309 	int i;
3310 	struct test_files_set test = get_test_files_set();
3311 
3312 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
3313 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir, "readahead=0", false),
3314 		  0);
3315 
3316 	for (i = 0; i < test.files_count; ++i) {
3317 		struct test_file *file = &test.files[i];
3318 
3319 		TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
3320 		TESTEQUAL(emit_file(cmd_fd, NULL, file->name, &file->id,
3321 				    file->size,	NULL),
3322 			  0);
3323 		close(cmd_fd);
3324 		cmd_fd = -1;
3325 
3326 		TESTEQUAL(validate_data_block_count(mount_dir, backing_dir,
3327 						    file),
3328 			  0);
3329 	}
3330 
3331 	result = TEST_SUCCESS;
3332 out:
3333 	close(cmd_fd);
3334 	umount(mount_dir);
3335 	free(backing_dir);
3336 	return result;
3337 }
3338 
validate_hash_block_count(const char * mount_dir,const char * backing_dir,struct test_file * file)3339 static int validate_hash_block_count(const char *mount_dir,
3340 				     const char *backing_dir,
3341 				     struct test_file *file)
3342 {
3343 	const int digest_size = SHA256_DIGEST_SIZE;
3344 	const int hash_per_block = INCFS_DATA_FILE_BLOCK_SIZE / digest_size;
3345 	const int total_data_blocks = 1 + (file->size - 1) /
3346 					INCFS_DATA_FILE_BLOCK_SIZE;
3347 
3348 	int result = TEST_FAILURE;
3349 	int hash_layer = total_data_blocks;
3350 	int total_hash_blocks = 0;
3351 	int filled_hash_blocks;
3352 	char *filename = NULL;
3353 	int fd = -1;
3354 	struct incfs_get_block_count_args bca = {};
3355 
3356 	while (hash_layer > 1) {
3357 		hash_layer = (hash_layer + hash_per_block - 1) / hash_per_block;
3358 		total_hash_blocks += hash_layer;
3359 	}
3360 	filled_hash_blocks = total_hash_blocks > 1 ? 1 : 0;
3361 
3362 	TEST(filename = concat_file_name(mount_dir, file->name), filename);
3363 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
3364 
3365 	TESTEQUAL(ioctl(fd, INCFS_IOC_GET_BLOCK_COUNT, &bca), 0);
3366 	TESTEQUAL(bca.total_data_blocks_out, total_data_blocks);
3367 	TESTEQUAL(bca.filled_data_blocks_out, 0);
3368 	TESTEQUAL(bca.total_hash_blocks_out, total_hash_blocks);
3369 	TESTEQUAL(bca.filled_hash_blocks_out, 0);
3370 
3371 	TESTEQUAL(emit_partial_test_file_hash(mount_dir, file), 0);
3372 
3373 	TESTEQUAL(ioctl(fd, INCFS_IOC_GET_BLOCK_COUNT, &bca), 0);
3374 	TESTEQUAL(bca.total_data_blocks_out, total_data_blocks);
3375 	TESTEQUAL(bca.filled_data_blocks_out, 0);
3376 	TESTEQUAL(bca.total_hash_blocks_out, total_hash_blocks);
3377 	TESTEQUAL(bca.filled_hash_blocks_out, filled_hash_blocks);
3378 	close(fd);
3379 	fd = -1;
3380 
3381 	if (filled_hash_blocks)
3382 		TESTEQUAL(validate_block_count(mount_dir, backing_dir, file,
3383 				       total_data_blocks, 0,
3384 				       total_hash_blocks, filled_hash_blocks),
3385 		  0);
3386 
3387 	result = TEST_SUCCESS;
3388 out:
3389 	close(fd);
3390 	free(filename);
3391 	return result;
3392 }
3393 
hash_block_count_test(const char * mount_dir)3394 static int hash_block_count_test(const char *mount_dir)
3395 {
3396 	int result = TEST_FAILURE;
3397 	char *backing_dir;
3398 	int cmd_fd = -1;
3399 	int i;
3400 	struct test_files_set test = get_test_files_set();
3401 
3402 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
3403 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir, "readahead=0", false),
3404 		  0);
3405 
3406 	for (i = 0; i < test.files_count; i++) {
3407 		struct test_file *file = &test.files[i];
3408 
3409 		TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
3410 		TESTEQUAL(crypto_emit_file(cmd_fd, NULL, file->name, &file->id,
3411 				     file->size, file->root_hash,
3412 				     file->sig.add_data),
3413 			  0);
3414 		close(cmd_fd);
3415 		cmd_fd = -1;
3416 
3417 		TESTEQUAL(validate_hash_block_count(mount_dir, backing_dir,
3418 						    &test.files[i]),
3419 			  0);
3420 	}
3421 
3422 	result = TEST_SUCCESS;
3423 out:
3424 	close(cmd_fd);
3425 	umount(mount_dir);
3426 	free(backing_dir);
3427 	return result;
3428 }
3429 
is_close(struct timespec * start,int expected_ms)3430 static int is_close(struct timespec *start, int expected_ms)
3431 {
3432 	const int allowed_variance = 100;
3433 	int result = TEST_FAILURE;
3434 	struct timespec finish;
3435 	int diff;
3436 
3437 	TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &finish), 0);
3438 	diff = (finish.tv_sec - start->tv_sec) * 1000 +
3439 		(finish.tv_nsec - start->tv_nsec) / 1000000;
3440 
3441 	TESTCOND(diff >= expected_ms - allowed_variance);
3442 	TESTCOND(diff <= expected_ms + allowed_variance);
3443 	result = TEST_SUCCESS;
3444 out:
3445 	return result;
3446 }
3447 
per_uid_read_timeouts_test(const char * mount_dir)3448 static int per_uid_read_timeouts_test(const char *mount_dir)
3449 {
3450 	struct test_file file = {
3451 		.name = "file",
3452 		.size = 16 * INCFS_DATA_FILE_BLOCK_SIZE
3453 	};
3454 
3455 	int result = TEST_FAILURE;
3456 	char *backing_dir = NULL;
3457 	int pid = -1;
3458 	int cmd_fd = -1;
3459 	char *filename = NULL;
3460 	int fd = -1;
3461 	struct timespec start;
3462 	char buffer[4096];
3463 	struct incfs_per_uid_read_timeouts purt_get[1];
3464 	struct incfs_get_read_timeouts_args grt = {
3465 		ptr_to_u64(purt_get),
3466 		sizeof(purt_get)
3467 	};
3468 	struct incfs_per_uid_read_timeouts purt_set[] = {
3469 		{
3470 			.uid = 0,
3471 			.min_time_us = 1000000,
3472 			.min_pending_time_us = 2000000,
3473 			.max_pending_time_us = 3000000,
3474 		},
3475 	};
3476 	struct incfs_set_read_timeouts_args srt = {
3477 		ptr_to_u64(purt_set),
3478 		sizeof(purt_set)
3479 	};
3480 	int status;
3481 
3482 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
3483 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir,
3484 			       "read_timeout_ms=1000,readahead=0", false), 0);
3485 
3486 	TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
3487 	TESTEQUAL(emit_file(cmd_fd, NULL, file.name, &file.id, file.size,
3488 			    NULL), 0);
3489 
3490 	TEST(filename = concat_file_name(mount_dir, file.name), filename);
3491 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
3492 	TESTEQUAL(fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC), 0);
3493 
3494 	/* Default mount options read failure is 1000 */
3495 	TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
3496 	TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), -1);
3497 	TESTEQUAL(is_close(&start, 1000), 0);
3498 
3499 	grt.timeouts_array_size = 0;
3500 	TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_GET_READ_TIMEOUTS, &grt), 0);
3501 	TESTEQUAL(grt.timeouts_array_size_out, 0);
3502 
3503 	/* Set it to 3000 */
3504 	TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_SET_READ_TIMEOUTS, &srt), 0);
3505 	TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
3506 	TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), -1);
3507 	TESTEQUAL(is_close(&start, 3000), 0);
3508 	TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_GET_READ_TIMEOUTS, &grt), -1);
3509 	TESTEQUAL(errno, E2BIG);
3510 	TESTEQUAL(grt.timeouts_array_size_out, sizeof(purt_get));
3511 	grt.timeouts_array_size = sizeof(purt_get);
3512 	TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_GET_READ_TIMEOUTS, &grt), 0);
3513 	TESTEQUAL(grt.timeouts_array_size_out, sizeof(purt_get));
3514 	TESTEQUAL(purt_get[0].uid, purt_set[0].uid);
3515 	TESTEQUAL(purt_get[0].min_time_us, purt_set[0].min_time_us);
3516 	TESTEQUAL(purt_get[0].min_pending_time_us,
3517 		  purt_set[0].min_pending_time_us);
3518 	TESTEQUAL(purt_get[0].max_pending_time_us,
3519 		  purt_set[0].max_pending_time_us);
3520 
3521 	/* Still 1000 in UID 2 */
3522 	TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
3523 	TEST(pid = fork(), pid != -1);
3524 	if (pid == 0) {
3525 		TESTEQUAL(setuid(2), 0);
3526 		TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), -1);
3527 		exit(0);
3528 	}
3529 	TESTNE(wait(&status), -1);
3530 	TESTEQUAL(WEXITSTATUS(status), 0);
3531 	TESTEQUAL(is_close(&start, 1000), 0);
3532 
3533 	/* Set it to default */
3534 	purt_set[0].max_pending_time_us = UINT32_MAX;
3535 	TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_SET_READ_TIMEOUTS, &srt), 0);
3536 	TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
3537 	TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), -1);
3538 	TESTEQUAL(is_close(&start, 1000), 0);
3539 
3540 	/* Test min read time */
3541 	TESTEQUAL(emit_test_block(mount_dir, &file, 0), 0);
3542 	TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
3543 	TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), sizeof(buffer));
3544 	TESTEQUAL(is_close(&start, 1000), 0);
3545 
3546 	/* Test min pending time */
3547 	purt_set[0].uid = 2;
3548 	TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_SET_READ_TIMEOUTS, &srt), 0);
3549 	TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0);
3550 	TEST(pid = fork(), pid != -1);
3551 	if (pid == 0) {
3552 		TESTEQUAL(setuid(2), 0);
3553 		TESTEQUAL(pread(fd, buffer, sizeof(buffer), sizeof(buffer)),
3554 			  sizeof(buffer));
3555 		exit(0);
3556 	}
3557 	sleep(1);
3558 	TESTEQUAL(emit_test_block(mount_dir, &file, 1), 0);
3559 	TESTNE(wait(&status), -1);
3560 	TESTEQUAL(WEXITSTATUS(status), 0);
3561 	TESTEQUAL(is_close(&start, 2000), 0);
3562 
3563 	/* Clear timeouts */
3564 	srt.timeouts_array_size = 0;
3565 	TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_SET_READ_TIMEOUTS, &srt), 0);
3566 	grt.timeouts_array_size = 0;
3567 	TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_GET_READ_TIMEOUTS, &grt), 0);
3568 	TESTEQUAL(grt.timeouts_array_size_out, 0);
3569 
3570 	result = TEST_SUCCESS;
3571 out:
3572 	close(fd);
3573 
3574 	if (pid == 0)
3575 		exit(result);
3576 
3577 	free(filename);
3578 	close(cmd_fd);
3579 	umount(mount_dir);
3580 	free(backing_dir);
3581 	return result;
3582 }
3583 
3584 #define DIRS 3
inotify_test(const char * mount_dir)3585 static int inotify_test(const char *mount_dir)
3586 {
3587 	const char *mapped_file_name = "mapped_name";
3588 	struct test_file file = {
3589 		.name = "file",
3590 		.size = 16 * INCFS_DATA_FILE_BLOCK_SIZE
3591 	};
3592 
3593 	int result = TEST_FAILURE;
3594 	char *backing_dir = NULL, *index_dir = NULL, *incomplete_dir = NULL;
3595 	char *file_name = NULL;
3596 	int cmd_fd = -1;
3597 	int notify_fd = -1;
3598 	int wds[DIRS];
3599 	char buffer[DIRS * (sizeof(struct inotify_event) + NAME_MAX + 1)];
3600 	char *ptr = buffer;
3601 	struct inotify_event *event;
3602 	struct inotify_event *events[DIRS] = {};
3603 	const char *names[DIRS] = {};
3604 	int res;
3605 	char id[sizeof(incfs_uuid_t) * 2 + 1];
3606 	struct incfs_create_mapped_file_args mfa;
3607 
3608 	/* File creation triggers inotify events in .index and .incomplete? */
3609 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
3610 	TEST(index_dir = concat_file_name(mount_dir, ".index"), index_dir);
3611 	TEST(incomplete_dir = concat_file_name(mount_dir, ".incomplete"),
3612 	     incomplete_dir);
3613 	TESTEQUAL(mount_fs(mount_dir, backing_dir, 50), 0);
3614 	TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
3615 	TEST(notify_fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC),
3616 	     notify_fd != -1);
3617 	TEST(wds[0] = inotify_add_watch(notify_fd, mount_dir,
3618 					IN_CREATE | IN_DELETE),
3619 	     wds[0] != -1);
3620 	TEST(wds[1] = inotify_add_watch(notify_fd, index_dir,
3621 					IN_CREATE | IN_DELETE),
3622 	     wds[1] != -1);
3623 	TEST(wds[2] = inotify_add_watch(notify_fd, incomplete_dir,
3624 					IN_CREATE | IN_DELETE),
3625 	     wds[2] != -1);
3626 	TESTEQUAL(emit_file(cmd_fd, NULL, file.name, &file.id, file.size,
3627 			   NULL), 0);
3628 	TEST(res = read(notify_fd, buffer, sizeof(buffer)), res != -1);
3629 
3630 	while (ptr < buffer + res) {
3631 		int i;
3632 
3633 		event = (struct inotify_event *) ptr;
3634 		TESTCOND(ptr + sizeof(*event) <= buffer + res);
3635 		for (i = 0; i < DIRS; ++i)
3636 			if (event->wd == wds[i]) {
3637 				TESTEQUAL(events[i], NULL);
3638 				events[i] = event;
3639 				ptr += sizeof(*event);
3640 				names[i] = ptr;
3641 				ptr += events[i]->len;
3642 				TESTCOND(ptr <= buffer + res);
3643 				break;
3644 			}
3645 		TESTCOND(i < DIRS);
3646 	}
3647 
3648 	TESTNE(events[0], NULL);
3649 	TESTNE(events[1], NULL);
3650 	TESTNE(events[2], NULL);
3651 
3652 	bin2hex(id, file.id.bytes, sizeof(incfs_uuid_t));
3653 
3654 	TESTEQUAL(events[0]->mask, IN_CREATE);
3655 	TESTEQUAL(events[1]->mask, IN_CREATE);
3656 	TESTEQUAL(events[2]->mask, IN_CREATE);
3657 	TESTEQUAL(strcmp(names[0], file.name), 0);
3658 	TESTEQUAL(strcmp(names[1], id), 0);
3659 	TESTEQUAL(strcmp(names[2], id), 0);
3660 
3661 	/* Creating a mapped file triggers inotify event */
3662 	mfa = (struct incfs_create_mapped_file_args) {
3663 		.size = INCFS_DATA_FILE_BLOCK_SIZE,
3664 		.mode = 0664,
3665 		.file_name = ptr_to_u64(mapped_file_name),
3666 		.source_file_id = file.id,
3667 		.source_offset = INCFS_DATA_FILE_BLOCK_SIZE,
3668 	};
3669 
3670 	TEST(res = ioctl(cmd_fd, INCFS_IOC_CREATE_MAPPED_FILE, &mfa),
3671 	     res != -1);
3672 	TEST(res = read(notify_fd, buffer, sizeof(buffer)), res != -1);
3673 	event = (struct inotify_event *) buffer;
3674 	TESTEQUAL(event->wd, wds[0]);
3675 	TESTEQUAL(event->mask, IN_CREATE);
3676 	TESTEQUAL(strcmp(event->name, mapped_file_name), 0);
3677 
3678 	/* File completion triggers inotify event in .incomplete? */
3679 	TESTEQUAL(emit_test_file_data(mount_dir, &file), 0);
3680 	TEST(res = read(notify_fd, buffer, sizeof(buffer)), res != -1);
3681 	event = (struct inotify_event *) buffer;
3682 	TESTEQUAL(event->wd, wds[2]);
3683 	TESTEQUAL(event->mask, IN_DELETE);
3684 	TESTEQUAL(strcmp(event->name, id), 0);
3685 
3686 	/* File unlinking triggers inotify event in .index? */
3687 	TEST(file_name = concat_file_name(mount_dir, file.name), file_name);
3688 	TESTEQUAL(unlink(file_name), 0);
3689 	TEST(res = read(notify_fd, buffer, sizeof(buffer)), res != -1);
3690 	memset(events, 0, sizeof(events));
3691 	memset(names, 0, sizeof(names));
3692 	for (ptr = buffer; ptr < buffer + res;) {
3693 		event = (struct inotify_event *) ptr;
3694 		int i;
3695 
3696 		TESTCOND(ptr + sizeof(*event) <= buffer + res);
3697 		for (i = 0; i < DIRS; ++i)
3698 			if (event->wd == wds[i]) {
3699 				TESTEQUAL(events[i], NULL);
3700 				events[i] = event;
3701 				ptr += sizeof(*event);
3702 				names[i] = ptr;
3703 				ptr += events[i]->len;
3704 				TESTCOND(ptr <= buffer + res);
3705 				break;
3706 			}
3707 		TESTCOND(i < DIRS);
3708 	}
3709 
3710 	TESTNE(events[0], NULL);
3711 	TESTNE(events[1], NULL);
3712 	TESTEQUAL(events[2], NULL);
3713 
3714 	TESTEQUAL(events[0]->mask, IN_DELETE);
3715 	TESTEQUAL(events[1]->mask, IN_DELETE);
3716 	TESTEQUAL(strcmp(names[0], file.name), 0);
3717 	TESTEQUAL(strcmp(names[1], id), 0);
3718 
3719 	result = TEST_SUCCESS;
3720 out:
3721 	free(file_name);
3722 	close(notify_fd);
3723 	close(cmd_fd);
3724 	umount(mount_dir);
3725 	free(backing_dir);
3726 	free(index_dir);
3727 	free(incomplete_dir);
3728 	return result;
3729 }
3730 
create_key(void)3731 static EVP_PKEY *create_key(void)
3732 {
3733 	EVP_PKEY *pkey = NULL;
3734 	RSA *rsa = NULL;
3735 	BIGNUM *bn = NULL;
3736 
3737 	pkey = EVP_PKEY_new();
3738 	if (!pkey)
3739 		goto fail;
3740 
3741 	bn = BN_new();
3742 	BN_set_word(bn, RSA_F4);
3743 
3744 	rsa = RSA_new();
3745 	if (!rsa)
3746 		goto fail;
3747 
3748 	RSA_generate_key_ex(rsa, 4096, bn, NULL);
3749 	EVP_PKEY_assign_RSA(pkey, rsa);
3750 
3751 	BN_free(bn);
3752 	return pkey;
3753 
3754 fail:
3755 	BN_free(bn);
3756 	EVP_PKEY_free(pkey);
3757 	return NULL;
3758 }
3759 
get_cert(EVP_PKEY * key)3760 static X509 *get_cert(EVP_PKEY *key)
3761 {
3762 	X509 *x509 = NULL;
3763 	X509_NAME *name = NULL;
3764 
3765 	x509 = X509_new();
3766 	if (!x509)
3767 		return NULL;
3768 
3769 	ASN1_INTEGER_set(X509_get_serialNumber(x509), 1);
3770 	X509_gmtime_adj(X509_get_notBefore(x509), 0);
3771 	X509_gmtime_adj(X509_get_notAfter(x509), 31536000L);
3772 	X509_set_pubkey(x509, key);
3773 
3774 	name = X509_get_subject_name(x509);
3775 	X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC,
3776 		   (const unsigned char *)"US", -1, -1, 0);
3777 	X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC,
3778 		   (const unsigned char *)"CA", -1, -1, 0);
3779 	X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC,
3780 		   (const unsigned char *)"San Jose", -1, -1, 0);
3781 	X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
3782 		   (const unsigned char *)"Example", -1, -1, 0);
3783 	X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC,
3784 		   (const unsigned char *)"Org", -1, -1, 0);
3785 	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
3786 		   (const unsigned char *)"www.example.com", -1, -1, 0);
3787 	X509_set_issuer_name(x509, name);
3788 
3789 	if (!X509_sign(x509, key, EVP_sha256()))
3790 		return NULL;
3791 
3792 	return x509;
3793 }
3794 
sign(EVP_PKEY * key,X509 * cert,const char * data,size_t len,unsigned char ** sig,size_t * sig_len)3795 static int sign(EVP_PKEY *key, X509 *cert, const char *data, size_t len,
3796 		unsigned char **sig, size_t *sig_len)
3797 {
3798 	const int pkcs7_flags = PKCS7_BINARY | PKCS7_NOATTR | PKCS7_PARTIAL |
3799 			  PKCS7_DETACHED;
3800 	const EVP_MD *md = EVP_sha256();
3801 
3802 	int result = TEST_FAILURE;
3803 
3804 	BIO *bio = NULL;
3805 	PKCS7 *p7 = NULL;
3806 	unsigned char *bio_buffer;
3807 
3808 	TEST(bio = BIO_new_mem_buf(data, len), bio);
3809 	TEST(p7 = PKCS7_sign(NULL, NULL, NULL, bio, pkcs7_flags), p7);
3810 	TESTNE(PKCS7_sign_add_signer(p7, cert, key, md, pkcs7_flags), 0);
3811 	TESTEQUAL(PKCS7_final(p7, bio, pkcs7_flags), 1);
3812 	TEST(*sig_len = i2d_PKCS7(p7, NULL), *sig_len);
3813 	TEST(bio_buffer = malloc(*sig_len), bio_buffer);
3814 	*sig = bio_buffer;
3815 	TEST(*sig_len = i2d_PKCS7(p7, &bio_buffer), *sig_len);
3816 	TESTEQUAL(PKCS7_verify(p7, NULL, NULL, bio, NULL,
3817 			 pkcs7_flags | PKCS7_NOVERIFY | PKCS7_NOSIGS), 1);
3818 
3819 	result = TEST_SUCCESS;
3820 out:
3821 	PKCS7_free(p7);
3822 	BIO_free(bio);
3823 	return result;
3824 }
3825 
verity_installed(const char * mount_dir,int cmd_fd,bool * installed)3826 static int verity_installed(const char *mount_dir, int cmd_fd, bool *installed)
3827 {
3828 	int result = TEST_FAILURE;
3829 	char *filename = NULL;
3830 	int fd = -1;
3831 	struct test_file *file = &get_test_files_set().files[0];
3832 
3833 	TESTEQUAL(emit_file(cmd_fd, NULL, file->name, &file->id, file->size,
3834 			    NULL), 0);
3835 	TEST(filename = concat_file_name(mount_dir, file->name), filename);
3836 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
3837 	TESTEQUAL(ioctl(fd, FS_IOC_ENABLE_VERITY, NULL), -1);
3838 	*installed = errno != EOPNOTSUPP;
3839 
3840 	result = TEST_SUCCESS;
3841 out:
3842 	close(fd);
3843 	if (filename)
3844 		remove(filename);
3845 	free(filename);
3846 	return result;
3847 }
3848 
enable_verity(const char * mount_dir,struct test_file * file,EVP_PKEY * key,X509 * cert,bool use_signatures)3849 static int enable_verity(const char *mount_dir, struct test_file *file,
3850 			   EVP_PKEY *key, X509 *cert, bool use_signatures)
3851 {
3852 	int result = TEST_FAILURE;
3853 	char *filename = NULL;
3854 	int fd = -1;
3855 	struct fsverity_enable_arg fear = {
3856 		.version = 1,
3857 		.hash_algorithm = FS_VERITY_HASH_ALG_SHA256,
3858 		.block_size = INCFS_DATA_FILE_BLOCK_SIZE,
3859 		.sig_size = 0,
3860 		.sig_ptr = 0,
3861 	};
3862 	struct {
3863 		__u8 version;           /* must be 1 */
3864 		__u8 hash_algorithm;    /* Merkle tree hash algorithm */
3865 		__u8 log_blocksize;     /* log2 of size of data and tree blocks */
3866 		__u8 salt_size;         /* size of salt in bytes; 0 if none */
3867 		__le32 sig_size;        /* must be 0 */
3868 		__le64 data_size;       /* size of file the Merkle tree is built over */
3869 		__u8 root_hash[64];     /* Merkle tree root hash */
3870 		__u8 salt[32];          /* salt prepended to each hashed block */
3871 		__u8 __reserved[144];   /* must be 0's */
3872 	} __packed fsverity_descriptor = {
3873 		.version = 1,
3874 		.hash_algorithm = 1,
3875 		.log_blocksize = 12,
3876 		.data_size = file->size,
3877 	};
3878 	struct {
3879 		char magic[8];                  /* must be "FSVerity" */
3880 		__le16 digest_algorithm;
3881 		__le16 digest_size;
3882 		__u8 digest[32];
3883 	} __packed fsverity_signed_digest =  {
3884 		.digest_algorithm = 1,
3885 		.digest_size = 32
3886 	};
3887 	unsigned char *sig = NULL;
3888 	size_t sig_size = 0;
3889 	uint64_t flags;
3890 	struct statx statxbuf = {};
3891 
3892 	memcpy(fsverity_signed_digest.magic, "FSVerity", 8);
3893 
3894 	TEST(filename = concat_file_name(mount_dir, file->name), filename);
3895 	TESTEQUAL(syscall(__NR_statx, AT_FDCWD, filename, 0, STATX_ALL,
3896 			  &statxbuf), 0);
3897 	TESTEQUAL(statxbuf.stx_attributes_mask & STATX_ATTR_VERITY,
3898 		  STATX_ATTR_VERITY);
3899 	TESTEQUAL(statxbuf.stx_attributes & STATX_ATTR_VERITY, 0);
3900 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
3901 	TESTEQUAL(ioctl(fd, FS_IOC_GETFLAGS, &flags), 0);
3902 	TESTEQUAL(flags & FS_VERITY_FL, 0);
3903 
3904 	/* First try to enable verity with random digest */
3905 	if (key) {
3906 		TESTEQUAL(sign(key, cert, (void *)&fsverity_signed_digest,
3907 			    sizeof(fsverity_signed_digest), &sig, &sig_size),
3908 			  0);
3909 
3910 		fear.sig_size = sig_size;
3911 		fear.sig_ptr = ptr_to_u64(sig);
3912 		TESTEQUAL(ioctl(fd, FS_IOC_ENABLE_VERITY, &fear), -1);
3913 	}
3914 
3915 	/* Now try with correct digest */
3916 	memcpy(fsverity_descriptor.root_hash, file->root_hash, 32);
3917 	sha256((char *)&fsverity_descriptor, sizeof(fsverity_descriptor),
3918 	       (char *)fsverity_signed_digest.digest);
3919 
3920 	if (ioctl(fd, FS_IOC_ENABLE_VERITY, NULL) == -1 &&
3921 	    errno == EOPNOTSUPP) {
3922 		result = TEST_SUCCESS;
3923 		goto out;
3924 	}
3925 
3926 	free(sig);
3927 	sig = NULL;
3928 
3929 	if (key)
3930 		TESTEQUAL(sign(key, cert, (void *)&fsverity_signed_digest,
3931 			       sizeof(fsverity_signed_digest),
3932 			       &sig, &sig_size),
3933 		  0);
3934 
3935 	if (use_signatures) {
3936 		fear.sig_size = sig_size;
3937 		file->verity_sig_size = sig_size;
3938 		fear.sig_ptr = ptr_to_u64(sig);
3939 		file->verity_sig = sig;
3940 		sig = NULL;
3941 	} else {
3942 		fear.sig_size = 0;
3943 		fear.sig_ptr = 0;
3944 	}
3945 	TESTEQUAL(ioctl(fd, FS_IOC_ENABLE_VERITY, &fear), 0);
3946 
3947 	result = TEST_SUCCESS;
3948 out:
3949 	free(sig);
3950 	close(fd);
3951 	free(filename);
3952 	return result;
3953 }
3954 
memzero(const unsigned char * buf,size_t size)3955 static int memzero(const unsigned char *buf, size_t size)
3956 {
3957 	size_t i;
3958 
3959 	for (i = 0; i < size; ++i)
3960 		if (buf[i])
3961 			return -1;
3962 	return 0;
3963 }
3964 
validate_verity(const char * mount_dir,struct test_file * file)3965 static int validate_verity(const char *mount_dir, struct test_file *file)
3966 {
3967 	int result = TEST_FAILURE;
3968 	char *filename = concat_file_name(mount_dir, file->name);
3969 	int fd = -1;
3970 	uint64_t flags;
3971 	struct fsverity_digest *digest;
3972 	struct statx statxbuf = {};
3973 	struct fsverity_read_metadata_arg frma = {};
3974 	uint8_t *buf = NULL;
3975 	struct fsverity_descriptor desc;
3976 
3977 	TEST(digest = malloc(sizeof(struct fsverity_digest) +
3978 			     INCFS_MAX_HASH_SIZE), digest != NULL);
3979 	TEST(filename = concat_file_name(mount_dir, file->name), filename);
3980 	TESTEQUAL(syscall(__NR_statx, AT_FDCWD, filename, 0, STATX_ALL,
3981 			  &statxbuf), 0);
3982 	TESTEQUAL(statxbuf.stx_attributes & STATX_ATTR_VERITY,
3983 		  STATX_ATTR_VERITY);
3984 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
3985 	TESTEQUAL(ioctl(fd, FS_IOC_GETFLAGS, &flags), 0);
3986 	TESTEQUAL(flags & FS_VERITY_FL, FS_VERITY_FL);
3987 	digest->digest_size = INCFS_MAX_HASH_SIZE;
3988 	TESTEQUAL(ioctl(fd, FS_IOC_MEASURE_VERITY, digest), 0);
3989 	TESTEQUAL(digest->digest_algorithm, FS_VERITY_HASH_ALG_SHA256);
3990 	TESTEQUAL(digest->digest_size, 32);
3991 
3992 	if (file->verity_sig) {
3993 		TEST(buf = malloc(file->verity_sig_size), buf);
3994 		frma = (struct fsverity_read_metadata_arg) {
3995 			.metadata_type = FS_VERITY_METADATA_TYPE_SIGNATURE,
3996 			.length = file->verity_sig_size,
3997 			.buf_ptr = ptr_to_u64(buf),
3998 		};
3999 		TESTEQUAL(ioctl(fd, FS_IOC_READ_VERITY_METADATA, &frma),
4000 			  file->verity_sig_size);
4001 		TESTEQUAL(memcmp(buf, file->verity_sig, file->verity_sig_size),
4002 			  0);
4003 	} else {
4004 		frma = (struct fsverity_read_metadata_arg) {
4005 			.metadata_type = FS_VERITY_METADATA_TYPE_SIGNATURE,
4006 		};
4007 		TESTEQUAL(ioctl(fd, FS_IOC_READ_VERITY_METADATA, &frma), -1);
4008 		TESTEQUAL(errno, ENODATA);
4009 	}
4010 
4011 	frma = (struct fsverity_read_metadata_arg) {
4012 		.metadata_type = FS_VERITY_METADATA_TYPE_DESCRIPTOR,
4013 		.length = sizeof(desc),
4014 		.buf_ptr = ptr_to_u64(&desc),
4015 	};
4016 	TESTEQUAL(ioctl(fd, FS_IOC_READ_VERITY_METADATA, &frma),
4017 		  sizeof(desc));
4018 	TESTEQUAL(desc.version, 1);
4019 	TESTEQUAL(desc.hash_algorithm, FS_VERITY_HASH_ALG_SHA256);
4020 	TESTEQUAL(desc.log_blocksize, ilog2(INCFS_DATA_FILE_BLOCK_SIZE));
4021 	TESTEQUAL(desc.salt_size, 0);
4022 	TESTEQUAL(desc.__reserved_0x04, 0);
4023 	TESTEQUAL(desc.data_size, file->size);
4024 	TESTEQUAL(memcmp(desc.root_hash, file->root_hash, SHA256_DIGEST_SIZE),
4025 		  0);
4026 	TESTEQUAL(memzero(desc.root_hash + SHA256_DIGEST_SIZE,
4027 			  sizeof(desc.root_hash) - SHA256_DIGEST_SIZE), 0);
4028 	TESTEQUAL(memzero(desc.salt, sizeof(desc.salt)), 0);
4029 	TESTEQUAL(memzero(desc.__reserved, sizeof(desc.__reserved)), 0);
4030 
4031 	result = TEST_SUCCESS;
4032 out:
4033 	free(buf);
4034 	close(fd);
4035 	free(filename);
4036 	free(digest);
4037 	return result;
4038 }
4039 
verity_test_optional_sigs(const char * mount_dir,bool use_signatures)4040 static int verity_test_optional_sigs(const char *mount_dir, bool use_signatures)
4041 {
4042 	int result = TEST_FAILURE;
4043 	char *backing_dir = NULL;
4044 	bool installed;
4045 	int cmd_fd = -1;
4046 	int i;
4047 	struct test_files_set test = get_test_files_set();
4048 	const int file_num = test.files_count;
4049 	EVP_PKEY *key = NULL;
4050 	X509 *cert = NULL;
4051 	BIO *mem = NULL;
4052 	long len;
4053 	void *ptr;
4054 	FILE *proc_key_fd = NULL;
4055 	char *line = NULL;
4056 	size_t read = 0;
4057 	int key_id = -1;
4058 
4059 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
4060 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir, "readahead=0", false),
4061 		  0);
4062 	TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
4063 	TESTEQUAL(verity_installed(mount_dir, cmd_fd, &installed), 0);
4064 	if (!installed) {
4065 		result = TEST_SUCCESS;
4066 		goto out;
4067 	}
4068 	TEST(key = create_key(), key);
4069 	TEST(cert = get_cert(key), cert);
4070 
4071 	TEST(proc_key_fd = fopen("/proc/keys", "r"), proc_key_fd != NULL);
4072 	while (getline(&line, &read, proc_key_fd) != -1)
4073 		if (strstr(line, ".fs-verity"))
4074 			key_id = strtol(line, NULL, 16);
4075 
4076 	TEST(mem = BIO_new(BIO_s_mem()), mem != NULL);
4077 	TESTEQUAL(i2d_X509_bio(mem, cert), 1);
4078 	TEST(len = BIO_get_mem_data(mem, &ptr), len != 0);
4079 	TESTCOND(key_id == -1
4080 		 || syscall(__NR_add_key, "asymmetric", "test:key", ptr, len,
4081 			    key_id) != -1);
4082 
4083 	for (i = 0; i < file_num; i++) {
4084 		struct test_file *file = &test.files[i];
4085 
4086 		build_mtree(file);
4087 		TESTEQUAL(crypto_emit_file(cmd_fd, NULL, file->name, &file->id,
4088 				     file->size, file->root_hash,
4089 				     file->sig.add_data), 0);
4090 
4091 		TESTEQUAL(load_hash_tree(mount_dir, file), 0);
4092 		TESTEQUAL(enable_verity(mount_dir, file, key, cert,
4093 					use_signatures),
4094 			  0);
4095 	}
4096 
4097 	for (i = 0; i < file_num; i++)
4098 		TESTEQUAL(validate_verity(mount_dir, &test.files[i]), 0);
4099 
4100 	close(cmd_fd);
4101 	cmd_fd = -1;
4102 	TESTEQUAL(umount(mount_dir), 0);
4103 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir, "readahead=0", false),
4104 		  0);
4105 
4106 	for (i = 0; i < file_num; i++)
4107 		TESTEQUAL(validate_verity(mount_dir, &test.files[i]), 0);
4108 
4109 	result = TEST_SUCCESS;
4110 out:
4111 	for (i = 0; i < file_num; i++) {
4112 		struct test_file *file = &test.files[i];
4113 
4114 		free(file->mtree);
4115 		free(file->verity_sig);
4116 
4117 		file->mtree = NULL;
4118 		file->verity_sig = NULL;
4119 	}
4120 
4121 	free(line);
4122 	BIO_free(mem);
4123 	X509_free(cert);
4124 	EVP_PKEY_free(key);
4125 	fclose(proc_key_fd);
4126 	close(cmd_fd);
4127 	umount(mount_dir);
4128 	free(backing_dir);
4129 	return result;
4130 }
4131 
verity_test(const char * mount_dir)4132 static int verity_test(const char *mount_dir)
4133 {
4134 	int result = TEST_FAILURE;
4135 
4136 	TESTEQUAL(verity_test_optional_sigs(mount_dir, true), TEST_SUCCESS);
4137 	TESTEQUAL(verity_test_optional_sigs(mount_dir, false), TEST_SUCCESS);
4138 	result = TEST_SUCCESS;
4139 out:
4140 	return result;
4141 }
4142 
verity_file_valid(const char * mount_dir,struct test_file * file)4143 static int verity_file_valid(const char *mount_dir, struct test_file *file)
4144 {
4145 	int result = TEST_FAILURE;
4146 	char *filename = NULL;
4147 	int fd = -1;
4148 	uint8_t buffer[INCFS_DATA_FILE_BLOCK_SIZE];
4149 	struct incfs_get_file_sig_args gfsa = {
4150 		.file_signature = ptr_to_u64(buffer),
4151 		.file_signature_buf_size = sizeof(buffer),
4152 	};
4153 	int i;
4154 
4155 	TEST(filename = concat_file_name(mount_dir, file->name), filename);
4156 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
4157 	TESTEQUAL(ioctl(fd, INCFS_IOC_READ_FILE_SIGNATURE, &gfsa), 0);
4158 	for (i = 0; i < file->size; i += sizeof(buffer))
4159 		TESTEQUAL(pread(fd, buffer, sizeof(buffer), i),
4160 			  file->size - i > sizeof(buffer) ?
4161 				sizeof(buffer) : file->size - i);
4162 
4163 	result = TEST_SUCCESS;
4164 out:
4165 	close(fd);
4166 	free(filename);
4167 	return result;
4168 }
4169 
enable_verity_test(const char * mount_dir)4170 static int enable_verity_test(const char *mount_dir)
4171 {
4172 	int result = TEST_FAILURE;
4173 	char *backing_dir = NULL;
4174 	bool installed;
4175 	int cmd_fd = -1;
4176 	struct test_files_set test = get_test_files_set();
4177 	int i;
4178 
4179 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
4180 	TESTEQUAL(mount_fs(mount_dir, backing_dir, 0), 0);
4181 	TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
4182 	TESTEQUAL(verity_installed(mount_dir, cmd_fd, &installed), 0);
4183 	if (!installed) {
4184 		result = TEST_SUCCESS;
4185 		goto out;
4186 	}
4187 	for (i = 0; i < test.files_count; ++i) {
4188 		struct test_file *file = &test.files[i];
4189 
4190 		TESTEQUAL(emit_file(cmd_fd, NULL, file->name, &file->id,
4191 				     file->size, NULL), 0);
4192 		TESTEQUAL(emit_test_file_data(mount_dir, file), 0);
4193 		TESTEQUAL(enable_verity(mount_dir, file, NULL, NULL, false), 0);
4194 	}
4195 
4196 	/* Check files are valid on disk */
4197 	close(cmd_fd);
4198 	cmd_fd = -1;
4199 	TESTEQUAL(umount(mount_dir), 0);
4200 	TESTEQUAL(mount_fs(mount_dir, backing_dir, 0), 0);
4201 	for (i = 0; i < test.files_count; ++i)
4202 		TESTEQUAL(verity_file_valid(mount_dir, &test.files[i]), 0);
4203 
4204 	result = TEST_SUCCESS;
4205 out:
4206 	close(cmd_fd);
4207 	umount(mount_dir);
4208 	free(backing_dir);
4209 	return result;
4210 }
4211 
mmap_test(const char * mount_dir)4212 static int mmap_test(const char *mount_dir)
4213 {
4214 	int result = TEST_FAILURE;
4215 	char *backing_dir = NULL;
4216 	int cmd_fd = -1;
4217 	/*
4218 	 * File is big enough to have a two layer tree with two hashes in the
4219 	 * higher level, so we can corrupt the second one
4220 	 */
4221 	int shas_per_block = INCFS_DATA_FILE_BLOCK_SIZE / SHA256_DIGEST_SIZE;
4222 	struct test_file file = {
4223 		  .name = "file",
4224 		  .size = INCFS_DATA_FILE_BLOCK_SIZE * shas_per_block * 2,
4225 	};
4226 	char *filename = NULL;
4227 	int fd = -1;
4228 	char *addr = (void *)-1;
4229 
4230 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
4231 	TESTEQUAL(mount_fs(mount_dir, backing_dir, 0), 0);
4232 	TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
4233 
4234 	TESTEQUAL(build_mtree(&file), 0);
4235 	file.mtree[1].data[INCFS_DATA_FILE_BLOCK_SIZE] ^= 0xff;
4236 	TESTEQUAL(crypto_emit_file(cmd_fd, NULL, file.name, &file.id,
4237 			       file.size, file.root_hash,
4238 			       file.sig.add_data), 0);
4239 	TESTEQUAL(emit_test_file_data(mount_dir, &file), 0);
4240 	TESTEQUAL(load_hash_tree(mount_dir, &file), 0);
4241 	TEST(filename = concat_file_name(mount_dir, file.name), filename);
4242 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
4243 	TEST(addr = mmap(NULL, file.size, PROT_READ, MAP_PRIVATE, fd, 0),
4244 	     addr != (void *) -1);
4245 	TESTEQUAL(mlock(addr, INCFS_DATA_FILE_BLOCK_SIZE), 0);
4246 	TESTEQUAL(munlock(addr, INCFS_DATA_FILE_BLOCK_SIZE), 0);
4247 	TESTEQUAL(mlock(addr + shas_per_block * INCFS_DATA_FILE_BLOCK_SIZE,
4248 			INCFS_DATA_FILE_BLOCK_SIZE), -1);
4249 	TESTEQUAL(mlock(addr + (shas_per_block - 1) *
4250 			       INCFS_DATA_FILE_BLOCK_SIZE,
4251 			INCFS_DATA_FILE_BLOCK_SIZE), 0);
4252 	TESTEQUAL(munlock(addr + (shas_per_block - 1) *
4253 				 INCFS_DATA_FILE_BLOCK_SIZE,
4254 			  INCFS_DATA_FILE_BLOCK_SIZE), 0);
4255 	TESTEQUAL(mlock(addr + (shas_per_block - 1) *
4256 			       INCFS_DATA_FILE_BLOCK_SIZE,
4257 			INCFS_DATA_FILE_BLOCK_SIZE * 2), -1);
4258 	TESTEQUAL(munmap(addr, file.size), 0);
4259 
4260 	result = TEST_SUCCESS;
4261 out:
4262 	free(file.mtree);
4263 	close(fd);
4264 	free(filename);
4265 	close(cmd_fd);
4266 	umount(mount_dir);
4267 	free(backing_dir);
4268 	return result;
4269 }
4270 
truncate_test(const char * mount_dir)4271 static int truncate_test(const char *mount_dir)
4272 {
4273 	int result = TEST_FAILURE;
4274 	char *backing_dir = NULL;
4275 	int cmd_fd = -1;
4276 	struct test_file file = {
4277 		  .name = "file",
4278 		  .size = INCFS_DATA_FILE_BLOCK_SIZE,
4279 	};
4280 	char *backing_file = NULL;
4281 	int fd = -1;
4282 	struct stat st;
4283 
4284 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
4285 	TESTEQUAL(mount_fs(mount_dir, backing_dir, 0), 0);
4286 	TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
4287 	TESTEQUAL(emit_file(cmd_fd, NULL, file.name, &file.id, file.size, NULL),
4288 		  0);
4289 	TEST(backing_file = concat_file_name(backing_dir, file.name),
4290 	     backing_file);
4291 	TEST(fd = open(backing_file, O_RDWR | O_CLOEXEC), fd != -1);
4292 	TESTEQUAL(stat(backing_file, &st), 0);
4293 	TESTCOND(st.st_blocks < 128);
4294 	TESTEQUAL(fallocate(fd, FALLOC_FL_KEEP_SIZE, 0, 1 << 24), 0);
4295 	TESTEQUAL(stat(backing_file, &st), 0);
4296 	TESTCOND(st.st_blocks > 32768);
4297 	TESTEQUAL(emit_test_file_data(mount_dir, &file), 0);
4298 	TESTEQUAL(stat(backing_file, &st), 0);
4299 	TESTCOND(st.st_blocks < 128);
4300 
4301 	result = TEST_SUCCESS;
4302 out:
4303 	close(fd);
4304 	free(backing_file);
4305 	close(cmd_fd);
4306 	umount(mount_dir);
4307 	free(backing_dir);
4308 	return result;
4309 }
4310 
stat_file_test(const char * mount_dir,int cmd_fd,struct test_file * file)4311 static int stat_file_test(const char *mount_dir, int cmd_fd,
4312 			  struct test_file *file)
4313 {
4314 	int result = TEST_FAILURE;
4315 	struct stat st;
4316 	char *filename = NULL;
4317 
4318 	TESTEQUAL(emit_file(cmd_fd, NULL, file->name, &file->id,
4319 				     file->size, NULL), 0);
4320 	TEST(filename = concat_file_name(mount_dir, file->name), filename);
4321 	TESTEQUAL(stat(filename, &st), 0);
4322 	TESTCOND(st.st_blocks < 32);
4323 	TESTEQUAL(emit_test_file_data(mount_dir, file), 0);
4324 	TESTEQUAL(stat(filename, &st), 0);
4325 	TESTCOND(st.st_blocks > file->size / 512);
4326 
4327 	result = TEST_SUCCESS;
4328 out:
4329 	free(filename);
4330 	return result;
4331 }
4332 
stat_test(const char * mount_dir)4333 static int stat_test(const char *mount_dir)
4334 {
4335 	int result = TEST_FAILURE;
4336 	char *backing_dir = NULL;
4337 	int cmd_fd = -1;
4338 	int i;
4339 	struct test_files_set test = get_test_files_set();
4340 	const int file_num = test.files_count;
4341 
4342 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
4343 	TESTEQUAL(mount_fs(mount_dir, backing_dir, 0), 0);
4344 	TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
4345 
4346 	for (i = 0; i < file_num; i++) {
4347 		struct test_file *file = &test.files[i];
4348 
4349 		TESTEQUAL(stat_file_test(mount_dir, cmd_fd, file), 0);
4350 	}
4351 
4352 	result = TEST_SUCCESS;
4353 out:
4354 	close(cmd_fd);
4355 	umount(mount_dir);
4356 	free(backing_dir);
4357 	return result;
4358 }
4359 
4360 #define SYSFS_DIR "/sys/fs/incremental-fs/instances/test_node/"
4361 
sysfs_test_value(const char * name,uint64_t value)4362 static int sysfs_test_value(const char *name, uint64_t value)
4363 {
4364 	int result = TEST_FAILURE;
4365 	char *filename = NULL;
4366 	FILE *file = NULL;
4367 	uint64_t res;
4368 
4369 	TEST(filename = concat_file_name(SYSFS_DIR, name), filename);
4370 	TEST(file = fopen(filename, "re"), file);
4371 	TESTEQUAL(fscanf(file, "%lu", &res), 1);
4372 	TESTEQUAL(res, value);
4373 
4374 	result = TEST_SUCCESS;
4375 out:
4376 	if (file)
4377 		fclose(file);
4378 	free(filename);
4379 	return result;
4380 }
4381 
sysfs_test_value_range(const char * name,uint64_t low,uint64_t high)4382 static int sysfs_test_value_range(const char *name, uint64_t low, uint64_t high)
4383 {
4384 	int result = TEST_FAILURE;
4385 	char *filename = NULL;
4386 	FILE *file = NULL;
4387 	uint64_t res;
4388 
4389 	TEST(filename = concat_file_name(SYSFS_DIR, name), filename);
4390 	TEST(file = fopen(filename, "re"), file);
4391 	TESTEQUAL(fscanf(file, "%lu", &res), 1);
4392 	TESTCOND(res >= low && res <= high);
4393 
4394 	result = TEST_SUCCESS;
4395 out:
4396 	if (file)
4397 		fclose(file);
4398 	free(filename);
4399 	return result;
4400 }
4401 
ioctl_test_last_error(int cmd_fd,const incfs_uuid_t * file_id,int page,int error)4402 static int ioctl_test_last_error(int cmd_fd, const incfs_uuid_t *file_id,
4403 				 int page, int error)
4404 {
4405 	int result = TEST_FAILURE;
4406 	struct incfs_get_last_read_error_args glre;
4407 
4408 	TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_GET_LAST_READ_ERROR, &glre), 0);
4409 	if (file_id)
4410 		TESTEQUAL(memcmp(&glre.file_id_out, file_id, sizeof(*file_id)),
4411 			  0);
4412 
4413 	TESTEQUAL(glre.page_out, page);
4414 	TESTEQUAL(glre.errno_out, error);
4415 	result = TEST_SUCCESS;
4416 out:
4417 	return result;
4418 }
4419 
sysfs_test(const char * mount_dir)4420 static int sysfs_test(const char *mount_dir)
4421 {
4422 	int result = TEST_FAILURE;
4423 	char *backing_dir = NULL;
4424 	int cmd_fd = -1;
4425 	struct test_file file = {
4426 		  .name = "file",
4427 		  .size = INCFS_DATA_FILE_BLOCK_SIZE,
4428 	};
4429 	char *filename = NULL;
4430 	int fd = -1;
4431 	int pid = -1;
4432 	char buffer[32];
4433 	char *null_buf = NULL;
4434 	int status;
4435 	struct incfs_per_uid_read_timeouts purt_set[] = {
4436 		{
4437 			.uid = 0,
4438 			.min_time_us = 1000000,
4439 			.min_pending_time_us = 1000000,
4440 			.max_pending_time_us = 2000000,
4441 		},
4442 	};
4443 	struct incfs_set_read_timeouts_args srt = {
4444 		ptr_to_u64(purt_set),
4445 		sizeof(purt_set)
4446 	};
4447 
4448 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
4449 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir, "sysfs_name=test_node",
4450 			       false),
4451 		  0);
4452 	TEST(cmd_fd = open_commands_file(mount_dir), cmd_fd != -1);
4453 	TESTEQUAL(build_mtree(&file), 0);
4454 	file.root_hash[0] ^= 0xff;
4455 	TESTEQUAL(crypto_emit_file(cmd_fd, NULL, file.name, &file.id, file.size,
4456 				   file.root_hash, file.sig.add_data),
4457 		  0);
4458 	TEST(filename = concat_file_name(mount_dir, file.name), filename);
4459 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
4460 	TESTEQUAL(ioctl_test_last_error(cmd_fd, NULL, 0, 0), 0);
4461 	TESTEQUAL(sysfs_test_value("reads_failed_timed_out", 0), 0);
4462 	TESTEQUAL(read(fd, null_buf, 1), -1);
4463 	TESTEQUAL(ioctl_test_last_error(cmd_fd, &file.id, 0, -ETIME), 0);
4464 	TESTEQUAL(sysfs_test_value("reads_failed_timed_out", 2), 0);
4465 
4466 	TESTEQUAL(emit_test_file_data(mount_dir, &file), 0);
4467 	TESTEQUAL(sysfs_test_value("reads_failed_hash_verification", 0), 0);
4468 	TESTEQUAL(read(fd, null_buf, 1), -1);
4469 	TESTEQUAL(sysfs_test_value("reads_failed_hash_verification", 1), 0);
4470 	TESTSYSCALL(close(fd));
4471 	fd = -1;
4472 
4473 	TESTSYSCALL(unlink(filename));
4474 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir,
4475 			       "read_timeout_ms=10000,sysfs_name=test_node",
4476 			       true),
4477 		  0);
4478 	TESTEQUAL(emit_file(cmd_fd, NULL, file.name, &file.id, file.size, NULL),
4479 		  0);
4480 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
4481 	TESTSYSCALL(fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC));
4482 	TEST(pid = fork(), pid != -1);
4483 	if (pid == 0) {
4484 		TESTEQUAL(read(fd, buffer, sizeof(buffer)), sizeof(buffer));
4485 		exit(0);
4486 	}
4487 	sleep(1);
4488 	TESTEQUAL(sysfs_test_value("reads_delayed_pending", 0), 0);
4489 	TESTEQUAL(emit_test_file_data(mount_dir, &file), 0);
4490 	TESTNE(wait(&status), -1);
4491 	TESTEQUAL(status, 0);
4492 	TESTEQUAL(sysfs_test_value("reads_delayed_pending", 1), 0);
4493 	/* Allow +/- 10% */
4494 	TESTEQUAL(sysfs_test_value_range("reads_delayed_pending_us", 900000, 1100000),
4495 		  0);
4496 
4497 	TESTSYSCALL(close(fd));
4498 	fd = -1;
4499 
4500 	TESTSYSCALL(unlink(filename));
4501 	TESTEQUAL(ioctl(cmd_fd, INCFS_IOC_SET_READ_TIMEOUTS, &srt), 0);
4502 	TESTEQUAL(emit_file(cmd_fd, NULL, file.name, &file.id, file.size, NULL),
4503 		  0);
4504 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
4505 	TESTEQUAL(sysfs_test_value("reads_delayed_min", 0), 0);
4506 	TESTEQUAL(emit_test_file_data(mount_dir, &file), 0);
4507 	TESTEQUAL(read(fd, buffer, sizeof(buffer)), sizeof(buffer));
4508 	TESTEQUAL(sysfs_test_value("reads_delayed_min", 1), 0);
4509 	/* This should be exact */
4510 	TESTEQUAL(sysfs_test_value("reads_delayed_min_us", 1000000), 0);
4511 
4512 	TESTSYSCALL(close(fd));
4513 	fd = -1;
4514 
4515 	TESTSYSCALL(unlink(filename));
4516 	TESTEQUAL(emit_file(cmd_fd, NULL, file.name, &file.id, file.size, NULL),
4517 		  0);
4518 	TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1);
4519 	TESTSYSCALL(fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC));
4520 	TEST(pid = fork(), pid != -1);
4521 	if (pid == 0) {
4522 		TESTEQUAL(read(fd, buffer, sizeof(buffer)), sizeof(buffer));
4523 		exit(0);
4524 	}
4525 	usleep(500000);
4526 	TESTEQUAL(sysfs_test_value("reads_delayed_pending", 1), 0);
4527 	TESTEQUAL(sysfs_test_value("reads_delayed_min", 1), 0);
4528 	TESTEQUAL(emit_test_file_data(mount_dir, &file), 0);
4529 	TESTNE(wait(&status), -1);
4530 	TESTEQUAL(status, 0);
4531 	TESTEQUAL(sysfs_test_value("reads_delayed_pending", 2), 0);
4532 	TESTEQUAL(sysfs_test_value("reads_delayed_min", 2), 0);
4533 	/* Exact 1000000 plus 500000 +/- 10% */
4534 	TESTEQUAL(sysfs_test_value_range("reads_delayed_min_us", 1450000, 1550000), 0);
4535 	/* Allow +/- 10% */
4536 	TESTEQUAL(sysfs_test_value_range("reads_delayed_pending_us", 1350000, 1650000),
4537 		  0);
4538 
4539 	result = TEST_SUCCESS;
4540 out:
4541 	if (pid == 0)
4542 		exit(result);
4543 	free(file.mtree);
4544 	free(filename);
4545 	close(fd);
4546 	close(cmd_fd);
4547 	umount(mount_dir);
4548 	free(backing_dir);
4549 	return result;
4550 }
4551 
sysfs_test_directories(bool one_present,bool two_present)4552 static int sysfs_test_directories(bool one_present, bool two_present)
4553 {
4554 	int result = TEST_FAILURE;
4555 	struct stat st;
4556 
4557 	TESTEQUAL(stat("/sys/fs/incremental-fs/instances/1", &st),
4558 		  one_present ? 0 : -1);
4559 	if (one_present)
4560 		TESTCOND(S_ISDIR(st.st_mode));
4561 	else
4562 		TESTEQUAL(errno, ENOENT);
4563 	TESTEQUAL(stat("/sys/fs/incremental-fs/instances/2", &st),
4564 		  two_present ? 0 : -1);
4565 	if (two_present)
4566 		TESTCOND(S_ISDIR(st.st_mode));
4567 	else
4568 		TESTEQUAL(errno, ENOENT);
4569 
4570 	result = TEST_SUCCESS;
4571 out:
4572 	return result;
4573 }
4574 
sysfs_rename_test(const char * mount_dir)4575 static int sysfs_rename_test(const char *mount_dir)
4576 {
4577 	int result = TEST_FAILURE;
4578 	char *backing_dir = NULL;
4579 	char *mount_dir2 = NULL;
4580 	int fd = -1;
4581 	char c;
4582 
4583 	/* Mount with no node */
4584 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
4585 	TESTEQUAL(mount_fs(mount_dir, backing_dir, 0), 0);
4586 	TESTEQUAL(sysfs_test_directories(false, false), 0);
4587 
4588 	/* Remount with node */
4589 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir, "sysfs_name=1", true),
4590 		  0);
4591 	TESTEQUAL(sysfs_test_directories(true, false), 0);
4592 	TEST(fd = open("/sys/fs/incremental-fs/instances/1/reads_delayed_min",
4593 		       O_RDONLY | O_CLOEXEC), fd != -1);
4594 	TESTEQUAL(pread(fd, &c, 1, 0), 1);
4595 	TESTEQUAL(c, '0');
4596 	TESTEQUAL(pread(fd, &c, 1, 0), 1);
4597 	TESTEQUAL(c, '0');
4598 
4599 	/* Rename node */
4600 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir, "sysfs_name=2", true),
4601 		  0);
4602 	TESTEQUAL(sysfs_test_directories(false, true), 0);
4603 	TESTEQUAL(pread(fd, &c, 1, 0), -1);
4604 
4605 	/* Try mounting another instance with same node name */
4606 	TEST(mount_dir2 = concat_file_name(backing_dir, "incfs-mount-dir2"),
4607 	     mount_dir2);
4608 	rmdir(mount_dir2); /* In case we crashed before */
4609 	TESTSYSCALL(mkdir(mount_dir2, 0777));
4610 	TEST(mount_fs_opt(mount_dir2, backing_dir, "sysfs_name=2", false),
4611 		  -1);
4612 
4613 	/* Try mounting another instance then remounting with existing name */
4614 	TESTEQUAL(mount_fs(mount_dir2, backing_dir, 0), 0);
4615 	TESTEQUAL(mount_fs_opt(mount_dir2, backing_dir, "sysfs_name=2", true),
4616 		  -1);
4617 
4618 	/* Remount with no node */
4619 	TESTEQUAL(mount_fs_opt(mount_dir, backing_dir, "", true),
4620 		  0);
4621 	TESTEQUAL(sysfs_test_directories(false, false), 0);
4622 
4623 	result = TEST_SUCCESS;
4624 out:
4625 	umount(mount_dir2);
4626 	rmdir(mount_dir2);
4627 	free(mount_dir2);
4628 	close(fd);
4629 	umount(mount_dir);
4630 	free(backing_dir);
4631 	return result;
4632 }
4633 
stacked_mount_test(const char * mount_dir)4634 static int stacked_mount_test(const char *mount_dir)
4635 {
4636 	int result = TEST_FAILURE;
4637 	char *backing_dir = NULL;
4638 
4639 	/* Mount with no node */
4640 	TEST(backing_dir = create_backing_dir(mount_dir), backing_dir);
4641 	TESTEQUAL(mount_fs(mount_dir, backing_dir, 0), 0);
4642 	/* Try mounting another instance with same name */
4643 	TESTEQUAL(mount_fs(mount_dir, backing_dir, 0), 0);
4644 	/* Try unmounting the first instance */
4645 	TESTEQUAL(umount_fs(mount_dir), 0);
4646 	/* Try unmounting the second instance */
4647 	TESTEQUAL(umount_fs(mount_dir), 0);
4648 	result = TEST_SUCCESS;
4649 out:
4650 	/* Cleanup */
4651 	rmdir(mount_dir);
4652 	rmdir(backing_dir);
4653 	free(backing_dir);
4654 	return result;
4655 }
4656 
setup_mount_dir()4657 static char *setup_mount_dir()
4658 {
4659 	struct stat st;
4660 	char *current_dir = getcwd(NULL, 0);
4661 	char *mount_dir = concat_file_name(current_dir, "incfs-mount-dir");
4662 
4663 	free(current_dir);
4664 	if (stat(mount_dir, &st) == 0) {
4665 		if (S_ISDIR(st.st_mode))
4666 			return mount_dir;
4667 
4668 		ksft_print_msg("%s is a file, not a dir.\n", mount_dir);
4669 		return NULL;
4670 	}
4671 
4672 	if (mkdir(mount_dir, 0777)) {
4673 		print_error("Can't create mount dir.");
4674 		return NULL;
4675 	}
4676 
4677 	return mount_dir;
4678 }
4679 
parse_options(int argc,char * const * argv)4680 int parse_options(int argc, char *const *argv)
4681 {
4682 	signed char c;
4683 
4684 	while ((c = getopt(argc, argv, "f:t:v")) != -1)
4685 		switch (c) {
4686 		case 'f':
4687 			options.file = strtol(optarg, NULL, 10);
4688 			break;
4689 
4690 		case 't':
4691 			options.test = strtol(optarg, NULL, 10);
4692 			break;
4693 
4694 		case 'v':
4695 			options.verbose = true;
4696 			break;
4697 
4698 		default:
4699 			return -EINVAL;
4700 		}
4701 
4702 	return 0;
4703 }
4704 
4705 struct test_case {
4706 	int (*pfunc)(const char *dir);
4707 	const char *name;
4708 };
4709 
run_one_test(const char * mount_dir,struct test_case * test_case)4710 void run_one_test(const char *mount_dir, struct test_case *test_case)
4711 {
4712 	int ret;
4713 
4714 	ksft_print_msg("Running %s\n", test_case->name);
4715 	ret = test_case->pfunc(mount_dir);
4716 
4717 	if (ret == TEST_SUCCESS)
4718 		ksft_test_result_pass("%s\n", test_case->name);
4719 	else if (ret == TEST_SKIP)
4720 		ksft_test_result_skip("%s\n", test_case->name);
4721 	else
4722 		ksft_test_result_fail("%s\n", test_case->name);
4723 }
4724 
main(int argc,char * argv[])4725 int main(int argc, char *argv[])
4726 {
4727 	char *mount_dir = NULL;
4728 	int i;
4729 	int fd, count;
4730 
4731 	if (parse_options(argc, argv))
4732 		ksft_exit_fail_msg("Bad options\n");
4733 
4734 	// Seed randomness pool for testing on QEMU
4735 	// NOTE - this abuses the concept of randomness - do *not* ever do this
4736 	// on a machine for production use - the device will think it has good
4737 	// randomness when it does not.
4738 	fd = open("/dev/urandom", O_WRONLY | O_CLOEXEC);
4739 	count = 4096;
4740 	for (int i = 0; i < 128; ++i)
4741 		ioctl(fd, RNDADDTOENTCNT, &count);
4742 	close(fd);
4743 
4744 	ksft_print_header();
4745 
4746 	if (geteuid() != 0)
4747 		ksft_print_msg("Not a root, might fail to mount.\n");
4748 
4749 	mount_dir = setup_mount_dir();
4750 	if (mount_dir == NULL)
4751 		ksft_exit_fail_msg("Can't create a mount dir\n");
4752 
4753 #define MAKE_TEST(test)                                                        \
4754 	{                                                                      \
4755 		test, #test                                                    \
4756 	}
4757 	struct test_case cases[] = {
4758 		MAKE_TEST(basic_file_ops_test),
4759 		MAKE_TEST(cant_touch_index_test),
4760 		MAKE_TEST(dynamic_files_and_data_test),
4761 		MAKE_TEST(concurrent_reads_and_writes_test),
4762 		MAKE_TEST(attribute_test),
4763 		MAKE_TEST(work_after_remount_test),
4764 		MAKE_TEST(child_procs_waiting_for_data_test),
4765 		MAKE_TEST(multiple_providers_test),
4766 		MAKE_TEST(hash_tree_test),
4767 		MAKE_TEST(read_log_test),
4768 		MAKE_TEST(get_blocks_test),
4769 		MAKE_TEST(get_hash_blocks_test),
4770 		MAKE_TEST(large_file_test),
4771 		MAKE_TEST(mapped_file_test),
4772 		MAKE_TEST(compatibility_test),
4773 		MAKE_TEST(data_block_count_test),
4774 		MAKE_TEST(hash_block_count_test),
4775 		MAKE_TEST(per_uid_read_timeouts_test),
4776 		MAKE_TEST(inotify_test),
4777 		MAKE_TEST(verity_test),
4778 		MAKE_TEST(enable_verity_test),
4779 		MAKE_TEST(mmap_test),
4780 		MAKE_TEST(truncate_test),
4781 		MAKE_TEST(stat_test),
4782 		MAKE_TEST(sysfs_test),
4783 		MAKE_TEST(sysfs_rename_test),
4784 		MAKE_TEST(stacked_mount_test),
4785 	};
4786 #undef MAKE_TEST
4787 
4788 	if (options.test) {
4789 		if (options.test <= 0 || options.test > ARRAY_SIZE(cases))
4790 			ksft_exit_fail_msg("Invalid test\n");
4791 
4792 		ksft_set_plan(1);
4793 		run_one_test(mount_dir, &cases[options.test - 1]);
4794 	} else {
4795 		ksft_set_plan(ARRAY_SIZE(cases));
4796 		for (i = 0; i < ARRAY_SIZE(cases); ++i)
4797 			run_one_test(mount_dir, &cases[i]);
4798 	}
4799 
4800 	umount2(mount_dir, MNT_FORCE);
4801 	rmdir(mount_dir);
4802 	return !ksft_get_fail_cnt() ? ksft_exit_pass() : ksft_exit_fail();
4803 }
4804