Merge 4.14-rc4 into usb-next
This merges in the USB fixes that we need here. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
@@ -88,6 +88,12 @@ struct kvm_s390_io_adapter_req {
|
||||
/* kvm attributes for KVM_S390_VM_TOD */
|
||||
#define KVM_S390_VM_TOD_LOW 0
|
||||
#define KVM_S390_VM_TOD_HIGH 1
|
||||
#define KVM_S390_VM_TOD_EXT 2
|
||||
|
||||
struct kvm_s390_vm_tod_clock {
|
||||
__u8 epoch_idx;
|
||||
__u64 tod;
|
||||
};
|
||||
|
||||
/* kvm attributes for KVM_S390_VM_CPU_MODEL */
|
||||
/* processor related attributes are r/w */
|
||||
|
||||
@@ -196,6 +196,7 @@
|
||||
|
||||
#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */
|
||||
#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
|
||||
#define X86_FEATURE_SME ( 7*32+10) /* AMD Secure Memory Encryption */
|
||||
|
||||
#define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */
|
||||
#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */
|
||||
@@ -287,6 +288,7 @@
|
||||
#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */
|
||||
#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */
|
||||
#define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* Virtual VMSAVE VMLOAD */
|
||||
#define X86_FEATURE_VGIF (15*32+16) /* Virtual GIF */
|
||||
|
||||
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
|
||||
#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
|
||||
|
||||
@@ -21,11 +21,13 @@
|
||||
# define DISABLE_K6_MTRR (1<<(X86_FEATURE_K6_MTRR & 31))
|
||||
# define DISABLE_CYRIX_ARR (1<<(X86_FEATURE_CYRIX_ARR & 31))
|
||||
# define DISABLE_CENTAUR_MCR (1<<(X86_FEATURE_CENTAUR_MCR & 31))
|
||||
# define DISABLE_PCID 0
|
||||
#else
|
||||
# define DISABLE_VME 0
|
||||
# define DISABLE_K6_MTRR 0
|
||||
# define DISABLE_CYRIX_ARR 0
|
||||
# define DISABLE_CENTAUR_MCR 0
|
||||
# define DISABLE_PCID (1<<(X86_FEATURE_PCID & 31))
|
||||
#endif /* CONFIG_X86_64 */
|
||||
|
||||
#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
|
||||
@@ -49,7 +51,7 @@
|
||||
#define DISABLED_MASK1 0
|
||||
#define DISABLED_MASK2 0
|
||||
#define DISABLED_MASK3 (DISABLE_CYRIX_ARR|DISABLE_CENTAUR_MCR|DISABLE_K6_MTRR)
|
||||
#define DISABLED_MASK4 0
|
||||
#define DISABLED_MASK4 (DISABLE_PCID)
|
||||
#define DISABLED_MASK5 0
|
||||
#define DISABLED_MASK6 0
|
||||
#define DISABLED_MASK7 0
|
||||
|
||||
34
tools/include/asm-generic/hugetlb_encode.h
Normal file
34
tools/include/asm-generic/hugetlb_encode.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef _ASM_GENERIC_HUGETLB_ENCODE_H_
|
||||
#define _ASM_GENERIC_HUGETLB_ENCODE_H_
|
||||
|
||||
/*
|
||||
* Several system calls take a flag to request "hugetlb" huge pages.
|
||||
* Without further specification, these system calls will use the
|
||||
* system's default huge page size. If a system supports multiple
|
||||
* huge page sizes, the desired huge page size can be specified in
|
||||
* bits [26:31] of the flag arguments. The value in these 6 bits
|
||||
* will encode the log2 of the huge page size.
|
||||
*
|
||||
* The following definitions are associated with this huge page size
|
||||
* encoding in flag arguments. System call specific header files
|
||||
* that use this encoding should include this file. They can then
|
||||
* provide definitions based on these with their own specific prefix.
|
||||
* for example:
|
||||
* #define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
|
||||
*/
|
||||
|
||||
#define HUGETLB_FLAG_ENCODE_SHIFT 26
|
||||
#define HUGETLB_FLAG_ENCODE_MASK 0x3f
|
||||
|
||||
#define HUGETLB_FLAG_ENCODE_64KB (16 << HUGETLB_FLAG_ENCODE_SHIFT)
|
||||
#define HUGETLB_FLAG_ENCODE_512KB (19 << HUGETLB_FLAG_ENCODE_SHIFT)
|
||||
#define HUGETLB_FLAG_ENCODE_1MB (20 << HUGETLB_FLAG_ENCODE_SHIFT)
|
||||
#define HUGETLB_FLAG_ENCODE_2MB (21 << HUGETLB_FLAG_ENCODE_SHIFT)
|
||||
#define HUGETLB_FLAG_ENCODE_8MB (23 << HUGETLB_FLAG_ENCODE_SHIFT)
|
||||
#define HUGETLB_FLAG_ENCODE_16MB (24 << HUGETLB_FLAG_ENCODE_SHIFT)
|
||||
#define HUGETLB_FLAG_ENCODE_256MB (28 << HUGETLB_FLAG_ENCODE_SHIFT)
|
||||
#define HUGETLB_FLAG_ENCODE_1GB (30 << HUGETLB_FLAG_ENCODE_SHIFT)
|
||||
#define HUGETLB_FLAG_ENCODE_2GB (31 << HUGETLB_FLAG_ENCODE_SHIFT)
|
||||
#define HUGETLB_FLAG_ENCODE_16GB (34 << HUGETLB_FLAG_ENCODE_SHIFT)
|
||||
|
||||
#endif /* _ASM_GENERIC_HUGETLB_ENCODE_H_ */
|
||||
@@ -58,20 +58,12 @@
|
||||
overrides the coredump filter bits */
|
||||
#define MADV_DODUMP 17 /* Clear the MADV_DONTDUMP flag */
|
||||
|
||||
#define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */
|
||||
#define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */
|
||||
|
||||
/* compatibility flags */
|
||||
#define MAP_FILE 0
|
||||
|
||||
/*
|
||||
* When MAP_HUGETLB is set bits [26:31] encode the log2 of the huge page size.
|
||||
* This gives us 6 bits, which is enough until someone invents 128 bit address
|
||||
* spaces.
|
||||
*
|
||||
* Assume these are all power of twos.
|
||||
* When 0 use the default page size.
|
||||
*/
|
||||
#define MAP_HUGE_SHIFT 26
|
||||
#define MAP_HUGE_MASK 0x3f
|
||||
|
||||
#define PKEY_DISABLE_ACCESS 0x1
|
||||
#define PKEY_DISABLE_WRITE 0x2
|
||||
#define PKEY_ACCESS_MASK (PKEY_DISABLE_ACCESS |\
|
||||
|
||||
@@ -700,6 +700,7 @@ struct drm_prime_handle {
|
||||
|
||||
struct drm_syncobj_create {
|
||||
__u32 handle;
|
||||
#define DRM_SYNCOBJ_CREATE_SIGNALED (1 << 0)
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
@@ -718,6 +719,24 @@ struct drm_syncobj_handle {
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
|
||||
#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
|
||||
struct drm_syncobj_wait {
|
||||
__u64 handles;
|
||||
/* absolute timeout */
|
||||
__s64 timeout_nsec;
|
||||
__u32 count_handles;
|
||||
__u32 flags;
|
||||
__u32 first_signaled; /* only valid when not waiting all */
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
struct drm_syncobj_array {
|
||||
__u64 handles;
|
||||
__u32 count_handles;
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
@@ -840,6 +859,9 @@ extern "C" {
|
||||
#define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy)
|
||||
#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle)
|
||||
#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle)
|
||||
#define DRM_IOCTL_SYNCOBJ_WAIT DRM_IOWR(0xC3, struct drm_syncobj_wait)
|
||||
#define DRM_IOCTL_SYNCOBJ_RESET DRM_IOWR(0xC4, struct drm_syncobj_array)
|
||||
#define DRM_IOCTL_SYNCOBJ_SIGNAL DRM_IOWR(0xC5, struct drm_syncobj_array)
|
||||
|
||||
/**
|
||||
* Device specific ioctls should only be in their respective headers
|
||||
|
||||
@@ -260,6 +260,8 @@ typedef struct _drm_i915_sarea {
|
||||
#define DRM_I915_GEM_CONTEXT_GETPARAM 0x34
|
||||
#define DRM_I915_GEM_CONTEXT_SETPARAM 0x35
|
||||
#define DRM_I915_PERF_OPEN 0x36
|
||||
#define DRM_I915_PERF_ADD_CONFIG 0x37
|
||||
#define DRM_I915_PERF_REMOVE_CONFIG 0x38
|
||||
|
||||
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
|
||||
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
|
||||
@@ -315,6 +317,8 @@ typedef struct _drm_i915_sarea {
|
||||
#define DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_GETPARAM, struct drm_i915_gem_context_param)
|
||||
#define DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_SETPARAM, struct drm_i915_gem_context_param)
|
||||
#define DRM_IOCTL_I915_PERF_OPEN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_OPEN, struct drm_i915_perf_open_param)
|
||||
#define DRM_IOCTL_I915_PERF_ADD_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_ADD_CONFIG, struct drm_i915_perf_oa_config)
|
||||
#define DRM_IOCTL_I915_PERF_REMOVE_CONFIG DRM_IOW(DRM_COMMAND_BASE + DRM_I915_PERF_REMOVE_CONFIG, __u64)
|
||||
|
||||
/* Allow drivers to submit batchbuffers directly to hardware, relying
|
||||
* on the security mechanisms provided by hardware.
|
||||
@@ -431,6 +435,11 @@ typedef struct drm_i915_irq_wait {
|
||||
*/
|
||||
#define I915_PARAM_HAS_EXEC_BATCH_FIRST 48
|
||||
|
||||
/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of
|
||||
* drm_i915_gem_exec_fence structures. See I915_EXEC_FENCE_ARRAY.
|
||||
*/
|
||||
#define I915_PARAM_HAS_EXEC_FENCE_ARRAY 49
|
||||
|
||||
typedef struct drm_i915_getparam {
|
||||
__s32 param;
|
||||
/*
|
||||
@@ -812,6 +821,17 @@ struct drm_i915_gem_exec_object2 {
|
||||
__u64 rsvd2;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_exec_fence {
|
||||
/**
|
||||
* User's handle for a drm_syncobj to wait on or signal.
|
||||
*/
|
||||
__u32 handle;
|
||||
|
||||
#define I915_EXEC_FENCE_WAIT (1<<0)
|
||||
#define I915_EXEC_FENCE_SIGNAL (1<<1)
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
struct drm_i915_gem_execbuffer2 {
|
||||
/**
|
||||
* List of gem_exec_object2 structs
|
||||
@@ -826,7 +846,11 @@ struct drm_i915_gem_execbuffer2 {
|
||||
__u32 DR1;
|
||||
__u32 DR4;
|
||||
__u32 num_cliprects;
|
||||
/** This is a struct drm_clip_rect *cliprects */
|
||||
/**
|
||||
* This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY
|
||||
* is not set. If I915_EXEC_FENCE_ARRAY is set, then this is a
|
||||
* struct drm_i915_gem_exec_fence *fences.
|
||||
*/
|
||||
__u64 cliprects_ptr;
|
||||
#define I915_EXEC_RING_MASK (7<<0)
|
||||
#define I915_EXEC_DEFAULT (0<<0)
|
||||
@@ -927,7 +951,14 @@ struct drm_i915_gem_execbuffer2 {
|
||||
* element).
|
||||
*/
|
||||
#define I915_EXEC_BATCH_FIRST (1<<18)
|
||||
#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_BATCH_FIRST<<1))
|
||||
|
||||
/* Setting I915_FENCE_ARRAY implies that num_cliprects and cliprects_ptr
|
||||
* define an array of i915_gem_exec_fence structures which specify a set of
|
||||
* dma fences to wait upon or signal.
|
||||
*/
|
||||
#define I915_EXEC_FENCE_ARRAY (1<<19)
|
||||
|
||||
#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_ARRAY<<1))
|
||||
|
||||
#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
|
||||
#define i915_execbuffer2_set_context_id(eb2, context) \
|
||||
@@ -1467,6 +1498,22 @@ enum drm_i915_perf_record_type {
|
||||
DRM_I915_PERF_RECORD_MAX /* non-ABI */
|
||||
};
|
||||
|
||||
/**
|
||||
* Structure to upload perf dynamic configuration into the kernel.
|
||||
*/
|
||||
struct drm_i915_perf_oa_config {
|
||||
/** String formatted like "%08x-%04x-%04x-%04x-%012x" */
|
||||
char uuid[36];
|
||||
|
||||
__u32 n_mux_regs;
|
||||
__u32 n_boolean_regs;
|
||||
__u32 n_flex_regs;
|
||||
|
||||
__u64 __user mux_regs_ptr;
|
||||
__u64 __user boolean_regs_ptr;
|
||||
__u64 __user flex_regs_ptr;
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -143,12 +143,6 @@ enum bpf_attach_type {
|
||||
|
||||
#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
|
||||
|
||||
enum bpf_sockmap_flags {
|
||||
BPF_SOCKMAP_UNSPEC,
|
||||
BPF_SOCKMAP_STRPARSER,
|
||||
__MAX_BPF_SOCKMAP_FLAG
|
||||
};
|
||||
|
||||
/* If BPF_F_ALLOW_OVERRIDE flag is used in BPF_PROG_ATTACH command
|
||||
* to the given target_fd cgroup the descendent cgroup will be able to
|
||||
* override effective bpf program that was inherited from this cgroup
|
||||
@@ -368,9 +362,20 @@ union bpf_attr {
|
||||
* int bpf_redirect(ifindex, flags)
|
||||
* redirect to another netdev
|
||||
* @ifindex: ifindex of the net device
|
||||
* @flags: bit 0 - if set, redirect to ingress instead of egress
|
||||
* other bits - reserved
|
||||
* Return: TC_ACT_REDIRECT
|
||||
* @flags:
|
||||
* cls_bpf:
|
||||
* bit 0 - if set, redirect to ingress instead of egress
|
||||
* other bits - reserved
|
||||
* xdp_bpf:
|
||||
* all bits - reserved
|
||||
* Return: cls_bpf: TC_ACT_REDIRECT on success or TC_ACT_SHOT on error
|
||||
* xdp_bfp: XDP_REDIRECT on success or XDP_ABORT on error
|
||||
* int bpf_redirect_map(map, key, flags)
|
||||
* redirect to endpoint in map
|
||||
* @map: pointer to dev map
|
||||
* @key: index in map to lookup
|
||||
* @flags: --
|
||||
* Return: XDP_REDIRECT on success or XDP_ABORT on error
|
||||
*
|
||||
* u32 bpf_get_route_realm(skb)
|
||||
* retrieve a dst's tclassid
|
||||
@@ -632,7 +637,7 @@ union bpf_attr {
|
||||
FN(skb_adjust_room), \
|
||||
FN(redirect_map), \
|
||||
FN(sk_redirect_map), \
|
||||
FN(sock_map_update),
|
||||
FN(sock_map_update), \
|
||||
|
||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||
* function eBPF program intends to call
|
||||
@@ -753,20 +758,23 @@ struct bpf_sock {
|
||||
__u32 family;
|
||||
__u32 type;
|
||||
__u32 protocol;
|
||||
__u32 mark;
|
||||
__u32 priority;
|
||||
};
|
||||
|
||||
#define XDP_PACKET_HEADROOM 256
|
||||
|
||||
/* User return codes for XDP prog type.
|
||||
* A valid XDP program must return one of these defined values. All other
|
||||
* return codes are reserved for future use. Unknown return codes will result
|
||||
* in packet drop.
|
||||
* return codes are reserved for future use. Unknown return codes will
|
||||
* result in packet drops and a warning via bpf_warn_invalid_xdp_action().
|
||||
*/
|
||||
enum xdp_action {
|
||||
XDP_ABORTED = 0,
|
||||
XDP_DROP,
|
||||
XDP_PASS,
|
||||
XDP_TX,
|
||||
XDP_REDIRECT,
|
||||
};
|
||||
|
||||
/* user accessible metadata for XDP packet hook
|
||||
|
||||
@@ -711,7 +711,8 @@ struct kvm_ppc_one_seg_page_size {
|
||||
struct kvm_ppc_smmu_info {
|
||||
__u64 flags;
|
||||
__u32 slb_size;
|
||||
__u32 pad;
|
||||
__u16 data_keys; /* # storage keys supported for data */
|
||||
__u16 instr_keys; /* # storage keys supported for instructions */
|
||||
struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ];
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#ifndef _UAPI_LINUX_MMAN_H
|
||||
#define _UAPI_LINUX_MMAN_H
|
||||
|
||||
#include <uapi/asm/mman.h>
|
||||
#include <asm/mman.h>
|
||||
#include <asm-generic/hugetlb_encode.h>
|
||||
|
||||
#define MREMAP_MAYMOVE 1
|
||||
#define MREMAP_FIXED 2
|
||||
@@ -10,4 +11,25 @@
|
||||
#define OVERCOMMIT_ALWAYS 1
|
||||
#define OVERCOMMIT_NEVER 2
|
||||
|
||||
/*
|
||||
* Huge page size encoding when MAP_HUGETLB is specified, and a huge page
|
||||
* size other than the default is desired. See hugetlb_encode.h.
|
||||
* All known huge page size encodings are provided here. It is the
|
||||
* responsibility of the application to know which sizes are supported on
|
||||
* the running system. See mmap(2) man page for details.
|
||||
*/
|
||||
#define MAP_HUGE_SHIFT HUGETLB_FLAG_ENCODE_SHIFT
|
||||
#define MAP_HUGE_MASK HUGETLB_FLAG_ENCODE_MASK
|
||||
|
||||
#define MAP_HUGE_64KB HUGETLB_FLAG_ENCODE_64KB
|
||||
#define MAP_HUGE_512KB HUGETLB_FLAG_ENCODE_512KB
|
||||
#define MAP_HUGE_1MB HUGETLB_FLAG_ENCODE_1MB
|
||||
#define MAP_HUGE_2MB HUGETLB_FLAG_ENCODE_2MB
|
||||
#define MAP_HUGE_8MB HUGETLB_FLAG_ENCODE_8MB
|
||||
#define MAP_HUGE_16MB HUGETLB_FLAG_ENCODE_16MB
|
||||
#define MAP_HUGE_256MB HUGETLB_FLAG_ENCODE_256MB
|
||||
#define MAP_HUGE_1GB HUGETLB_FLAG_ENCODE_1GB
|
||||
#define MAP_HUGE_2GB HUGETLB_FLAG_ENCODE_2GB
|
||||
#define MAP_HUGE_16GB HUGETLB_FLAG_ENCODE_16GB
|
||||
|
||||
#endif /* _UAPI_LINUX_MMAN_H */
|
||||
|
||||
@@ -194,10 +194,10 @@ they mean, and suggestions for how to fix them.
|
||||
If it's a GCC-compiled .c file, the error may be because the function
|
||||
uses an inline asm() statement which has a "call" instruction. An
|
||||
asm() statement with a call instruction must declare the use of the
|
||||
stack pointer in its output operand. For example, on x86_64:
|
||||
stack pointer in its output operand. On x86_64, this means adding
|
||||
the ASM_CALL_CONSTRAINT as an output constraint:
|
||||
|
||||
register void *__sp asm("rsp");
|
||||
asm volatile("call func" : "+r" (__sp));
|
||||
asm volatile("call func" : ASM_CALL_CONSTRAINT);
|
||||
|
||||
Otherwise the stack frame may not get created before the call.
|
||||
|
||||
|
||||
@@ -208,14 +208,14 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
|
||||
break;
|
||||
|
||||
case 0x89:
|
||||
if (rex == 0x48 && modrm == 0xe5) {
|
||||
if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) {
|
||||
|
||||
/* mov %rsp, %rbp */
|
||||
/* mov %rsp, reg */
|
||||
*type = INSN_STACK;
|
||||
op->src.type = OP_SRC_REG;
|
||||
op->src.reg = CFI_SP;
|
||||
op->dest.type = OP_DEST_REG;
|
||||
op->dest.reg = CFI_BP;
|
||||
op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -284,11 +284,16 @@ int arch_decode_instruction(struct elf *elf, struct section *sec,
|
||||
case 0x8d:
|
||||
if (sib == 0x24 && rex_w && !rex_b && !rex_x) {
|
||||
|
||||
/* lea disp(%rsp), reg */
|
||||
*type = INSN_STACK;
|
||||
op->src.type = OP_SRC_ADD;
|
||||
if (!insn.displacement.value) {
|
||||
/* lea (%rsp), reg */
|
||||
op->src.type = OP_SRC_REG;
|
||||
} else {
|
||||
/* lea disp(%rsp), reg */
|
||||
op->src.type = OP_SRC_ADD;
|
||||
op->src.offset = insn.displacement.value;
|
||||
}
|
||||
op->src.reg = CFI_SP;
|
||||
op->src.offset = insn.displacement.value;
|
||||
op->dest.type = OP_DEST_REG;
|
||||
op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
|
||||
|
||||
|
||||
@@ -1203,24 +1203,39 @@ static int update_insn_state(struct instruction *insn, struct insn_state *state)
|
||||
switch (op->src.type) {
|
||||
|
||||
case OP_SRC_REG:
|
||||
if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP) {
|
||||
if (op->src.reg == CFI_SP && op->dest.reg == CFI_BP &&
|
||||
cfa->base == CFI_SP &&
|
||||
regs[CFI_BP].base == CFI_CFA &&
|
||||
regs[CFI_BP].offset == -cfa->offset) {
|
||||
|
||||
if (cfa->base == CFI_SP &&
|
||||
regs[CFI_BP].base == CFI_CFA &&
|
||||
regs[CFI_BP].offset == -cfa->offset) {
|
||||
/* mov %rsp, %rbp */
|
||||
cfa->base = op->dest.reg;
|
||||
state->bp_scratch = false;
|
||||
}
|
||||
|
||||
/* mov %rsp, %rbp */
|
||||
cfa->base = op->dest.reg;
|
||||
state->bp_scratch = false;
|
||||
}
|
||||
else if (op->src.reg == CFI_SP &&
|
||||
op->dest.reg == CFI_BP && state->drap) {
|
||||
|
||||
else if (state->drap) {
|
||||
/* drap: mov %rsp, %rbp */
|
||||
regs[CFI_BP].base = CFI_BP;
|
||||
regs[CFI_BP].offset = -state->stack_size;
|
||||
state->bp_scratch = false;
|
||||
}
|
||||
|
||||
/* drap: mov %rsp, %rbp */
|
||||
regs[CFI_BP].base = CFI_BP;
|
||||
regs[CFI_BP].offset = -state->stack_size;
|
||||
state->bp_scratch = false;
|
||||
}
|
||||
else if (op->src.reg == CFI_SP && cfa->base == CFI_SP) {
|
||||
|
||||
/*
|
||||
* mov %rsp, %reg
|
||||
*
|
||||
* This is needed for the rare case where GCC
|
||||
* does:
|
||||
*
|
||||
* mov %rsp, %rax
|
||||
* ...
|
||||
* mov %rax, %rsp
|
||||
*/
|
||||
state->vals[op->dest.reg].base = CFI_CFA;
|
||||
state->vals[op->dest.reg].offset = -state->stack_size;
|
||||
}
|
||||
|
||||
else if (op->dest.reg == cfa->base) {
|
||||
|
||||
@@ -175,19 +175,20 @@ static int read_sections(struct elf *elf)
|
||||
return -1;
|
||||
}
|
||||
|
||||
sec->data = elf_getdata(s, NULL);
|
||||
if (!sec->data) {
|
||||
WARN_ELF("elf_getdata");
|
||||
return -1;
|
||||
if (sec->sh.sh_size != 0) {
|
||||
sec->data = elf_getdata(s, NULL);
|
||||
if (!sec->data) {
|
||||
WARN_ELF("elf_getdata");
|
||||
return -1;
|
||||
}
|
||||
if (sec->data->d_off != 0 ||
|
||||
sec->data->d_size != sec->sh.sh_size) {
|
||||
WARN("unexpected data attributes for %s",
|
||||
sec->name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (sec->data->d_off != 0 ||
|
||||
sec->data->d_size != sec->sh.sh_size) {
|
||||
WARN("unexpected data attributes for %s", sec->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sec->len = sec->data->d_size;
|
||||
sec->len = sec->sh.sh_size;
|
||||
}
|
||||
|
||||
/* sanity check, one more call to elf_nextscn() should return NULL */
|
||||
@@ -508,6 +509,7 @@ struct section *elf_create_rela_section(struct elf *elf, struct section *base)
|
||||
strcat(relaname, base->name);
|
||||
|
||||
sec = elf_create_section(elf, relaname, sizeof(GElf_Rela), 0);
|
||||
free(relaname);
|
||||
if (!sec)
|
||||
return NULL;
|
||||
|
||||
@@ -561,6 +563,7 @@ int elf_write(struct elf *elf)
|
||||
struct section *sec;
|
||||
Elf_Scn *s;
|
||||
|
||||
/* Update section headers for changed sections: */
|
||||
list_for_each_entry(sec, &elf->sections, list) {
|
||||
if (sec->changed) {
|
||||
s = elf_getscn(elf->elf, sec->idx);
|
||||
@@ -568,13 +571,17 @@ int elf_write(struct elf *elf)
|
||||
WARN_ELF("elf_getscn");
|
||||
return -1;
|
||||
}
|
||||
if (!gelf_update_shdr (s, &sec->sh)) {
|
||||
if (!gelf_update_shdr(s, &sec->sh)) {
|
||||
WARN_ELF("gelf_update_shdr");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure the new section header entries get updated properly. */
|
||||
elf_flagelf(elf->elf, ELF_C_SET, ELF_F_DIRTY);
|
||||
|
||||
/* Write all changes to the file. */
|
||||
if (elf_update(elf->elf, ELF_C_WRITE) < 0) {
|
||||
WARN_ELF("elf_update");
|
||||
return -1;
|
||||
|
||||
@@ -1,34 +1,8 @@
|
||||
tools/perf
|
||||
tools/arch/alpha/include/asm/barrier.h
|
||||
tools/arch/arm/include/asm/barrier.h
|
||||
tools/arch/arm64/include/asm/barrier.h
|
||||
tools/arch/ia64/include/asm/barrier.h
|
||||
tools/arch/mips/include/asm/barrier.h
|
||||
tools/arch/powerpc/include/asm/barrier.h
|
||||
tools/arch/s390/include/asm/barrier.h
|
||||
tools/arch/sh/include/asm/barrier.h
|
||||
tools/arch/sparc/include/asm/barrier.h
|
||||
tools/arch/sparc/include/asm/barrier_32.h
|
||||
tools/arch/sparc/include/asm/barrier_64.h
|
||||
tools/arch/tile/include/asm/barrier.h
|
||||
tools/arch/x86/include/asm/barrier.h
|
||||
tools/arch/x86/include/asm/cmpxchg.h
|
||||
tools/arch/x86/include/asm/cpufeatures.h
|
||||
tools/arch/x86/include/asm/disabled-features.h
|
||||
tools/arch/x86/include/asm/required-features.h
|
||||
tools/arch/x86/include/uapi/asm/svm.h
|
||||
tools/arch/x86/include/uapi/asm/vmx.h
|
||||
tools/arch/x86/include/uapi/asm/kvm.h
|
||||
tools/arch/x86/include/uapi/asm/kvm_perf.h
|
||||
tools/arch/x86/lib/memcpy_64.S
|
||||
tools/arch/x86/lib/memset_64.S
|
||||
tools/arch/s390/include/uapi/asm/kvm_perf.h
|
||||
tools/arch/s390/include/uapi/asm/sie.h
|
||||
tools/arch/xtensa/include/asm/barrier.h
|
||||
tools/arch
|
||||
tools/scripts
|
||||
tools/build
|
||||
tools/arch/x86/include/asm/atomic.h
|
||||
tools/arch/x86/include/asm/rmwcc.h
|
||||
tools/include
|
||||
tools/lib/traceevent
|
||||
tools/lib/api
|
||||
tools/lib/bpf
|
||||
@@ -42,60 +16,3 @@ tools/lib/find_bit.c
|
||||
tools/lib/bitmap.c
|
||||
tools/lib/str_error_r.c
|
||||
tools/lib/vsprintf.c
|
||||
tools/include/asm/alternative-asm.h
|
||||
tools/include/asm/atomic.h
|
||||
tools/include/asm/barrier.h
|
||||
tools/include/asm/bug.h
|
||||
tools/include/asm-generic/atomic-gcc.h
|
||||
tools/include/asm-generic/barrier.h
|
||||
tools/include/asm-generic/bitops/arch_hweight.h
|
||||
tools/include/asm-generic/bitops/atomic.h
|
||||
tools/include/asm-generic/bitops/const_hweight.h
|
||||
tools/include/asm-generic/bitops/__ffs.h
|
||||
tools/include/asm-generic/bitops/__ffz.h
|
||||
tools/include/asm-generic/bitops/__fls.h
|
||||
tools/include/asm-generic/bitops/find.h
|
||||
tools/include/asm-generic/bitops/fls64.h
|
||||
tools/include/asm-generic/bitops/fls.h
|
||||
tools/include/asm-generic/bitops/hweight.h
|
||||
tools/include/asm-generic/bitops.h
|
||||
tools/include/linux/atomic.h
|
||||
tools/include/linux/bitops.h
|
||||
tools/include/linux/compiler.h
|
||||
tools/include/linux/compiler-gcc.h
|
||||
tools/include/linux/coresight-pmu.h
|
||||
tools/include/linux/bug.h
|
||||
tools/include/linux/filter.h
|
||||
tools/include/linux/hash.h
|
||||
tools/include/linux/kernel.h
|
||||
tools/include/linux/list.h
|
||||
tools/include/linux/log2.h
|
||||
tools/include/uapi/asm-generic/fcntl.h
|
||||
tools/include/uapi/asm-generic/ioctls.h
|
||||
tools/include/uapi/asm-generic/mman-common.h
|
||||
tools/include/uapi/asm-generic/mman.h
|
||||
tools/include/uapi/drm/drm.h
|
||||
tools/include/uapi/drm/i915_drm.h
|
||||
tools/include/uapi/linux/bpf.h
|
||||
tools/include/uapi/linux/bpf_common.h
|
||||
tools/include/uapi/linux/fcntl.h
|
||||
tools/include/uapi/linux/hw_breakpoint.h
|
||||
tools/include/uapi/linux/kvm.h
|
||||
tools/include/uapi/linux/mman.h
|
||||
tools/include/uapi/linux/perf_event.h
|
||||
tools/include/uapi/linux/sched.h
|
||||
tools/include/uapi/linux/stat.h
|
||||
tools/include/uapi/linux/vhost.h
|
||||
tools/include/uapi/sound/asound.h
|
||||
tools/include/linux/poison.h
|
||||
tools/include/linux/rbtree.h
|
||||
tools/include/linux/rbtree_augmented.h
|
||||
tools/include/linux/refcount.h
|
||||
tools/include/linux/string.h
|
||||
tools/include/linux/stringify.h
|
||||
tools/include/linux/types.h
|
||||
tools/include/linux/err.h
|
||||
tools/include/linux/bitmap.h
|
||||
tools/include/linux/time64.h
|
||||
tools/arch/*/include/uapi/asm/mman.h
|
||||
tools/arch/*/include/uapi/asm/perf_regs.h
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
libperf-y += header.o
|
||||
libperf-y += sym-handling.o
|
||||
libperf-y += kvm-stat.o
|
||||
|
||||
libperf-$(CONFIG_DWARF) += dwarf-regs.o
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Architecture specific ELF symbol handling and relocation mapping.
|
||||
*
|
||||
* Copyright 2017 IBM Corp.
|
||||
* Author(s): Thomas Richter <tmricht@linux.vnet.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License (version 2 only)
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "symbol.h"
|
||||
|
||||
#ifdef HAVE_LIBELF_SUPPORT
|
||||
bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
|
||||
{
|
||||
if (ehdr.e_type == ET_EXEC)
|
||||
return false;
|
||||
return ehdr.e_type == ET_REL || ehdr.e_type == ET_DYN;
|
||||
}
|
||||
|
||||
void arch__adjust_sym_map_offset(GElf_Sym *sym,
|
||||
GElf_Shdr *shdr __maybe_unused,
|
||||
struct map *map)
|
||||
{
|
||||
if (map->type == MAP__FUNCTION)
|
||||
sym->st_value += map->start;
|
||||
}
|
||||
#endif
|
||||
@@ -65,8 +65,6 @@ static int parse_callchain_mode(const char *value)
|
||||
callchain_param.mode = CHAIN_FOLDED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_err("Invalid callchain mode: %s\n", value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -82,8 +80,6 @@ static int parse_callchain_order(const char *value)
|
||||
callchain_param.order_set = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_err("Invalid callchain order: %s\n", value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -105,8 +101,6 @@ static int parse_callchain_sort_key(const char *value)
|
||||
callchain_param.branch_callstack = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_err("Invalid callchain sort key: %s\n", value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -124,8 +118,6 @@ static int parse_callchain_value(const char *value)
|
||||
callchain_param.value = CCVAL_COUNT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_err("Invalid callchain config key: %s\n", value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -319,12 +311,27 @@ int perf_callchain_config(const char *var, const char *value)
|
||||
|
||||
return ret;
|
||||
}
|
||||
if (!strcmp(var, "print-type"))
|
||||
return parse_callchain_mode(value);
|
||||
if (!strcmp(var, "order"))
|
||||
return parse_callchain_order(value);
|
||||
if (!strcmp(var, "sort-key"))
|
||||
return parse_callchain_sort_key(value);
|
||||
if (!strcmp(var, "print-type")){
|
||||
int ret;
|
||||
ret = parse_callchain_mode(value);
|
||||
if (ret == -1)
|
||||
pr_err("Invalid callchain mode: %s\n", value);
|
||||
return ret;
|
||||
}
|
||||
if (!strcmp(var, "order")){
|
||||
int ret;
|
||||
ret = parse_callchain_order(value);
|
||||
if (ret == -1)
|
||||
pr_err("Invalid callchain order: %s\n", value);
|
||||
return ret;
|
||||
}
|
||||
if (!strcmp(var, "sort-key")){
|
||||
int ret;
|
||||
ret = parse_callchain_sort_key(value);
|
||||
if (ret == -1)
|
||||
pr_err("Invalid callchain sort key: %s\n", value);
|
||||
return ret;
|
||||
}
|
||||
if (!strcmp(var, "threshold")) {
|
||||
callchain_param.min_percent = strtod(value, &endptr);
|
||||
if (value == endptr) {
|
||||
|
||||
@@ -271,12 +271,17 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
|
||||
return evsel;
|
||||
}
|
||||
|
||||
static bool perf_event_can_profile_kernel(void)
|
||||
{
|
||||
return geteuid() == 0 || perf_event_paranoid() == -1;
|
||||
}
|
||||
|
||||
struct perf_evsel *perf_evsel__new_cycles(bool precise)
|
||||
{
|
||||
struct perf_event_attr attr = {
|
||||
.type = PERF_TYPE_HARDWARE,
|
||||
.config = PERF_COUNT_HW_CPU_CYCLES,
|
||||
.exclude_kernel = geteuid() != 0,
|
||||
.exclude_kernel = !perf_event_can_profile_kernel(),
|
||||
};
|
||||
struct perf_evsel *evsel;
|
||||
|
||||
|
||||
@@ -810,12 +810,6 @@ static u64 ref_reloc(struct kmap *kmap)
|
||||
void __weak arch__sym_update(struct symbol *s __maybe_unused,
|
||||
GElf_Sym *sym __maybe_unused) { }
|
||||
|
||||
void __weak arch__adjust_sym_map_offset(GElf_Sym *sym, GElf_Shdr *shdr,
|
||||
struct map *map __maybe_unused)
|
||||
{
|
||||
sym->st_value -= shdr->sh_addr - shdr->sh_offset;
|
||||
}
|
||||
|
||||
int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
|
||||
struct symsrc *runtime_ss, int kmodule)
|
||||
{
|
||||
@@ -996,7 +990,7 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
|
||||
|
||||
/* Adjust symbol to map to file offset */
|
||||
if (adjust_kernel_syms)
|
||||
arch__adjust_sym_map_offset(&sym, &shdr, map);
|
||||
sym.st_value -= shdr.sh_addr - shdr.sh_offset;
|
||||
|
||||
if (strcmp(section_name,
|
||||
(curr_dso->short_name +
|
||||
|
||||
@@ -344,9 +344,6 @@ int setup_intlist(struct intlist **list, const char *list_str,
|
||||
#ifdef HAVE_LIBELF_SUPPORT
|
||||
bool elf__needs_adjust_symbols(GElf_Ehdr ehdr);
|
||||
void arch__sym_update(struct symbol *s, GElf_Sym *sym);
|
||||
void arch__adjust_sym_map_offset(GElf_Sym *sym,
|
||||
GElf_Shdr *shdr __maybe_unused,
|
||||
struct map *map __maybe_unused);
|
||||
#endif
|
||||
|
||||
#define SYMBOL_A 0
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
|
||||
#include "syscalltbl.h"
|
||||
#include <stdlib.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#ifdef HAVE_SYSCALL_TABLE
|
||||
#include <linux/compiler.h>
|
||||
#include <string.h>
|
||||
#include "string2.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -1527,9 +1527,6 @@ static void nfit_test1_setup(struct nfit_test *t)
|
||||
set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en);
|
||||
set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
|
||||
set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en);
|
||||
}
|
||||
|
||||
static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa,
|
||||
|
||||
@@ -52,6 +52,10 @@ override LDFLAGS =
|
||||
override MAKEFLAGS =
|
||||
endif
|
||||
|
||||
ifneq ($(KBUILD_SRC),)
|
||||
override LDFLAGS =
|
||||
endif
|
||||
|
||||
BUILD := $(O)
|
||||
ifndef BUILD
|
||||
BUILD := $(KBUILD_OUTPUT)
|
||||
@@ -62,32 +66,32 @@ endif
|
||||
|
||||
export BUILD
|
||||
all:
|
||||
for TARGET in $(TARGETS); do \
|
||||
@for TARGET in $(TARGETS); do \
|
||||
BUILD_TARGET=$$BUILD/$$TARGET; \
|
||||
mkdir $$BUILD_TARGET -p; \
|
||||
make OUTPUT=$$BUILD_TARGET -C $$TARGET;\
|
||||
done;
|
||||
|
||||
run_tests: all
|
||||
for TARGET in $(TARGETS); do \
|
||||
@for TARGET in $(TARGETS); do \
|
||||
BUILD_TARGET=$$BUILD/$$TARGET; \
|
||||
make OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests;\
|
||||
done;
|
||||
|
||||
hotplug:
|
||||
for TARGET in $(TARGETS_HOTPLUG); do \
|
||||
@for TARGET in $(TARGETS_HOTPLUG); do \
|
||||
BUILD_TARGET=$$BUILD/$$TARGET; \
|
||||
make OUTPUT=$$BUILD_TARGET -C $$TARGET;\
|
||||
done;
|
||||
|
||||
run_hotplug: hotplug
|
||||
for TARGET in $(TARGETS_HOTPLUG); do \
|
||||
@for TARGET in $(TARGETS_HOTPLUG); do \
|
||||
BUILD_TARGET=$$BUILD/$$TARGET; \
|
||||
make OUTPUT=$$BUILD_TARGET -C $$TARGET run_full_test;\
|
||||
done;
|
||||
|
||||
clean_hotplug:
|
||||
for TARGET in $(TARGETS_HOTPLUG); do \
|
||||
@for TARGET in $(TARGETS_HOTPLUG); do \
|
||||
BUILD_TARGET=$$BUILD/$$TARGET; \
|
||||
make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\
|
||||
done;
|
||||
@@ -103,7 +107,7 @@ install:
|
||||
ifdef INSTALL_PATH
|
||||
@# Ask all targets to install their files
|
||||
mkdir -p $(INSTALL_PATH)
|
||||
for TARGET in $(TARGETS); do \
|
||||
@for TARGET in $(TARGETS); do \
|
||||
BUILD_TARGET=$$BUILD/$$TARGET; \
|
||||
make OUTPUT=$$BUILD_TARGET -C $$TARGET INSTALL_PATH=$(INSTALL_PATH)/$$TARGET install; \
|
||||
done;
|
||||
@@ -128,7 +132,7 @@ else
|
||||
endif
|
||||
|
||||
clean:
|
||||
for TARGET in $(TARGETS); do \
|
||||
@for TARGET in $(TARGETS); do \
|
||||
BUILD_TARGET=$$BUILD/$$TARGET; \
|
||||
make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\
|
||||
done;
|
||||
|
||||
@@ -12,6 +12,7 @@ static inline unsigned int bpf_num_possible_cpus(void)
|
||||
unsigned int start, end, possible_cpus = 0;
|
||||
char buff[128];
|
||||
FILE *fp;
|
||||
int n;
|
||||
|
||||
fp = fopen(fcpu, "r");
|
||||
if (!fp) {
|
||||
@@ -20,17 +21,17 @@ static inline unsigned int bpf_num_possible_cpus(void)
|
||||
}
|
||||
|
||||
while (fgets(buff, sizeof(buff), fp)) {
|
||||
if (sscanf(buff, "%u-%u", &start, &end) == 2) {
|
||||
possible_cpus = start == 0 ? end + 1 : 0;
|
||||
break;
|
||||
n = sscanf(buff, "%u-%u", &start, &end);
|
||||
if (n == 0) {
|
||||
printf("Failed to retrieve # possible CPUs!\n");
|
||||
exit(1);
|
||||
} else if (n == 1) {
|
||||
end = start;
|
||||
}
|
||||
possible_cpus = start == 0 ? end + 1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
if (!possible_cpus) {
|
||||
printf("Failed to retrieve # possible CPUs!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return possible_cpus;
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
uname_M := $(shell uname -m 2>/dev/null || echo not)
|
||||
ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
|
||||
|
||||
TEST_GEN_PROGS := step_after_suspend_test
|
||||
|
||||
ifeq ($(ARCH),x86)
|
||||
TEST_GEN_PROGS := breakpoint_test
|
||||
TEST_GEN_PROGS += breakpoint_test
|
||||
endif
|
||||
ifneq (,$(filter $(ARCH),aarch64 arm64))
|
||||
TEST_GEN_PROGS := breakpoint_test_arm64
|
||||
TEST_GEN_PROGS += breakpoint_test_arm64
|
||||
endif
|
||||
|
||||
TEST_GEN_PROGS += step_after_suspend_test
|
||||
|
||||
include ../lib.mk
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#!/bin/sh
|
||||
# description: Register/unregister many kprobe events
|
||||
|
||||
[ -f kprobe_events ] || exit_unsupported # this is configurable
|
||||
|
||||
# ftrace fentry skip size depends on the machine architecture.
|
||||
# Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc64le
|
||||
case `uname -m` in
|
||||
|
||||
@@ -7,14 +7,17 @@ TEST_PROGS := run.sh
|
||||
include ../lib.mk
|
||||
|
||||
all:
|
||||
for DIR in $(SUBDIRS); do \
|
||||
@for DIR in $(SUBDIRS); do \
|
||||
BUILD_TARGET=$(OUTPUT)/$$DIR; \
|
||||
mkdir $$BUILD_TARGET -p; \
|
||||
make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
|
||||
if [ -e $$DIR/$(TEST_PROGS) ]; then
|
||||
rsync -a $$DIR/$(TEST_PROGS) $$BUILD_TARGET/;
|
||||
fi
|
||||
done
|
||||
|
||||
override define RUN_TESTS
|
||||
$(OUTPUT)/run.sh
|
||||
@cd $(OUTPUT); ./run.sh
|
||||
endef
|
||||
|
||||
override define INSTALL_RULE
|
||||
@@ -33,7 +36,7 @@ override define EMIT_TESTS
|
||||
endef
|
||||
|
||||
override define CLEAN
|
||||
for DIR in $(SUBDIRS); do \
|
||||
@for DIR in $(SUBDIRS); do \
|
||||
BUILD_TARGET=$(OUTPUT)/$$DIR; \
|
||||
mkdir $$BUILD_TARGET -p; \
|
||||
make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
CFLAGS := $(CFLAGS) -Wall -D_GNU_SOURCE
|
||||
LDLIBS := $(LDLIBS) -lm
|
||||
|
||||
ifeq (,$(filter $(ARCH),x86))
|
||||
TEST_GEN_FILES := msr aperf
|
||||
endif
|
||||
|
||||
TEST_PROGS := run.sh
|
||||
|
||||
|
||||
@@ -29,13 +29,12 @@
|
||||
|
||||
EVALUATE_ONLY=0
|
||||
|
||||
max_cpus=$(($(nproc)-1))
|
||||
if ! uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ | grep -q x86; then
|
||||
echo "$0 # Skipped: Test can only run on x86 architectures."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# compile programs
|
||||
gcc aperf.c -Wall -D_GNU_SOURCE -o aperf -lm
|
||||
[ $? -ne 0 ] && echo "Problem compiling aperf.c." && exit 1
|
||||
gcc -o msr msr.c -lm
|
||||
[ $? -ne 0 ] && echo "Problem compiling msr.c." && exit 1
|
||||
max_cpus=$(($(nproc)-1))
|
||||
|
||||
function run_test () {
|
||||
|
||||
|
||||
@@ -6,7 +6,14 @@ ifeq (0,$(MAKELEVEL))
|
||||
OUTPUT := $(shell pwd)
|
||||
endif
|
||||
|
||||
# The following are built by lib.mk common compile rules.
|
||||
# TEST_CUSTOM_PROGS should be used by tests that require
|
||||
# custom build rule and prevent common build rule use.
|
||||
# TEST_PROGS are for test shell scripts.
|
||||
# TEST_CUSTOM_PROGS and TEST_PROGS will be run by common run_tests
|
||||
# and install targets. Common clean doesn't touch them.
|
||||
TEST_GEN_PROGS := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS))
|
||||
TEST_GEN_PROGS_EXTENDED := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_PROGS_EXTENDED))
|
||||
TEST_GEN_FILES := $(patsubst %,$(OUTPUT)/%,$(TEST_GEN_FILES))
|
||||
|
||||
all: $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES)
|
||||
@@ -20,17 +27,28 @@ define RUN_TESTS
|
||||
test_num=`echo $$test_num+1 | bc`; \
|
||||
echo "selftests: $$BASENAME_TEST"; \
|
||||
echo "========================================"; \
|
||||
if [ ! -x $$BASENAME_TEST ]; then \
|
||||
if [ ! -x $$TEST ]; then \
|
||||
echo "selftests: Warning: file $$BASENAME_TEST is not executable, correct this.";\
|
||||
echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; \
|
||||
else \
|
||||
cd `dirname $$TEST` > /dev/null; (./$$BASENAME_TEST && echo "ok 1..$$test_num selftests: $$BASENAME_TEST [PASS]") || echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; cd - > /dev/null;\
|
||||
cd `dirname $$TEST` > /dev/null; (./$$BASENAME_TEST > /tmp/$$BASENAME_TEST 2>&1 && echo "ok 1..$$test_num selftests: $$BASENAME_TEST [PASS]") || echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; cd - > /dev/null;\
|
||||
fi; \
|
||||
done;
|
||||
endef
|
||||
|
||||
run_tests: all
|
||||
$(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_PROGS))
|
||||
ifneq ($(KBUILD_SRC),)
|
||||
@if [ "X$(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES)" != "X" ]; then
|
||||
@rsync -aq $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(OUTPUT)
|
||||
fi
|
||||
@if [ "X$(TEST_PROGS)" != "X" ]; then
|
||||
$(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(OUTPUT)/$(TEST_PROGS))
|
||||
else
|
||||
$(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS))
|
||||
fi
|
||||
else
|
||||
$(call RUN_TESTS, $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS))
|
||||
endif
|
||||
|
||||
define INSTALL_RULE
|
||||
@if [ "X$(TEST_PROGS)$(TEST_PROGS_EXTENDED)$(TEST_FILES)" != "X" ]; then \
|
||||
@@ -38,10 +56,10 @@ define INSTALL_RULE
|
||||
echo "rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/"; \
|
||||
rsync -a $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) $(INSTALL_PATH)/; \
|
||||
fi
|
||||
@if [ "X$(TEST_GEN_PROGS)$(TEST_GEN_PROGS_EXTENDED)$(TEST_GEN_FILES)" != "X" ]; then \
|
||||
@if [ "X$(TEST_GEN_PROGS)$(TEST_CUSTOM_PROGS)$(TEST_GEN_PROGS_EXTENDED)$(TEST_GEN_FILES)" != "X" ]; then \
|
||||
mkdir -p ${INSTALL_PATH}; \
|
||||
echo "rsync -a $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/"; \
|
||||
rsync -a $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/; \
|
||||
echo "rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/"; \
|
||||
rsync -a $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(INSTALL_PATH)/; \
|
||||
fi
|
||||
endef
|
||||
|
||||
@@ -53,15 +71,20 @@ else
|
||||
endif
|
||||
|
||||
define EMIT_TESTS
|
||||
@for TEST in $(TEST_GEN_PROGS) $(TEST_PROGS); do \
|
||||
@for TEST in $(TEST_GEN_PROGS) $(TEST_CUSTOM_PROGS) $(TEST_PROGS); do \
|
||||
BASENAME_TEST=`basename $$TEST`; \
|
||||
echo "(./$$BASENAME_TEST && echo \"selftests: $$BASENAME_TEST [PASS]\") || echo \"selftests: $$BASENAME_TEST [FAIL]\""; \
|
||||
echo "(./$$BASENAME_TEST > /tmp/$$BASENAME_TEST 2>&1 && echo \"selftests: $$BASENAME_TEST [PASS]\") || echo \"selftests: $$BASENAME_TEST [FAIL]\""; \
|
||||
done;
|
||||
endef
|
||||
|
||||
emit_tests:
|
||||
$(EMIT_TESTS)
|
||||
|
||||
# define if isn't already. It is undefined in make O= case.
|
||||
ifeq ($(RM),)
|
||||
RM := rm -f
|
||||
endif
|
||||
|
||||
define CLEAN
|
||||
$(RM) -r $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(EXTRA_CLEAN)
|
||||
endef
|
||||
@@ -69,6 +92,15 @@ endef
|
||||
clean:
|
||||
$(CLEAN)
|
||||
|
||||
# When make O= with kselftest target from main level
|
||||
# the following aren't defined.
|
||||
#
|
||||
ifneq ($(KBUILD_SRC),)
|
||||
LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
|
||||
COMPILE.S = $(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
|
||||
LINK.S = $(CC) $(ASFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)
|
||||
endif
|
||||
|
||||
$(OUTPUT)/%:%.c
|
||||
$(LINK.c) $^ $(LDLIBS) -o $@
|
||||
|
||||
|
||||
0
tools/testing/selftests/memfd/run_tests.sh
Normal file → Executable file
0
tools/testing/selftests/memfd/run_tests.sh
Normal file → Executable file
@@ -5,8 +5,8 @@ TEST_GEN_PROGS := mq_open_tests mq_perf_tests
|
||||
include ../lib.mk
|
||||
|
||||
override define RUN_TESTS
|
||||
@./mq_open_tests /test1 || echo "selftests: mq_open_tests [FAIL]"
|
||||
@./mq_perf_tests || echo "selftests: mq_perf_tests [FAIL]"
|
||||
$(OUTPUT)/mq_open_tests /test1 || echo "selftests: mq_open_tests [FAIL]"
|
||||
$(OUTPUT)//mq_perf_tests || echo "selftests: mq_perf_tests [FAIL]"
|
||||
endef
|
||||
|
||||
override define EMIT_TESTS
|
||||
|
||||
1
tools/testing/selftests/net/.gitignore
vendored
1
tools/testing/selftests/net/.gitignore
vendored
@@ -6,3 +6,4 @@ reuseport_bpf
|
||||
reuseport_bpf_cpu
|
||||
reuseport_bpf_numa
|
||||
reuseport_dualstack
|
||||
reuseaddr_conflict
|
||||
|
||||
@@ -5,9 +5,9 @@ CFLAGS += -I../../../../usr/include/
|
||||
|
||||
TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh
|
||||
TEST_GEN_FILES = socket
|
||||
TEST_GEN_FILES += psock_fanout psock_tpacket
|
||||
TEST_GEN_FILES += reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
|
||||
TEST_GEN_FILES += reuseport_dualstack msg_zerocopy
|
||||
TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy
|
||||
TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
|
||||
TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict
|
||||
|
||||
include ../lib.mk
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef SO_EE_ORIGIN_ZEROCOPY
|
||||
#define SO_EE_ORIGIN_ZEROCOPY SO_EE_ORIGIN_UPAGE
|
||||
#define SO_EE_ORIGIN_ZEROCOPY 5
|
||||
#endif
|
||||
|
||||
#ifndef SO_ZEROCOPY
|
||||
|
||||
@@ -178,7 +178,7 @@ if [ "$(id -u)" -ne 0 ];then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ip -Version 2>/dev/null >/dev/null
|
||||
ip link show 2>/dev/null >/dev/null
|
||||
if [ $? -ne 0 ];then
|
||||
echo "SKIP: Could not run test without the ip tool"
|
||||
exit 0
|
||||
|
||||
114
tools/testing/selftests/net/reuseaddr_conflict.c
Normal file
114
tools/testing/selftests/net/reuseaddr_conflict.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Test for the regression introduced by
|
||||
*
|
||||
* b9470c27607b ("inet: kill smallest_size and smallest_port")
|
||||
*
|
||||
* If we open an ipv4 socket on a port with reuseaddr we shouldn't reset the tb
|
||||
* when we open the ipv6 conterpart, which is what was happening previously.
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define PORT 9999
|
||||
|
||||
int open_port(int ipv6, int any)
|
||||
{
|
||||
int fd = -1;
|
||||
int reuseaddr = 1;
|
||||
int v6only = 1;
|
||||
int addrlen;
|
||||
int ret = -1;
|
||||
struct sockaddr *addr;
|
||||
int family = ipv6 ? AF_INET6 : AF_INET;
|
||||
|
||||
struct sockaddr_in6 addr6 = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_port = htons(PORT),
|
||||
.sin6_addr = in6addr_any
|
||||
};
|
||||
struct sockaddr_in addr4 = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(PORT),
|
||||
.sin_addr.s_addr = any ? htonl(INADDR_ANY) : inet_addr("127.0.0.1"),
|
||||
};
|
||||
|
||||
|
||||
if (ipv6) {
|
||||
addr = (struct sockaddr*)&addr6;
|
||||
addrlen = sizeof(addr6);
|
||||
} else {
|
||||
addr = (struct sockaddr*)&addr4;
|
||||
addrlen = sizeof(addr4);
|
||||
}
|
||||
|
||||
if ((fd = socket(family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
|
||||
perror("socket");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ipv6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&v6only,
|
||||
sizeof(v6only)) < 0) {
|
||||
perror("setsockopt IPV6_V6ONLY");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
|
||||
sizeof(reuseaddr)) < 0) {
|
||||
perror("setsockopt SO_REUSEADDR");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bind(fd, addr, addrlen) < 0) {
|
||||
perror("bind");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (any)
|
||||
return fd;
|
||||
|
||||
if (listen(fd, 1) < 0) {
|
||||
perror("listen");
|
||||
goto out;
|
||||
}
|
||||
return fd;
|
||||
out:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int listenfd;
|
||||
int fd1, fd2;
|
||||
|
||||
fprintf(stderr, "Opening 127.0.0.1:%d\n", PORT);
|
||||
listenfd = open_port(0, 0);
|
||||
if (listenfd < 0)
|
||||
error(1, errno, "Couldn't open listen socket");
|
||||
fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT);
|
||||
fd1 = open_port(0, 1);
|
||||
if (fd1 >= 0)
|
||||
error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket");
|
||||
fprintf(stderr, "Opening in6addr_any:%d\n", PORT);
|
||||
fd1 = open_port(1, 1);
|
||||
if (fd1 < 0)
|
||||
error(1, errno, "Couldn't open ipv6 reuseport");
|
||||
fprintf(stderr, "Opening INADDR_ANY:%d\n", PORT);
|
||||
fd2 = open_port(0, 1);
|
||||
if (fd2 >= 0)
|
||||
error(1, 0, "Was allowed to create an ipv4 reuseport on a already bound non-reuseport socket");
|
||||
close(fd1);
|
||||
fprintf(stderr, "Opening INADDR_ANY:%d after closing ipv6 socket\n", PORT);
|
||||
fd1 = open_port(0, 1);
|
||||
if (fd1 >= 0)
|
||||
error(1, 0, "Was allowed to create an ipv4 reuseport on an already bound non-reuseport socket with no ipv6");
|
||||
fprintf(stderr, "Success");
|
||||
return 0;
|
||||
}
|
||||
@@ -1,8 +1,16 @@
|
||||
TEST_GEN_PROGS := seccomp_bpf
|
||||
CFLAGS += -Wl,-no-as-needed -Wall
|
||||
LDFLAGS += -lpthread
|
||||
all:
|
||||
|
||||
include ../lib.mk
|
||||
|
||||
$(TEST_GEN_PROGS): seccomp_bpf.c ../kselftest_harness.h
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
|
||||
.PHONY: all clean
|
||||
|
||||
BINARIES := seccomp_bpf seccomp_benchmark
|
||||
CFLAGS += -Wl,-no-as-needed -Wall
|
||||
|
||||
seccomp_bpf: seccomp_bpf.c ../kselftest_harness.h
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -lpthread $< -o $@
|
||||
|
||||
TEST_PROGS += $(BINARIES)
|
||||
EXTRA_CLEAN := $(BINARIES)
|
||||
|
||||
all: $(BINARIES)
|
||||
|
||||
99
tools/testing/selftests/seccomp/seccomp_benchmark.c
Normal file
99
tools/testing/selftests/seccomp/seccomp_benchmark.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Strictly speaking, this is not a test. But it can report during test
|
||||
* runs so relative performace can be measured.
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/seccomp.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
unsigned long long timing(clockid_t clk_id, unsigned long long samples)
|
||||
{
|
||||
pid_t pid, ret;
|
||||
unsigned long long i;
|
||||
struct timespec start, finish;
|
||||
|
||||
pid = getpid();
|
||||
assert(clock_gettime(clk_id, &start) == 0);
|
||||
for (i = 0; i < samples; i++) {
|
||||
ret = syscall(__NR_getpid);
|
||||
assert(pid == ret);
|
||||
}
|
||||
assert(clock_gettime(clk_id, &finish) == 0);
|
||||
|
||||
i = finish.tv_sec - start.tv_sec;
|
||||
i *= 1000000000;
|
||||
i += finish.tv_nsec - start.tv_nsec;
|
||||
|
||||
printf("%lu.%09lu - %lu.%09lu = %llu\n",
|
||||
finish.tv_sec, finish.tv_nsec,
|
||||
start.tv_sec, start.tv_nsec,
|
||||
i);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
unsigned long long calibrate(void)
|
||||
{
|
||||
unsigned long long i;
|
||||
|
||||
printf("Calibrating reasonable sample size...\n");
|
||||
|
||||
for (i = 5; ; i++) {
|
||||
unsigned long long samples = 1 << i;
|
||||
|
||||
/* Find something that takes more than 5 seconds to run. */
|
||||
if (timing(CLOCK_REALTIME, samples) / 1000000000ULL > 5)
|
||||
return samples;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct sock_filter filter[] = {
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
|
||||
};
|
||||
struct sock_fprog prog = {
|
||||
.len = (unsigned short)ARRAY_SIZE(filter),
|
||||
.filter = filter,
|
||||
};
|
||||
long ret;
|
||||
unsigned long long samples;
|
||||
unsigned long long native, filtered;
|
||||
|
||||
if (argc > 1)
|
||||
samples = strtoull(argv[1], NULL, 0);
|
||||
else
|
||||
samples = calibrate();
|
||||
|
||||
printf("Benchmarking %llu samples...\n", samples);
|
||||
|
||||
native = timing(CLOCK_PROCESS_CPUTIME_ID, samples) / samples;
|
||||
printf("getpid native: %llu ns\n", native);
|
||||
|
||||
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
|
||||
assert(ret == 0);
|
||||
|
||||
filtered = timing(CLOCK_PROCESS_CPUTIME_ID, samples) / samples;
|
||||
printf("getpid RET_ALLOW: %llu ns\n", filtered);
|
||||
|
||||
printf("Estimated seccomp overhead per syscall: %llu ns\n",
|
||||
filtered - native);
|
||||
|
||||
if (filtered == native)
|
||||
printf("Trying running again with more samples.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -6,10 +6,18 @@
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asm/siginfo.h>
|
||||
#define __have_siginfo_t 1
|
||||
#define __have_sigval_t 1
|
||||
#define __have_sigevent_t 1
|
||||
|
||||
/*
|
||||
* glibc 2.26 and later have SIGSYS in siginfo_t. Before that,
|
||||
* we need to use the kernel's siginfo.h file and trick glibc
|
||||
* into accepting it.
|
||||
*/
|
||||
#if !__GLIBC_PREREQ(2, 26)
|
||||
# include <asm/siginfo.h>
|
||||
# define __have_siginfo_t 1
|
||||
# define __have_sigval_t 1
|
||||
# define __have_sigevent_t 1
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <linux/filter.h>
|
||||
@@ -68,17 +76,7 @@
|
||||
#define SECCOMP_MODE_FILTER 2
|
||||
#endif
|
||||
|
||||
#ifndef SECCOMP_RET_KILL
|
||||
#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
|
||||
#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
|
||||
#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
|
||||
#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
|
||||
#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
|
||||
|
||||
/* Masks for the return value sections. */
|
||||
#define SECCOMP_RET_ACTION 0x7fff0000U
|
||||
#define SECCOMP_RET_DATA 0x0000ffffU
|
||||
|
||||
#ifndef SECCOMP_RET_ALLOW
|
||||
struct seccomp_data {
|
||||
int nr;
|
||||
__u32 arch;
|
||||
@@ -87,6 +85,70 @@ struct seccomp_data {
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef SECCOMP_RET_KILL_PROCESS
|
||||
#define SECCOMP_RET_KILL_PROCESS 0x80000000U /* kill the process */
|
||||
#define SECCOMP_RET_KILL_THREAD 0x00000000U /* kill the thread */
|
||||
#endif
|
||||
#ifndef SECCOMP_RET_KILL
|
||||
#define SECCOMP_RET_KILL SECCOMP_RET_KILL_THREAD
|
||||
#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
|
||||
#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
|
||||
#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
|
||||
#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
|
||||
#endif
|
||||
#ifndef SECCOMP_RET_LOG
|
||||
#define SECCOMP_RET_LOG 0x7ffc0000U /* allow after logging */
|
||||
#endif
|
||||
|
||||
#ifndef __NR_seccomp
|
||||
# if defined(__i386__)
|
||||
# define __NR_seccomp 354
|
||||
# elif defined(__x86_64__)
|
||||
# define __NR_seccomp 317
|
||||
# elif defined(__arm__)
|
||||
# define __NR_seccomp 383
|
||||
# elif defined(__aarch64__)
|
||||
# define __NR_seccomp 277
|
||||
# elif defined(__hppa__)
|
||||
# define __NR_seccomp 338
|
||||
# elif defined(__powerpc__)
|
||||
# define __NR_seccomp 358
|
||||
# elif defined(__s390__)
|
||||
# define __NR_seccomp 348
|
||||
# else
|
||||
# warning "seccomp syscall number unknown for this architecture"
|
||||
# define __NR_seccomp 0xffff
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SECCOMP_SET_MODE_STRICT
|
||||
#define SECCOMP_SET_MODE_STRICT 0
|
||||
#endif
|
||||
|
||||
#ifndef SECCOMP_SET_MODE_FILTER
|
||||
#define SECCOMP_SET_MODE_FILTER 1
|
||||
#endif
|
||||
|
||||
#ifndef SECCOMP_GET_ACTION_AVAIL
|
||||
#define SECCOMP_GET_ACTION_AVAIL 2
|
||||
#endif
|
||||
|
||||
#ifndef SECCOMP_FILTER_FLAG_TSYNC
|
||||
#define SECCOMP_FILTER_FLAG_TSYNC 1
|
||||
#endif
|
||||
|
||||
#ifndef SECCOMP_FILTER_FLAG_LOG
|
||||
#define SECCOMP_FILTER_FLAG_LOG 2
|
||||
#endif
|
||||
|
||||
#ifndef seccomp
|
||||
int seccomp(unsigned int op, unsigned int flags, void *args)
|
||||
{
|
||||
errno = 0;
|
||||
return syscall(__NR_seccomp, op, flags, args);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define syscall_arg(_n) (offsetof(struct seccomp_data, args[_n]))
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
@@ -136,7 +198,7 @@ TEST(no_new_privs_support)
|
||||
}
|
||||
}
|
||||
|
||||
/* Tests kernel support by checking for a copy_from_user() fault on * NULL. */
|
||||
/* Tests kernel support by checking for a copy_from_user() fault on NULL. */
|
||||
TEST(mode_filter_support)
|
||||
{
|
||||
long ret;
|
||||
@@ -342,6 +404,28 @@ TEST(empty_prog)
|
||||
EXPECT_EQ(EINVAL, errno);
|
||||
}
|
||||
|
||||
TEST(log_all)
|
||||
{
|
||||
struct sock_filter filter[] = {
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
|
||||
};
|
||||
struct sock_fprog prog = {
|
||||
.len = (unsigned short)ARRAY_SIZE(filter),
|
||||
.filter = filter,
|
||||
};
|
||||
long ret;
|
||||
pid_t parent = getppid();
|
||||
|
||||
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
/* getppid() should succeed and be logged (no check for logging) */
|
||||
EXPECT_EQ(parent, syscall(__NR_getppid));
|
||||
}
|
||||
|
||||
TEST_SIGNAL(unknown_ret_is_kill_inside, SIGSYS)
|
||||
{
|
||||
struct sock_filter filter[] = {
|
||||
@@ -520,6 +604,117 @@ TEST_SIGNAL(KILL_one_arg_six, SIGSYS)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* This is a thread task to die via seccomp filter violation. */
|
||||
void *kill_thread(void *data)
|
||||
{
|
||||
bool die = (bool)data;
|
||||
|
||||
if (die) {
|
||||
prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
|
||||
return (void *)SIBLING_EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return (void *)SIBLING_EXIT_UNKILLED;
|
||||
}
|
||||
|
||||
/* Prepare a thread that will kill itself or both of us. */
|
||||
void kill_thread_or_group(struct __test_metadata *_metadata, bool kill_process)
|
||||
{
|
||||
pthread_t thread;
|
||||
void *status;
|
||||
/* Kill only when calling __NR_prctl. */
|
||||
struct sock_filter filter_thread[] = {
|
||||
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
|
||||
offsetof(struct seccomp_data, nr)),
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_THREAD),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
|
||||
};
|
||||
struct sock_fprog prog_thread = {
|
||||
.len = (unsigned short)ARRAY_SIZE(filter_thread),
|
||||
.filter = filter_thread,
|
||||
};
|
||||
struct sock_filter filter_process[] = {
|
||||
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
|
||||
offsetof(struct seccomp_data, nr)),
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_PROCESS),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
|
||||
};
|
||||
struct sock_fprog prog_process = {
|
||||
.len = (unsigned short)ARRAY_SIZE(filter_process),
|
||||
.filter = filter_process,
|
||||
};
|
||||
|
||||
ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
|
||||
TH_LOG("Kernel does not support PR_SET_NO_NEW_PRIVS!");
|
||||
}
|
||||
|
||||
ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0,
|
||||
kill_process ? &prog_process : &prog_thread));
|
||||
|
||||
/*
|
||||
* Add the KILL_THREAD rule again to make sure that the KILL_PROCESS
|
||||
* flag cannot be downgraded by a new filter.
|
||||
*/
|
||||
ASSERT_EQ(0, seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog_thread));
|
||||
|
||||
/* Start a thread that will exit immediately. */
|
||||
ASSERT_EQ(0, pthread_create(&thread, NULL, kill_thread, (void *)false));
|
||||
ASSERT_EQ(0, pthread_join(thread, &status));
|
||||
ASSERT_EQ(SIBLING_EXIT_UNKILLED, (unsigned long)status);
|
||||
|
||||
/* Start a thread that will die immediately. */
|
||||
ASSERT_EQ(0, pthread_create(&thread, NULL, kill_thread, (void *)true));
|
||||
ASSERT_EQ(0, pthread_join(thread, &status));
|
||||
ASSERT_NE(SIBLING_EXIT_FAILURE, (unsigned long)status);
|
||||
|
||||
/*
|
||||
* If we get here, only the spawned thread died. Let the parent know
|
||||
* the whole process didn't die (i.e. this thread, the spawner,
|
||||
* stayed running).
|
||||
*/
|
||||
exit(42);
|
||||
}
|
||||
|
||||
TEST(KILL_thread)
|
||||
{
|
||||
int status;
|
||||
pid_t child_pid;
|
||||
|
||||
child_pid = fork();
|
||||
ASSERT_LE(0, child_pid);
|
||||
if (child_pid == 0) {
|
||||
kill_thread_or_group(_metadata, false);
|
||||
_exit(38);
|
||||
}
|
||||
|
||||
ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
|
||||
|
||||
/* If only the thread was killed, we'll see exit 42. */
|
||||
ASSERT_TRUE(WIFEXITED(status));
|
||||
ASSERT_EQ(42, WEXITSTATUS(status));
|
||||
}
|
||||
|
||||
TEST(KILL_process)
|
||||
{
|
||||
int status;
|
||||
pid_t child_pid;
|
||||
|
||||
child_pid = fork();
|
||||
ASSERT_LE(0, child_pid);
|
||||
if (child_pid == 0) {
|
||||
kill_thread_or_group(_metadata, true);
|
||||
_exit(38);
|
||||
}
|
||||
|
||||
ASSERT_EQ(child_pid, waitpid(child_pid, &status, 0));
|
||||
|
||||
/* If the entire process was killed, we'll see SIGSYS. */
|
||||
ASSERT_TRUE(WIFSIGNALED(status));
|
||||
ASSERT_EQ(SIGSYS, WTERMSIG(status));
|
||||
}
|
||||
|
||||
/* TODO(wad) add 64-bit versus 32-bit arg tests. */
|
||||
TEST(arg_out_of_range)
|
||||
{
|
||||
@@ -541,26 +736,30 @@ TEST(arg_out_of_range)
|
||||
EXPECT_EQ(EINVAL, errno);
|
||||
}
|
||||
|
||||
#define ERRNO_FILTER(name, errno) \
|
||||
struct sock_filter _read_filter_##name[] = { \
|
||||
BPF_STMT(BPF_LD|BPF_W|BPF_ABS, \
|
||||
offsetof(struct seccomp_data, nr)), \
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1), \
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | errno), \
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), \
|
||||
}; \
|
||||
struct sock_fprog prog_##name = { \
|
||||
.len = (unsigned short)ARRAY_SIZE(_read_filter_##name), \
|
||||
.filter = _read_filter_##name, \
|
||||
}
|
||||
|
||||
/* Make sure basic errno values are correctly passed through a filter. */
|
||||
TEST(ERRNO_valid)
|
||||
{
|
||||
struct sock_filter filter[] = {
|
||||
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
|
||||
offsetof(struct seccomp_data, nr)),
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | E2BIG),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
|
||||
};
|
||||
struct sock_fprog prog = {
|
||||
.len = (unsigned short)ARRAY_SIZE(filter),
|
||||
.filter = filter,
|
||||
};
|
||||
ERRNO_FILTER(valid, E2BIG);
|
||||
long ret;
|
||||
pid_t parent = getppid();
|
||||
|
||||
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_valid);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
EXPECT_EQ(parent, syscall(__NR_getppid));
|
||||
@@ -568,26 +767,17 @@ TEST(ERRNO_valid)
|
||||
EXPECT_EQ(E2BIG, errno);
|
||||
}
|
||||
|
||||
/* Make sure an errno of zero is correctly handled by the arch code. */
|
||||
TEST(ERRNO_zero)
|
||||
{
|
||||
struct sock_filter filter[] = {
|
||||
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
|
||||
offsetof(struct seccomp_data, nr)),
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | 0),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
|
||||
};
|
||||
struct sock_fprog prog = {
|
||||
.len = (unsigned short)ARRAY_SIZE(filter),
|
||||
.filter = filter,
|
||||
};
|
||||
ERRNO_FILTER(zero, 0);
|
||||
long ret;
|
||||
pid_t parent = getppid();
|
||||
|
||||
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_zero);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
EXPECT_EQ(parent, syscall(__NR_getppid));
|
||||
@@ -595,26 +785,21 @@ TEST(ERRNO_zero)
|
||||
EXPECT_EQ(0, read(0, NULL, 0));
|
||||
}
|
||||
|
||||
/*
|
||||
* The SECCOMP_RET_DATA mask is 16 bits wide, but errno is smaller.
|
||||
* This tests that the errno value gets capped correctly, fixed by
|
||||
* 580c57f10768 ("seccomp: cap SECCOMP_RET_ERRNO data to MAX_ERRNO").
|
||||
*/
|
||||
TEST(ERRNO_capped)
|
||||
{
|
||||
struct sock_filter filter[] = {
|
||||
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
|
||||
offsetof(struct seccomp_data, nr)),
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_read, 0, 1),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | 4096),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
|
||||
};
|
||||
struct sock_fprog prog = {
|
||||
.len = (unsigned short)ARRAY_SIZE(filter),
|
||||
.filter = filter,
|
||||
};
|
||||
ERRNO_FILTER(capped, 4096);
|
||||
long ret;
|
||||
pid_t parent = getppid();
|
||||
|
||||
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_capped);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
EXPECT_EQ(parent, syscall(__NR_getppid));
|
||||
@@ -622,6 +807,37 @@ TEST(ERRNO_capped)
|
||||
EXPECT_EQ(4095, errno);
|
||||
}
|
||||
|
||||
/*
|
||||
* Filters are processed in reverse order: last applied is executed first.
|
||||
* Since only the SECCOMP_RET_ACTION mask is tested for return values, the
|
||||
* SECCOMP_RET_DATA mask results will follow the most recently applied
|
||||
* matching filter return (and not the lowest or highest value).
|
||||
*/
|
||||
TEST(ERRNO_order)
|
||||
{
|
||||
ERRNO_FILTER(first, 11);
|
||||
ERRNO_FILTER(second, 13);
|
||||
ERRNO_FILTER(third, 12);
|
||||
long ret;
|
||||
pid_t parent = getppid();
|
||||
|
||||
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_first);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_second);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog_third);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
EXPECT_EQ(parent, syscall(__NR_getppid));
|
||||
EXPECT_EQ(-1, read(0, NULL, 0));
|
||||
EXPECT_EQ(12, errno);
|
||||
}
|
||||
|
||||
FIXTURE_DATA(TRAP) {
|
||||
struct sock_fprog prog;
|
||||
};
|
||||
@@ -676,7 +892,7 @@ TEST_F_SIGNAL(TRAP, ign, SIGSYS)
|
||||
syscall(__NR_getpid);
|
||||
}
|
||||
|
||||
static struct siginfo TRAP_info;
|
||||
static siginfo_t TRAP_info;
|
||||
static volatile int TRAP_nr;
|
||||
static void TRAP_action(int nr, siginfo_t *info, void *void_context)
|
||||
{
|
||||
@@ -735,6 +951,7 @@ TEST_F(TRAP, handler)
|
||||
|
||||
FIXTURE_DATA(precedence) {
|
||||
struct sock_fprog allow;
|
||||
struct sock_fprog log;
|
||||
struct sock_fprog trace;
|
||||
struct sock_fprog error;
|
||||
struct sock_fprog trap;
|
||||
@@ -746,6 +963,13 @@ FIXTURE_SETUP(precedence)
|
||||
struct sock_filter allow_insns[] = {
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
|
||||
};
|
||||
struct sock_filter log_insns[] = {
|
||||
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
|
||||
offsetof(struct seccomp_data, nr)),
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 1, 0),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_LOG),
|
||||
};
|
||||
struct sock_filter trace_insns[] = {
|
||||
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
|
||||
offsetof(struct seccomp_data, nr)),
|
||||
@@ -782,6 +1006,7 @@ FIXTURE_SETUP(precedence)
|
||||
memcpy(self->_x.filter, &_x##_insns, sizeof(_x##_insns)); \
|
||||
self->_x.len = (unsigned short)ARRAY_SIZE(_x##_insns)
|
||||
FILTER_ALLOC(allow);
|
||||
FILTER_ALLOC(log);
|
||||
FILTER_ALLOC(trace);
|
||||
FILTER_ALLOC(error);
|
||||
FILTER_ALLOC(trap);
|
||||
@@ -792,6 +1017,7 @@ FIXTURE_TEARDOWN(precedence)
|
||||
{
|
||||
#define FILTER_FREE(_x) if (self->_x.filter) free(self->_x.filter)
|
||||
FILTER_FREE(allow);
|
||||
FILTER_FREE(log);
|
||||
FILTER_FREE(trace);
|
||||
FILTER_FREE(error);
|
||||
FILTER_FREE(trap);
|
||||
@@ -809,6 +1035,8 @@ TEST_F(precedence, allow_ok)
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
||||
@@ -833,6 +1061,8 @@ TEST_F_SIGNAL(precedence, kill_is_highest, SIGSYS)
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
||||
@@ -864,6 +1094,8 @@ TEST_F_SIGNAL(precedence, kill_is_highest_in_any_order, SIGSYS)
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
|
||||
@@ -885,6 +1117,8 @@ TEST_F_SIGNAL(precedence, trap_is_second, SIGSYS)
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
||||
@@ -910,6 +1144,8 @@ TEST_F_SIGNAL(precedence, trap_is_second_in_any_order, SIGSYS)
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trap);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
||||
@@ -931,6 +1167,8 @@ TEST_F(precedence, errno_is_third)
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
||||
@@ -949,6 +1187,8 @@ TEST_F(precedence, errno_is_third_in_any_order)
|
||||
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->error);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
||||
@@ -971,6 +1211,8 @@ TEST_F(precedence, trace_is_fourth)
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->trace);
|
||||
ASSERT_EQ(0, ret);
|
||||
/* Should work just fine. */
|
||||
@@ -992,12 +1234,54 @@ TEST_F(precedence, trace_is_fourth_in_any_order)
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
||||
ASSERT_EQ(0, ret);
|
||||
/* Should work just fine. */
|
||||
EXPECT_EQ(parent, syscall(__NR_getppid));
|
||||
/* No ptracer */
|
||||
EXPECT_EQ(-1, syscall(__NR_getpid));
|
||||
}
|
||||
|
||||
TEST_F(precedence, log_is_fifth)
|
||||
{
|
||||
pid_t mypid, parent;
|
||||
long ret;
|
||||
|
||||
mypid = getpid();
|
||||
parent = getppid();
|
||||
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
||||
ASSERT_EQ(0, ret);
|
||||
/* Should work just fine. */
|
||||
EXPECT_EQ(parent, syscall(__NR_getppid));
|
||||
/* Should also work just fine */
|
||||
EXPECT_EQ(mypid, syscall(__NR_getpid));
|
||||
}
|
||||
|
||||
TEST_F(precedence, log_is_fifth_in_any_order)
|
||||
{
|
||||
pid_t mypid, parent;
|
||||
long ret;
|
||||
|
||||
mypid = getpid();
|
||||
parent = getppid();
|
||||
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->log);
|
||||
ASSERT_EQ(0, ret);
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->allow);
|
||||
ASSERT_EQ(0, ret);
|
||||
/* Should work just fine. */
|
||||
EXPECT_EQ(parent, syscall(__NR_getppid));
|
||||
/* Should also work just fine */
|
||||
EXPECT_EQ(mypid, syscall(__NR_getpid));
|
||||
}
|
||||
|
||||
#ifndef PTRACE_O_TRACESECCOMP
|
||||
#define PTRACE_O_TRACESECCOMP 0x00000080
|
||||
#endif
|
||||
@@ -1262,6 +1546,13 @@ TEST_F(TRACE_poke, getpid_runs_normally)
|
||||
# error "Do not know how to find your architecture's registers and syscalls"
|
||||
#endif
|
||||
|
||||
/* When the syscall return can't be changed, stub out the tests for it. */
|
||||
#ifdef SYSCALL_NUM_RET_SHARE_REG
|
||||
# define EXPECT_SYSCALL_RETURN(val, action) EXPECT_EQ(-1, action)
|
||||
#else
|
||||
# define EXPECT_SYSCALL_RETURN(val, action) EXPECT_EQ(val, action)
|
||||
#endif
|
||||
|
||||
/* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
|
||||
* architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux).
|
||||
*/
|
||||
@@ -1357,7 +1648,7 @@ void change_syscall(struct __test_metadata *_metadata,
|
||||
#ifdef SYSCALL_NUM_RET_SHARE_REG
|
||||
TH_LOG("Can't modify syscall return on this architecture");
|
||||
#else
|
||||
regs.SYSCALL_RET = 1;
|
||||
regs.SYSCALL_RET = EPERM;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETREGS
|
||||
@@ -1426,6 +1717,8 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
|
||||
|
||||
if (nr == __NR_getpid)
|
||||
change_syscall(_metadata, tracee, __NR_getppid);
|
||||
if (nr == __NR_open)
|
||||
change_syscall(_metadata, tracee, -1);
|
||||
}
|
||||
|
||||
FIXTURE_DATA(TRACE_syscall) {
|
||||
@@ -1480,6 +1773,28 @@ FIXTURE_TEARDOWN(TRACE_syscall)
|
||||
free(self->prog.filter);
|
||||
}
|
||||
|
||||
TEST_F(TRACE_syscall, ptrace_syscall_redirected)
|
||||
{
|
||||
/* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
|
||||
teardown_trace_fixture(_metadata, self->tracer);
|
||||
self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
|
||||
true);
|
||||
|
||||
/* Tracer will redirect getpid to getppid. */
|
||||
EXPECT_NE(self->mypid, syscall(__NR_getpid));
|
||||
}
|
||||
|
||||
TEST_F(TRACE_syscall, ptrace_syscall_dropped)
|
||||
{
|
||||
/* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
|
||||
teardown_trace_fixture(_metadata, self->tracer);
|
||||
self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
|
||||
true);
|
||||
|
||||
/* Tracer should skip the open syscall, resulting in EPERM. */
|
||||
EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_open));
|
||||
}
|
||||
|
||||
TEST_F(TRACE_syscall, syscall_allowed)
|
||||
{
|
||||
long ret;
|
||||
@@ -1520,13 +1835,8 @@ TEST_F(TRACE_syscall, syscall_dropped)
|
||||
ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
#ifdef SYSCALL_NUM_RET_SHARE_REG
|
||||
/* gettid has been skipped */
|
||||
EXPECT_EQ(-1, syscall(__NR_gettid));
|
||||
#else
|
||||
/* gettid has been skipped and an altered return value stored. */
|
||||
EXPECT_EQ(1, syscall(__NR_gettid));
|
||||
#endif
|
||||
EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_gettid));
|
||||
EXPECT_NE(self->mytid, syscall(__NR_gettid));
|
||||
}
|
||||
|
||||
@@ -1557,6 +1867,7 @@ TEST_F(TRACE_syscall, skip_after_RET_TRACE)
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
/* Tracer will redirect getpid to getppid, and we should see EPERM. */
|
||||
errno = 0;
|
||||
EXPECT_EQ(-1, syscall(__NR_getpid));
|
||||
EXPECT_EQ(EPERM, errno);
|
||||
}
|
||||
@@ -1654,47 +1965,6 @@ TEST_F_SIGNAL(TRACE_syscall, kill_after_ptrace, SIGSYS)
|
||||
EXPECT_NE(self->mypid, syscall(__NR_getpid));
|
||||
}
|
||||
|
||||
#ifndef __NR_seccomp
|
||||
# if defined(__i386__)
|
||||
# define __NR_seccomp 354
|
||||
# elif defined(__x86_64__)
|
||||
# define __NR_seccomp 317
|
||||
# elif defined(__arm__)
|
||||
# define __NR_seccomp 383
|
||||
# elif defined(__aarch64__)
|
||||
# define __NR_seccomp 277
|
||||
# elif defined(__hppa__)
|
||||
# define __NR_seccomp 338
|
||||
# elif defined(__powerpc__)
|
||||
# define __NR_seccomp 358
|
||||
# elif defined(__s390__)
|
||||
# define __NR_seccomp 348
|
||||
# else
|
||||
# warning "seccomp syscall number unknown for this architecture"
|
||||
# define __NR_seccomp 0xffff
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef SECCOMP_SET_MODE_STRICT
|
||||
#define SECCOMP_SET_MODE_STRICT 0
|
||||
#endif
|
||||
|
||||
#ifndef SECCOMP_SET_MODE_FILTER
|
||||
#define SECCOMP_SET_MODE_FILTER 1
|
||||
#endif
|
||||
|
||||
#ifndef SECCOMP_FILTER_FLAG_TSYNC
|
||||
#define SECCOMP_FILTER_FLAG_TSYNC 1
|
||||
#endif
|
||||
|
||||
#ifndef seccomp
|
||||
int seccomp(unsigned int op, unsigned int flags, void *args)
|
||||
{
|
||||
errno = 0;
|
||||
return syscall(__NR_seccomp, op, flags, args);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(seccomp_syscall)
|
||||
{
|
||||
struct sock_filter filter[] = {
|
||||
@@ -1783,6 +2053,67 @@ TEST(seccomp_syscall_mode_lock)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test detection of known and unknown filter flags. Userspace needs to be able
|
||||
* to check if a filter flag is supported by the current kernel and a good way
|
||||
* of doing that is by attempting to enter filter mode, with the flag bit in
|
||||
* question set, and a NULL pointer for the _args_ parameter. EFAULT indicates
|
||||
* that the flag is valid and EINVAL indicates that the flag is invalid.
|
||||
*/
|
||||
TEST(detect_seccomp_filter_flags)
|
||||
{
|
||||
unsigned int flags[] = { SECCOMP_FILTER_FLAG_TSYNC,
|
||||
SECCOMP_FILTER_FLAG_LOG };
|
||||
unsigned int flag, all_flags;
|
||||
int i;
|
||||
long ret;
|
||||
|
||||
/* Test detection of known-good filter flags */
|
||||
for (i = 0, all_flags = 0; i < ARRAY_SIZE(flags); i++) {
|
||||
flag = flags[i];
|
||||
ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
|
||||
ASSERT_NE(ENOSYS, errno) {
|
||||
TH_LOG("Kernel does not support seccomp syscall!");
|
||||
}
|
||||
EXPECT_EQ(-1, ret);
|
||||
EXPECT_EQ(EFAULT, errno) {
|
||||
TH_LOG("Failed to detect that a known-good filter flag (0x%X) is supported!",
|
||||
flag);
|
||||
}
|
||||
|
||||
all_flags |= flag;
|
||||
}
|
||||
|
||||
/* Test detection of all known-good filter flags */
|
||||
ret = seccomp(SECCOMP_SET_MODE_FILTER, all_flags, NULL);
|
||||
EXPECT_EQ(-1, ret);
|
||||
EXPECT_EQ(EFAULT, errno) {
|
||||
TH_LOG("Failed to detect that all known-good filter flags (0x%X) are supported!",
|
||||
all_flags);
|
||||
}
|
||||
|
||||
/* Test detection of an unknown filter flag */
|
||||
flag = -1;
|
||||
ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
|
||||
EXPECT_EQ(-1, ret);
|
||||
EXPECT_EQ(EINVAL, errno) {
|
||||
TH_LOG("Failed to detect that an unknown filter flag (0x%X) is unsupported!",
|
||||
flag);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test detection of an unknown filter flag that may simply need to be
|
||||
* added to this test
|
||||
*/
|
||||
flag = flags[ARRAY_SIZE(flags) - 1] << 1;
|
||||
ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
|
||||
EXPECT_EQ(-1, ret);
|
||||
EXPECT_EQ(EINVAL, errno) {
|
||||
TH_LOG("Failed to detect that an unknown filter flag (0x%X) is unsupported! Does a new flag need to be added to this test?",
|
||||
flag);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TSYNC_first)
|
||||
{
|
||||
struct sock_filter filter[] = {
|
||||
@@ -2421,6 +2752,99 @@ TEST(syscall_restart)
|
||||
_metadata->passed = 0;
|
||||
}
|
||||
|
||||
TEST_SIGNAL(filter_flag_log, SIGSYS)
|
||||
{
|
||||
struct sock_filter allow_filter[] = {
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
|
||||
};
|
||||
struct sock_filter kill_filter[] = {
|
||||
BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
|
||||
offsetof(struct seccomp_data, nr)),
|
||||
BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
|
||||
BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
|
||||
};
|
||||
struct sock_fprog allow_prog = {
|
||||
.len = (unsigned short)ARRAY_SIZE(allow_filter),
|
||||
.filter = allow_filter,
|
||||
};
|
||||
struct sock_fprog kill_prog = {
|
||||
.len = (unsigned short)ARRAY_SIZE(kill_filter),
|
||||
.filter = kill_filter,
|
||||
};
|
||||
long ret;
|
||||
pid_t parent = getppid();
|
||||
|
||||
ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
||||
ASSERT_EQ(0, ret);
|
||||
|
||||
/* Verify that the FILTER_FLAG_LOG flag isn't accepted in strict mode */
|
||||
ret = seccomp(SECCOMP_SET_MODE_STRICT, SECCOMP_FILTER_FLAG_LOG,
|
||||
&allow_prog);
|
||||
ASSERT_NE(ENOSYS, errno) {
|
||||
TH_LOG("Kernel does not support seccomp syscall!");
|
||||
}
|
||||
EXPECT_NE(0, ret) {
|
||||
TH_LOG("Kernel accepted FILTER_FLAG_LOG flag in strict mode!");
|
||||
}
|
||||
EXPECT_EQ(EINVAL, errno) {
|
||||
TH_LOG("Kernel returned unexpected errno for FILTER_FLAG_LOG flag in strict mode!");
|
||||
}
|
||||
|
||||
/* Verify that a simple, permissive filter can be added with no flags */
|
||||
ret = seccomp(SECCOMP_SET_MODE_FILTER, 0, &allow_prog);
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
/* See if the same filter can be added with the FILTER_FLAG_LOG flag */
|
||||
ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
|
||||
&allow_prog);
|
||||
ASSERT_NE(EINVAL, errno) {
|
||||
TH_LOG("Kernel does not support the FILTER_FLAG_LOG flag!");
|
||||
}
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
/* Ensure that the kill filter works with the FILTER_FLAG_LOG flag */
|
||||
ret = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_LOG,
|
||||
&kill_prog);
|
||||
EXPECT_EQ(0, ret);
|
||||
|
||||
EXPECT_EQ(parent, syscall(__NR_getppid));
|
||||
/* getpid() should never return. */
|
||||
EXPECT_EQ(0, syscall(__NR_getpid));
|
||||
}
|
||||
|
||||
TEST(get_action_avail)
|
||||
{
|
||||
__u32 actions[] = { SECCOMP_RET_KILL_THREAD, SECCOMP_RET_TRAP,
|
||||
SECCOMP_RET_ERRNO, SECCOMP_RET_TRACE,
|
||||
SECCOMP_RET_LOG, SECCOMP_RET_ALLOW };
|
||||
__u32 unknown_action = 0x10000000U;
|
||||
int i;
|
||||
long ret;
|
||||
|
||||
ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &actions[0]);
|
||||
ASSERT_NE(ENOSYS, errno) {
|
||||
TH_LOG("Kernel does not support seccomp syscall!");
|
||||
}
|
||||
ASSERT_NE(EINVAL, errno) {
|
||||
TH_LOG("Kernel does not support SECCOMP_GET_ACTION_AVAIL operation!");
|
||||
}
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(actions); i++) {
|
||||
ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &actions[i]);
|
||||
EXPECT_EQ(ret, 0) {
|
||||
TH_LOG("Expected action (0x%X) not available!",
|
||||
actions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that an unknown action is handled properly (EOPNOTSUPP) */
|
||||
ret = seccomp(SECCOMP_GET_ACTION_AVAIL, 0, &unknown_action);
|
||||
EXPECT_EQ(ret, -1);
|
||||
EXPECT_EQ(errno, EOPNOTSUPP);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - add microbenchmarks
|
||||
@@ -2429,6 +2853,8 @@ TEST(syscall_restart)
|
||||
* - endianness checking when appropriate
|
||||
* - 64-bit arg prodding
|
||||
* - arch value testing (x86 modes especially)
|
||||
* - verify that FILTER_FLAG_LOG filters generate log messages
|
||||
* - verify that RET_LOG generates log messages
|
||||
* - ...
|
||||
*/
|
||||
|
||||
|
||||
@@ -39,7 +39,11 @@ void my_usr1(int sig, siginfo_t *si, void *u)
|
||||
stack_t stk;
|
||||
struct stk_data *p;
|
||||
|
||||
#if __s390x__
|
||||
register unsigned long sp asm("%15");
|
||||
#else
|
||||
register unsigned long sp asm("sp");
|
||||
#endif
|
||||
|
||||
if (sp < (unsigned long)sstack ||
|
||||
sp >= (unsigned long)sstack + SIGSTKSZ) {
|
||||
|
||||
@@ -2,12 +2,16 @@ CFLAGS += -O2 -g -std=gnu89 -pthread -Wall -Wextra
|
||||
CFLAGS += -I../../../../usr/include/
|
||||
LDFLAGS += -pthread
|
||||
|
||||
TEST_PROGS = sync_test
|
||||
|
||||
all: $(TEST_PROGS)
|
||||
.PHONY: all clean
|
||||
|
||||
include ../lib.mk
|
||||
|
||||
# lib.mk TEST_CUSTOM_PROGS var is for custom tests that need special
|
||||
# build rules. lib.mk will run and install them.
|
||||
|
||||
TEST_CUSTOM_PROGS := $(OUTPUT)/sync_test
|
||||
all: $(TEST_CUSTOM_PROGS)
|
||||
|
||||
OBJS = sync_test.o sync.o
|
||||
|
||||
TESTS += sync_alloc.o
|
||||
@@ -18,6 +22,16 @@ TESTS += sync_stress_parallelism.o
|
||||
TESTS += sync_stress_consumer.o
|
||||
TESTS += sync_stress_merge.o
|
||||
|
||||
sync_test: $(OBJS) $(TESTS)
|
||||
OBJS := $(patsubst %,$(OUTPUT)/%,$(OBJS))
|
||||
TESTS := $(patsubst %,$(OUTPUT)/%,$(TESTS))
|
||||
|
||||
EXTRA_CLEAN := sync_test $(OBJS) $(TESTS)
|
||||
$(TEST_CUSTOM_PROGS): $(TESTS) $(OBJS)
|
||||
$(CC) -o $(TEST_CUSTOM_PROGS) $(OBJS) $(TESTS) $(CFLAGS) $(LDFLAGS)
|
||||
|
||||
$(OBJS): $(OUTPUT)/%.o: %.c
|
||||
$(CC) -c $^ -o $@
|
||||
|
||||
$(TESTS): $(OUTPUT)/%.o: %.c
|
||||
$(CC) -c $^ -o $@
|
||||
|
||||
EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) $(OBJS) $(TESTS)
|
||||
|
||||
@@ -143,7 +143,8 @@ int setup_timer(int clock_id, int flags, int interval, timer_t *tm1)
|
||||
printf("%-22s %s missing CAP_WAKE_ALARM? : [UNSUPPORTED]\n",
|
||||
clockstring(clock_id),
|
||||
flags ? "ABSTIME":"RELTIME");
|
||||
return 0;
|
||||
/* Indicate timer isn't set, so caller doesn't wait */
|
||||
return 1;
|
||||
}
|
||||
printf("%s - timer_create() failed\n", clockstring(clock_id));
|
||||
return -1;
|
||||
@@ -213,8 +214,9 @@ int do_timer(int clock_id, int flags)
|
||||
int err;
|
||||
|
||||
err = setup_timer(clock_id, flags, interval, &tm1);
|
||||
/* Unsupported case - return 0 to not fail the test */
|
||||
if (err)
|
||||
return err;
|
||||
return err == 1 ? 0 : err;
|
||||
|
||||
while (alarmcount < 5)
|
||||
sleep(1);
|
||||
@@ -228,18 +230,17 @@ int do_timer_oneshot(int clock_id, int flags)
|
||||
timer_t tm1;
|
||||
const int interval = 0;
|
||||
struct timeval timeout;
|
||||
fd_set fds;
|
||||
int err;
|
||||
|
||||
err = setup_timer(clock_id, flags, interval, &tm1);
|
||||
/* Unsupported case - return 0 to not fail the test */
|
||||
if (err)
|
||||
return err;
|
||||
return err == 1 ? 0 : err;
|
||||
|
||||
memset(&timeout, 0, sizeof(timeout));
|
||||
timeout.tv_sec = 5;
|
||||
FD_ZERO(&fds);
|
||||
do {
|
||||
err = select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
|
||||
err = select(0, NULL, NULL, NULL, &timeout);
|
||||
} while (err == -1 && errno == EINTR);
|
||||
|
||||
timer_delete(tm1);
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
TEST_PROGS := watchdog-test
|
||||
|
||||
all: $(TEST_PROGS)
|
||||
TEST_GEN_PROGS := watchdog-test
|
||||
|
||||
include ../lib.mk
|
||||
|
||||
clean:
|
||||
rm -fr $(TEST_PROGS)
|
||||
|
||||
Reference in New Issue
Block a user