1 // SPDX-License-Identifier: GPL-2.0
14 #include <sys/socket.h>
16 #include <linux/filter.h>
17 #include <linux/bpf.h>
18 #include <linux/if_alg.h>
22 #include "../../../include/linux/filter.h"
23 #include "bpf_rlimit.h"
25 static struct bpf_insn prog[BPF_MAXINSNS];
27 static void bpf_gen_imm_prog(unsigned int insns, int fd_map)
32 for (i = 0; i < insns; i++)
33 prog[i] = BPF_ALU64_IMM(BPF_MOV, i % BPF_REG_10, rand());
34 prog[i - 1] = BPF_EXIT_INSN();
37 static void bpf_gen_map_prog(unsigned int insns, int fd_map)
41 for (i = 0; i + 1 < insns; i += 2) {
42 struct bpf_insn tmp[] = {
43 BPF_LD_MAP_FD(j++ % BPF_REG_10, fd_map)
46 memcpy(&prog[i], tmp, sizeof(tmp));
49 prog[insns - 2] = BPF_ALU64_IMM(BPF_MOV, i % BPF_REG_10, 42);
50 prog[insns - 1] = BPF_EXIT_INSN();
53 static int bpf_try_load_prog(int insns, int fd_map,
54 void (*bpf_filler)(unsigned int insns,
59 bpf_filler(insns, fd_map);
60 fd_prog = bpf_load_program(BPF_PROG_TYPE_SCHED_CLS, prog, insns, "", 0,
68 static int __hex2bin(char ch)
70 if ((ch >= '0') && (ch <= '9'))
73 if ((ch >= 'a') && (ch <= 'f'))
78 static int hex2bin(uint8_t *dst, const char *src, size_t count)
81 int hi = __hex2bin(*src++);
82 int lo = __hex2bin(*src++);
84 if ((hi < 0) || (lo < 0))
86 *dst++ = (hi << 4) | lo;
91 static void tag_from_fdinfo(int fd_prog, uint8_t *tag, uint32_t len)
93 const int prefix_len = sizeof("prog_tag:\t") - 1;
98 snprintf(buff, sizeof(buff), "/proc/%d/fdinfo/%d", getpid(),
100 fp = fopen(buff, "r");
103 while (fgets(buff, sizeof(buff), fp)) {
104 if (strncmp(buff, "prog_tag:\t", prefix_len))
106 ret = hex2bin(tag, buff + prefix_len, len);
114 static void tag_from_alg(int insns, uint8_t *tag, uint32_t len)
116 static const struct sockaddr_alg alg = {
117 .salg_family = AF_ALG,
121 int fd_base, fd_alg, ret;
124 fd_base = socket(AF_ALG, SOCK_SEQPACKET, 0);
127 ret = bind(fd_base, (struct sockaddr *)&alg, sizeof(alg));
130 fd_alg = accept(fd_base, NULL, 0);
133 insns *= sizeof(struct bpf_insn);
134 size = write(fd_alg, prog, insns);
135 assert(size == insns);
137 size = read(fd_alg, tag, len);
144 static void tag_dump(const char *prefix, uint8_t *tag, uint32_t len)
148 printf("%s", prefix);
149 for (i = 0; i < len; i++)
150 printf("%02x", tag[i]);
154 static void tag_exit_report(int insns, int fd_map, uint8_t *ftag,
155 uint8_t *atag, uint32_t len)
157 printf("Program tag mismatch for %d insns%s!\n", insns,
158 fd_map < 0 ? "" : " with map");
160 tag_dump(" fdinfo result: ", ftag, len);
161 tag_dump(" af_alg result: ", atag, len);
165 static void do_test(uint32_t *tests, int start_insns, int fd_map,
166 void (*bpf_filler)(unsigned int insns, int fd))
170 for (i = start_insns; i <= BPF_MAXINSNS; i++) {
171 uint8_t ftag[8], atag[sizeof(ftag)];
173 fd_prog = bpf_try_load_prog(i, fd_map, bpf_filler);
174 tag_from_fdinfo(fd_prog, ftag, sizeof(ftag));
175 tag_from_alg(i, atag, sizeof(atag));
176 if (memcmp(ftag, atag, sizeof(ftag)))
177 tag_exit_report(i, fd_map, ftag, atag, sizeof(ftag));
190 fd_map = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(int),
191 sizeof(int), 1, BPF_F_NO_PREALLOC);
194 for (i = 0; i < 5; i++) {
195 do_test(&tests, 2, -1, bpf_gen_imm_prog);
196 do_test(&tests, 3, fd_map, bpf_gen_map_prog);
199 printf("test_tag: OK (%u tests)\n", tests);