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

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

DEFINITIONS

This source file includes following definitions.
  1. ptr_to_u64
  2. load
  3. check_ret
  4. check_ones
  5. test_log_good
  6. test_log_bad
  7. main

   1 #include <errno.h>
   2 #include <stdlib.h>
   3 #include <stdio.h>
   4 #include <string.h>
   5 #include <unistd.h>
   6 #include <sys/time.h>
   7 
   8 #include <linux/bpf.h>
   9 #include <linux/filter.h>
  10 #include <linux/unistd.h>
  11 
  12 #include <bpf/bpf.h>
  13 
  14 #include "bpf_rlimit.h"
  15 
  16 #define LOG_SIZE (1 << 20)
  17 
  18 #define err(str...)     printf("ERROR: " str)
  19 
  20 static const struct bpf_insn code_sample[] = {
  21         /* We need a few instructions to pass the min log length */
  22         BPF_MOV64_IMM(BPF_REG_0, 0),
  23         BPF_MOV64_IMM(BPF_REG_0, 0),
  24         BPF_MOV64_IMM(BPF_REG_0, 0),
  25         BPF_MOV64_IMM(BPF_REG_0, 0),
  26         BPF_MOV64_IMM(BPF_REG_0, 0),
  27         BPF_MOV64_IMM(BPF_REG_0, 0),
  28         BPF_MOV64_IMM(BPF_REG_0, 0),
  29         BPF_MOV64_IMM(BPF_REG_0, 0),
  30         BPF_MOV64_IMM(BPF_REG_0, 0),
  31         BPF_MOV64_IMM(BPF_REG_0, 0),
  32         BPF_MOV64_IMM(BPF_REG_0, 0),
  33         BPF_MOV64_IMM(BPF_REG_0, 0),
  34         BPF_MOV64_IMM(BPF_REG_0, 0),
  35         BPF_MOV64_IMM(BPF_REG_0, 0),
  36         BPF_MOV64_IMM(BPF_REG_0, 0),
  37         BPF_MOV64_IMM(BPF_REG_0, 0),
  38         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
  39                      BPF_FUNC_map_lookup_elem),
  40         BPF_EXIT_INSN(),
  41 };
  42 
  43 static inline __u64 ptr_to_u64(const void *ptr)
  44 {
  45         return (__u64) (unsigned long) ptr;
  46 }
  47 
  48 static int load(char *log, size_t log_len, int log_level)
  49 {
  50         union bpf_attr attr;
  51 
  52         bzero(&attr, sizeof(attr));
  53         attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
  54         attr.insn_cnt = (__u32)(sizeof(code_sample) / sizeof(struct bpf_insn));
  55         attr.insns = ptr_to_u64(code_sample);
  56         attr.license = ptr_to_u64("GPL");
  57         attr.log_buf = ptr_to_u64(log);
  58         attr.log_size = log_len;
  59         attr.log_level = log_level;
  60 
  61         return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
  62 }
  63 
  64 static void check_ret(int ret, int exp_errno)
  65 {
  66         if (ret > 0) {
  67                 close(ret);
  68                 err("broken sample loaded successfully!?\n");
  69                 exit(1);
  70         }
  71 
  72         if (!ret || errno != exp_errno) {
  73                 err("Program load returned: ret:%d/errno:%d, expected ret:%d/errno:%d\n",
  74                     ret, errno, -1, exp_errno);
  75                 exit(1);
  76         }
  77 }
  78 
  79 static void check_ones(const char *buf, size_t len, const char *msg)
  80 {
  81         while (len--)
  82                 if (buf[len] != 1) {
  83                         err("%s", msg);
  84                         exit(1);
  85                 }
  86 }
  87 
  88 static void test_log_good(char *log, size_t buf_len, size_t log_len,
  89                           size_t exp_len, int exp_errno, const char *full_log)
  90 {
  91         size_t len;
  92         int ret;
  93 
  94         memset(log, 1, buf_len);
  95 
  96         ret = load(log, log_len, 1);
  97         check_ret(ret, exp_errno);
  98 
  99         len = strnlen(log, buf_len);
 100         if (len == buf_len) {
 101                 err("verifier did not NULL terminate the log\n");
 102                 exit(1);
 103         }
 104         if (exp_len && len != exp_len) {
 105                 err("incorrect log length expected:%zd have:%zd\n",
 106                     exp_len, len);
 107                 exit(1);
 108         }
 109 
 110         if (strchr(log, 1)) {
 111                 err("verifier leaked a byte through\n");
 112                 exit(1);
 113         }
 114 
 115         check_ones(log + len + 1, buf_len - len - 1,
 116                    "verifier wrote bytes past NULL termination\n");
 117 
 118         if (memcmp(full_log, log, LOG_SIZE)) {
 119                 err("log did not match expected output\n");
 120                 exit(1);
 121         }
 122 }
 123 
 124 static void test_log_bad(char *log, size_t log_len, int log_level)
 125 {
 126         int ret;
 127 
 128         ret = load(log, log_len, log_level);
 129         check_ret(ret, EINVAL);
 130         if (log)
 131                 check_ones(log, LOG_SIZE,
 132                            "verifier touched log with bad parameters\n");
 133 }
 134 
 135 int main(int argc, char **argv)
 136 {
 137         char full_log[LOG_SIZE];
 138         char log[LOG_SIZE];
 139         size_t want_len;
 140         int i;
 141 
 142         memset(log, 1, LOG_SIZE);
 143 
 144         /* Test incorrect attr */
 145         printf("Test log_level 0...\n");
 146         test_log_bad(log, LOG_SIZE, 0);
 147 
 148         printf("Test log_size < 128...\n");
 149         test_log_bad(log, 15, 1);
 150 
 151         printf("Test log_buff = NULL...\n");
 152         test_log_bad(NULL, LOG_SIZE, 1);
 153 
 154         /* Test with log big enough */
 155         printf("Test oversized buffer...\n");
 156         test_log_good(full_log, LOG_SIZE, LOG_SIZE, 0, EACCES, full_log);
 157 
 158         want_len = strlen(full_log);
 159 
 160         printf("Test exact buffer...\n");
 161         test_log_good(log, LOG_SIZE, want_len + 2, want_len, EACCES, full_log);
 162 
 163         printf("Test undersized buffers...\n");
 164         for (i = 0; i < 64; i++) {
 165                 full_log[want_len - i + 1] = 1;
 166                 full_log[want_len - i] = 0;
 167 
 168                 test_log_good(log, LOG_SIZE, want_len + 1 - i, want_len - i,
 169                               ENOSPC, full_log);
 170         }
 171 
 172         printf("test_verifier_log: OK\n");
 173         return 0;
 174 }

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