• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2021 Google LLC
4  */
5 
6 #include "test_fuse.h"
7 
8 #include <dirent.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <gelf.h>
12 #include <libelf.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 
17 #include <sys/mount.h>
18 #include <sys/stat.h>
19 #include <sys/statfs.h>
20 #include <sys/xattr.h>
21 
22 #include <linux/unistd.h>
23 
24 #include <include/uapi/linux/fuse.h>
25 #include <include/uapi/linux/bpf.h>
26 
27 struct _test_options test_options;
28 
s(const char * s1)29 struct s s(const char *s1)
30 {
31 	struct s s = {0};
32 
33 	if (!s1)
34 		return s;
35 
36 	s.s = malloc(strlen(s1) + 1);
37 	if (!s.s)
38 		return s;
39 
40 	strcpy(s.s, s1);
41 	return s;
42 }
43 
sn(const char * s1,const char * s2)44 struct s sn(const char *s1, const char *s2)
45 {
46 	struct s s = {0};
47 
48 	if (!s1)
49 		return s;
50 
51 	s.s = malloc(s2 - s1 + 1);
52 	if (!s.s)
53 		return s;
54 
55 	strncpy(s.s, s1, s2 - s1);
56 	s.s[s2 - s1] = 0;
57 	return s;
58 }
59 
s_cmp(struct s s1,struct s s2)60 int s_cmp(struct s s1, struct s s2)
61 {
62 	int result = -1;
63 
64 	if (!s1.s || !s2.s)
65 		goto out;
66 	result = strcmp(s1.s, s2.s);
67 out:
68 	free(s1.s);
69 	free(s2.s);
70 	return result;
71 }
72 
s_cat(struct s s1,struct s s2)73 struct s s_cat(struct s s1, struct s s2)
74 {
75 	struct s s = {0};
76 
77 	if (!s1.s || !s2.s)
78 		goto out;
79 
80 	s.s = malloc(strlen(s1.s) + strlen(s2.s) + 1);
81 	if (!s.s)
82 		goto out;
83 
84 	strcpy(s.s, s1.s);
85 	strcat(s.s, s2.s);
86 out:
87 	free(s1.s);
88 	free(s2.s);
89 	return s;
90 }
91 
s_splitleft(struct s s1,char c)92 struct s s_splitleft(struct s s1, char c)
93 {
94 	struct s s = {0};
95 	char *split;
96 
97 	if (!s1.s)
98 		return s;
99 
100 	split = strchr(s1.s, c);
101 	if (split)
102 		s = sn(s1.s, split);
103 
104 	free(s1.s);
105 	return s;
106 }
107 
s_splitright(struct s s1,char c)108 struct s s_splitright(struct s s1, char c)
109 {
110 	struct s s2 = {0};
111 	char *split;
112 
113 	if (!s1.s)
114 		return s2;
115 
116 	split = strchr(s1.s, c);
117 	if (split)
118 		s2 = s(split + 1);
119 
120 	free(s1.s);
121 	return s2;
122 }
123 
s_word(struct s s1,char c,size_t n)124 struct s s_word(struct s s1, char c, size_t n)
125 {
126 	while (n--)
127 		s1 = s_splitright(s1, c);
128 	return s_splitleft(s1, c);
129 }
130 
s_path(struct s s1,struct s s2)131 struct s s_path(struct s s1, struct s s2)
132 {
133 	return s_cat(s_cat(s1, s("/")), s2);
134 }
135 
s_pathn(size_t n,struct s s1,...)136 struct s s_pathn(size_t n, struct s s1, ...)
137 {
138 	va_list argp;
139 
140 	va_start(argp, s1);
141 	while (--n)
142 		s1 = s_path(s1, va_arg(argp, struct s));
143 	va_end(argp);
144 	return s1;
145 }
146 
s_link(struct s src_pathname,struct s dst_pathname)147 int s_link(struct s src_pathname, struct s dst_pathname)
148 {
149 	int res;
150 
151 	if (src_pathname.s && dst_pathname.s) {
152 		res = link(src_pathname.s, dst_pathname.s);
153 	} else {
154 		res = -1;
155 		errno = ENOMEM;
156 	}
157 
158 	free(src_pathname.s);
159 	free(dst_pathname.s);
160 	return res;
161 }
162 
s_symlink(struct s src_pathname,struct s dst_pathname)163 int s_symlink(struct s src_pathname, struct s dst_pathname)
164 {
165 	int res;
166 
167 	if (src_pathname.s && dst_pathname.s) {
168 		res = symlink(src_pathname.s, dst_pathname.s);
169 	} else {
170 		res = -1;
171 		errno = ENOMEM;
172 	}
173 
174 	free(src_pathname.s);
175 	free(dst_pathname.s);
176 	return res;
177 }
178 
179 
s_mkdir(struct s pathname,mode_t mode)180 int s_mkdir(struct s pathname, mode_t mode)
181 {
182 	int res;
183 
184 	if (!pathname.s) {
185 		errno = ENOMEM;
186 		return -1;
187 	}
188 
189 	res = mkdir(pathname.s, mode);
190 	free(pathname.s);
191 	return res;
192 }
193 
s_rmdir(struct s pathname)194 int s_rmdir(struct s pathname)
195 {
196 	int res;
197 
198 	if (!pathname.s) {
199 		errno = ENOMEM;
200 		return -1;
201 	}
202 
203 	res = rmdir(pathname.s);
204 	free(pathname.s);
205 	return res;
206 }
207 
s_unlink(struct s pathname)208 int s_unlink(struct s pathname)
209 {
210 	int res;
211 
212 	if (!pathname.s) {
213 		errno = ENOMEM;
214 		return -1;
215 	}
216 
217 	res = unlink(pathname.s);
218 	free(pathname.s);
219 	return res;
220 }
221 
s_open(struct s pathname,int flags,...)222 int s_open(struct s pathname, int flags, ...)
223 {
224 	va_list ap;
225 	int res;
226 
227 	va_start(ap, flags);
228 	if (!pathname.s) {
229 		errno = ENOMEM;
230 		return -1;
231 	}
232 
233 	if (flags & (O_CREAT | O_TMPFILE))
234 		res = open(pathname.s, flags, va_arg(ap, mode_t));
235 	else
236 		res = open(pathname.s, flags);
237 
238 	free(pathname.s);
239 	va_end(ap);
240 	return res;
241 }
242 
s_openat(int dirfd,struct s pathname,int flags,...)243 int s_openat(int dirfd, struct s pathname, int flags, ...)
244 {
245 	va_list ap;
246 	int res;
247 
248 	va_start(ap, flags);
249 	if (!pathname.s) {
250 		errno = ENOMEM;
251 		return -1;
252 	}
253 
254 	if (flags & (O_CREAT | O_TMPFILE))
255 		res = openat(dirfd, pathname.s, flags, va_arg(ap, mode_t));
256 	else
257 		res = openat(dirfd, pathname.s, flags);
258 
259 	free(pathname.s);
260 	va_end(ap);
261 	return res;
262 }
263 
s_creat(struct s pathname,mode_t mode)264 int s_creat(struct s pathname, mode_t mode)
265 {
266 	int res;
267 
268 	if (!pathname.s) {
269 		errno = ENOMEM;
270 		return -1;
271 	}
272 
273 	res = open(pathname.s, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
274 	free(pathname.s);
275 	return res;
276 }
277 
s_mkfifo(struct s pathname,mode_t mode)278 int s_mkfifo(struct s pathname, mode_t mode)
279 {
280 	int res;
281 
282 	if (!pathname.s) {
283 		errno = ENOMEM;
284 		return -1;
285 	}
286 
287 	res = mknod(pathname.s, S_IFIFO | mode, 0);
288 	free(pathname.s);
289 	return res;
290 }
291 
s_stat(struct s pathname,struct stat * st)292 int s_stat(struct s pathname, struct stat *st)
293 {
294 	int res;
295 
296 	if (!pathname.s) {
297 		errno = ENOMEM;
298 		return -1;
299 	}
300 
301 	res = stat(pathname.s, st);
302 	free(pathname.s);
303 	return res;
304 }
305 
s_statfs(struct s pathname,struct statfs * st)306 int s_statfs(struct s pathname, struct statfs *st)
307 {
308 	int res;
309 
310 	if (!pathname.s) {
311 		errno = ENOMEM;
312 		return -1;
313 	}
314 
315 	res = statfs(pathname.s, st);
316 	free(pathname.s);
317 	return res;
318 }
319 
s_opendir(struct s pathname)320 DIR *s_opendir(struct s pathname)
321 {
322 	DIR *res;
323 
324 	res = opendir(pathname.s);
325 	free(pathname.s);
326 	return res;
327 }
328 
s_getxattr(struct s pathname,const char name[],void * value,size_t size,ssize_t * ret_size)329 int s_getxattr(struct s pathname, const char name[], void *value, size_t size,
330 	       ssize_t *ret_size)
331 {
332 	if (!pathname.s) {
333 		errno = ENOMEM;
334 		return -1;
335 	}
336 
337 	*ret_size = getxattr(pathname.s, name, value, size);
338 	free(pathname.s);
339 	return *ret_size >= 0 ? 0 : -1;
340 }
341 
s_listxattr(struct s pathname,void * list,size_t size,ssize_t * ret_size)342 int s_listxattr(struct s pathname, void *list, size_t size, ssize_t *ret_size)
343 {
344 	if (!pathname.s) {
345 		errno = ENOMEM;
346 		return -1;
347 	}
348 
349 	*ret_size = listxattr(pathname.s, list, size);
350 	free(pathname.s);
351 	return *ret_size >= 0 ? 0 : -1;
352 }
353 
s_setxattr(struct s pathname,const char name[],const void * value,size_t size,int flags)354 int s_setxattr(struct s pathname, const char name[], const void *value, size_t size, int flags)
355 {
356 	int res;
357 
358 	if (!pathname.s) {
359 		errno = ENOMEM;
360 		return -1;
361 	}
362 
363 	res = setxattr(pathname.s, name, value, size, flags);
364 	free(pathname.s);
365 	return res;
366 }
367 
s_removexattr(struct s pathname,const char name[])368 int s_removexattr(struct s pathname, const char name[])
369 {
370 	int res;
371 
372 	if (!pathname.s) {
373 		errno = ENOMEM;
374 		return -1;
375 	}
376 
377 	res = removexattr(pathname.s, name);
378 	free(pathname.s);
379 	return res;
380 }
381 
s_rename(struct s oldpathname,struct s newpathname)382 int s_rename(struct s oldpathname, struct s newpathname)
383 {
384 	int res;
385 
386 	if (!oldpathname.s || !newpathname.s) {
387 		errno = ENOMEM;
388 		return -1;
389 	}
390 
391 	res = rename(oldpathname.s, newpathname.s);
392 	free(oldpathname.s);
393 	free(newpathname.s);
394 	return res;
395 }
396 
s_mount(struct s source,struct s target,struct s filesystem,unsigned long mountflags,struct s data)397 int s_mount(struct s source, struct s target, struct s filesystem,
398 	    unsigned long mountflags, struct s data)
399 {
400 	int res;
401 
402 	res = mount(source.s, target.s, filesystem.s, mountflags, data.s);
403 	free(source.s);
404 	free(target.s);
405 	free(filesystem.s);
406 	free(data.s);
407 
408 	return res;
409 }
410 
s_umount(struct s target)411 int s_umount(struct s target)
412 {
413 	int res;
414 
415 	res = umount(target.s);
416 	free(target.s);
417 	return res;
418 }
419 
s_fuse_attr(struct s pathname,struct fuse_attr * fuse_attr_out)420 int s_fuse_attr(struct s pathname, struct fuse_attr *fuse_attr_out)
421 {
422 
423 	struct stat st;
424 	int result = TEST_FAILURE;
425 
426 	TESTSYSCALL(s_stat(pathname, &st));
427 
428 	fuse_attr_out->ino = st.st_ino;
429 	fuse_attr_out->mode = st.st_mode;
430 	fuse_attr_out->nlink = st.st_nlink;
431 	fuse_attr_out->uid = st.st_uid;
432 	fuse_attr_out->gid = st.st_gid;
433 	fuse_attr_out->rdev = st.st_rdev;
434 	fuse_attr_out->size = st.st_size;
435 	fuse_attr_out->blksize = st.st_blksize;
436 	fuse_attr_out->blocks = st.st_blocks;
437 	fuse_attr_out->atime = st.st_atime;
438 	fuse_attr_out->mtime = st.st_mtime;
439 	fuse_attr_out->ctime = st.st_ctime;
440 	fuse_attr_out->atimensec = UINT32_MAX;
441 	fuse_attr_out->mtimensec = UINT32_MAX;
442 	fuse_attr_out->ctimensec = UINT32_MAX;
443 
444 	result = TEST_SUCCESS;
445 out:
446 	return result;
447 }
448 
tracing_folder(void)449 struct s tracing_folder(void)
450 {
451 	struct s trace = {0};
452 	FILE *mounts = NULL;
453 	char *line = NULL;
454 	size_t size = 0;
455 
456 	TEST(mounts = fopen("/proc/mounts", "re"), mounts);
457 	while (getline(&line, &size, mounts) != -1) {
458 		if (!s_cmp(s_word(sn(line, line + size), ' ', 2),
459 			   s("tracefs"))) {
460 			trace = s_word(sn(line, line + size), ' ', 1);
461 			break;
462 		}
463 
464 		if (!s_cmp(s_word(sn(line, line + size), ' ', 2), s("debugfs")))
465 			trace = s_path(s_word(sn(line, line + size), ' ', 1),
466 				       s("tracing"));
467 	}
468 
469 out:
470 	free(line);
471 	fclose(mounts);
472 	return trace;
473 }
474 
tracing_on(void)475 int tracing_on(void)
476 {
477 	int result = TEST_FAILURE;
478 	int tracing_on = -1;
479 
480 	TEST(tracing_on = s_open(s_path(tracing_folder(), s("tracing_on")),
481 				 O_WRONLY | O_CLOEXEC),
482 	     tracing_on != -1);
483 	TESTEQUAL(write(tracing_on, "1", 1), 1);
484 	result = TEST_SUCCESS;
485 out:
486 	close(tracing_on);
487 	return result;
488 }
489 
concat_file_name(const char * dir,const char * file)490 char *concat_file_name(const char *dir, const char *file)
491 {
492 	char full_name[FILENAME_MAX] = "";
493 
494 	if (snprintf(full_name, ARRAY_SIZE(full_name), "%s/%s", dir, file) < 0)
495 		return NULL;
496 	return strdup(full_name);
497 }
498 
setup_mount_dir(const char * name)499 char *setup_mount_dir(const char *name)
500 {
501 	struct stat st;
502 	char *current_dir = getcwd(NULL, 0);
503 	char *mount_dir = concat_file_name(current_dir, name);
504 
505 	free(current_dir);
506 	if (stat(mount_dir, &st) == 0) {
507 		if (S_ISDIR(st.st_mode))
508 			return mount_dir;
509 
510 		ksft_print_msg("%s is a file, not a dir.\n", mount_dir);
511 		return NULL;
512 	}
513 
514 	if (mkdir(mount_dir, 0777)) {
515 		ksft_print_msg("Can't create mount dir.");
516 		return NULL;
517 	}
518 
519 	return mount_dir;
520 }
521 
delete_dir_tree(const char * dir_path,bool remove_root)522 int delete_dir_tree(const char *dir_path, bool remove_root)
523 {
524 	DIR *dir = NULL;
525 	struct dirent *dp;
526 	int result = 0;
527 
528 	dir = opendir(dir_path);
529 	if (!dir) {
530 		result = -errno;
531 		goto out;
532 	}
533 
534 	while ((dp = readdir(dir))) {
535 		char *full_path;
536 
537 		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
538 			continue;
539 
540 		full_path = concat_file_name(dir_path, dp->d_name);
541 		if (dp->d_type == DT_DIR)
542 			result = delete_dir_tree(full_path, true);
543 		else
544 			result = unlink(full_path);
545 		free(full_path);
546 		if (result)
547 			goto out;
548 	}
549 
550 out:
551 	if (dir)
552 		closedir(dir);
553 	if (!result && remove_root)
554 		rmdir(dir_path);
555 	return result;
556 }
557 
mount_fuse_maybe_init(const char * mount_dir,int bpf_fd,int dir_fd,int * fuse_dev_ptr,bool init)558 static int mount_fuse_maybe_init(const char *mount_dir, int bpf_fd, int dir_fd,
559 			     int *fuse_dev_ptr, bool init)
560 {
561 	int result = TEST_FAILURE;
562 	int fuse_dev = -1;
563 	char options[FILENAME_MAX];
564 	uint8_t bytes_in[FUSE_MIN_READ_BUFFER];
565 	uint8_t bytes_out[FUSE_MIN_READ_BUFFER];
566 
567 	DECL_FUSE_IN(init);
568 
569 	TEST(fuse_dev = open("/dev/fuse", O_RDWR | O_CLOEXEC), fuse_dev != -1);
570 	snprintf(options, FILENAME_MAX, "fd=%d,user_id=0,group_id=0,rootmode=0040000",
571 		 fuse_dev);
572 	if (bpf_fd != -1)
573 		snprintf(options + strlen(options),
574 			 sizeof(options) - strlen(options),
575 			 ",root_bpf=%d", bpf_fd);
576 	if (dir_fd != -1)
577 		snprintf(options + strlen(options),
578 			 sizeof(options) - strlen(options),
579 			 ",root_dir=%d", dir_fd);
580 	TESTSYSCALL(mount("ABC", mount_dir, "fuse", 0, options));
581 
582 	if (init) {
583 		TESTFUSEIN(FUSE_INIT, init_in);
584 		TESTEQUAL(init_in->major, FUSE_KERNEL_VERSION);
585 		TESTEQUAL(init_in->minor, FUSE_KERNEL_MINOR_VERSION);
586 		TESTFUSEOUT1(fuse_init_out, ((struct fuse_init_out) {
587 			.major = FUSE_KERNEL_VERSION,
588 			.minor = FUSE_KERNEL_MINOR_VERSION,
589 			.max_readahead = 4096,
590 			.flags = 0,
591 			.max_background = 0,
592 			.congestion_threshold = 0,
593 			.max_write = 4096,
594 			.time_gran = 1000,
595 			.max_pages = 12,
596 			.map_alignment = 4096,
597 		}));
598 	}
599 
600 	if (fuse_dev_ptr)
601 		*fuse_dev_ptr = fuse_dev;
602 	else
603 		TESTSYSCALL(close(fuse_dev));
604 	fuse_dev = -1;
605 	result = TEST_SUCCESS;
606 out:
607 	close(fuse_dev);
608 	return result;
609 }
610 
mount_fuse(const char * mount_dir,int bpf_fd,int dir_fd,int * fuse_dev_ptr)611 int mount_fuse(const char *mount_dir, int bpf_fd, int dir_fd, int *fuse_dev_ptr)
612 {
613 	return mount_fuse_maybe_init(mount_dir, bpf_fd, dir_fd, fuse_dev_ptr,
614 				     true);
615 }
616 
mount_fuse_no_init(const char * mount_dir,int bpf_fd,int dir_fd,int * fuse_dev_ptr)617 int mount_fuse_no_init(const char *mount_dir, int bpf_fd, int dir_fd,
618 		       int *fuse_dev_ptr)
619 {
620 	return mount_fuse_maybe_init(mount_dir, bpf_fd, dir_fd, fuse_dev_ptr,
621 				     false);
622 }
623 
624 struct fuse_bpf_map {
625 	unsigned int map_type;
626 	size_t key_size;
627 	size_t value_size;
628 	unsigned int max_entries;
629 };
630 
install_maps(Elf_Data * maps,int maps_index,Elf * elf,Elf_Data * symbols,int symbol_index,struct map_relocation ** mr,size_t * map_count)631 static int install_maps(Elf_Data *maps, int maps_index, Elf *elf,
632 			Elf_Data *symbols, int symbol_index,
633 			struct map_relocation **mr, size_t *map_count)
634 {
635 	int result = TEST_FAILURE;
636 	int i;
637 	GElf_Sym symbol;
638 
639 	TESTNE((void *)symbols, NULL);
640 
641 	for (i = 0; i < symbols->d_size / sizeof(symbol); ++i) {
642 		TESTNE((void *)gelf_getsym(symbols, i, &symbol), 0);
643 		if (symbol.st_shndx == maps_index) {
644 			struct fuse_bpf_map *map;
645 			union bpf_attr attr;
646 			int map_fd;
647 
648 			map = (struct fuse_bpf_map *)
649 				((char *)maps->d_buf + symbol.st_value);
650 
651 			attr = (union bpf_attr) {
652 				.map_type = map->map_type,
653 				.key_size = map->key_size,
654 				.value_size = map->value_size,
655 				.max_entries = map->max_entries,
656 			};
657 
658 			TEST(*mr = realloc(*mr, ++*map_count *
659 					   sizeof(struct fuse_bpf_map)),
660 			     *mr);
661 			TEST(map_fd = syscall(__NR_bpf, BPF_MAP_CREATE,
662 					      &attr, sizeof(attr)),
663 			     map_fd != -1);
664 			(*mr)[*map_count - 1] = (struct map_relocation) {
665 				.name = strdup(elf_strptr(elf, symbol_index,
666 							  symbol.st_name)),
667 				.fd = map_fd,
668 				.value = symbol.st_value,
669 			};
670 		}
671 	}
672 
673 	result = TEST_SUCCESS;
674 out:
675 	return result;
676 }
677 
relocate_maps(GElf_Shdr * rel_header,Elf_Data * rel_data,Elf_Data * prog_data,Elf_Data * symbol_data,struct map_relocation * map_relocations,size_t map_count)678 static inline int relocate_maps(GElf_Shdr *rel_header, Elf_Data *rel_data,
679 			 Elf_Data *prog_data, Elf_Data *symbol_data,
680 			 struct map_relocation *map_relocations,
681 			 size_t map_count)
682 {
683 	int result = TEST_FAILURE;
684 	int i;
685 	struct bpf_insn *insns = (struct bpf_insn *) prog_data->d_buf;
686 
687 	for (i = 0; i < rel_header->sh_size / rel_header->sh_entsize; ++i) {
688 		GElf_Sym sym;
689 		GElf_Rel rel;
690 		unsigned int insn_idx;
691 		int map_idx;
692 
693 		gelf_getrel(rel_data, i, &rel);
694 		insn_idx = rel.r_offset / sizeof(struct bpf_insn);
695 		insns[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
696 
697 		gelf_getsym(symbol_data, GELF_R_SYM(rel.r_info), &sym);
698 		for (map_idx = 0; map_idx < map_count; map_idx++) {
699 			if (map_relocations[map_idx].value == sym.st_value) {
700 				insns[insn_idx].imm =
701 					map_relocations[map_idx].fd;
702 				break;
703 			}
704 		}
705 		TESTNE(map_idx, map_count);
706 	}
707 
708 	result = TEST_SUCCESS;
709 out:
710 	return result;
711 }
712 
install_elf_bpf(const char * file,const char * section,int * fd,struct map_relocation ** map_relocations,size_t * map_count)713 int install_elf_bpf(const char *file, const char *section, int *fd,
714 		    struct map_relocation **map_relocations, size_t *map_count)
715 {
716 	int result = TEST_FAILURE;
717 	char path[PATH_MAX] = {};
718 	char *last_slash;
719 	int filter_fd = -1;
720 	union bpf_attr bpf_attr;
721 	static char log[1 << 20];
722 	Elf *elf = NULL;
723 	GElf_Ehdr ehdr;
724 	Elf_Data *data_prog = NULL, *data_maps = NULL, *data_symbols = NULL;
725 	int maps_index, symbol_index, prog_index;
726 	int i;
727 	int bpf_prog_type_fuse_fd = -1;
728 	char buffer[10] = {0};
729 	int bpf_prog_type_fuse;
730 
731 	TESTNE(readlink("/proc/self/exe", path, PATH_MAX), -1);
732 	TEST(last_slash = strrchr(path, '/'), last_slash);
733 	strcpy(last_slash + 1, file);
734 	TEST(filter_fd = open(path, O_RDONLY | O_CLOEXEC), filter_fd != -1);
735 	TESTNE(elf_version(EV_CURRENT), EV_NONE);
736 	TEST(elf = elf_begin(filter_fd, ELF_C_READ, NULL), elf);
737 	TESTEQUAL((void *) gelf_getehdr(elf, &ehdr), &ehdr);
738 	for (i = 1; i < ehdr.e_shnum; i++) {
739 		char *shname;
740 		GElf_Shdr shdr;
741 		Elf_Scn *scn;
742 
743 		TEST(scn = elf_getscn(elf, i), scn);
744 		TESTEQUAL((void *)gelf_getshdr(scn, &shdr), &shdr);
745 		TEST(shname = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name),
746 		     shname);
747 
748 		if (!strcmp(shname, "maps")) {
749 			TEST(data_maps = elf_getdata(scn, 0), data_maps);
750 			maps_index = i;
751 		} else if (shdr.sh_type == SHT_SYMTAB) {
752 			TEST(data_symbols = elf_getdata(scn, 0), data_symbols);
753 			symbol_index = shdr.sh_link;
754 		} else if (!strcmp(shname, section)) {
755 			TEST(data_prog = elf_getdata(scn, 0), data_prog);
756 			prog_index = i;
757 		}
758 	}
759 	TESTNE((void *) data_prog, NULL);
760 
761 	if (data_maps)
762 		TESTEQUAL(install_maps(data_maps, maps_index, elf,
763 				       data_symbols, symbol_index,
764 				       map_relocations, map_count), 0);
765 
766 	/* Now relocate maps */
767 	for (i = 1; i < ehdr.e_shnum; i++) {
768 		GElf_Shdr rel_header;
769 		Elf_Scn *scn;
770 		Elf_Data *rel_data;
771 
772 		TEST(scn = elf_getscn(elf, i), scn);
773 		TESTEQUAL((void *)gelf_getshdr(scn, &rel_header),
774 			&rel_header);
775 		if (rel_header.sh_type != SHT_REL)
776 			continue;
777 		TEST(rel_data = elf_getdata(scn, 0), rel_data);
778 
779 		if (rel_header.sh_info != prog_index)
780 			continue;
781 		TESTEQUAL(relocate_maps(&rel_header, rel_data,
782 					data_prog, data_symbols,
783 					*map_relocations, *map_count),
784 			  0);
785 	}
786 
787 	TEST(bpf_prog_type_fuse_fd = open("/sys/fs/fuse/bpf_prog_type_fuse",
788 					  O_RDONLY | O_CLOEXEC),
789 	     bpf_prog_type_fuse_fd != -1);
790 	TESTGE(read(bpf_prog_type_fuse_fd, buffer, sizeof(buffer)), 1);
791 	TEST(bpf_prog_type_fuse = strtol(buffer, NULL, 10),
792 	     bpf_prog_type_fuse != 0);
793 
794 	bpf_attr = (union bpf_attr) {
795 		.prog_type = bpf_prog_type_fuse,
796 		.insn_cnt = data_prog->d_size / 8,
797 		.insns = ptr_to_u64(data_prog->d_buf),
798 		.license = ptr_to_u64("GPL"),
799 		.log_buf = test_options.verbose ? ptr_to_u64(log) : 0,
800 		.log_size = test_options.verbose ? sizeof(log) : 0,
801 		.log_level = test_options.verbose ? 2 : 0,
802 	};
803 	*fd = syscall(__NR_bpf, BPF_PROG_LOAD, &bpf_attr, sizeof(bpf_attr));
804 	if (test_options.verbose)
805 		ksft_print_msg("%s\n", log);
806 	if (*fd == -1 && errno == ENOSPC)
807 		ksft_print_msg("bpf log size too small!\n");
808 	TESTNE(*fd, -1);
809 
810 	result = TEST_SUCCESS;
811 out:
812 	close(filter_fd);
813 	close(bpf_prog_type_fuse_fd);
814 	return result;
815 }
816 
817 
818