root/tools/testing/selftests/bpf/test_tag.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. bpf_gen_imm_prog
  2. bpf_gen_map_prog
  3. bpf_try_load_prog
  4. __hex2bin
  5. hex2bin
  6. tag_from_fdinfo
  7. tag_from_alg
  8. tag_dump
  9. tag_exit_report
  10. do_test
  11. main

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <stdint.h>
   3 #include <stdio.h>
   4 #include <stdlib.h>
   5 #include <ctype.h>
   6 #include <time.h>
   7 #include <errno.h>
   8 #include <unistd.h>
   9 #include <string.h>
  10 #include <sched.h>
  11 #include <limits.h>
  12 #include <assert.h>
  13 
  14 #include <sys/socket.h>
  15 
  16 #include <linux/filter.h>
  17 #include <linux/bpf.h>
  18 #include <linux/if_alg.h>
  19 
  20 #include <bpf/bpf.h>
  21 
  22 #include "../../../include/linux/filter.h"
  23 #include "bpf_rlimit.h"
  24 
  25 static struct bpf_insn prog[BPF_MAXINSNS];
  26 
  27 static void bpf_gen_imm_prog(unsigned int insns, int fd_map)
  28 {
  29         int i;
  30 
  31         srand(time(NULL));
  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();
  35 }
  36 
  37 static void bpf_gen_map_prog(unsigned int insns, int fd_map)
  38 {
  39         int i, j = 0;
  40 
  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)
  44                 };
  45 
  46                 memcpy(&prog[i], tmp, sizeof(tmp));
  47         }
  48         if (insns % 2 == 0)
  49                 prog[insns - 2] = BPF_ALU64_IMM(BPF_MOV, i % BPF_REG_10, 42);
  50         prog[insns - 1] = BPF_EXIT_INSN();
  51 }
  52 
  53 static int bpf_try_load_prog(int insns, int fd_map,
  54                              void (*bpf_filler)(unsigned int insns,
  55                                                 int fd_map))
  56 {
  57         int fd_prog;
  58 
  59         bpf_filler(insns, fd_map);
  60         fd_prog = bpf_load_program(BPF_PROG_TYPE_SCHED_CLS, prog, insns, "", 0,
  61                                    NULL, 0);
  62         assert(fd_prog > 0);
  63         if (fd_map > 0)
  64                 bpf_filler(insns, 0);
  65         return fd_prog;
  66 }
  67 
  68 static int __hex2bin(char ch)
  69 {
  70         if ((ch >= '0') && (ch <= '9'))
  71                 return ch - '0';
  72         ch = tolower(ch);
  73         if ((ch >= 'a') && (ch <= 'f'))
  74                 return ch - 'a' + 10;
  75         return -1;
  76 }
  77 
  78 static int hex2bin(uint8_t *dst, const char *src, size_t count)
  79 {
  80         while (count--) {
  81                 int hi = __hex2bin(*src++);
  82                 int lo = __hex2bin(*src++);
  83 
  84                 if ((hi < 0) || (lo < 0))
  85                         return -1;
  86                 *dst++ = (hi << 4) | lo;
  87         }
  88         return 0;
  89 }
  90 
  91 static void tag_from_fdinfo(int fd_prog, uint8_t *tag, uint32_t len)
  92 {
  93         const int prefix_len = sizeof("prog_tag:\t") - 1;
  94         char buff[256];
  95         int ret = -1;
  96         FILE *fp;
  97 
  98         snprintf(buff, sizeof(buff), "/proc/%d/fdinfo/%d", getpid(),
  99                  fd_prog);
 100         fp = fopen(buff, "r");
 101         assert(fp);
 102 
 103         while (fgets(buff, sizeof(buff), fp)) {
 104                 if (strncmp(buff, "prog_tag:\t", prefix_len))
 105                         continue;
 106                 ret = hex2bin(tag, buff + prefix_len, len);
 107                 break;
 108         }
 109 
 110         fclose(fp);
 111         assert(!ret);
 112 }
 113 
 114 static void tag_from_alg(int insns, uint8_t *tag, uint32_t len)
 115 {
 116         static const struct sockaddr_alg alg = {
 117                 .salg_family    = AF_ALG,
 118                 .salg_type      = "hash",
 119                 .salg_name      = "sha1",
 120         };
 121         int fd_base, fd_alg, ret;
 122         ssize_t size;
 123 
 124         fd_base = socket(AF_ALG, SOCK_SEQPACKET, 0);
 125         assert(fd_base > 0);
 126 
 127         ret = bind(fd_base, (struct sockaddr *)&alg, sizeof(alg));
 128         assert(!ret);
 129 
 130         fd_alg = accept(fd_base, NULL, 0);
 131         assert(fd_alg > 0);
 132 
 133         insns *= sizeof(struct bpf_insn);
 134         size = write(fd_alg, prog, insns);
 135         assert(size == insns);
 136 
 137         size = read(fd_alg, tag, len);
 138         assert(size == len);
 139 
 140         close(fd_alg);
 141         close(fd_base);
 142 }
 143 
 144 static void tag_dump(const char *prefix, uint8_t *tag, uint32_t len)
 145 {
 146         int i;
 147 
 148         printf("%s", prefix);
 149         for (i = 0; i < len; i++)
 150                 printf("%02x", tag[i]);
 151         printf("\n");
 152 }
 153 
 154 static void tag_exit_report(int insns, int fd_map, uint8_t *ftag,
 155                             uint8_t *atag, uint32_t len)
 156 {
 157         printf("Program tag mismatch for %d insns%s!\n", insns,
 158                fd_map < 0 ? "" : " with map");
 159 
 160         tag_dump("  fdinfo result: ", ftag, len);
 161         tag_dump("  af_alg result: ", atag, len);
 162         exit(1);
 163 }
 164 
 165 static void do_test(uint32_t *tests, int start_insns, int fd_map,
 166                     void (*bpf_filler)(unsigned int insns, int fd))
 167 {
 168         int i, fd_prog;
 169 
 170         for (i = start_insns; i <= BPF_MAXINSNS; i++) {
 171                 uint8_t ftag[8], atag[sizeof(ftag)];
 172 
 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));
 178 
 179                 close(fd_prog);
 180                 sched_yield();
 181                 (*tests)++;
 182         }
 183 }
 184 
 185 int main(void)
 186 {
 187         uint32_t tests = 0;
 188         int i, fd_map;
 189 
 190         fd_map = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(int),
 191                                 sizeof(int), 1, BPF_F_NO_PREALLOC);
 192         assert(fd_map > 0);
 193 
 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);
 197         }
 198 
 199         printf("test_tag: OK (%u tests)\n", tests);
 200         close(fd_map);
 201         return 0;
 202 }

/* [<][>][^][v][top][bottom][index][help] */