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