Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
All conflicts seemed rather trivial, with some guidance from Saeed Mameed on the tc_ct.c one. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
#include <asm/alternative-asm.h>
|
||||
#include <asm/export.h>
|
||||
|
||||
.pushsection .noinstr.text, "ax"
|
||||
|
||||
/*
|
||||
* We build a jump to memcpy_orig by default which gets NOPped out on
|
||||
* the majority of x86 CPUs which set REP_GOOD. In addition, CPUs which
|
||||
@@ -184,6 +186,8 @@ SYM_FUNC_START(memcpy_orig)
|
||||
retq
|
||||
SYM_FUNC_END(memcpy_orig)
|
||||
|
||||
.popsection
|
||||
|
||||
#ifndef CONFIG_UML
|
||||
|
||||
MCSAFE_TEST_CTL
|
||||
|
@@ -18,8 +18,7 @@
|
||||
* position @h. For example
|
||||
* GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
|
||||
*/
|
||||
#if !defined(__ASSEMBLY__) && \
|
||||
(!defined(CONFIG_CC_IS_GCC) || CONFIG_GCC_VERSION >= 49000)
|
||||
#if !defined(__ASSEMBLY__)
|
||||
#include <linux/build_bug.h>
|
||||
#define GENMASK_INPUT_CHECK(h, l) \
|
||||
(BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
|
||||
|
@@ -3174,13 +3174,12 @@ union bpf_attr {
|
||||
* int bpf_ringbuf_output(void *ringbuf, void *data, u64 size, u64 flags)
|
||||
* Description
|
||||
* Copy *size* bytes from *data* into a ring buffer *ringbuf*.
|
||||
* If BPF_RB_NO_WAKEUP is specified in *flags*, no notification of
|
||||
* new data availability is sent.
|
||||
* IF BPF_RB_FORCE_WAKEUP is specified in *flags*, notification of
|
||||
* new data availability is sent unconditionally.
|
||||
* If **BPF_RB_NO_WAKEUP** is specified in *flags*, no notification
|
||||
* of new data availability is sent.
|
||||
* If **BPF_RB_FORCE_WAKEUP** is specified in *flags*, notification
|
||||
* of new data availability is sent unconditionally.
|
||||
* Return
|
||||
* 0, on success;
|
||||
* < 0, on error.
|
||||
* 0 on success, or a negative error in case of failure.
|
||||
*
|
||||
* void *bpf_ringbuf_reserve(void *ringbuf, u64 size, u64 flags)
|
||||
* Description
|
||||
@@ -3192,20 +3191,20 @@ union bpf_attr {
|
||||
* void bpf_ringbuf_submit(void *data, u64 flags)
|
||||
* Description
|
||||
* Submit reserved ring buffer sample, pointed to by *data*.
|
||||
* If BPF_RB_NO_WAKEUP is specified in *flags*, no notification of
|
||||
* new data availability is sent.
|
||||
* IF BPF_RB_FORCE_WAKEUP is specified in *flags*, notification of
|
||||
* new data availability is sent unconditionally.
|
||||
* If **BPF_RB_NO_WAKEUP** is specified in *flags*, no notification
|
||||
* of new data availability is sent.
|
||||
* If **BPF_RB_FORCE_WAKEUP** is specified in *flags*, notification
|
||||
* of new data availability is sent unconditionally.
|
||||
* Return
|
||||
* Nothing. Always succeeds.
|
||||
*
|
||||
* void bpf_ringbuf_discard(void *data, u64 flags)
|
||||
* Description
|
||||
* Discard reserved ring buffer sample, pointed to by *data*.
|
||||
* If BPF_RB_NO_WAKEUP is specified in *flags*, no notification of
|
||||
* new data availability is sent.
|
||||
* IF BPF_RB_FORCE_WAKEUP is specified in *flags*, notification of
|
||||
* new data availability is sent unconditionally.
|
||||
* If **BPF_RB_NO_WAKEUP** is specified in *flags*, no notification
|
||||
* of new data availability is sent.
|
||||
* If **BPF_RB_FORCE_WAKEUP** is specified in *flags*, notification
|
||||
* of new data availability is sent unconditionally.
|
||||
* Return
|
||||
* Nothing. Always succeeds.
|
||||
*
|
||||
@@ -3213,16 +3212,18 @@ union bpf_attr {
|
||||
* Description
|
||||
* Query various characteristics of provided ring buffer. What
|
||||
* exactly is queries is determined by *flags*:
|
||||
* - BPF_RB_AVAIL_DATA - amount of data not yet consumed;
|
||||
* - BPF_RB_RING_SIZE - the size of ring buffer;
|
||||
* - BPF_RB_CONS_POS - consumer position (can wrap around);
|
||||
* - BPF_RB_PROD_POS - producer(s) position (can wrap around);
|
||||
* Data returned is just a momentary snapshots of actual values
|
||||
*
|
||||
* * **BPF_RB_AVAIL_DATA**: Amount of data not yet consumed.
|
||||
* * **BPF_RB_RING_SIZE**: The size of ring buffer.
|
||||
* * **BPF_RB_CONS_POS**: Consumer position (can wrap around).
|
||||
* * **BPF_RB_PROD_POS**: Producer(s) position (can wrap around).
|
||||
*
|
||||
* Data returned is just a momentary snapshot of actual values
|
||||
* and could be inaccurate, so this facility should be used to
|
||||
* power heuristics and for reporting, not to make 100% correct
|
||||
* calculation.
|
||||
* Return
|
||||
* Requested value, or 0, if flags are not recognized.
|
||||
* Requested value, or 0, if *flags* are not recognized.
|
||||
*
|
||||
* long bpf_csum_level(struct sk_buff *skb, u64 level)
|
||||
* Description
|
||||
|
@@ -233,6 +233,8 @@ LIBBPF_API int bpf_load_btf(void *btf, __u32 btf_size, char *log_buf,
|
||||
LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf,
|
||||
__u32 *buf_len, __u32 *prog_id, __u32 *fd_type,
|
||||
__u64 *probe_offset, __u64 *probe_addr);
|
||||
|
||||
enum bpf_stats_type; /* defined in up-to-date linux/bpf.h */
|
||||
LIBBPF_API int bpf_enable_stats(enum bpf_stats_type type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -11,14 +11,18 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
#ifndef __WORDSIZE
|
||||
#define __WORDSIZE (__SIZEOF_LONG__ * 8)
|
||||
#endif
|
||||
|
||||
static inline size_t hash_bits(size_t h, int bits)
|
||||
{
|
||||
/* shuffle bits and return requested number of upper bits */
|
||||
return (h * 11400714819323198485llu) >> (__WORDSIZE - bits);
|
||||
#if (__SIZEOF_SIZE_T__ == __SIZEOF_LONG_LONG__)
|
||||
/* LP64 case */
|
||||
return (h * 11400714819323198485llu) >> (__SIZEOF_LONG_LONG__ * 8 - bits);
|
||||
#elif (__SIZEOF_SIZE_T__ <= __SIZEOF_LONG__)
|
||||
return (h * 2654435769lu) >> (__SIZEOF_LONG__ * 8 - bits);
|
||||
#else
|
||||
# error "Unsupported size_t size"
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef size_t (*hashmap_hash_fn)(const void *key, void *ctx);
|
||||
|
@@ -4977,7 +4977,13 @@ bpf_core_reloc_fields(struct bpf_object *obj, const char *targ_btf_path)
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
prog = bpf_object__find_program_by_title(obj, sec_name);
|
||||
prog = NULL;
|
||||
for (i = 0; i < obj->nr_programs; i++) {
|
||||
if (!strcmp(obj->programs[i].section_name, sec_name)) {
|
||||
prog = &obj->programs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!prog) {
|
||||
pr_warn("failed to find program '%s' for CO-RE offset relocation\n",
|
||||
sec_name);
|
||||
@@ -6904,7 +6910,7 @@ static const struct bpf_sec_def section_defs[] = {
|
||||
.expected_attach_type = BPF_TRACE_ITER,
|
||||
.is_attach_btf = true,
|
||||
.attach_fn = attach_iter),
|
||||
BPF_EAPROG_SEC("xdp_devmap", BPF_PROG_TYPE_XDP,
|
||||
BPF_EAPROG_SEC("xdp_devmap/", BPF_PROG_TYPE_XDP,
|
||||
BPF_XDP_DEVMAP),
|
||||
BPF_PROG_SEC("xdp", BPF_PROG_TYPE_XDP),
|
||||
BPF_PROG_SEC("perf_event", BPF_PROG_TYPE_PERF_EVENT),
|
||||
|
@@ -361,6 +361,7 @@ translate_data(struct kbuffer *kbuf, void *data, void **rptr,
|
||||
break;
|
||||
|
||||
case KBUFFER_TYPE_TIME_EXTEND:
|
||||
case KBUFFER_TYPE_TIME_STAMP:
|
||||
extend = read_4(kbuf, data);
|
||||
data += 4;
|
||||
extend <<= TS_SHIFT;
|
||||
@@ -369,10 +370,6 @@ translate_data(struct kbuffer *kbuf, void *data, void **rptr,
|
||||
*length = 0;
|
||||
break;
|
||||
|
||||
case KBUFFER_TYPE_TIME_STAMP:
|
||||
data += 12;
|
||||
*length = 0;
|
||||
break;
|
||||
case 0:
|
||||
*length = read_4(kbuf, data) - 4;
|
||||
*length = (*length + 3) & ~3;
|
||||
@@ -397,7 +394,11 @@ static unsigned int update_pointers(struct kbuffer *kbuf)
|
||||
|
||||
type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
|
||||
|
||||
kbuf->timestamp += delta;
|
||||
if (type_len == KBUFFER_TYPE_TIME_STAMP)
|
||||
kbuf->timestamp = delta;
|
||||
else
|
||||
kbuf->timestamp += delta;
|
||||
|
||||
kbuf->index = calc_index(kbuf, ptr);
|
||||
kbuf->next = kbuf->index + length;
|
||||
|
||||
@@ -454,7 +455,9 @@ static int __next_event(struct kbuffer *kbuf)
|
||||
if (kbuf->next >= kbuf->size)
|
||||
return -1;
|
||||
type = update_pointers(kbuf);
|
||||
} while (type == KBUFFER_TYPE_TIME_EXTEND || type == KBUFFER_TYPE_PADDING);
|
||||
} while (type == KBUFFER_TYPE_TIME_EXTEND ||
|
||||
type == KBUFFER_TYPE_TIME_STAMP ||
|
||||
type == KBUFFER_TYPE_PADDING);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -546,6 +549,34 @@ int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* kbuffer_subbuf_timestamp - read the timestamp from a sub buffer
|
||||
* @kbuf: The kbuffer to load
|
||||
* @subbuf: The subbuffer to read from.
|
||||
*
|
||||
* Return the timestamp from a subbuffer.
|
||||
*/
|
||||
unsigned long long kbuffer_subbuf_timestamp(struct kbuffer *kbuf, void *subbuf)
|
||||
{
|
||||
return kbuf->read_8(subbuf);
|
||||
}
|
||||
|
||||
/**
|
||||
* kbuffer_ptr_delta - read the delta field from a record
|
||||
* @kbuf: The kbuffer to load
|
||||
* @ptr: The record in the buffe.
|
||||
*
|
||||
* Return the timestamp delta from a record
|
||||
*/
|
||||
unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr)
|
||||
{
|
||||
unsigned int type_len_ts;
|
||||
|
||||
type_len_ts = read_4(kbuf, ptr);
|
||||
return ts4host(kbuf, type_len_ts);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* kbuffer_read_event - read the next event in the kbuffer subbuffer
|
||||
* @kbuf: The kbuffer to read from
|
||||
|
@@ -49,6 +49,8 @@ int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer);
|
||||
void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts);
|
||||
void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts);
|
||||
unsigned long long kbuffer_timestamp(struct kbuffer *kbuf);
|
||||
unsigned long long kbuffer_subbuf_timestamp(struct kbuffer *kbuf, void *subbuf);
|
||||
unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr);
|
||||
|
||||
void *kbuffer_translate_data(int swap, void *data, unsigned int *size);
|
||||
|
||||
|
@@ -84,4 +84,6 @@ unsigned long arch_jump_destination(struct instruction *insn);
|
||||
|
||||
unsigned long arch_dest_rela_offset(int addend);
|
||||
|
||||
const char *arch_nop_insn(int len);
|
||||
|
||||
#endif /* _ARCH_H */
|
||||
|
@@ -565,3 +565,21 @@ void arch_initial_func_cfi_state(struct cfi_init_state *state)
|
||||
state->regs[16].base = CFI_CFA;
|
||||
state->regs[16].offset = -8;
|
||||
}
|
||||
|
||||
const char *arch_nop_insn(int len)
|
||||
{
|
||||
static const char nops[5][5] = {
|
||||
/* 1 */ { 0x90 },
|
||||
/* 2 */ { 0x66, 0x90 },
|
||||
/* 3 */ { 0x0f, 0x1f, 0x00 },
|
||||
/* 4 */ { 0x0f, 0x1f, 0x40, 0x00 },
|
||||
/* 5 */ { 0x0f, 0x1f, 0x44, 0x00, 0x00 },
|
||||
};
|
||||
|
||||
if (len < 1 || len > 5) {
|
||||
WARN("invalid NOP size: %d\n", len);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nops[len-1];
|
||||
}
|
||||
|
6
tools/objtool/arch/x86/include/arch_elf.h
Normal file
6
tools/objtool/arch/x86/include/arch_elf.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _OBJTOOL_ARCH_ELF
|
||||
#define _OBJTOOL_ARCH_ELF
|
||||
|
||||
#define R_NONE R_X86_64_NONE
|
||||
|
||||
#endif /* _OBJTOOL_ARCH_ELF */
|
@@ -12,6 +12,7 @@
|
||||
#include "check.h"
|
||||
#include "special.h"
|
||||
#include "warn.h"
|
||||
#include "arch_elf.h"
|
||||
|
||||
#include <linux/hashtable.h>
|
||||
#include <linux/kernel.h>
|
||||
@@ -765,6 +766,24 @@ static int add_call_destinations(struct objtool_file *file)
|
||||
} else
|
||||
insn->call_dest = rela->sym;
|
||||
|
||||
/*
|
||||
* Many compilers cannot disable KCOV with a function attribute
|
||||
* so they need a little help, NOP out any KCOV calls from noinstr
|
||||
* text.
|
||||
*/
|
||||
if (insn->sec->noinstr &&
|
||||
!strncmp(insn->call_dest->name, "__sanitizer_cov_", 16)) {
|
||||
if (rela) {
|
||||
rela->type = R_NONE;
|
||||
elf_write_rela(file->elf, rela);
|
||||
}
|
||||
|
||||
elf_write_insn(file->elf, insn->sec,
|
||||
insn->offset, insn->len,
|
||||
arch_nop_insn(insn->len));
|
||||
insn->type = INSN_NOP;
|
||||
}
|
||||
|
||||
/*
|
||||
* Whatever stack impact regular CALLs have, should be undone
|
||||
* by the RETURN of the called function.
|
||||
@@ -2190,10 +2209,36 @@ static inline const char *call_dest_name(struct instruction *insn)
|
||||
return "{dynamic}";
|
||||
}
|
||||
|
||||
static inline bool noinstr_call_dest(struct symbol *func)
|
||||
{
|
||||
/*
|
||||
* We can't deal with indirect function calls at present;
|
||||
* assume they're instrumented.
|
||||
*/
|
||||
if (!func)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If the symbol is from a noinstr section; we good.
|
||||
*/
|
||||
if (func->sec->noinstr)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* The __ubsan_handle_*() calls are like WARN(), they only happen when
|
||||
* something 'BAD' happened. At the risk of taking the machine down,
|
||||
* let them proceed to get the message out.
|
||||
*/
|
||||
if (!strncmp(func->name, "__ubsan_handle_", 15))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int validate_call(struct instruction *insn, struct insn_state *state)
|
||||
{
|
||||
if (state->noinstr && state->instr <= 0 &&
|
||||
(!insn->call_dest || !insn->call_dest->sec->noinstr)) {
|
||||
!noinstr_call_dest(insn->call_dest)) {
|
||||
WARN_FUNC("call to %s() leaves .noinstr.text section",
|
||||
insn->sec, insn->offset, call_dest_name(insn));
|
||||
return 1;
|
||||
@@ -2740,13 +2785,13 @@ int check(const char *_objname, bool orc)
|
||||
|
||||
objname = _objname;
|
||||
|
||||
file.elf = elf_open_read(objname, orc ? O_RDWR : O_RDONLY);
|
||||
file.elf = elf_open_read(objname, O_RDWR);
|
||||
if (!file.elf)
|
||||
return 1;
|
||||
|
||||
INIT_LIST_HEAD(&file.insn_list);
|
||||
hash_init(file.insn_hash);
|
||||
file.c_file = find_section_by_name(file.elf, ".comment");
|
||||
file.c_file = !vmlinux && find_section_by_name(file.elf, ".comment");
|
||||
file.ignore_unreachables = no_unreachable;
|
||||
file.hints = false;
|
||||
|
||||
@@ -2801,7 +2846,9 @@ int check(const char *_objname, bool orc)
|
||||
ret = create_orc_sections(&file);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (file.elf->changed) {
|
||||
ret = elf_write(file.elf);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@@ -529,8 +529,9 @@ static int read_relas(struct elf *elf)
|
||||
rela->addend = rela->rela.r_addend;
|
||||
rela->offset = rela->rela.r_offset;
|
||||
symndx = GELF_R_SYM(rela->rela.r_info);
|
||||
rela->sym = find_symbol_by_index(elf, symndx);
|
||||
rela->sec = sec;
|
||||
rela->idx = i;
|
||||
rela->sym = find_symbol_by_index(elf, symndx);
|
||||
if (!rela->sym) {
|
||||
WARN("can't find rela entry symbol %d for %s",
|
||||
symndx, sec->name);
|
||||
@@ -713,6 +714,8 @@ struct section *elf_create_section(struct elf *elf, const char *name,
|
||||
elf_hash_add(elf->section_hash, &sec->hash, sec->idx);
|
||||
elf_hash_add(elf->section_name_hash, &sec->name_hash, str_hash(sec->name));
|
||||
|
||||
elf->changed = true;
|
||||
|
||||
return sec;
|
||||
}
|
||||
|
||||
@@ -746,7 +749,7 @@ struct section *elf_create_rela_section(struct elf *elf, struct section *base)
|
||||
return sec;
|
||||
}
|
||||
|
||||
int elf_rebuild_rela_section(struct section *sec)
|
||||
int elf_rebuild_rela_section(struct elf *elf, struct section *sec)
|
||||
{
|
||||
struct rela *rela;
|
||||
int nr, idx = 0, size;
|
||||
@@ -763,6 +766,9 @@ int elf_rebuild_rela_section(struct section *sec)
|
||||
return -1;
|
||||
}
|
||||
|
||||
sec->changed = true;
|
||||
elf->changed = true;
|
||||
|
||||
sec->data->d_buf = relas;
|
||||
sec->data->d_size = size;
|
||||
|
||||
@@ -779,7 +785,44 @@ int elf_rebuild_rela_section(struct section *sec)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int elf_write(const struct elf *elf)
|
||||
int elf_write_insn(struct elf *elf, struct section *sec,
|
||||
unsigned long offset, unsigned int len,
|
||||
const char *insn)
|
||||
{
|
||||
Elf_Data *data = sec->data;
|
||||
|
||||
if (data->d_type != ELF_T_BYTE || data->d_off) {
|
||||
WARN("write to unexpected data for section: %s", sec->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(data->d_buf + offset, insn, len);
|
||||
elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY);
|
||||
|
||||
elf->changed = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int elf_write_rela(struct elf *elf, struct rela *rela)
|
||||
{
|
||||
struct section *sec = rela->sec;
|
||||
|
||||
rela->rela.r_info = GELF_R_INFO(rela->sym->idx, rela->type);
|
||||
rela->rela.r_addend = rela->addend;
|
||||
rela->rela.r_offset = rela->offset;
|
||||
|
||||
if (!gelf_update_rela(sec->data, rela->idx, &rela->rela)) {
|
||||
WARN_ELF("gelf_update_rela");
|
||||
return -1;
|
||||
}
|
||||
|
||||
elf->changed = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int elf_write(struct elf *elf)
|
||||
{
|
||||
struct section *sec;
|
||||
Elf_Scn *s;
|
||||
@@ -796,6 +839,8 @@ int elf_write(const struct elf *elf)
|
||||
WARN_ELF("gelf_update_shdr");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sec->changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -808,6 +853,8 @@ int elf_write(const struct elf *elf)
|
||||
return -1;
|
||||
}
|
||||
|
||||
elf->changed = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -64,9 +64,10 @@ struct rela {
|
||||
GElf_Rela rela;
|
||||
struct section *sec;
|
||||
struct symbol *sym;
|
||||
unsigned int type;
|
||||
unsigned long offset;
|
||||
unsigned int type;
|
||||
int addend;
|
||||
int idx;
|
||||
bool jump_table_start;
|
||||
};
|
||||
|
||||
@@ -76,6 +77,7 @@ struct elf {
|
||||
Elf *elf;
|
||||
GElf_Ehdr ehdr;
|
||||
int fd;
|
||||
bool changed;
|
||||
char *name;
|
||||
struct list_head sections;
|
||||
DECLARE_HASHTABLE(symbol_hash, ELF_HASH_BITS);
|
||||
@@ -118,7 +120,11 @@ struct elf *elf_open_read(const char *name, int flags);
|
||||
struct section *elf_create_section(struct elf *elf, const char *name, size_t entsize, int nr);
|
||||
struct section *elf_create_rela_section(struct elf *elf, struct section *base);
|
||||
void elf_add_rela(struct elf *elf, struct rela *rela);
|
||||
int elf_write(const struct elf *elf);
|
||||
int elf_write_insn(struct elf *elf, struct section *sec,
|
||||
unsigned long offset, unsigned int len,
|
||||
const char *insn);
|
||||
int elf_write_rela(struct elf *elf, struct rela *rela);
|
||||
int elf_write(struct elf *elf);
|
||||
void elf_close(struct elf *elf);
|
||||
|
||||
struct section *find_section_by_name(const struct elf *elf, const char *name);
|
||||
@@ -130,7 +136,7 @@ struct rela *find_rela_by_dest(const struct elf *elf, struct section *sec, unsig
|
||||
struct rela *find_rela_by_dest_range(const struct elf *elf, struct section *sec,
|
||||
unsigned long offset, unsigned int len);
|
||||
struct symbol *find_func_containing(struct section *sec, unsigned long offset);
|
||||
int elf_rebuild_rela_section(struct section *sec);
|
||||
int elf_rebuild_rela_section(struct elf *elf, struct section *sec);
|
||||
|
||||
#define for_each_sec(file, sec) \
|
||||
list_for_each_entry(sec, &file->elf->sections, list)
|
||||
|
@@ -222,7 +222,7 @@ int create_orc_sections(struct objtool_file *file)
|
||||
}
|
||||
}
|
||||
|
||||
if (elf_rebuild_rela_section(ip_relasec))
|
||||
if (elf_rebuild_rela_section(file->elf, ip_relasec))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
|
@@ -641,6 +641,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
|
||||
}
|
||||
evsel->core.attr.freq = 0;
|
||||
evsel->core.attr.sample_period = 1;
|
||||
evsel->no_aux_samples = true;
|
||||
intel_pt_evsel = evsel;
|
||||
opts->full_auxtrace = true;
|
||||
}
|
||||
|
@@ -852,20 +852,20 @@ static int record__open(struct record *rec)
|
||||
* event synthesis.
|
||||
*/
|
||||
if (opts->initial_delay || target__has_cpu(&opts->target)) {
|
||||
if (perf_evlist__add_dummy(evlist))
|
||||
return -ENOMEM;
|
||||
pos = perf_evlist__get_tracking_event(evlist);
|
||||
if (!evsel__is_dummy_event(pos)) {
|
||||
/* Set up dummy event. */
|
||||
if (perf_evlist__add_dummy(evlist))
|
||||
return -ENOMEM;
|
||||
pos = evlist__last(evlist);
|
||||
perf_evlist__set_tracking_event(evlist, pos);
|
||||
}
|
||||
|
||||
/* Disable tracking of mmaps on lead event. */
|
||||
pos = evlist__first(evlist);
|
||||
pos->tracking = 0;
|
||||
/* Set up dummy event. */
|
||||
pos = evlist__last(evlist);
|
||||
pos->tracking = 1;
|
||||
/*
|
||||
* Enable the dummy event when the process is forked for
|
||||
* initial_delay, immediately for system wide.
|
||||
*/
|
||||
if (opts->initial_delay)
|
||||
if (opts->initial_delay && !pos->immediate)
|
||||
pos->core.attr.enable_on_exec = 1;
|
||||
else
|
||||
pos->immediate = 1;
|
||||
|
@@ -462,7 +462,7 @@ static int perf_evsel__check_attr(struct evsel *evsel, struct perf_session *sess
|
||||
return -EINVAL;
|
||||
|
||||
if (PRINT_FIELD(IREGS) &&
|
||||
evsel__check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS", PERF_OUTPUT_IREGS))
|
||||
evsel__do_check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS", PERF_OUTPUT_IREGS, allow_user_set))
|
||||
return -EINVAL;
|
||||
|
||||
if (PRINT_FIELD(UREGS) &&
|
||||
|
@@ -1055,7 +1055,7 @@ def cbr(id, raw_buf):
|
||||
cbr = data[0]
|
||||
MHz = (data[4] + 500) / 1000
|
||||
percent = ((cbr * 1000 / data[2]) + 5) / 10
|
||||
value = struct.pack("!hiqiiiiii", 4, 8, id, 4, cbr, 4, MHz, 4, percent)
|
||||
value = struct.pack("!hiqiiiiii", 4, 8, id, 4, cbr, 4, int(MHz), 4, int(percent))
|
||||
cbr_file.write(value)
|
||||
|
||||
def mwait(id, raw_buf):
|
||||
|
@@ -768,7 +768,8 @@ class CallGraphModel(CallGraphModelBase):
|
||||
" FROM calls"
|
||||
" INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
|
||||
" INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
|
||||
" WHERE symbols.name" + match +
|
||||
" WHERE calls.id <> 0"
|
||||
" AND symbols.name" + match +
|
||||
" GROUP BY comm_id, thread_id, call_path_id"
|
||||
" ORDER BY comm_id, thread_id, call_path_id")
|
||||
|
||||
@@ -963,7 +964,8 @@ class CallTreeModel(CallGraphModelBase):
|
||||
" FROM calls"
|
||||
" INNER JOIN call_paths ON calls.call_path_id = call_paths.id"
|
||||
" INNER JOIN symbols ON call_paths.symbol_id = symbols.id"
|
||||
" WHERE symbols.name" + match +
|
||||
" WHERE calls.id <> 0"
|
||||
" AND symbols.name" + match +
|
||||
" ORDER BY comm_id, thread_id, call_time, calls.id")
|
||||
|
||||
def FindPath(self, query):
|
||||
@@ -1050,6 +1052,7 @@ class TreeWindowBase(QMdiSubWindow):
|
||||
child = self.model.index(row, 0, parent)
|
||||
if child.internalPointer().dbid == dbid:
|
||||
found = True
|
||||
self.view.setExpanded(parent, True)
|
||||
self.view.setCurrentIndex(child)
|
||||
parent = child
|
||||
break
|
||||
@@ -1127,6 +1130,7 @@ class CallTreeWindow(TreeWindowBase):
|
||||
child = self.model.index(row, 0, parent)
|
||||
if child.internalPointer().dbid == dbid:
|
||||
found = True
|
||||
self.view.setExpanded(parent, True)
|
||||
self.view.setCurrentIndex(child)
|
||||
parent = child
|
||||
break
|
||||
@@ -1139,6 +1143,7 @@ class CallTreeWindow(TreeWindowBase):
|
||||
return
|
||||
last_child = None
|
||||
for row in xrange(n):
|
||||
self.view.setExpanded(parent, True)
|
||||
child = self.model.index(row, 0, parent)
|
||||
child_call_time = child.internalPointer().call_time
|
||||
if child_call_time < time:
|
||||
@@ -1151,9 +1156,11 @@ class CallTreeWindow(TreeWindowBase):
|
||||
if not last_child:
|
||||
if not found:
|
||||
child = self.model.index(0, 0, parent)
|
||||
self.view.setExpanded(parent, True)
|
||||
self.view.setCurrentIndex(child)
|
||||
return
|
||||
found = True
|
||||
self.view.setExpanded(parent, True)
|
||||
self.view.setCurrentIndex(last_child)
|
||||
parent = last_child
|
||||
|
||||
|
@@ -17,6 +17,7 @@
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import os
|
||||
import io
|
||||
import argparse
|
||||
import json
|
||||
|
||||
@@ -81,7 +82,7 @@ class FlameGraphCLI:
|
||||
|
||||
if self.args.format == "html":
|
||||
try:
|
||||
with open(self.args.template) as f:
|
||||
with io.open(self.args.template, encoding="utf-8") as f:
|
||||
output_str = f.read().replace("/** @flamegraph_json **/",
|
||||
json_str)
|
||||
except IOError as e:
|
||||
@@ -93,11 +94,12 @@ class FlameGraphCLI:
|
||||
output_fn = self.args.output or "stacks.json"
|
||||
|
||||
if output_fn == "-":
|
||||
sys.stdout.write(output_str)
|
||||
with io.open(sys.stdout.fileno(), "w", encoding="utf-8", closefd=False) as out:
|
||||
out.write(output_str)
|
||||
else:
|
||||
print("dumping data to {}".format(output_fn))
|
||||
try:
|
||||
with open(output_fn, "w") as out:
|
||||
with io.open(output_fn, "w", encoding="utf-8") as out:
|
||||
out.write(output_str)
|
||||
except IOError as e:
|
||||
print("Error writing output file: {}".format(e), file=sys.stderr)
|
||||
|
@@ -2288,6 +2288,11 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *browser
|
||||
return browser->he_selection->thread;
|
||||
}
|
||||
|
||||
static struct res_sample *hist_browser__selected_res_sample(struct hist_browser *browser)
|
||||
{
|
||||
return browser->he_selection ? browser->he_selection->res_samples : NULL;
|
||||
}
|
||||
|
||||
/* Check whether the browser is for 'top' or 'report' */
|
||||
static inline bool is_report_browser(void *timer)
|
||||
{
|
||||
@@ -3357,16 +3362,16 @@ skip_annotation:
|
||||
&options[nr_options], NULL, NULL, evsel);
|
||||
nr_options += add_res_sample_opt(browser, &actions[nr_options],
|
||||
&options[nr_options],
|
||||
hist_browser__selected_entry(browser)->res_samples,
|
||||
evsel, A_NORMAL);
|
||||
hist_browser__selected_res_sample(browser),
|
||||
evsel, A_NORMAL);
|
||||
nr_options += add_res_sample_opt(browser, &actions[nr_options],
|
||||
&options[nr_options],
|
||||
hist_browser__selected_entry(browser)->res_samples,
|
||||
evsel, A_ASM);
|
||||
hist_browser__selected_res_sample(browser),
|
||||
evsel, A_ASM);
|
||||
nr_options += add_res_sample_opt(browser, &actions[nr_options],
|
||||
&options[nr_options],
|
||||
hist_browser__selected_entry(browser)->res_samples,
|
||||
evsel, A_SOURCE);
|
||||
hist_browser__selected_res_sample(browser),
|
||||
evsel, A_SOURCE);
|
||||
nr_options += add_switch_opt(browser, &actions[nr_options],
|
||||
&options[nr_options]);
|
||||
skip_scripting:
|
||||
@@ -3598,6 +3603,23 @@ static int __perf_evlist__tui_browse_hists(struct evlist *evlist,
|
||||
hbt, warn_lost_event);
|
||||
}
|
||||
|
||||
static bool perf_evlist__single_entry(struct evlist *evlist)
|
||||
{
|
||||
int nr_entries = evlist->core.nr_entries;
|
||||
|
||||
if (nr_entries == 1)
|
||||
return true;
|
||||
|
||||
if (nr_entries == 2) {
|
||||
struct evsel *last = evlist__last(evlist);
|
||||
|
||||
if (evsel__is_dummy_event(last))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int perf_evlist__tui_browse_hists(struct evlist *evlist, const char *help,
|
||||
struct hist_browser_timer *hbt,
|
||||
float min_pcnt,
|
||||
@@ -3608,7 +3630,7 @@ int perf_evlist__tui_browse_hists(struct evlist *evlist, const char *help,
|
||||
int nr_entries = evlist->core.nr_entries;
|
||||
|
||||
single_entry:
|
||||
if (nr_entries == 1) {
|
||||
if (perf_evlist__single_entry(evlist)) {
|
||||
struct evsel *first = evlist__first(evlist);
|
||||
|
||||
return perf_evsel__hists_browse(first, nr_entries, help,
|
||||
|
@@ -1566,6 +1566,18 @@ void perf_evlist__to_front(struct evlist *evlist,
|
||||
list_splice(&move, &evlist->core.entries);
|
||||
}
|
||||
|
||||
struct evsel *perf_evlist__get_tracking_event(struct evlist *evlist)
|
||||
{
|
||||
struct evsel *evsel;
|
||||
|
||||
evlist__for_each_entry(evlist, evsel) {
|
||||
if (evsel->tracking)
|
||||
return evsel;
|
||||
}
|
||||
|
||||
return evlist__first(evlist);
|
||||
}
|
||||
|
||||
void perf_evlist__set_tracking_event(struct evlist *evlist,
|
||||
struct evsel *tracking_evsel)
|
||||
{
|
||||
|
@@ -335,6 +335,7 @@ void perf_evlist__to_front(struct evlist *evlist,
|
||||
evlist__cpu_iter_start(evlist); \
|
||||
perf_cpu_map__for_each_cpu (cpu, index, (evlist)->core.all_cpus)
|
||||
|
||||
struct evsel *perf_evlist__get_tracking_event(struct evlist *evlist);
|
||||
void perf_evlist__set_tracking_event(struct evlist *evlist,
|
||||
struct evsel *tracking_evsel);
|
||||
|
||||
|
@@ -898,12 +898,6 @@ static void evsel__apply_config_terms(struct evsel *evsel,
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_dummy_event(struct evsel *evsel)
|
||||
{
|
||||
return (evsel->core.attr.type == PERF_TYPE_SOFTWARE) &&
|
||||
(evsel->core.attr.config == PERF_COUNT_SW_DUMMY);
|
||||
}
|
||||
|
||||
struct evsel_config_term *__evsel__get_config_term(struct evsel *evsel, enum evsel_term_type type)
|
||||
{
|
||||
struct evsel_config_term *term, *found_term = NULL;
|
||||
@@ -1020,12 +1014,12 @@ void evsel__config(struct evsel *evsel, struct record_opts *opts,
|
||||
if (callchain && callchain->enabled && !evsel->no_aux_samples)
|
||||
evsel__config_callchain(evsel, opts, callchain);
|
||||
|
||||
if (opts->sample_intr_regs) {
|
||||
if (opts->sample_intr_regs && !evsel->no_aux_samples) {
|
||||
attr->sample_regs_intr = opts->sample_intr_regs;
|
||||
evsel__set_sample_bit(evsel, REGS_INTR);
|
||||
}
|
||||
|
||||
if (opts->sample_user_regs) {
|
||||
if (opts->sample_user_regs && !evsel->no_aux_samples) {
|
||||
attr->sample_regs_user |= opts->sample_user_regs;
|
||||
evsel__set_sample_bit(evsel, REGS_USER);
|
||||
}
|
||||
@@ -1161,7 +1155,7 @@ void evsel__config(struct evsel *evsel, struct record_opts *opts,
|
||||
* The software event will trigger -EOPNOTSUPP error out,
|
||||
* if BRANCH_STACK bit is set.
|
||||
*/
|
||||
if (is_dummy_event(evsel))
|
||||
if (evsel__is_dummy_event(evsel))
|
||||
evsel__reset_sample_bit(evsel, BRANCH_STACK);
|
||||
}
|
||||
|
||||
|
@@ -399,6 +399,12 @@ static inline bool evsel__has_br_stack(const struct evsel *evsel)
|
||||
evsel->synth_sample_type & PERF_SAMPLE_BRANCH_STACK;
|
||||
}
|
||||
|
||||
static inline bool evsel__is_dummy_event(struct evsel *evsel)
|
||||
{
|
||||
return (evsel->core.attr.type == PERF_TYPE_SOFTWARE) &&
|
||||
(evsel->core.attr.config == PERF_COUNT_SW_DUMMY);
|
||||
}
|
||||
|
||||
struct perf_env *evsel__env(struct evsel *evsel);
|
||||
|
||||
int evsel__store_ids(struct evsel *evsel, struct evlist *evlist);
|
||||
|
@@ -1735,6 +1735,7 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
|
||||
u64 sample_type = evsel->core.attr.sample_type;
|
||||
u64 id = evsel->core.id[0];
|
||||
u8 cpumode;
|
||||
u64 regs[8 * sizeof(sample.intr_regs.mask)];
|
||||
|
||||
if (intel_pt_skip_event(pt))
|
||||
return 0;
|
||||
@@ -1784,8 +1785,8 @@ static int intel_pt_synth_pebs_sample(struct intel_pt_queue *ptq)
|
||||
}
|
||||
|
||||
if (sample_type & PERF_SAMPLE_REGS_INTR &&
|
||||
items->mask[INTEL_PT_GP_REGS_POS]) {
|
||||
u64 regs[sizeof(sample.intr_regs.mask)];
|
||||
(items->mask[INTEL_PT_GP_REGS_POS] ||
|
||||
items->mask[INTEL_PT_XMM_POS])) {
|
||||
u64 regs_mask = evsel->core.attr.sample_regs_intr;
|
||||
u64 *pos;
|
||||
|
||||
|
@@ -82,7 +82,9 @@ def build_tests(linux: kunit_kernel.LinuxSourceTree,
|
||||
request.make_options)
|
||||
build_end = time.time()
|
||||
if not success:
|
||||
return KunitResult(KunitStatus.BUILD_FAILURE, 'could not build kernel')
|
||||
return KunitResult(KunitStatus.BUILD_FAILURE,
|
||||
'could not build kernel',
|
||||
build_end - build_start)
|
||||
if not success:
|
||||
return KunitResult(KunitStatus.BUILD_FAILURE,
|
||||
'could not build kernel',
|
||||
|
@@ -10,7 +10,7 @@ import collections
|
||||
import re
|
||||
|
||||
CONFIG_IS_NOT_SET_PATTERN = r'^# CONFIG_(\w+) is not set$'
|
||||
CONFIG_PATTERN = r'^CONFIG_(\w+)=(\S+)$'
|
||||
CONFIG_PATTERN = r'^CONFIG_(\w+)=(\S+|".*")$'
|
||||
|
||||
KconfigEntryBase = collections.namedtuple('KconfigEntry', ['name', 'value'])
|
||||
|
||||
|
@@ -265,11 +265,9 @@ def bubble_up_suite_errors(test_suite_list: List[TestSuite]) -> TestStatus:
|
||||
return bubble_up_errors(lambda x: x.status, test_suite_list)
|
||||
|
||||
def parse_test_result(lines: List[str]) -> TestResult:
|
||||
if not lines:
|
||||
return TestResult(TestStatus.NO_TESTS, [], lines)
|
||||
consume_non_diagnositic(lines)
|
||||
if not parse_tap_header(lines):
|
||||
return None
|
||||
if not lines or not parse_tap_header(lines):
|
||||
return TestResult(TestStatus.NO_TESTS, [], lines)
|
||||
test_suites = []
|
||||
test_suite = parse_test_suite(lines)
|
||||
while test_suite:
|
||||
@@ -282,6 +280,8 @@ def parse_run_tests(kernel_output) -> TestResult:
|
||||
failed_tests = 0
|
||||
crashed_tests = 0
|
||||
test_result = parse_test_result(list(isolate_kunit_output(kernel_output)))
|
||||
if test_result.status == TestStatus.NO_TESTS:
|
||||
print_with_timestamp(red('[ERROR] ') + 'no kunit output detected')
|
||||
for test_suite in test_result.suites:
|
||||
if test_suite.status == TestStatus.SUCCESS:
|
||||
print_suite_divider(green('[PASSED] ') + test_suite.name)
|
||||
|
@@ -170,6 +170,17 @@ class KUnitParserTest(unittest.TestCase):
|
||||
result.status)
|
||||
file.close()
|
||||
|
||||
def test_no_kunit_output(self):
|
||||
crash_log = get_absolute_path(
|
||||
'test_data/test_insufficient_memory.log')
|
||||
file = open(crash_log)
|
||||
print_mock = mock.patch('builtins.print').start()
|
||||
result = kunit_parser.parse_run_tests(
|
||||
kunit_parser.isolate_kunit_output(file.readlines()))
|
||||
print_mock.assert_any_call(StrContains("no kunit output detected"))
|
||||
print_mock.stop()
|
||||
file.close()
|
||||
|
||||
def test_crashed_test(self):
|
||||
crashed_log = get_absolute_path(
|
||||
'test_data/test_is_test_passed-crash.log')
|
||||
|
@@ -21,10 +21,6 @@ include ../../lib.mk
|
||||
$(TEST_GEN_PROGS): $(PROGS)
|
||||
cp $(PROGS) $(OUTPUT)/
|
||||
|
||||
clean:
|
||||
$(CLEAN)
|
||||
rm -f $(PROGS)
|
||||
|
||||
# Common test-unit targets to build common-layout test-cases executables
|
||||
# Needs secondary expansion to properly include the testcase c-file in pre-reqs
|
||||
.SECONDEXPANSION:
|
||||
|
@@ -36,7 +36,7 @@ void test_fentry_fexit(void)
|
||||
fentry_res = (__u64 *)fentry_skel->bss;
|
||||
fexit_res = (__u64 *)fexit_skel->bss;
|
||||
printf("%lld\n", fentry_skel->bss->test1_result);
|
||||
for (i = 0; i < 6; i++) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
CHECK(fentry_res[i] != 1, "result",
|
||||
"fentry_test%d failed err %lld\n", i + 1, fentry_res[i]);
|
||||
CHECK(fexit_res[i] != 1, "result",
|
||||
|
@@ -527,8 +527,8 @@ static void test_skb_less_prog_attach(struct bpf_flow *skel, int tap_fd)
|
||||
|
||||
run_tests_skb_less(tap_fd, skel->maps.last_dissection);
|
||||
|
||||
err = bpf_prog_detach(prog_fd, BPF_FLOW_DISSECTOR);
|
||||
CHECK(err, "bpf_prog_detach", "err %d errno %d\n", err, errno);
|
||||
err = bpf_prog_detach2(prog_fd, 0, BPF_FLOW_DISSECTOR);
|
||||
CHECK(err, "bpf_prog_detach2", "err %d errno %d\n", err, errno);
|
||||
}
|
||||
|
||||
static void test_skb_less_link_create(struct bpf_flow *skel, int tap_fd)
|
||||
|
@@ -1,9 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Test that the flow_dissector program can be updated with a single
|
||||
* syscall by attaching a new program that replaces the existing one.
|
||||
*
|
||||
* Corner case - the same program cannot be attached twice.
|
||||
* Tests for attaching, detaching, and replacing flow_dissector BPF program.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
@@ -116,7 +113,7 @@ static void test_prog_attach_prog_attach(int netns, int prog1, int prog2)
|
||||
CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog2));
|
||||
|
||||
out_detach:
|
||||
err = bpf_prog_detach(0, BPF_FLOW_DISSECTOR);
|
||||
err = bpf_prog_detach2(prog2, 0, BPF_FLOW_DISSECTOR);
|
||||
if (CHECK_FAIL(err))
|
||||
perror("bpf_prog_detach");
|
||||
CHECK_FAIL(prog_is_attached(netns));
|
||||
@@ -152,7 +149,7 @@ static void test_prog_attach_link_create(int netns, int prog1, int prog2)
|
||||
DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
|
||||
int err, link;
|
||||
|
||||
err = bpf_prog_attach(prog1, -1, BPF_FLOW_DISSECTOR, 0);
|
||||
err = bpf_prog_attach(prog1, 0, BPF_FLOW_DISSECTOR, 0);
|
||||
if (CHECK_FAIL(err)) {
|
||||
perror("bpf_prog_attach(prog1)");
|
||||
return;
|
||||
@@ -168,7 +165,7 @@ static void test_prog_attach_link_create(int netns, int prog1, int prog2)
|
||||
close(link);
|
||||
CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
|
||||
|
||||
err = bpf_prog_detach(-1, BPF_FLOW_DISSECTOR);
|
||||
err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
|
||||
if (CHECK_FAIL(err))
|
||||
perror("bpf_prog_detach");
|
||||
CHECK_FAIL(prog_is_attached(netns));
|
||||
@@ -188,7 +185,7 @@ static void test_link_create_prog_attach(int netns, int prog1, int prog2)
|
||||
|
||||
/* Expect failure attaching prog when link exists */
|
||||
errno = 0;
|
||||
err = bpf_prog_attach(prog2, -1, BPF_FLOW_DISSECTOR, 0);
|
||||
err = bpf_prog_attach(prog2, 0, BPF_FLOW_DISSECTOR, 0);
|
||||
if (CHECK_FAIL(!err || errno != EEXIST))
|
||||
perror("bpf_prog_attach(prog2) expected EEXIST");
|
||||
CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
|
||||
@@ -211,7 +208,7 @@ static void test_link_create_prog_detach(int netns, int prog1, int prog2)
|
||||
|
||||
/* Expect failure detaching prog when link exists */
|
||||
errno = 0;
|
||||
err = bpf_prog_detach(-1, BPF_FLOW_DISSECTOR);
|
||||
err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
|
||||
if (CHECK_FAIL(!err || errno != EINVAL))
|
||||
perror("bpf_prog_detach expected EINVAL");
|
||||
CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
|
||||
@@ -231,7 +228,7 @@ static void test_prog_attach_detach_query(int netns, int prog1, int prog2)
|
||||
}
|
||||
CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
|
||||
|
||||
err = bpf_prog_detach(0, BPF_FLOW_DISSECTOR);
|
||||
err = bpf_prog_detach2(prog1, 0, BPF_FLOW_DISSECTOR);
|
||||
if (CHECK_FAIL(err)) {
|
||||
perror("bpf_prog_detach");
|
||||
return;
|
||||
@@ -308,6 +305,31 @@ static void test_link_update_replace_old_prog(int netns, int prog1, int prog2)
|
||||
CHECK_FAIL(prog_is_attached(netns));
|
||||
}
|
||||
|
||||
static void test_link_update_same_prog(int netns, int prog1, int prog2)
|
||||
{
|
||||
DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
|
||||
DECLARE_LIBBPF_OPTS(bpf_link_update_opts, update_opts);
|
||||
int err, link;
|
||||
|
||||
link = bpf_link_create(prog1, netns, BPF_FLOW_DISSECTOR, &create_opts);
|
||||
if (CHECK_FAIL(link < 0)) {
|
||||
perror("bpf_link_create(prog1)");
|
||||
return;
|
||||
}
|
||||
CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
|
||||
|
||||
/* Expect success updating the prog with the same one */
|
||||
update_opts.flags = 0;
|
||||
update_opts.old_prog_fd = 0;
|
||||
err = bpf_link_update(link, prog1, &update_opts);
|
||||
if (CHECK_FAIL(err))
|
||||
perror("bpf_link_update");
|
||||
CHECK_FAIL(query_attached_prog_id(netns) != query_prog_id(prog1));
|
||||
|
||||
close(link);
|
||||
CHECK_FAIL(prog_is_attached(netns));
|
||||
}
|
||||
|
||||
static void test_link_update_invalid_opts(int netns, int prog1, int prog2)
|
||||
{
|
||||
DECLARE_LIBBPF_OPTS(bpf_link_create_opts, create_opts);
|
||||
@@ -571,6 +593,8 @@ static void run_tests(int netns)
|
||||
test_link_update_no_old_prog },
|
||||
{ "link update with replace old prog",
|
||||
test_link_update_replace_old_prog },
|
||||
{ "link update with same prog",
|
||||
test_link_update_same_prog },
|
||||
{ "link update invalid opts",
|
||||
test_link_update_invalid_opts },
|
||||
{ "link update invalid prog",
|
||||
|
@@ -7,7 +7,21 @@
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
static inline struct inode *SOCK_INODE(struct socket *socket)
|
||||
#define sk_rmem_alloc sk_backlog.rmem_alloc
|
||||
#define sk_refcnt __sk_common.skc_refcnt
|
||||
|
||||
struct bpf_iter_meta {
|
||||
struct seq_file *seq;
|
||||
__u64 session_id;
|
||||
__u64 seq_num;
|
||||
} __attribute__((preserve_access_index));
|
||||
|
||||
struct bpf_iter__netlink {
|
||||
struct bpf_iter_meta *meta;
|
||||
struct netlink_sock *sk;
|
||||
} __attribute__((preserve_access_index));
|
||||
|
||||
static __attribute__((noinline)) struct inode *SOCK_INODE(struct socket *socket)
|
||||
{
|
||||
return &container_of(socket, struct socket_alloc, socket)->vfs_inode;
|
||||
}
|
||||
|
@@ -55,3 +55,25 @@ int BPF_PROG(test6, __u64 a, void *b, short c, int d, void * e, __u64 f)
|
||||
e == (void *)20 && f == 21;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bpf_fentry_test_t {
|
||||
struct bpf_fentry_test_t *a;
|
||||
};
|
||||
|
||||
__u64 test7_result = 0;
|
||||
SEC("fentry/bpf_fentry_test7")
|
||||
int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
|
||||
{
|
||||
if (arg == 0)
|
||||
test7_result = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__u64 test8_result = 0;
|
||||
SEC("fentry/bpf_fentry_test8")
|
||||
int BPF_PROG(test8, struct bpf_fentry_test_t *arg)
|
||||
{
|
||||
if (arg->a == 0)
|
||||
test8_result = 1;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -56,3 +56,25 @@ int BPF_PROG(test6, __u64 a, void *b, short c, int d, void *e, __u64 f, int ret)
|
||||
e == (void *)20 && f == 21 && ret == 111;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct bpf_fentry_test_t {
|
||||
struct bpf_fentry_test *a;
|
||||
};
|
||||
|
||||
__u64 test7_result = 0;
|
||||
SEC("fexit/bpf_fentry_test7")
|
||||
int BPF_PROG(test7, struct bpf_fentry_test_t *arg)
|
||||
{
|
||||
if (arg == 0)
|
||||
test7_result = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__u64 test8_result = 0;
|
||||
SEC("fexit/bpf_fentry_test8")
|
||||
int BPF_PROG(test8, struct bpf_fentry_test_t *arg)
|
||||
{
|
||||
if (arg->a == 0)
|
||||
test8_result = 1;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -79,7 +79,7 @@ struct {
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(max_entries, 2);
|
||||
__uint(max_entries, 3);
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
} sock_skb_opts SEC(".maps");
|
||||
@@ -94,6 +94,12 @@ struct {
|
||||
SEC("sk_skb1")
|
||||
int bpf_prog1(struct __sk_buff *skb)
|
||||
{
|
||||
int *f, two = 2;
|
||||
|
||||
f = bpf_map_lookup_elem(&sock_skb_opts, &two);
|
||||
if (f && *f) {
|
||||
return *f;
|
||||
}
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
|
@@ -27,7 +27,7 @@ int xdp_dummy_prog(struct xdp_md *ctx)
|
||||
/* valid program on DEVMAP entry via SEC name;
|
||||
* has access to egress and ingress ifindex
|
||||
*/
|
||||
SEC("xdp_devmap")
|
||||
SEC("xdp_devmap/map_prog")
|
||||
int xdp_dummy_dm(struct xdp_md *ctx)
|
||||
{
|
||||
char fmt[] = "devmap redirect: dev %u -> dev %u len %u\n";
|
||||
|
@@ -789,19 +789,19 @@ static void test_sockmap(unsigned int tasks, void *data)
|
||||
}
|
||||
|
||||
err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
|
||||
if (err) {
|
||||
if (!err) {
|
||||
printf("Failed empty parser prog detach\n");
|
||||
goto out_sockmap;
|
||||
}
|
||||
|
||||
err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
|
||||
if (err) {
|
||||
if (!err) {
|
||||
printf("Failed empty verdict prog detach\n");
|
||||
goto out_sockmap;
|
||||
}
|
||||
|
||||
err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT);
|
||||
if (err) {
|
||||
if (!err) {
|
||||
printf("Failed empty msg verdict prog detach\n");
|
||||
goto out_sockmap;
|
||||
}
|
||||
@@ -1090,19 +1090,19 @@ static void test_sockmap(unsigned int tasks, void *data)
|
||||
assert(status == 0);
|
||||
}
|
||||
|
||||
err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
|
||||
err = bpf_prog_detach2(parse_prog, map_fd_rx, __MAX_BPF_ATTACH_TYPE);
|
||||
if (!err) {
|
||||
printf("Detached an invalid prog type.\n");
|
||||
goto out_sockmap;
|
||||
}
|
||||
|
||||
err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
|
||||
err = bpf_prog_detach2(parse_prog, map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
|
||||
if (err) {
|
||||
printf("Failed parser prog detach\n");
|
||||
goto out_sockmap;
|
||||
}
|
||||
|
||||
err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
|
||||
err = bpf_prog_detach2(verdict_prog, map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
|
||||
if (err) {
|
||||
printf("Failed parser prog detach\n");
|
||||
goto out_sockmap;
|
||||
|
@@ -85,6 +85,7 @@ int txmsg_ktls_skb_drop;
|
||||
int txmsg_ktls_skb_redir;
|
||||
int ktls;
|
||||
int peek_flag;
|
||||
int skb_use_parser;
|
||||
|
||||
static const struct option long_options[] = {
|
||||
{"help", no_argument, NULL, 'h' },
|
||||
@@ -174,6 +175,7 @@ static void test_reset(void)
|
||||
txmsg_apply = txmsg_cork = 0;
|
||||
txmsg_ingress = txmsg_redir_skb = 0;
|
||||
txmsg_ktls_skb = txmsg_ktls_skb_drop = txmsg_ktls_skb_redir = 0;
|
||||
skb_use_parser = 0;
|
||||
}
|
||||
|
||||
static int test_start_subtest(const struct _test *t, struct sockmap_options *o)
|
||||
@@ -1211,6 +1213,11 @@ run:
|
||||
}
|
||||
}
|
||||
|
||||
if (skb_use_parser) {
|
||||
i = 2;
|
||||
err = bpf_map_update_elem(map_fd[7], &i, &skb_use_parser, BPF_ANY);
|
||||
}
|
||||
|
||||
if (txmsg_drop)
|
||||
options->drop_expected = true;
|
||||
|
||||
@@ -1650,6 +1657,16 @@ static void test_txmsg_cork(int cgrp, struct sockmap_options *opt)
|
||||
test_send(opt, cgrp);
|
||||
}
|
||||
|
||||
static void test_txmsg_ingress_parser(int cgrp, struct sockmap_options *opt)
|
||||
{
|
||||
txmsg_pass = 1;
|
||||
skb_use_parser = 512;
|
||||
opt->iov_length = 256;
|
||||
opt->iov_count = 1;
|
||||
opt->rate = 2;
|
||||
test_exec(cgrp, opt);
|
||||
}
|
||||
|
||||
char *map_names[] = {
|
||||
"sock_map",
|
||||
"sock_map_txmsg",
|
||||
@@ -1748,6 +1765,7 @@ struct _test test[] = {
|
||||
{"txmsg test pull-data", test_txmsg_pull},
|
||||
{"txmsg test pop-data", test_txmsg_pop},
|
||||
{"txmsg test push/pop data", test_txmsg_push_pop},
|
||||
{"txmsg text ingress parser", test_txmsg_ingress_parser},
|
||||
};
|
||||
|
||||
static int check_whitelist(struct _test *t, struct sockmap_options *opt)
|
||||
|
@@ -63,6 +63,8 @@ ALL_TESTS="$ALL_TESTS 0008:150:1"
|
||||
ALL_TESTS="$ALL_TESTS 0009:150:1"
|
||||
ALL_TESTS="$ALL_TESTS 0010:1:1"
|
||||
ALL_TESTS="$ALL_TESTS 0011:1:1"
|
||||
ALL_TESTS="$ALL_TESTS 0012:1:1"
|
||||
ALL_TESTS="$ALL_TESTS 0013:1:1"
|
||||
|
||||
# Kselftest framework requirement - SKIP code is 4.
|
||||
ksft_skip=4
|
||||
@@ -470,6 +472,38 @@ kmod_test_0011()
|
||||
echo "$MODPROBE" > /proc/sys/kernel/modprobe
|
||||
}
|
||||
|
||||
kmod_check_visibility()
|
||||
{
|
||||
local name="$1"
|
||||
local cmd="$2"
|
||||
|
||||
modprobe $DEFAULT_KMOD_DRIVER
|
||||
|
||||
local priv=$(eval $cmd)
|
||||
local unpriv=$(capsh --drop=CAP_SYSLOG -- -c "$cmd")
|
||||
|
||||
if [ "$priv" = "$unpriv" ] || \
|
||||
[ "${priv:0:3}" = "0x0" ] || \
|
||||
[ "${unpriv:0:3}" != "0x0" ] ; then
|
||||
echo "${FUNCNAME[0]}: FAIL, $name visible to unpriv: '$priv' vs '$unpriv'" >&2
|
||||
exit 1
|
||||
else
|
||||
echo "${FUNCNAME[0]}: OK!"
|
||||
fi
|
||||
}
|
||||
|
||||
kmod_test_0012()
|
||||
{
|
||||
kmod_check_visibility /proc/modules \
|
||||
"grep '^${DEFAULT_KMOD_DRIVER}\b' /proc/modules | awk '{print \$NF}'"
|
||||
}
|
||||
|
||||
kmod_test_0013()
|
||||
{
|
||||
kmod_check_visibility '/sys/module/*/sections/*' \
|
||||
"cat /sys/module/${DEFAULT_KMOD_DRIVER}/sections/.*text | head -n1"
|
||||
}
|
||||
|
||||
list_tests()
|
||||
{
|
||||
echo "Test ID list:"
|
||||
@@ -489,6 +523,8 @@ list_tests()
|
||||
echo "0009 x $(get_test_count 0009) - multithreaded - push kmod_concurrent over max_modprobes for get_fs_type()"
|
||||
echo "0010 x $(get_test_count 0010) - test nonexistent modprobe path"
|
||||
echo "0011 x $(get_test_count 0011) - test completely disabling module autoloading"
|
||||
echo "0012 x $(get_test_count 0012) - test /proc/modules address visibility under CAP_SYSLOG"
|
||||
echo "0013 x $(get_test_count 0013) - test /sys/module/*/sections/* visibility under CAP_SYSLOG"
|
||||
}
|
||||
|
||||
usage()
|
||||
|
@@ -36,7 +36,7 @@ struct ksft_count {
|
||||
static struct ksft_count ksft_cnt;
|
||||
static unsigned int ksft_plan;
|
||||
|
||||
static inline int ksft_test_num(void)
|
||||
static inline unsigned int ksft_test_num(void)
|
||||
{
|
||||
return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail +
|
||||
ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass +
|
||||
|
@@ -747,6 +747,19 @@ ipv6_fcnal_runtime()
|
||||
run_cmd "$IP nexthop add id 86 via 2001:db8:91::2 dev veth1"
|
||||
run_cmd "$IP ro add 2001:db8:101::1/128 nhid 81"
|
||||
|
||||
# rpfilter and default route
|
||||
$IP nexthop flush >/dev/null 2>&1
|
||||
run_cmd "ip netns exec me ip6tables -t mangle -I PREROUTING 1 -m rpfilter --invert -j DROP"
|
||||
run_cmd "$IP nexthop add id 91 via 2001:db8:91::2 dev veth1"
|
||||
run_cmd "$IP nexthop add id 92 via 2001:db8:92::2 dev veth3"
|
||||
run_cmd "$IP nexthop add id 93 group 91/92"
|
||||
run_cmd "$IP -6 ro add default nhid 91"
|
||||
run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
|
||||
log_test $? 0 "Nexthop with default route and rpfilter"
|
||||
run_cmd "$IP -6 ro replace default nhid 93"
|
||||
run_cmd "ip netns exec me ping -c1 -w1 2001:db8:101::1"
|
||||
log_test $? 0 "Nexthop with multipath default route and rpfilter"
|
||||
|
||||
# TO-DO:
|
||||
# existing route with old nexthop; append route with new nexthop
|
||||
# existing route with old nexthop; replace route with new
|
||||
|
@@ -7,7 +7,7 @@ noarg:
|
||||
# The EBB handler is 64-bit code and everything links against it
|
||||
CFLAGS += -m64
|
||||
|
||||
TMPOUT = $(OUTPUT)/
|
||||
TMPOUT = $(OUTPUT)/TMPDIR/
|
||||
# Toolchains may build PIE by default which breaks the assembly
|
||||
no-pie-option := $(call try-run, echo 'int main() { return 0; }' | \
|
||||
$(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -no-pie -x c - -o "$$TMP", -no-pie)
|
||||
|
@@ -1,15 +1,10 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
|
||||
|
||||
# Kselftest framework requirement - SKIP code is 4.
|
||||
ksft_skip=4
|
||||
|
||||
[ -f /dev/tpm0 ] || exit $ksft_skip
|
||||
[ -e /dev/tpm0 ] || exit $ksft_skip
|
||||
|
||||
python -m unittest -v tpm2_tests.SmokeTest
|
||||
python -m unittest -v tpm2_tests.AsyncTest
|
||||
|
||||
CLEAR_CMD=$(which tpm2_clear)
|
||||
if [ -n $CLEAR_CMD ]; then
|
||||
tpm2_clear -T device
|
||||
fi
|
||||
python3 -m unittest -v tpm2_tests.SmokeTest
|
||||
python3 -m unittest -v tpm2_tests.AsyncTest
|
||||
|
@@ -1,9 +1,9 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
|
||||
|
||||
# Kselftest framework requirement - SKIP code is 4.
|
||||
ksft_skip=4
|
||||
|
||||
[ -f /dev/tpmrm0 ] || exit $ksft_skip
|
||||
[ -e /dev/tpmrm0 ] || exit $ksft_skip
|
||||
|
||||
python -m unittest -v tpm2_tests.SpaceTest
|
||||
python3 -m unittest -v tpm2_tests.SpaceTest
|
||||
|
@@ -247,14 +247,14 @@ class ProtocolError(Exception):
|
||||
class AuthCommand(object):
|
||||
"""TPMS_AUTH_COMMAND"""
|
||||
|
||||
def __init__(self, session_handle=TPM2_RS_PW, nonce='', session_attributes=0,
|
||||
hmac=''):
|
||||
def __init__(self, session_handle=TPM2_RS_PW, nonce=bytes(),
|
||||
session_attributes=0, hmac=bytes()):
|
||||
self.session_handle = session_handle
|
||||
self.nonce = nonce
|
||||
self.session_attributes = session_attributes
|
||||
self.hmac = hmac
|
||||
|
||||
def __str__(self):
|
||||
def __bytes__(self):
|
||||
fmt = '>I H%us B H%us' % (len(self.nonce), len(self.hmac))
|
||||
return struct.pack(fmt, self.session_handle, len(self.nonce),
|
||||
self.nonce, self.session_attributes, len(self.hmac),
|
||||
@@ -268,11 +268,11 @@ class AuthCommand(object):
|
||||
class SensitiveCreate(object):
|
||||
"""TPMS_SENSITIVE_CREATE"""
|
||||
|
||||
def __init__(self, user_auth='', data=''):
|
||||
def __init__(self, user_auth=bytes(), data=bytes()):
|
||||
self.user_auth = user_auth
|
||||
self.data = data
|
||||
|
||||
def __str__(self):
|
||||
def __bytes__(self):
|
||||
fmt = '>H%us H%us' % (len(self.user_auth), len(self.data))
|
||||
return struct.pack(fmt, len(self.user_auth), self.user_auth,
|
||||
len(self.data), self.data)
|
||||
@@ -296,8 +296,9 @@ class Public(object):
|
||||
return '>HHIH%us%usH%us' % \
|
||||
(len(self.auth_policy), len(self.parameters), len(self.unique))
|
||||
|
||||
def __init__(self, object_type, name_alg, object_attributes, auth_policy='',
|
||||
parameters='', unique=''):
|
||||
def __init__(self, object_type, name_alg, object_attributes,
|
||||
auth_policy=bytes(), parameters=bytes(),
|
||||
unique=bytes()):
|
||||
self.object_type = object_type
|
||||
self.name_alg = name_alg
|
||||
self.object_attributes = object_attributes
|
||||
@@ -305,7 +306,7 @@ class Public(object):
|
||||
self.parameters = parameters
|
||||
self.unique = unique
|
||||
|
||||
def __str__(self):
|
||||
def __bytes__(self):
|
||||
return struct.pack(self.__fmt(),
|
||||
self.object_type,
|
||||
self.name_alg,
|
||||
@@ -343,7 +344,7 @@ def get_algorithm(name):
|
||||
|
||||
def hex_dump(d):
|
||||
d = [format(ord(x), '02x') for x in d]
|
||||
d = [d[i: i + 16] for i in xrange(0, len(d), 16)]
|
||||
d = [d[i: i + 16] for i in range(0, len(d), 16)]
|
||||
d = [' '.join(x) for x in d]
|
||||
d = os.linesep.join(d)
|
||||
|
||||
@@ -401,7 +402,7 @@ class Client:
|
||||
pcrsel_len = max((i >> 3) + 1, 3)
|
||||
pcrsel = [0] * pcrsel_len
|
||||
pcrsel[i >> 3] = 1 << (i & 7)
|
||||
pcrsel = ''.join(map(chr, pcrsel))
|
||||
pcrsel = ''.join(map(chr, pcrsel)).encode()
|
||||
|
||||
fmt = '>HII IHB%us' % (pcrsel_len)
|
||||
cmd = struct.pack(fmt,
|
||||
@@ -443,7 +444,7 @@ class Client:
|
||||
TPM2_CC_PCR_EXTEND,
|
||||
i,
|
||||
len(auth_cmd),
|
||||
str(auth_cmd),
|
||||
bytes(auth_cmd),
|
||||
1, bank_alg, dig)
|
||||
|
||||
self.send_cmd(cmd)
|
||||
@@ -457,7 +458,7 @@ class Client:
|
||||
TPM2_RH_NULL,
|
||||
TPM2_RH_NULL,
|
||||
16,
|
||||
'\0' * 16,
|
||||
('\0' * 16).encode(),
|
||||
0,
|
||||
session_type,
|
||||
TPM2_ALG_NULL,
|
||||
@@ -472,7 +473,7 @@ class Client:
|
||||
|
||||
for i in pcrs:
|
||||
pcr = self.read_pcr(i, bank_alg)
|
||||
if pcr == None:
|
||||
if pcr is None:
|
||||
return None
|
||||
x += pcr
|
||||
|
||||
@@ -489,7 +490,7 @@ class Client:
|
||||
pcrsel = [0] * pcrsel_len
|
||||
for i in pcrs:
|
||||
pcrsel[i >> 3] |= 1 << (i & 7)
|
||||
pcrsel = ''.join(map(chr, pcrsel))
|
||||
pcrsel = ''.join(map(chr, pcrsel)).encode()
|
||||
|
||||
fmt = '>HII IH%usIHB3s' % ds
|
||||
cmd = struct.pack(fmt,
|
||||
@@ -497,7 +498,8 @@ class Client:
|
||||
struct.calcsize(fmt),
|
||||
TPM2_CC_POLICY_PCR,
|
||||
handle,
|
||||
len(dig), str(dig),
|
||||
len(dig),
|
||||
bytes(dig),
|
||||
1,
|
||||
bank_alg,
|
||||
pcrsel_len, pcrsel)
|
||||
@@ -534,7 +536,7 @@ class Client:
|
||||
|
||||
self.send_cmd(cmd)
|
||||
|
||||
def create_root_key(self, auth_value = ''):
|
||||
def create_root_key(self, auth_value = bytes()):
|
||||
attributes = \
|
||||
Public.FIXED_TPM | \
|
||||
Public.FIXED_PARENT | \
|
||||
@@ -570,11 +572,11 @@ class Client:
|
||||
TPM2_CC_CREATE_PRIMARY,
|
||||
TPM2_RH_OWNER,
|
||||
len(auth_cmd),
|
||||
str(auth_cmd),
|
||||
bytes(auth_cmd),
|
||||
len(sensitive),
|
||||
str(sensitive),
|
||||
bytes(sensitive),
|
||||
len(public),
|
||||
str(public),
|
||||
bytes(public),
|
||||
0, 0)
|
||||
|
||||
return struct.unpack('>I', self.send_cmd(cmd)[10:14])[0]
|
||||
@@ -587,7 +589,7 @@ class Client:
|
||||
attributes = 0
|
||||
if not policy_dig:
|
||||
attributes |= Public.USER_WITH_AUTH
|
||||
policy_dig = ''
|
||||
policy_dig = bytes()
|
||||
|
||||
auth_cmd = AuthCommand()
|
||||
sensitive = SensitiveCreate(user_auth=auth_value, data=data)
|
||||
@@ -608,11 +610,11 @@ class Client:
|
||||
TPM2_CC_CREATE,
|
||||
parent_key,
|
||||
len(auth_cmd),
|
||||
str(auth_cmd),
|
||||
bytes(auth_cmd),
|
||||
len(sensitive),
|
||||
str(sensitive),
|
||||
bytes(sensitive),
|
||||
len(public),
|
||||
str(public),
|
||||
bytes(public),
|
||||
0, 0)
|
||||
|
||||
rsp = self.send_cmd(cmd)
|
||||
@@ -635,7 +637,7 @@ class Client:
|
||||
TPM2_CC_LOAD,
|
||||
parent_key,
|
||||
len(auth_cmd),
|
||||
str(auth_cmd),
|
||||
bytes(auth_cmd),
|
||||
blob)
|
||||
|
||||
data_handle = struct.unpack('>I', self.send_cmd(cmd)[10:14])[0]
|
||||
@@ -653,7 +655,7 @@ class Client:
|
||||
TPM2_CC_UNSEAL,
|
||||
data_handle,
|
||||
len(auth_cmd),
|
||||
str(auth_cmd))
|
||||
bytes(auth_cmd))
|
||||
|
||||
try:
|
||||
rsp = self.send_cmd(cmd)
|
||||
@@ -675,7 +677,7 @@ class Client:
|
||||
TPM2_CC_DICTIONARY_ATTACK_LOCK_RESET,
|
||||
TPM2_RH_LOCKOUT,
|
||||
len(auth_cmd),
|
||||
str(auth_cmd))
|
||||
bytes(auth_cmd))
|
||||
|
||||
self.send_cmd(cmd)
|
||||
|
||||
@@ -693,7 +695,7 @@ class Client:
|
||||
more_data, cap, cnt = struct.unpack('>BII', rsp[:9])
|
||||
rsp = rsp[9:]
|
||||
|
||||
for i in xrange(0, cnt):
|
||||
for i in range(0, cnt):
|
||||
handle = struct.unpack('>I', rsp[:4])[0]
|
||||
handles.append(handle)
|
||||
rsp = rsp[4:]
|
||||
|
@@ -20,8 +20,8 @@ class SmokeTest(unittest.TestCase):
|
||||
self.client.close()
|
||||
|
||||
def test_seal_with_auth(self):
|
||||
data = 'X' * 64
|
||||
auth = 'A' * 15
|
||||
data = ('X' * 64).encode()
|
||||
auth = ('A' * 15).encode()
|
||||
|
||||
blob = self.client.seal(self.root_key, data, auth, None)
|
||||
result = self.client.unseal(self.root_key, blob, auth, None)
|
||||
@@ -30,8 +30,8 @@ class SmokeTest(unittest.TestCase):
|
||||
def test_seal_with_policy(self):
|
||||
handle = self.client.start_auth_session(tpm2.TPM2_SE_TRIAL)
|
||||
|
||||
data = 'X' * 64
|
||||
auth = 'A' * 15
|
||||
data = ('X' * 64).encode()
|
||||
auth = ('A' * 15).encode()
|
||||
pcrs = [16]
|
||||
|
||||
try:
|
||||
@@ -58,14 +58,15 @@ class SmokeTest(unittest.TestCase):
|
||||
self.assertEqual(data, result)
|
||||
|
||||
def test_unseal_with_wrong_auth(self):
|
||||
data = 'X' * 64
|
||||
auth = 'A' * 20
|
||||
data = ('X' * 64).encode()
|
||||
auth = ('A' * 20).encode()
|
||||
rc = 0
|
||||
|
||||
blob = self.client.seal(self.root_key, data, auth, None)
|
||||
try:
|
||||
result = self.client.unseal(self.root_key, blob, auth[:-1] + 'B', None)
|
||||
except ProtocolError, e:
|
||||
result = self.client.unseal(self.root_key, blob,
|
||||
auth[:-1] + 'B'.encode(), None)
|
||||
except ProtocolError as e:
|
||||
rc = e.rc
|
||||
|
||||
self.assertEqual(rc, tpm2.TPM2_RC_AUTH_FAIL)
|
||||
@@ -73,8 +74,8 @@ class SmokeTest(unittest.TestCase):
|
||||
def test_unseal_with_wrong_policy(self):
|
||||
handle = self.client.start_auth_session(tpm2.TPM2_SE_TRIAL)
|
||||
|
||||
data = 'X' * 64
|
||||
auth = 'A' * 17
|
||||
data = ('X' * 64).encode()
|
||||
auth = ('A' * 17).encode()
|
||||
pcrs = [16]
|
||||
|
||||
try:
|
||||
@@ -91,7 +92,7 @@ class SmokeTest(unittest.TestCase):
|
||||
# This should succeed.
|
||||
|
||||
ds = tpm2.get_digest_size(tpm2.TPM2_ALG_SHA1)
|
||||
self.client.extend_pcr(1, 'X' * ds)
|
||||
self.client.extend_pcr(1, ('X' * ds).encode())
|
||||
|
||||
handle = self.client.start_auth_session(tpm2.TPM2_SE_POLICY)
|
||||
|
||||
@@ -108,7 +109,7 @@ class SmokeTest(unittest.TestCase):
|
||||
|
||||
# Then, extend a PCR that is part of the policy and try to unseal.
|
||||
# This should fail.
|
||||
self.client.extend_pcr(16, 'X' * ds)
|
||||
self.client.extend_pcr(16, ('X' * ds).encode())
|
||||
|
||||
handle = self.client.start_auth_session(tpm2.TPM2_SE_POLICY)
|
||||
|
||||
@@ -119,7 +120,7 @@ class SmokeTest(unittest.TestCase):
|
||||
self.client.policy_password(handle)
|
||||
|
||||
result = self.client.unseal(self.root_key, blob, auth, handle)
|
||||
except ProtocolError, e:
|
||||
except ProtocolError as e:
|
||||
rc = e.rc
|
||||
self.client.flush_context(handle)
|
||||
except:
|
||||
@@ -130,13 +131,13 @@ class SmokeTest(unittest.TestCase):
|
||||
|
||||
def test_seal_with_too_long_auth(self):
|
||||
ds = tpm2.get_digest_size(tpm2.TPM2_ALG_SHA1)
|
||||
data = 'X' * 64
|
||||
auth = 'A' * (ds + 1)
|
||||
data = ('X' * 64).encode()
|
||||
auth = ('A' * (ds + 1)).encode()
|
||||
|
||||
rc = 0
|
||||
try:
|
||||
blob = self.client.seal(self.root_key, data, auth, None)
|
||||
except ProtocolError, e:
|
||||
except ProtocolError as e:
|
||||
rc = e.rc
|
||||
|
||||
self.assertEqual(rc, tpm2.TPM2_RC_SIZE)
|
||||
@@ -152,7 +153,7 @@ class SmokeTest(unittest.TestCase):
|
||||
0xDEADBEEF)
|
||||
|
||||
self.client.send_cmd(cmd)
|
||||
except IOError, e:
|
||||
except IOError as e:
|
||||
rejected = True
|
||||
except:
|
||||
pass
|
||||
@@ -212,7 +213,7 @@ class SmokeTest(unittest.TestCase):
|
||||
self.client.tpm.write(cmd)
|
||||
rsp = self.client.tpm.read()
|
||||
|
||||
except IOError, e:
|
||||
except IOError as e:
|
||||
# read the response
|
||||
rsp = self.client.tpm.read()
|
||||
rejected = True
|
||||
@@ -283,7 +284,7 @@ class SpaceTest(unittest.TestCase):
|
||||
rc = 0
|
||||
try:
|
||||
space1.send_cmd(cmd)
|
||||
except ProtocolError, e:
|
||||
except ProtocolError as e:
|
||||
rc = e.rc
|
||||
|
||||
self.assertEqual(rc, tpm2.TPM2_RC_COMMAND_CODE |
|
||||
|
@@ -70,10 +70,10 @@ all_64: $(BINARIES_64)
|
||||
|
||||
EXTRA_CLEAN := $(BINARIES_32) $(BINARIES_64)
|
||||
|
||||
$(BINARIES_32): $(OUTPUT)/%_32: %.c
|
||||
$(BINARIES_32): $(OUTPUT)/%_32: %.c helpers.h
|
||||
$(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm
|
||||
|
||||
$(BINARIES_64): $(OUTPUT)/%_64: %.c
|
||||
$(BINARIES_64): $(OUTPUT)/%_64: %.c helpers.h
|
||||
$(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
|
||||
|
||||
# x86_64 users should be encouraged to install 32-bit libraries
|
||||
|
41
tools/testing/selftests/x86/helpers.h
Normal file
41
tools/testing/selftests/x86/helpers.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#ifndef __SELFTESTS_X86_HELPERS_H
|
||||
#define __SELFTESTS_X86_HELPERS_H
|
||||
|
||||
#include <asm/processor-flags.h>
|
||||
|
||||
static inline unsigned long get_eflags(void)
|
||||
{
|
||||
unsigned long eflags;
|
||||
|
||||
asm volatile (
|
||||
#ifdef __x86_64__
|
||||
"subq $128, %%rsp\n\t"
|
||||
"pushfq\n\t"
|
||||
"popq %0\n\t"
|
||||
"addq $128, %%rsp"
|
||||
#else
|
||||
"pushfl\n\t"
|
||||
"popl %0"
|
||||
#endif
|
||||
: "=r" (eflags) :: "memory");
|
||||
|
||||
return eflags;
|
||||
}
|
||||
|
||||
static inline void set_eflags(unsigned long eflags)
|
||||
{
|
||||
asm volatile (
|
||||
#ifdef __x86_64__
|
||||
"subq $128, %%rsp\n\t"
|
||||
"pushq %0\n\t"
|
||||
"popfq\n\t"
|
||||
"addq $128, %%rsp"
|
||||
#else
|
||||
"pushl %0\n\t"
|
||||
"popfl"
|
||||
#endif
|
||||
:: "r" (eflags) : "flags", "memory");
|
||||
}
|
||||
|
||||
#endif /* __SELFTESTS_X86_HELPERS_H */
|
@@ -31,6 +31,8 @@
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
|
||||
int flags)
|
||||
{
|
||||
@@ -67,21 +69,6 @@ static unsigned char altstack_data[SIGSTKSZ];
|
||||
# define INT80_CLOBBERS
|
||||
#endif
|
||||
|
||||
static unsigned long get_eflags(void)
|
||||
{
|
||||
unsigned long eflags;
|
||||
asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
|
||||
return eflags;
|
||||
}
|
||||
|
||||
static void set_eflags(unsigned long eflags)
|
||||
{
|
||||
asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
|
||||
: : "rm" (eflags) : "flags");
|
||||
}
|
||||
|
||||
#define X86_EFLAGS_TF (1UL << 8)
|
||||
|
||||
static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
|
||||
{
|
||||
ucontext_t *ctx = (ucontext_t*)ctx_void;
|
||||
|
@@ -15,30 +15,11 @@
|
||||
#include <setjmp.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __x86_64__
|
||||
# define WIDTH "q"
|
||||
#else
|
||||
# define WIDTH "l"
|
||||
#endif
|
||||
#include "helpers.h"
|
||||
|
||||
/* Our sigaltstack scratch space. */
|
||||
static unsigned char altstack_data[SIGSTKSZ];
|
||||
|
||||
static unsigned long get_eflags(void)
|
||||
{
|
||||
unsigned long eflags;
|
||||
asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
|
||||
return eflags;
|
||||
}
|
||||
|
||||
static void set_eflags(unsigned long eflags)
|
||||
{
|
||||
asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
|
||||
: : "rm" (eflags) : "flags");
|
||||
}
|
||||
|
||||
#define X86_EFLAGS_TF (1UL << 8)
|
||||
|
||||
static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
|
||||
int flags)
|
||||
{
|
||||
|
@@ -13,29 +13,11 @@
|
||||
#include <signal.h>
|
||||
#include <err.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <asm/processor-flags.h>
|
||||
|
||||
#ifdef __x86_64__
|
||||
# define WIDTH "q"
|
||||
#else
|
||||
# define WIDTH "l"
|
||||
#endif
|
||||
#include "helpers.h"
|
||||
|
||||
static unsigned int nerrs;
|
||||
|
||||
static unsigned long get_eflags(void)
|
||||
{
|
||||
unsigned long eflags;
|
||||
asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
|
||||
return eflags;
|
||||
}
|
||||
|
||||
static void set_eflags(unsigned long eflags)
|
||||
{
|
||||
asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
|
||||
: : "rm" (eflags) : "flags");
|
||||
}
|
||||
|
||||
static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
|
||||
int flags)
|
||||
{
|
||||
@@ -59,6 +41,7 @@ static void do_it(unsigned long extraflags)
|
||||
set_eflags(get_eflags() | extraflags);
|
||||
syscall(SYS_getpid);
|
||||
flags = get_eflags();
|
||||
set_eflags(X86_EFLAGS_IF | X86_EFLAGS_FIXED);
|
||||
if ((flags & extraflags) == extraflags) {
|
||||
printf("[OK]\tThe syscall worked and flags are still set\n");
|
||||
} else {
|
||||
@@ -73,6 +56,12 @@ int main(void)
|
||||
printf("[RUN]\tSet NT and issue a syscall\n");
|
||||
do_it(X86_EFLAGS_NT);
|
||||
|
||||
printf("[RUN]\tSet AC and issue a syscall\n");
|
||||
do_it(X86_EFLAGS_AC);
|
||||
|
||||
printf("[RUN]\tSet NT|AC and issue a syscall\n");
|
||||
do_it(X86_EFLAGS_NT | X86_EFLAGS_AC);
|
||||
|
||||
/*
|
||||
* Now try it again with TF set -- TF forces returns via IRET in all
|
||||
* cases except non-ptregs-using 64-bit full fast path syscalls.
|
||||
@@ -80,8 +69,28 @@ int main(void)
|
||||
|
||||
sethandler(SIGTRAP, sigtrap, 0);
|
||||
|
||||
printf("[RUN]\tSet TF and issue a syscall\n");
|
||||
do_it(X86_EFLAGS_TF);
|
||||
|
||||
printf("[RUN]\tSet NT|TF and issue a syscall\n");
|
||||
do_it(X86_EFLAGS_NT | X86_EFLAGS_TF);
|
||||
|
||||
printf("[RUN]\tSet AC|TF and issue a syscall\n");
|
||||
do_it(X86_EFLAGS_AC | X86_EFLAGS_TF);
|
||||
|
||||
printf("[RUN]\tSet NT|AC|TF and issue a syscall\n");
|
||||
do_it(X86_EFLAGS_NT | X86_EFLAGS_AC | X86_EFLAGS_TF);
|
||||
|
||||
/*
|
||||
* Now try DF. This is evil and it's plausible that we will crash
|
||||
* glibc, but glibc would have to do something rather surprising
|
||||
* for this to happen.
|
||||
*/
|
||||
printf("[RUN]\tSet DF and issue a syscall\n");
|
||||
do_it(X86_EFLAGS_DF);
|
||||
|
||||
printf("[RUN]\tSet TF|DF and issue a syscall\n");
|
||||
do_it(X86_EFLAGS_TF | X86_EFLAGS_DF);
|
||||
|
||||
return nerrs == 0 ? 0 : 1;
|
||||
}
|
||||
|
@@ -20,6 +20,8 @@
|
||||
#include <setjmp.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
# define VSYS(x) (x)
|
||||
#else
|
||||
@@ -493,21 +495,8 @@ static int test_process_vm_readv(void)
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define X86_EFLAGS_TF (1UL << 8)
|
||||
static volatile sig_atomic_t num_vsyscall_traps;
|
||||
|
||||
static unsigned long get_eflags(void)
|
||||
{
|
||||
unsigned long eflags;
|
||||
asm volatile ("pushfq\n\tpopq %0" : "=rm" (eflags));
|
||||
return eflags;
|
||||
}
|
||||
|
||||
static void set_eflags(unsigned long eflags)
|
||||
{
|
||||
asm volatile ("pushq %0\n\tpopfq" : : "rm" (eflags) : "flags");
|
||||
}
|
||||
|
||||
static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
|
||||
{
|
||||
ucontext_t *ctx = (ucontext_t *)ctx_void;
|
||||
|
@@ -11,6 +11,8 @@
|
||||
#include <features.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16
|
||||
|
||||
int main()
|
||||
@@ -53,27 +55,6 @@ static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
|
||||
err(1, "sigaction");
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
# define WIDTH "q"
|
||||
#else
|
||||
# define WIDTH "l"
|
||||
#endif
|
||||
|
||||
static unsigned long get_eflags(void)
|
||||
{
|
||||
unsigned long eflags;
|
||||
asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
|
||||
return eflags;
|
||||
}
|
||||
|
||||
static void set_eflags(unsigned long eflags)
|
||||
{
|
||||
asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
|
||||
: : "rm" (eflags) : "flags");
|
||||
}
|
||||
|
||||
#define X86_EFLAGS_TF (1UL << 8)
|
||||
|
||||
static volatile sig_atomic_t nerrs;
|
||||
static unsigned long sysinfo;
|
||||
static bool got_sysinfo = false;
|
||||
|
Reference in New Issue
Block a user