cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

testing_helpers.c (4785B)


      1// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
      2/* Copyright (C) 2019 Netronome Systems, Inc. */
      3/* Copyright (C) 2020 Facebook, Inc. */
      4#include <stdlib.h>
      5#include <string.h>
      6#include <errno.h>
      7#include <bpf/bpf.h>
      8#include <bpf/libbpf.h>
      9#include "test_progs.h"
     10#include "testing_helpers.h"
     11
     12int parse_num_list(const char *s, bool **num_set, int *num_set_len)
     13{
     14	int i, set_len = 0, new_len, num, start = 0, end = -1;
     15	bool *set = NULL, *tmp, parsing_end = false;
     16	char *next;
     17
     18	while (s[0]) {
     19		errno = 0;
     20		num = strtol(s, &next, 10);
     21		if (errno)
     22			return -errno;
     23
     24		if (parsing_end)
     25			end = num;
     26		else
     27			start = num;
     28
     29		if (!parsing_end && *next == '-') {
     30			s = next + 1;
     31			parsing_end = true;
     32			continue;
     33		} else if (*next == ',') {
     34			parsing_end = false;
     35			s = next + 1;
     36			end = num;
     37		} else if (*next == '\0') {
     38			parsing_end = false;
     39			s = next;
     40			end = num;
     41		} else {
     42			return -EINVAL;
     43		}
     44
     45		if (start > end)
     46			return -EINVAL;
     47
     48		if (end + 1 > set_len) {
     49			new_len = end + 1;
     50			tmp = realloc(set, new_len);
     51			if (!tmp) {
     52				free(set);
     53				return -ENOMEM;
     54			}
     55			for (i = set_len; i < start; i++)
     56				tmp[i] = false;
     57			set = tmp;
     58			set_len = new_len;
     59		}
     60		for (i = start; i <= end; i++)
     61			set[i] = true;
     62	}
     63
     64	if (!set || parsing_end)
     65		return -EINVAL;
     66
     67	*num_set = set;
     68	*num_set_len = set_len;
     69
     70	return 0;
     71}
     72
     73int parse_test_list(const char *s,
     74		    struct test_filter_set *set,
     75		    bool is_glob_pattern)
     76{
     77	char *input, *state = NULL, *next;
     78	struct test_filter *tmp, *tests = NULL;
     79	int i, j, cnt = 0;
     80
     81	input = strdup(s);
     82	if (!input)
     83		return -ENOMEM;
     84
     85	while ((next = strtok_r(state ? NULL : input, ",", &state))) {
     86		char *subtest_str = strchr(next, '/');
     87		char *pattern = NULL;
     88		int glob_chars = 0;
     89
     90		tmp = realloc(tests, sizeof(*tests) * (cnt + 1));
     91		if (!tmp)
     92			goto err;
     93		tests = tmp;
     94
     95		tests[cnt].subtest_cnt = 0;
     96		tests[cnt].subtests = NULL;
     97
     98		if (is_glob_pattern) {
     99			pattern = "%s";
    100		} else {
    101			pattern = "*%s*";
    102			glob_chars = 2;
    103		}
    104
    105		if (subtest_str) {
    106			char **tmp_subtests = NULL;
    107			int subtest_cnt = tests[cnt].subtest_cnt;
    108
    109			*subtest_str = '\0';
    110			subtest_str += 1;
    111			tmp_subtests = realloc(tests[cnt].subtests,
    112					       sizeof(*tmp_subtests) *
    113					       (subtest_cnt + 1));
    114			if (!tmp_subtests)
    115				goto err;
    116			tests[cnt].subtests = tmp_subtests;
    117
    118			tests[cnt].subtests[subtest_cnt] =
    119				malloc(strlen(subtest_str) + glob_chars + 1);
    120			if (!tests[cnt].subtests[subtest_cnt])
    121				goto err;
    122			sprintf(tests[cnt].subtests[subtest_cnt],
    123				pattern,
    124				subtest_str);
    125
    126			tests[cnt].subtest_cnt++;
    127		}
    128
    129		tests[cnt].name = malloc(strlen(next) + glob_chars + 1);
    130		if (!tests[cnt].name)
    131			goto err;
    132		sprintf(tests[cnt].name, pattern, next);
    133
    134		cnt++;
    135	}
    136
    137	tmp = realloc(set->tests, sizeof(*tests) * (cnt + set->cnt));
    138	if (!tmp)
    139		goto err;
    140
    141	memcpy(tmp +  set->cnt, tests, sizeof(*tests) * cnt);
    142	set->tests = tmp;
    143	set->cnt += cnt;
    144
    145	free(tests);
    146	free(input);
    147	return 0;
    148
    149err:
    150	for (i = 0; i < cnt; i++) {
    151		for (j = 0; j < tests[i].subtest_cnt; j++)
    152			free(tests[i].subtests[j]);
    153
    154		free(tests[i].name);
    155	}
    156	free(tests);
    157	free(input);
    158	return -ENOMEM;
    159}
    160
    161__u32 link_info_prog_id(const struct bpf_link *link, struct bpf_link_info *info)
    162{
    163	__u32 info_len = sizeof(*info);
    164	int err;
    165
    166	memset(info, 0, sizeof(*info));
    167	err = bpf_obj_get_info_by_fd(bpf_link__fd(link), info, &info_len);
    168	if (err) {
    169		printf("failed to get link info: %d\n", -errno);
    170		return 0;
    171	}
    172	return info->prog_id;
    173}
    174
    175int extra_prog_load_log_flags = 0;
    176
    177int bpf_prog_test_load(const char *file, enum bpf_prog_type type,
    178		       struct bpf_object **pobj, int *prog_fd)
    179{
    180	LIBBPF_OPTS(bpf_object_open_opts, opts,
    181		.kernel_log_level = extra_prog_load_log_flags,
    182	);
    183	struct bpf_object *obj;
    184	struct bpf_program *prog;
    185	__u32 flags;
    186	int err;
    187
    188	obj = bpf_object__open_file(file, &opts);
    189	if (!obj)
    190		return -errno;
    191
    192	prog = bpf_object__next_program(obj, NULL);
    193	if (!prog) {
    194		err = -ENOENT;
    195		goto err_out;
    196	}
    197
    198	if (type != BPF_PROG_TYPE_UNSPEC)
    199		bpf_program__set_type(prog, type);
    200
    201	flags = bpf_program__flags(prog) | BPF_F_TEST_RND_HI32;
    202	bpf_program__set_flags(prog, flags);
    203
    204	err = bpf_object__load(obj);
    205	if (err)
    206		goto err_out;
    207
    208	*pobj = obj;
    209	*prog_fd = bpf_program__fd(prog);
    210
    211	return 0;
    212err_out:
    213	bpf_object__close(obj);
    214	return err;
    215}
    216
    217int bpf_test_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
    218			  size_t insns_cnt, const char *license,
    219			  __u32 kern_version, char *log_buf,
    220			  size_t log_buf_sz)
    221{
    222	LIBBPF_OPTS(bpf_prog_load_opts, opts,
    223		.kern_version = kern_version,
    224		.prog_flags = BPF_F_TEST_RND_HI32,
    225		.log_level = extra_prog_load_log_flags,
    226		.log_buf = log_buf,
    227		.log_size = log_buf_sz,
    228	);
    229
    230	return bpf_prog_load(type, NULL, license, insns, insns_cnt, &opts);
    231}