18c2ecf20Sopenharmony_ci#include <errno.h> 28c2ecf20Sopenharmony_ci#include <stdlib.h> 38c2ecf20Sopenharmony_ci#include <stdio.h> 48c2ecf20Sopenharmony_ci#include <string.h> 58c2ecf20Sopenharmony_ci#include <unistd.h> 68c2ecf20Sopenharmony_ci#include <sys/time.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/bpf.h> 98c2ecf20Sopenharmony_ci#include <linux/filter.h> 108c2ecf20Sopenharmony_ci#include <linux/unistd.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <bpf/bpf.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include "bpf_rlimit.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define LOG_SIZE (1 << 20) 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define err(str...) printf("ERROR: " str) 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic const struct bpf_insn code_sample[] = { 218c2ecf20Sopenharmony_ci /* We need a few instructions to pass the min log length */ 228c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 238c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 248c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 258c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 268c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 278c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 288c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 298c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 308c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 318c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 328c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 338c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 348c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 358c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 368c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 378c2ecf20Sopenharmony_ci BPF_MOV64_IMM(BPF_REG_0, 0), 388c2ecf20Sopenharmony_ci BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, 398c2ecf20Sopenharmony_ci BPF_FUNC_map_lookup_elem), 408c2ecf20Sopenharmony_ci BPF_EXIT_INSN(), 418c2ecf20Sopenharmony_ci}; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic inline __u64 ptr_to_u64(const void *ptr) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci return (__u64) (unsigned long) ptr; 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic int load(char *log, size_t log_len, int log_level) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci union bpf_attr attr; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci bzero(&attr, sizeof(attr)); 538c2ecf20Sopenharmony_ci attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER; 548c2ecf20Sopenharmony_ci attr.insn_cnt = (__u32)(sizeof(code_sample) / sizeof(struct bpf_insn)); 558c2ecf20Sopenharmony_ci attr.insns = ptr_to_u64(code_sample); 568c2ecf20Sopenharmony_ci attr.license = ptr_to_u64("GPL"); 578c2ecf20Sopenharmony_ci attr.log_buf = ptr_to_u64(log); 588c2ecf20Sopenharmony_ci attr.log_size = log_len; 598c2ecf20Sopenharmony_ci attr.log_level = log_level; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr)); 628c2ecf20Sopenharmony_ci} 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic void check_ret(int ret, int exp_errno) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci if (ret > 0) { 678c2ecf20Sopenharmony_ci close(ret); 688c2ecf20Sopenharmony_ci err("broken sample loaded successfully!?\n"); 698c2ecf20Sopenharmony_ci exit(1); 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci if (!ret || errno != exp_errno) { 738c2ecf20Sopenharmony_ci err("Program load returned: ret:%d/errno:%d, expected ret:%d/errno:%d\n", 748c2ecf20Sopenharmony_ci ret, errno, -1, exp_errno); 758c2ecf20Sopenharmony_ci exit(1); 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic void check_ones(const char *buf, size_t len, const char *msg) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci while (len--) 828c2ecf20Sopenharmony_ci if (buf[len] != 1) { 838c2ecf20Sopenharmony_ci err("%s", msg); 848c2ecf20Sopenharmony_ci exit(1); 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistatic void test_log_good(char *log, size_t buf_len, size_t log_len, 898c2ecf20Sopenharmony_ci size_t exp_len, int exp_errno, const char *full_log) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci size_t len; 928c2ecf20Sopenharmony_ci int ret; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci memset(log, 1, buf_len); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci ret = load(log, log_len, 1); 978c2ecf20Sopenharmony_ci check_ret(ret, exp_errno); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci len = strnlen(log, buf_len); 1008c2ecf20Sopenharmony_ci if (len == buf_len) { 1018c2ecf20Sopenharmony_ci err("verifier did not NULL terminate the log\n"); 1028c2ecf20Sopenharmony_ci exit(1); 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci if (exp_len && len != exp_len) { 1058c2ecf20Sopenharmony_ci err("incorrect log length expected:%zd have:%zd\n", 1068c2ecf20Sopenharmony_ci exp_len, len); 1078c2ecf20Sopenharmony_ci exit(1); 1088c2ecf20Sopenharmony_ci } 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (strchr(log, 1)) { 1118c2ecf20Sopenharmony_ci err("verifier leaked a byte through\n"); 1128c2ecf20Sopenharmony_ci exit(1); 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci check_ones(log + len + 1, buf_len - len - 1, 1168c2ecf20Sopenharmony_ci "verifier wrote bytes past NULL termination\n"); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci if (memcmp(full_log, log, LOG_SIZE)) { 1198c2ecf20Sopenharmony_ci err("log did not match expected output\n"); 1208c2ecf20Sopenharmony_ci exit(1); 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic void test_log_bad(char *log, size_t log_len, int log_level) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci int ret; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci ret = load(log, log_len, log_level); 1298c2ecf20Sopenharmony_ci check_ret(ret, EINVAL); 1308c2ecf20Sopenharmony_ci if (log) 1318c2ecf20Sopenharmony_ci check_ones(log, LOG_SIZE, 1328c2ecf20Sopenharmony_ci "verifier touched log with bad parameters\n"); 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ciint main(int argc, char **argv) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci char full_log[LOG_SIZE]; 1388c2ecf20Sopenharmony_ci char log[LOG_SIZE]; 1398c2ecf20Sopenharmony_ci size_t want_len; 1408c2ecf20Sopenharmony_ci int i; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci memset(log, 1, LOG_SIZE); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* Test incorrect attr */ 1458c2ecf20Sopenharmony_ci printf("Test log_level 0...\n"); 1468c2ecf20Sopenharmony_ci test_log_bad(log, LOG_SIZE, 0); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci printf("Test log_size < 128...\n"); 1498c2ecf20Sopenharmony_ci test_log_bad(log, 15, 1); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci printf("Test log_buff = NULL...\n"); 1528c2ecf20Sopenharmony_ci test_log_bad(NULL, LOG_SIZE, 1); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci /* Test with log big enough */ 1558c2ecf20Sopenharmony_ci printf("Test oversized buffer...\n"); 1568c2ecf20Sopenharmony_ci test_log_good(full_log, LOG_SIZE, LOG_SIZE, 0, EACCES, full_log); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci want_len = strlen(full_log); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci printf("Test exact buffer...\n"); 1618c2ecf20Sopenharmony_ci test_log_good(log, LOG_SIZE, want_len + 2, want_len, EACCES, full_log); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci printf("Test undersized buffers...\n"); 1648c2ecf20Sopenharmony_ci for (i = 0; i < 64; i++) { 1658c2ecf20Sopenharmony_ci full_log[want_len - i + 1] = 1; 1668c2ecf20Sopenharmony_ci full_log[want_len - i] = 0; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci test_log_good(log, LOG_SIZE, want_len + 1 - i, want_len - i, 1698c2ecf20Sopenharmony_ci ENOSPC, full_log); 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci printf("test_verifier_log: OK\n"); 1738c2ecf20Sopenharmony_ci return 0; 1748c2ecf20Sopenharmony_ci} 175