cregit-Linux how code gets into the kernel

Release 4.11 tools/testing/selftests/bpf/test_tag.c

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sched.h>
#include <limits.h>
#include <assert.h>

#include <sys/socket.h>
#include <sys/resource.h>

#include <linux/filter.h>
#include <linux/bpf.h>
#include <linux/if_alg.h>

#include <bpf/bpf.h>

#include "../../../include/linux/filter.h"


static struct bpf_insn prog[BPF_MAXINSNS];


static void bpf_gen_imm_prog(unsigned int insns, int fd_map) { int i; srand(time(NULL)); for (i = 0; i < insns; i++) prog[i] = BPF_ALU64_IMM(BPF_MOV, i % BPF_REG_10, rand()); prog[i - 1] = BPF_EXIT_INSN(); }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann64100.00%1100.00%
Total64100.00%1100.00%


static void bpf_gen_map_prog(unsigned int insns, int fd_map) { int i, j = 0; for (i = 0; i + 1 < insns; i += 2) { struct bpf_insn tmp[] = { BPF_LD_MAP_FD(j++ % BPF_REG_10, fd_map) }; memcpy(&prog[i], tmp, sizeof(tmp)); } if (insns % 2 == 0) prog[insns - 2] = BPF_ALU64_IMM(BPF_MOV, i % BPF_REG_10, 42); prog[insns - 1] = BPF_EXIT_INSN(); }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann104100.00%1100.00%
Total104100.00%1100.00%


static int bpf_try_load_prog(int insns, int fd_map, void (*bpf_filler)(unsigned int insns, int fd_map)) { int fd_prog; bpf_filler(insns, fd_map); fd_prog = bpf_load_program(BPF_PROG_TYPE_SCHED_CLS, prog, insns, "", 0, NULL, 0); assert(fd_prog > 0); if (fd_map > 0) bpf_filler(insns, 0); return fd_prog; }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann7596.15%150.00%
Mickaël Salaün33.85%150.00%
Total78100.00%2100.00%


static int __hex2bin(char ch) { if ((ch >= '0') && (ch <= '9')) return ch - '0'; ch = tolower(ch); if ((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10; return -1; }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann60100.00%1100.00%
Total60100.00%1100.00%


static int hex2bin(uint8_t *dst, const char *src, size_t count) { while (count--) { int hi = __hex2bin(*src++); int lo = __hex2bin(*src++); if ((hi < 0) || (lo < 0)) return -1; *dst++ = (hi << 4) | lo; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann78100.00%1100.00%
Total78100.00%1100.00%


static void tag_from_fdinfo(int fd_prog, uint8_t *tag, uint32_t len) { const int prefix_len = sizeof("prog_tag:\t") - 1; char buff[256]; int ret = -1; FILE *fp; snprintf(buff, sizeof(buff), "/proc/%d/fdinfo/%d", getpid(), fd_prog); fp = fopen(buff, "r"); assert(fp); while (fgets(buff, sizeof(buff), fp)) { if (strncmp(buff, "prog_tag:\t", prefix_len)) continue; ret = hex2bin(tag, buff + prefix_len, len); break; } fclose(fp); assert(!ret); }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann127100.00%2100.00%
Total127100.00%2100.00%


static void tag_from_alg(int insns, uint8_t *tag, uint32_t len) { static const struct sockaddr_alg alg = { .salg_family = AF_ALG, .salg_type = "hash", .salg_name = "sha1", }; int fd_base, fd_alg, ret; ssize_t size; fd_base = socket(AF_ALG, SOCK_SEQPACKET, 0); assert(fd_base > 0); ret = bind(fd_base, (struct sockaddr *)&alg, sizeof(alg)); assert(!ret); fd_alg = accept(fd_base, NULL, 0); assert(fd_alg > 0); insns *= sizeof(struct bpf_insn); size = write(fd_alg, prog, insns); assert(size == insns); size = read(fd_alg, tag, len); assert(size == len); close(fd_alg); close(fd_base); }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann165100.00%1100.00%
Total165100.00%1100.00%


static void tag_dump(const char *prefix, uint8_t *tag, uint32_t len) { int i; printf("%s", prefix); for (i = 0; i < len; i++) printf("%02x", tag[i]); printf("\n"); }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann56100.00%1100.00%
Total56100.00%1100.00%


static void tag_exit_report(int insns, int fd_map, uint8_t *ftag, uint8_t *atag, uint32_t len) { printf("Program tag mismatch for %d insns%s!\n", insns, fd_map < 0 ? "" : " with map"); tag_dump(" fdinfo result: ", ftag, len); tag_dump(" af_alg result: ", atag, len); exit(1); }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann61100.00%1100.00%
Total61100.00%1100.00%


static void do_test(uint32_t *tests, int start_insns, int fd_map, void (*bpf_filler)(unsigned int insns, int fd)) { int i, fd_prog; for (i = start_insns; i <= BPF_MAXINSNS; i++) { uint8_t ftag[8], atag[sizeof(ftag)]; fd_prog = bpf_try_load_prog(i, fd_map, bpf_filler); tag_from_fdinfo(fd_prog, ftag, sizeof(ftag)); tag_from_alg(i, atag, sizeof(atag)); if (memcmp(ftag, atag, sizeof(ftag))) tag_exit_report(i, fd_map, ftag, atag, sizeof(ftag)); close(fd_prog); sched_yield(); (*tests)++; } }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann143100.00%1100.00%
Total143100.00%1100.00%


int main(void) { struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY }; uint32_t tests = 0; int i, fd_map; setrlimit(RLIMIT_MEMLOCK, &rinf); fd_map = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(int), sizeof(int), 1, BPF_F_NO_PREALLOC); assert(fd_map > 0); for (i = 0; i < 5; i++) { do_test(&tests, 2, -1, bpf_gen_imm_prog); do_test(&tests, 3, fd_map, bpf_gen_map_prog); } printf("test_tag: OK (%u tests)\n", tests); close(fd_map); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann11799.15%150.00%
Mickaël Salaün10.85%150.00%
Total118100.00%2100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Daniel Borkmann110699.10%240.00%
Mickaël Salaün100.90%360.00%
Total1116100.00%5100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.