How to store packet offset in BPF Map or skb->cb field? - ebpf

Example Code
I want to pass the offset to the following tail calls. But when I try to store it in BPF MAP(Method 1) or skb->cb field(Method 2), I get an error offset is outside of the packet.
If Method 1/2 code is removed, the bpf program can be loaded sucessfully.
#include <vmlinux.h>
#include <bpf/bpf_endian.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__type(key, __u32);
__type(value, __u32);
__uint(max_entries, 100);
} state_vars SEC(".maps");
SEC("tc")
int tc_ingress(struct __sk_buff *ctx) {
void *data_end = (void *)(__u64)ctx->data_end;
void *data = (void *)(__u64)ctx->data;
u32 data_len = data_end - data;
u32 rn = 0;
u32 rn_idx = 0;
for (rn = 0; rn < 1000 && rn < data_len && data + rn < data_end; rn++) {
char c = *(char*)(data + rn);
if (c == '\r') {
rn_idx = rn;
break;
}
}
/// Method 1
// u32 var_idx = 0;
// bpf_map_update_elem(&state_vars, &var_idx, &rn_idx, BPF_ANY);
/// Method 2
// ctx->cb[0] = rn_idx;
return TC_ACT_OK;
}
Error Message
Method 1
; void *data = (void *)(__u64)ctx->data;
0: (61) r2 = *(u32 *)(r1 +76)
; void *data_end = (void *)(__u64)ctx->data_end;
1: (61) r3 = *(u32 *)(r1 +80)
2: (b7) r1 = 0
; u32 rn_idx = 0;
3: (63) *(u32 *)(r10 -4) = r1
last_idx 3 first_idx 0
regs=2 stack=0 before 2: (b7) r1 = 0
; u32 data_len = data_end - data;
4: (bf) r4 = r3
5: (1f) r4 -= r2
6: (67) r4 <<= 32
7: (77) r4 >>= 32
; for (rn = 0; rn < 1000 && rn < data_len && data + rn < data_end; rn++) {
8: (15) if r4 == 0x0 goto pc+10
R1_w=invP0 R2_w=pkt(id=0,off=0,r=0,imm=0) R3_w=pkt_end(id=0,off=0,imm=0) R4_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R10=fp0 fp-8=0000????
; for (rn = 0; rn < 1000 && rn < data_len && data + rn < data_end; rn++) {
9: (bf) r5 = r2
10: (0f) r5 += r1
; for (rn = 0; rn < 1000 && rn < data_len && data + rn < data_end; rn++) {
11: (3d) if r5 >= r3 goto pc+7
R1_w=invP0 R2_w=pkt(id=0,off=0,r=0,imm=0) R3_w=pkt_end(id=0,off=0,imm=0) R4_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R5_w=pkt(id=0,off=0,r=0,imm=0) R10=fp0 fp-8=0000????
; char c = *(char*)(data + rn);
12: (71) r5 = *(u8 *)(r5 +0)
invalid access to packet, off=0 size=1, R5(id=0,off=0,r=0)
R5 offset is outside of the packet
processed 13 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
Method 2
; void *data = (void *)(__u64)ctx->data;
1: (61) r3 = *(u32 *)(r1 +76)
; void *data_end = (void *)(__u64)ctx->data_end;
2: (61) r4 = *(u32 *)(r1 +80)
; u32 data_len = data_end - data;
3: (bf) r5 = r4
4: (1f) r5 -= r3
5: (bf) r0 = r5
6: (67) r0 <<= 32
7: (77) r0 >>= 32
; for (rn = 0; rn < 1000 && rn < data_len && data + rn < data_end; rn++) {
8: (15) if r0 == 0x0 goto pc+21
R0_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R1=ctx(id=0,off=0,imm=0) R2_w=inv0 R3_w=pkt(id=0,off=0,r=0,imm=0) R4_w=pkt_end(id=0,off=0,imm=0) R5_w=inv(id=0) R10=fp0
9: (b7) r2 = 0
10: (b7) r0 = 0
; for (rn = 0; rn < 1000 && rn < data_len && data + rn < data_end; rn++) {
11: (bf) r6 = r3
12: (0f) r6 += r0
last_idx 12 first_idx 0
regs=1 stack=0 before 11: (bf) r6 = r3
regs=1 stack=0 before 10: (b7) r0 = 0
; for (rn = 0; rn < 1000 && rn < data_len && data + rn < data_end; rn++) {
13: (3d) if r6 >= r4 goto pc+16
R0_w=invP0 R1=ctx(id=0,off=0,imm=0) R2_w=inv0 R3_w=pkt(id=0,off=0,r=0,imm=0) R4_w=pkt_end(id=0,off=0,imm=0) R5_w=inv(id=0) R6_w=pkt(id=0,off=0,r=0,imm=0) R10=fp0
; char c = *(char*)(data + rn);
14: (71) r6 = *(u8 *)(r6 +0)
invalid access to packet, off=0 size=1, R6(id=0,off=0,r=0)
R6 offset is outside of the packet
processed 15 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0
Question
Why does the error appear when Method 1/2 code is added?
How could I store the offset value in BPF MAP or skb->cb field?
Update 2022.11.1
follow #pchaigno's advice, add +1 in the condition, I get similar error:
; int tc_ingress(struct __sk_buff *ctx)
0: (b7) r2 = 0
; void *data = (void *)(__u64)ctx->data;
1: (61) r3 = *(u32 *)(r1 +76)
; void *data_end = (void *)(__u64)ctx->data_end;
2: (61) r4 = *(u32 *)(r1 +80)
; u32 data_len = data_end - data;
3: (bf) r5 = r4
4: (1f) r5 -= r3
5: (bf) r0 = r5
6: (67) r0 <<= 32
7: (77) r0 >>= 32
; for (rn = 0; rn < 1000 && rn < data_len && data + rn + 1 < data_end; rn++) {
8: (15) if r0 == 0x0 goto pc+23
R0_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R1=ctx(id=0,off=0,imm=0) R2_w=inv0 R3_w=pkt(id=0,off=0,r=0,imm=0) R4_w=pkt_end(id=0,off=0,imm=0) R5_w=inv(id=0) R10=fp0
9: (b7) r2 = 0
10: (b7) r0 = 0
; for (rn = 0; rn < 1000 && rn < data_len && data + rn + 1 < data_end; rn++) {
11: (bf) r6 = r3
12: (0f) r6 += r0
last_idx 12 first_idx 0
regs=1 stack=0 before 11: (bf) r6 = r3
regs=1 stack=0 before 10: (b7) r0 = 0
13: (bf) r7 = r6
14: (07) r7 += 1
; for (rn = 0; rn < 1000 && rn < data_len && data + rn + 1 < data_end; rn++) {
15: (3d) if r7 >= r4 goto pc+16
R0_w=invP0 R1=ctx(id=0,off=0,imm=0) R2_w=inv0 R3_w=pkt(id=0,off=0,r=0,imm=0) R4_w=pkt_end(id=0,off=0,imm=0) R5_w=inv(id=0) R6_w=pkt(id=0,off=0,r=0,imm=0) R7_w=pkt(id=0,off=1,r=0,imm=0) R10=fp0
; char c = *(char*)(data + rn);
16: (71) r6 = *(u8 *)(r6 +0)
invalid access to packet, off=0 size=1, R6(id=0,off=0,r=0)
R6 offset is outside of the packet
processed 17 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0

TL;DR. The issue is when you read the packet data, not when you write it. You have an off-by-one issue on the bounds check. The issue only appears once you use the read data because otherwise the compiler optimizes out the code.
Verifier Error Explanation
; for (rn = 0; rn < 1000 && rn < data_len && data + rn < data_end; rn++) {
11: (3d) if r5 >= r3 goto pc+7
R1_w=invP0 R2_w=pkt(id=0,off=0,r=0,imm=0) R3_w=pkt_end(id=0,off=0,imm=0) R4_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R5_w=pkt(id=0,off=0,r=0,imm=0) R10=fp0 fp-8=0000????
; char c = *(char*)(data + rn);
12: (71) r5 = *(u8 *)(r5 +0)
invalid access to packet, off=0 size=1, R5(id=0,off=0,r=0)
The verifier says that that the packet access is out of bounds by one: R5's offset + size > R3's offset. That is, both offsets are 0 and the access size is 1.
Root Cause
Your bounds check is off by one:
for (rn = 0; rn < 1000 && rn < data_len && data + rn < data_end; rn++) {
char c = *(char*)(data + rn);
To account for the access size, it should be:
for (rn = 0; rn < 1000 && rn < data_len && data + rn + 1 < data_end; rn++) {
char c = *(char*)(data + rn);
Why does it only happen once you write the packet data?
If you don't write rn_idx anywhere, then the compiler understands that rn_idx and c are not needed. All code for those variables is compiled out and the out-of-bound packet access is removed.

Related

eBPF: 'bpf_map_update()' returns the 'invalid indirect read from stack' error

I have an eBPF program with the following map definitions:
struct bpf_map_def SEC("maps") servers = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct ip_key),
.value_size = sizeof(struct dest_info),
.max_entries = MAX_SERVERS,
};
struct bpf_map_def SEC("maps") client_addrs = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(struct port_key),
.value_size = sizeof(struct client_port_addr),
.max_entries = MAX_CLIENTS,
};
where the struct definitions are as below:
struct port_key {
__u16 port;
__u16 pad[3];
};
struct ip_key {
__u32 key;
__u32 pad;
};
struct dest_info {
__u32 saddr;
__u32 daddr;
__u64 bytes;
__u64 pkts;
__u8 dmac[6];
__u16 pad;
};
struct client_port_addr {
__u32 client_ip;
__u8 dmac[6];
__u16 pad[3];
};
The program itself, after the pointer verifications and initial checks, is shown below.
struct port_key key = {0};
struct client_port_addr val;
key.port = udp->source;
val.client_ip = iph->saddr;
memcpy (val.dmac, eth->h_source, 6 * sizeof(__u8));
bpf_map_update_elem(&client_addrs, &key, &val, BPF_ANY);
iph->saddr = IP_ADDRESS(BALANCER);
iph->daddr = dest_tnl->daddr;
memcpy (eth->h_source, eth->h_dest, 6 * sizeof(__u8));
memcpy (eth->h_dest, dest_tnl->dmac, 6 * sizeof(__u8));
So, the problem is that I use bpf_map_update() in my code, but while using it, I get the invalid indirect read from the stack error as shown below.
libbpf:
0: (bf) r6 = r1
1: (61) r9 = *(u32 *)(r6 +4)
2: (61) r7 = *(u32 *)(r6 +0)
3: (18) r1 = 0xffffa59ac00b6000
5: (b7) r2 = 24
6: (85) call bpf_trace_printk#6
R1_w=map_value(id=0,off=0,ks=4,vs=50,imm=0) R2_w=inv24 R6_w=ctx(id=0,off=0,imm=0) R7_w=pkt(id=0,off=0,r=0,imm=0) R9_w=pkt_end(id=0,off=0,imm=0) R10=fp0
last_idx 6 first_idx 0
regs=4 stack=0 before 5: (b7) r2 = 24
7: (b7) r8 = 1
8: (bf) r1 = r7
9: (07) r1 += 14
10: (2d) if r1 > r9 goto pc+130
R0_w=inv(id=0) R1_w=pkt(id=0,off=14,r=14,imm=0) R6_w=ctx(id=0,off=0,imm=0) R7_w=pkt(id=0,off=0,r=14,imm=0) R8_w=inv1 R9_w=pkt_end(id=0,off=0,imm=0) R10=fp0
11: (71) r1 = *(u8 *)(r7 +12)
12: (71) r2 = *(u8 *)(r7 +13)
13: (67) r2 <<= 8
14: (4f) r2 |= r1
15: (b7) r8 = 2
16: (55) if r2 != 0x8 goto pc+124
R0=inv(id=0) R1=inv(id=0,umax_value=255,var_off=(0x0; 0xff)) R2=inv8 R6=ctx(id=0,off=0,imm=0) R7=pkt(id=0,off=0,r=14,imm=0) R8=inv2 R9=pkt_end(id=0,off=0,imm=0) R10=fp0
17: (61) r7 = *(u32 *)(r6 +4)
18: (61) r9 = *(u32 *)(r6 +0)
19: (bf) r6 = r9
20: (07) r6 += 14
21: (b7) r8 = 1
22: (2d) if r6 > r7 goto pc+118
R0=inv(id=0) R1=inv(id=0,umax_value=255,var_off=(0x0; 0xff)) R2=inv8 R6_w=pkt(id=0,off=14,r=14,imm=0) R7_w=pkt_end(id=0,off=0,imm=0) R8_w=inv1 R9_w=pkt(id=0,off=0,r=14,imm=0) R10=fp0
23: (bf) r1 = r9
24: (07) r1 += 34
25: (b7) r8 = 1
26: (2d) if r1 > r7 goto pc+114
R0=inv(id=0) R1=pkt(id=0,off=34,r=34,imm=0) R2=inv8 R6=pkt(id=0,off=14,r=34,imm=0) R7=pkt_end(id=0,off=0,imm=0) R8=inv1 R9=pkt(id=0,off=0,r=34,imm=0) R10=fp0
27: (71) r1 = *(u8 *)(r6 +0)
28: (57) r1 &= 15
29: (b7) r8 = 1
30: (55) if r1 != 0x5 goto pc+110
R0=inv(id=0) R1_w=inv5 R2=inv8 R6=pkt(id=0,off=14,r=34,imm=0) R7=pkt_end(id=0,off=0,imm=0) R8_w=inv1 R9=pkt(id=0,off=0,r=34,imm=0) R10=fp0
31: (61) r3 = *(u32 *)(r9 +26)
32: (18) r1 = 0xffffa59ac00b6018
34: (b7) r2 = 26
35: (85) call bpf_trace_printk#6
R0=inv(id=0) R1_w=map_value(id=0,off=24,ks=4,vs=50,imm=0) R2_w=inv26 R3_w=inv(id=0,umax_value=4294967295,var_off=(0x0; 0xffffffff)) R6=pkt(id=0,off=14,r=34,imm=0) R7=pkt_end(id=0,off=0,imm=0) R8_w=inv1 R9=pkt(id=0,off=0,r=34,imm=0) R10=fp0
last_idx 35 first_idx 26
regs=4 stack=0 before 34: (b7) r2 = 26
36: (69) r1 = *(u16 *)(r9 +20)
37: (57) r1 &= 65343
38: (b7) r8 = 1
39: (55) if r1 != 0x0 goto pc+101
R0=inv(id=0) R1_w=inv0 R6=pkt(id=0,off=14,r=34,imm=0) R7=pkt_end(id=0,off=0,imm=0) R8_w=inv1 R9=pkt(id=0,off=0,r=34,imm=0) R10=fp0
40: (71) r1 = *(u8 *)(r9 +23)
41: (b7) r8 = 2
42: (55) if r1 != 0x11 goto pc+98
R0=inv(id=0) R1_w=inv17 R6=pkt(id=0,off=14,r=34,imm=0) R7=pkt_end(id=0,off=0,imm=0) R8_w=inv2 R9=pkt(id=0,off=0,r=34,imm=0) R10=fp0
43: (bf) r1 = r9
44: (07) r1 += 42
45: (b7) r8 = 1
46: (2d) if r1 > r7 goto pc+94
R0=inv(id=0) R1=pkt(id=0,off=42,r=42,imm=0) R6=pkt(id=0,off=14,r=42,imm=0) R7=pkt_end(id=0,off=0,imm=0) R8=inv1 R9=pkt(id=0,off=0,r=42,imm=0) R10=fp0
47: (b7) r8 = 0
48: (7b) *(u64 *)(r10 -8) = r8
last_idx 48 first_idx 46
regs=100 stack=0 before 47: (b7) r8 = 0
49: (bf) r2 = r10
50: (07) r2 += -8
51: (18) r1 = 0xffff9a7bed1bc000
53: (85) call bpf_map_lookup_elem#1
54: (bf) r7 = r0
55: (15) if r7 == 0x0 goto pc+85
R0=map_value(id=0,off=0,ks=8,vs=32,imm=0) R6=pkt(id=0,off=14,r=42,imm=0) R7=map_value(id=0,off=0,ks=8,vs=32,imm=0) R8=invP0 R9=pkt(id=0,off=0,r=42,imm=0) R10=fp0 fp-8=mmmmmmmm
56: (b7) r8 = 0
57: (7b) *(u64 *)(r10 -16) = r8
last_idx 57 first_idx 55
regs=100 stack=0 before 56: (b7) r8 = 0
58: (69) r1 = *(u16 *)(r9 +34)
59: (6b) *(u16 *)(r10 -16) = r1
60: (61) r1 = *(u32 *)(r9 +26)
61: (63) *(u32 *)(r10 -32) = r1
62: (71) r1 = *(u8 *)(r9 +11)
63: (73) *(u8 *)(r10 -23) = r1
64: (71) r1 = *(u8 *)(r9 +10)
65: (73) *(u8 *)(r10 -24) = r1
66: (71) r1 = *(u8 *)(r9 +7)
67: (67) r1 <<= 8
68: (71) r2 = *(u8 *)(r9 +6)
69: (4f) r1 |= r2
70: (71) r2 = *(u8 *)(r9 +9)
71: (67) r2 <<= 8
72: (71) r3 = *(u8 *)(r9 +8)
73: (4f) r2 |= r3
74: (67) r2 <<= 16
75: (4f) r2 |= r1
76: (63) *(u32 *)(r10 -28) = r2
77: (bf) r2 = r10
78: (07) r2 += -16
79: (bf) r3 = r10
80: (07) r3 += -32
81: (18) r1 = 0xffff9a7bed1bf400
83: (b7) r4 = 0
84: (85) call bpf_map_update_elem#2
invalid indirect read from stack R3 off -32+10 size 16
processed 81 insns (limit 1000000) max_states_per_insn 0 total_states 5 peak_states 5 mark_read 2
libbpf: -- END LOG --
libbpf: failed to load program 'loadbal'
All of the defined structs for keys and values are padded to their next multiple of 8 bytes. Since I could not find any useful and descriptive explanation on my issue, explanations of this topic and maybe even a bit of detail are much appreciated.
Please let me know if you need more information.
The verifier complains because your code is trying to read uninitialised data from the stack, in particular in your variable val.
If we look at your code:
struct client_port_addr {
__u32 client_ip;
__u8 dmac[6];
__u16 pad[3];
};
struct client_port_addr val;
[...]
val.client_ip = iph->saddr; // val.client_ip
memcpy (val.dmac, eth->h_source, 6 * sizeof(__u8)); // val.dmac
// val.pad where??
bpf_map_update_elem(&client_addrs, &key, &val, BPF_ANY);
You initialised val.client_ip, and val.dmac, but val.pad is never initialised. When you pass val to bpf_map_update_elem(), the eBPF verifier realises that the helper function might read this variable which contains uninitialised memory from kernel space. This is a security risk, therefore, the verifier rejects the program.
To fix the issue, make sure you initialise the memory before using it. You have at least three ways to do so:
You could initialise val when declaring it, like for your key:
struct client_port_addr val = {0};
This should work in your case, but is not generally recommended, because this will set all fields to 0 but if your struct contains padding that was not explicitely added, it may remain uninitialised.
In your case, you could fill val.pad with zeroes with memcpy(). Same as the first option, this won't help if the compiler pads your struct.
The safest option would be to memset() the struct after declaring it:
struct client_port_addr val;
memset(&val, 0, sizeof(val));
Then you can fill the relevant fields of the struct, and pass it to the map update helper.

Register errors when trying to separate strings and print them using BCC

I would like to separate some strings and print them out one by one but it seems almost impossible due to these errors. Trying to change const char str[] to const char *str seems to just net me an opcode 00 error. It seems like I am heading down the right path but just need help to print these lines out one by one. Here is the code running on an online compiler to see what its output looks like String Parser online IDE
from bcc import BPF
# BPF PROGRAM
bpfprogram = """
int helloworld2(void *ctx)
{
const char str[] = "here are some words";
int length = sizeof(str);
int start = 0;
//#pragma unroll Tried using this but does not really fix the issue.
for (int i = 0; i < sizeof(str); i++) {
if (str[i] == ' ') {
bpf_trace_printk("%s\\n", i - start, str + start);
start = i + 1;
}
}
bpf_trace_printk("%s\\n", length - start, str + start);
return 0;
}
"""
# This compiles the program defined by the bpfprogram string into bpf bytecode and
#loads it to the kernel BPF verifier.
b = BPF(text=bpfprogram)
# This attaches the compiled BPF program to a kernel event of your choosing,
#in this case to the sys_clone syscall which will cause the BPF program to run
#everytime the sys_clone call occurs.
b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="helloworld2")
# Capture and print the BPF program's trace output
b.trace_print()
Here is the error that I am seeing, Trying a pointer instead of a char array just nets me an opcode 00 error. Trying #pragma unroll does not seem to really fix the issue either. I am wondering if there is a solution to this problem that I am just not seeing. One notable error is near the end here: R4 bitwise operator |= on pointer prohibited
bpf: Failed to load program: Permission denied
btf_vmlinux is malformed
Unrecognized arg#0 type PTR
; int helloworld2(void *ctx)
0: (b7) r1 = 7562354
; const char str[] = "here are some words";
1: (63) *(u32 *)(r10 -8) = r1
2: (18) r1 = 0x6f7720656d6f7320
4: (7b) *(u64 *)(r10 -16) = r1
5: (18) r1 = 0x6572612065726568
7: (7b) *(u64 *)(r10 -24) = r1
8: (b7) r6 = 684837
; ({ char _fmt[] = "%s\n"; bpf_trace_printk_(_fmt, sizeof(_fmt), i - start, str + start); });
9: (63) *(u32 *)(r10 -28) = r6
10: (bf) r1 = r10
;
11: (07) r1 += -28
12: (bf) r4 = r10
13: (07) r4 += -24
; ({ char _fmt[] = "%s\n"; bpf_trace_printk_(_fmt, sizeof(_fmt), i - start, str + start); });
14: (b7) r2 = 4
15: (b7) r3 = 4
16: (85) call bpf_trace_printk#6
last_idx 16 first_idx 0
regs=4 stack=0 before 15: (b7) r3 = 4
regs=4 stack=0 before 14: (b7) r2 = 4
17: (b7) r1 = 5
; if (str[i] == ' ') {
18: (71) r2 = *(u8 *)(r10 -19)
; if (str[i] == ' ') {
19: (55) if r2 != 0x20 goto pc+9
R0_w=inv(id=0) R1_w=inv5 R2_w=inv32 R6_w=inv684837 R10=fp0 fp-8=????mmmm fp-16_w=inv8031924080438375200 fp-24_w=inv7310011936944579944 fp-32=mmmm????
;
20: (bf) r4 = r10
21: (07) r4 += -19
; ({ char _fmt[] = "%s\n"; bpf_trace_printk_(_fmt, sizeof(_fmt), i - start, str + start); });
22: (63) *(u32 *)(r10 -28) = r6
23: (bf) r1 = r10
;
24: (07) r1 += -28
; ({ char _fmt[] = "%s\n"; bpf_trace_printk_(_fmt, sizeof(_fmt), i - start, str + start); });
25: (b7) r2 = 4
26: (b7) r3 = 0
27: (85) call bpf_trace_printk#6
last_idx 27 first_idx 0
regs=4 stack=0 before 26: (b7) r3 = 0
regs=4 stack=0 before 25: (b7) r2 = 4
28: (b7) r1 = 6
; if (str[i] == ' ') {
29: (71) r2 = *(u8 *)(r10 -18)
; if (str[i] == ' ') {
30: (55) if r2 != 0x20 goto pc+12
R0=inv(id=0) R1_w=inv6 R2_w=inv32 R6=inv684837 R10=fp0 fp-8=????mmmm fp-16=inv8031924080438375200 fp-24=inv7310011936944579944 fp-32=mmmm????
31: (b7) r2 = 684837
; ({ char _fmt[] = "%s\n"; bpf_trace_printk_(_fmt, sizeof(_fmt), i - start, str + start); });
32: (63) *(u32 *)(r10 -28) = r2
33: (b7) r3 = 6
; ({ char _fmt[] = "%s\n"; bpf_trace_printk_(_fmt, sizeof(_fmt), i - start, str + start); });
34: (1f) r3 -= r1
35: (bf) r4 = r10
;
36: (07) r4 += -24
; ({ char _fmt[] = "%s\n"; bpf_trace_printk_(_fmt, sizeof(_fmt), i - start, str + start); });
37: (4f) r4 |= r1
last_idx 37 first_idx 28
regs=2 stack=0 before 36: (07) r4 += -24
regs=2 stack=0 before 35: (bf) r4 = r10
regs=2 stack=0 before 34: (1f) r3 -= r1
regs=2 stack=0 before 33: (b7) r3 = 6
regs=2 stack=0 before 32: (63) *(u32 *)(r10 -28) = r2
regs=2 stack=0 before 31: (b7) r2 = 684837
regs=2 stack=0 before 30: (55) if r2 != 0x20 goto pc+12
regs=2 stack=0 before 29: (71) r2 = *(u8 *)(r10 -18)
regs=2 stack=0 before 28: (b7) r1 = 6
R4 bitwise operator |= on pointer prohibited
processed 36 insns (limit 1000000) max_states_per_insn 0 total_states 1 peak_states 1 mark_read 1
Traceback (most recent call last):
File "BPFHelloWorld.py", line 31, in <module>
b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="helloworld2")
File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 654, in attach_kprobe
fn = self.load_func(fn_name, BPF.KPROBE)
File "/usr/lib/python3/dist-packages/bcc/__init__.py", line 394, in load_func
raise Exception("Failed to load BPF program %s: %s" %
Exception: Failed to load BPF program b'helloworld2': Permission denied
You are using bcc's bpf_trace_print function which expects different arguments from the kernel helper.
In bcc, bpf_trace_print is a sort of wrapper around the corresponding BPF helper. If you check its documentation, it expects a single mandatory argument, a string and several optional arguments:
Syntax: int bpf_trace_printk(const char *fmt, ...)
So you can write things like:
bpf_trace_printk("remote-port: %d, local-port: %d\\n", skk.remote_port,
skk.local_port);
In contrast, the BPF helper expects the first argument to be the string and the second to be the size of the string:
static const struct bpf_func_proto bpf_trace_printk_proto = {
.func = bpf_trace_printk,
.gpl_only = true,
.ret_type = RET_INTEGER,
.arg1_type = ARG_PTR_TO_MEM,
.arg2_type = ARG_CONST_SIZE,
};

Solving linear equation systems in Coq [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 3 years ago.
Improve this question
I need to prove that this system of equations does not have a solution (the reason is that it is over-determined). Is there an easy way to do it in Coq? I.e. a tactic or library?
Require Import Reals.
Open Scope R.
Lemma no_solution:
forall
b11 b12 b13 b14 b21 b22 b23 b24 b31 b32 b33 b34
r r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 : R,
1 = r * b11 + r0 * b21 + r1 * b31 ->
0 = r * b12 + r0 * b22 + r1 * b32 ->
0 = r * b13 + r0 * b23 + r1 * b33 ->
0 = r * b14 + r0 * b24 + r1 * b34 ->
0 = r2 * b11 + r3 * b21 + r4 * b31 ->
1 = r2 * b12 + r3 * b22 + r4 * b32 ->
0 = r2 * b13 + r3 * b23 + r4 * b33 ->
0 = r2 * b14 + r3 * b24 + r4 * b34 ->
0 = r5 * b11 + r6 * b21 + r7 * b31 ->
0 = r5 * b12 + r6 * b22 + r7 * b32 ->
1 = r5 * b13 + r6 * b23 + r7 * b33 ->
0 = r5 * b14 + r6 * b24 + r7 * b34 ->
0 = r8 * b11 + r9 * b21 + r10 * b31 ->
0 = r8 * b12 + r9 * b22 + r10 * b32 ->
0 = r8 * b13 + r9 * b23 + r10 * b33 ->
1 = r8 * b14 + r9 * b24 + r10 * b34 ->
False.
If I understand well, this bunch of equations cannot be simultaneously true because it would require the rank of a 3x4 matrix to be higher than 3.
The main theorem for your result is called mulmx_max_rank in the mathematical components library. I had more work connecting your unstructured presentation of the problem to a
structured one using matrices than finding the right theorem. This experiment was made in coq-8.7, with coq-mathcomp-ssreflect and coq-mathcomp-algebra loaded through opam (version 1.6.2 of the packages).
Note that this results holds for any field structure.
From mathcomp Require Import all_ssreflect all_algebra.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Import GRing.Theory Num.Theory.
Open Scope ring_scope.
Section Solving_linear_equation_systems_in_Coq.
Variable R : fieldType.
Definition seq2matrix m n (s : seq (seq R)) :=
\matrix_(i < m, j < n)
nth 0 (nth nil s i) j.
Lemma no_solution:
forall
b11 b12 b13 b14 b21 b22 b23 b24 b31 b32 b33 b34
r r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 : R,
1 = r * b11 + r0 * b21 + r1 * b31 ->
0 = r * b12 + r0 * b22 + r1 * b32 ->
0 = r * b13 + r0 * b23 + r1 * b33 ->
0 = r * b14 + r0 * b24 + r1 * b34 ->
0 = r2 * b11 + r3 * b21 + r4 * b31 ->
1 = r2 * b12 + r3 * b22 + r4 * b32 ->
0 = r2 * b13 + r3 * b23 + r4 * b33 ->
0 = r2 * b14 + r3 * b24 + r4 * b34 ->
0 = r5 * b11 + r6 * b21 + r7 * b31 ->
0 = r5 * b12 + r6 * b22 + r7 * b32 ->
1 = r5 * b13 + r6 * b23 + r7 * b33 ->
0 = r5 * b14 + r6 * b24 + r7 * b34 ->
0 = r8 * b11 + r9 * b21 + r10 * b31 ->
0 = r8 * b12 + r9 * b22 + r10 * b32 ->
0 = r8 * b13 + r9 * b23 + r10 * b33 ->
1 = r8 * b14 + r9 * b24 + r10 * b34 ->
False.
Proof.
move => b11 b12 b13 b14 b21 b22 b23 b24 b31 b32 b33 b34
r r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 eq1 eq2 eq3 eq4
eq5 eq6 eq7 eq8 eq9 eq10 eq11 eq12 eq13 eq14 eq15 eq16.
set Inp := seq2matrix 4 3
[:: [:: r; r0; r1];
[:: r2; r3; r4];
[:: r5; r6; r7];
[:: r8; r9; r10]].
set B := seq2matrix 3 4 [:: [:: b11; b12; b13; b14];
[:: b21; b22; b23; b24];
[:: b31; b32; b33; b34]].
suff abs: Inp *m B = 1%:M.
have : (\rank (Inp *m B) <= 3)%N by apply: mulmx_max_rank.
by rewrite abs mxrank1.
by apply/matrixP=> [[ [ | [ | [ | [ | ?]]]] pi]]
[ [ | [ | [ | [ | ?]]]] pj] //;
rewrite /Inp /seq2matrix /= !(mxE, big_ord_recr, big_ord0) //= add0r /=
-?(eq1, eq2, eq3, eq4, eq5, eq6, eq7, eq8, eq9, eq10, eq11, eq12).
Qed.
End Solving_linear_equation_systems_in_Coq.

how to select wanted ( needed situations) dual elements which are randomly generated by using random sampling in matlab?

I have 2 different random selected variables. The first one is number of bedrooms which is r1 and the second one is number of people in the dwelling which is r2. there are different certain constant values, which are going to be used for selection of house size.Wanted combinations
There are 24 different combinations that both of random generators can produce by using number of bedrooms and number of people in the house. there is no problem if the random generators produce wanted combinations.If not, there is a problem come out which is unwanted combinations.
How can get rid of this unwanted combinations or how to solve this problem in another way?
My code is as follows:
R1 = randsample('xyzq',1,true,[0.1 0.2 0.43 0.27]); % Probability of number of bedrooms in dwellings
r1=R1;
R2 = randsample('abcdef',1,true,[0.283 0.358 0.163 0.134 0.044 0.018]); %Probability of Household size in UK
r2=R2;
if (r1 == 'x' && r2 == 'a') % 37m2 1 bed, 1 per
A_roof = 37;
A_floor = 37;
A_wall = 35;
A_door = 3;
A_windows = 3;
elseif (r1 == 'x' && r2 == 'b') % 50m2 1 bed, 2 per
A_roof = 50;
A_floor = 50;
A_wall = 47;
A_door = 6;
A_windows = 6;
elseif (r1 == 'y' && r2 == 'c') % 61m2 2 bed, 3 per
A_roof = 61;
A_floor = 61;
A_wall = 42;
A_door = 5;
A_windows = 5;
elseif (r1 == 'y' && r2 == 'd') % 70m2 2 bed, 4 per
A_roof = 70;
A_floor = 70;
A_wall = 50;
A_door = 5;
A_windows = 5;
elseif (r1 == 'y' && r2 == 'd') % 74m2 3 bed, 4 per
A_roof = 74;
A_floor = 74;
A_wall = 51;
A_door = 6;
A_windows = 6;
elseif (r1 == 'z' && r2 == 'e') % 86m2 3 bed, 5 per
A_roof = 86;
A_floor = 86;
A_wall = 55;
A_door = 6;
A_windows = 6;
elseif (r1 == 'z' && r2 == 'f') % 95m2 3 bed, 6 per
A_roof = 95;
A_floor = 95;
A_wall = 70;
A_door = 7;
A_windows = 7;
elseif (r1 == 'q' && r2 == 'e') % 90m2 4 bed, 5 per
A_roof = 90;
A_floor = 90;
A_wall = 68;
A_door = 7;
A_windows = 7;
elseif (r1 == 'q' && r2 == 'f') % 99m2 4 bed, 6 per
A_roof = 99;
A_floor = 99;
A_wall = 74;
A_door = 8;
A_windows = 8;
elseif (r1 == 'y' && r2 == 'd') % 83m2 2 bed, 4 per
A_roof = 40;
A_floor = 83;
A_wall = 105;
A_door = 8;
A_windows = 8;
elseif (r1 == 'z') && (r2 == 'd') % 87m2 3 bed, 4 per
A_roof = 42;
A_floor = 87;
A_wall = 105;
A_door = 8;
A_windows = 8;
elseif (r1 == 'z' && r2 == 'e') % 96m2 3 bed, 5 per
A_roof = 46;
A_floor = 96;
A_wall = 150;
A_door = 10;
A_windows = 10;
elseif (r1 == 'q' && r2 == 'e') % 100m2 4 bed, 5 per
A_roof = 50;
A_floor = 100;
A_wall = 180;
A_door = 10;
A_windows = 10;
elseif(r1 == 'q' && r2 == 'f') % 107m2 4 bed, 6 per
A_roof = 55;
A_floor = 107;
A_wall = 125;
A_door = 10;
A_windows = 10;
elseif (r1 == 'z' && r2 == 'e') % 102m2 3 bed, 5 per
A_roof = 50;
A_floor = 102;
A_wall = 200;
A_door = 10;
A_windows = 10;
elseif (r1 == 'q' && r2 == 'e') % 106m2 4 bed, 5 per
A_roof = 55;
A_floor = 106;
A_wall = 200;
A_door = 10;
A_windows = 10;
elseif (r1 == 'q' && r2 == 'f') % 113m2 4 bed, 6 per
A_roof = 60;
A_floor = 113;
A_wall = 200;
A_door = 10;
A_windows = 10;
end

VHDL PS/2 interface

I am using VHDL and an FPGA board, a VGA interface and a PS/2 keyboard interface to create a maze and make a square that can move through the maze. When I press one of the keys (WASD), the square moves only one position and then will not move again. I need it to move every time one of the keys is pressed. Here is my code:
ENTITY hw_image_generator IS
PORT(
ps2_code : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
game_clk : IN STD_LOGIC;
disp_ena : IN STD_LOGIC; --display enable ('1' = display time, '0' = blanking time)
row : IN INTEGER; --row pixel coordinate
column : IN INTEGER; --column pixel coordinate
red : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '0'); --red magnitude output to DAC
green : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '0'); --green magnitude output to DAC
blue : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '0')); --blue magnitude output to DAC
END hw_image_generator;
ARCHITECTURE behavior OF hw_image_generator IS
signal x_position: INTEGER := 20;
signal y_position: INTEGER := 20;
CONSTANT max_count: NATURAL := 500000;
SIGNAL reset: STD_LOGIC;
BEGIN
PROCESS(game_clk, reset, x_position, y_position)
VARIABLE count : NATURAL range 0 to max_count;
BEGIN
IF (reset = '1') THEN
count := 0;
x_position <= 20;
y_position <= 20;
ELSIF(rising_edge(game_clk) AND count = 0) THEN
IF(count < max_count)THEN
IF(ps2_code = "00101001") THEN -- space bar
count := 0;
x_position <= 20;
y_position <= 20;
END IF;
IF(ps2_code = "00011101") THEN --W key
count := count + 1;
y_position <= y_position;
x_position <= x_position - 10;
END IF;
IF(ps2_code = "00011011") THEN --S key
count := count + 1;
y_position <= y_position;
x_position <= x_position + 10;
END IF;
IF(ps2_code = "00100011") THEN --D key
count := count + 1;
x_position <= x_position;
y_position <= y_position + 10;
END IF;
IF(ps2_code = "00011100") THEN --A key
count := count + 1;
x_position <= x_position;
y_position <= y_position - 10;
END IF;
ELSE
count := 0;
END IF;
END IF;
END PROCESS;
PROCESS(disp_ena, row, column)
BEGIN
IF(disp_ena = '1') THEN --display time
IF(row < 512 AND column > 231 AND column < 281) THEN
red <= (OTHERS => '0');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
ELSIF(row > 743 AND row < 793 AND column < 512) THEN
red <= (OTHERS => '0');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
ELSIF(row > 1024 AND column > 231 AND column < 281) THEN
red <= (OTHERS => '0');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
ELSIF(row > 256 AND row < 1024 AND column > 487 AND column < 537) THEN
red <= (OTHERS => '0');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
ELSIF(row > 487 AND row < 537 AND column > 536 AND column < 768) THEN
red <= (OTHERS => '0');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
ELSIF(row > 231 AND row < 281 AND column > 768) THEN
red <= (OTHERS => '0');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
ELSIF(row > 743 AND row < 793 AND column > 768) THEN
red <= (OTHERS => '0');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
ELSIF(row > 974 AND row < 1024 AND column > 536 AND column < 768) THEN
red <= (OTHERS => '0');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
ELSE
red <= (OTHERS => '1');
green <= (OTHERS => '1');
blue <= (OTHERS => '1');
END IF;
IF(row > x_position AND row < x_position+50 AND column > y_position AND column < y_position+50) THEN
red <= (OTHERS => '1');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
END IF;
ELSE --blanking time
red <= (OTHERS => '0');
green <= (OTHERS => '0');
blue <= (OTHERS => '0');
END IF;
END PROCESS;
END behavior;
In your unlabelled process sensitive to game_clk:
process (game_clk, reset, x_position, y_position)
variable count: natural range 0 to max_count;
begin
if reset = '1' then
count := 0;
x_position <= 20;
y_position <= 20;
elsif rising_edge(game_clk) and count = 0 then
if count < max_count then
if ps2_code = "00101001" then -- space bar
count := 0;
x_position <= 20;
y_position <= 20;
end if;
if ps2_code = "00011101" then --w key
count := count + 1;
y_position <= y_position;
x_position <= x_position - 10;
end if;
if ps2_code = "00011011" then --s key
count := count + 1;
y_position <= y_position;
x_position <= x_position + 10;
end if;
if ps2_code = "00100011" then --d key
count := count + 1;
x_position <= x_position;
y_position <= y_position + 10;
end if;
if ps2_code = "00011100" then --a key
count := count + 1;
x_position <= x_position;
y_position <= y_position - 10;
end if;
else
count := 0;
end if;
end if;
end process;
Notice you don't need x_position and y_position in the sensitivity list. All signal assignments are either due to a reset event or a game_clk event.
Also note the enable count = 0 in the condition for the elsif:
elsif rising_edge(game_clk) and count = 0 then
And the condition in the following if statement:
if count < max_count then
Once any of your ps2_code recognizers (except the space bar) is valid you'll increment count and no longer enable any flip flops and registers you're assigning here on the rising edge of game_clk. You also can't tell if you hit successive space bars. without hitting another recognizer.
Your code matches your description of your problem, it's a feature.
PROCESS(game_clk)
BEGIN
IF(game_clk'EVENT AND game_clk = '1')THEN
count <= count + 1;
IF(count = 5000000 AND ps2_code = "00101001")THEN --space key
count <= 0;
x_position <= 20;
y_position <= 20;
END IF;
IF(count = 5000000 AND ps2_code = "00011101")THEN --W key
count <= 0;
IF((y_position > 0 AND y_position < 181 AND x_position > 0 and x_position < 512) --1
OR (y_position > 0 AND y_position < 437 AND x_position > 512 AND x_position < 693) --2
OR (y_position > 281 AND y_position < 437 AND x_position > 0 and x_position < 512) --3
OR (y_position > 437 AND y_position < 537 AND x_position > 0 AND x_position < 206) --4
OR (y_position > 537 AND y_position < 1227 AND x_position > 0 AND x_position < 181) --5
OR (y_position > 537 AND y_position < 718 AND x_position > 181 AND x_position < 437) --6
OR (y_position > 768 AND y_position < 1227 AND x_position > 281 AND x_position < 718) --7
OR (y_position > 537 AND y_position < 768 AND x_position > 537 AND x_position < 693) --8
OR (y_position > 537 AND y_position < 718 AND x_position > 693 AND x_position < 793) --9
OR (y_position > 537 AND y_position < 768 AND x_position > 793 AND x_position < 975) --10
OR (y_position > 768 AND y_position < 1227 AND x_position > 793 AND x_position < 1027) --11
OR (y_position > 718 AND y_position < 768 AND x_position > 281 AND x_position < 437) --12
) THEN
x_position <= x_position - 10;
ELSE
x_position <= x_position + 5;
y_position <= y_position;
END IF;
ELSIF(count = 5000000 AND ps2_code = "00011011") THEN --S key
count <= 0;
IF((y_position > 0 AND y_position < 181 AND x_position > 0 and x_position < 512) --1
OR (y_position > 0 AND y_position < 437 AND x_position > 512 AND x_position < 693) --2
OR (y_position > 281 AND y_position < 437 AND x_position > 0 and x_position < 512) --3
OR (y_position > 437 AND y_position < 537 AND x_position > 0 AND x_position < 206) --4
OR (y_position > 537 AND y_position < 1227 AND x_position > 0 AND x_position < 181) --5
OR (y_position > 537 AND y_position < 718 AND x_position > 181 AND x_position < 437) --6
OR (y_position > 768 AND y_position < 1227 AND x_position > 281 AND x_position < 718) --7
OR (y_position > 537 AND y_position < 768 AND x_position > 537 AND x_position < 693) --8
OR (y_position > 537 AND y_position < 718 AND x_position > 693 AND x_position < 793) --9
OR (y_position > 537 AND y_position < 768 AND x_position > 793 AND x_position < 975) --10
OR (y_position > 768 AND y_position < 1227 AND x_position > 793 AND x_position < 1027) --11
OR (y_position > 718 AND y_position < 768 AND x_position > 281 AND x_position < 437) --12
) THEN
x_position <= x_position + 10;
ELSE
x_position <= x_position - 5;
y_position <= y_position;
END IF;
ELSIF(count = 5000000 AND ps2_code = "00100011") THEN --D key
count <= 0;
IF((y_position > 0 AND y_position < 181 AND x_position > 0 and x_position < 512) --1
OR (y_position > 0 AND y_position < 437 AND x_position > 512 AND x_position < 693) --2
OR (y_position > 281 AND y_position < 437 AND x_position > 0 and x_position < 512) --3
OR (y_position > 437 AND y_position < 537 AND x_position > 0 AND x_position < 206) --4
OR (y_position > 537 AND y_position < 1227 AND x_position > 0 AND x_position < 181) --5
OR (y_position > 537 AND y_position < 718 AND x_position > 181 AND x_position < 437) --6
OR (y_position > 768 AND y_position < 1227 AND x_position > 281 AND x_position < 718) --7
OR (y_position > 537 AND y_position < 768 AND x_position > 537 AND x_position < 693) --8
OR (y_position > 537 AND y_position < 718 AND x_position > 693 AND x_position < 793) --9
OR (y_position > 537 AND y_position < 768 AND x_position > 793 AND x_position < 975) --10
OR (y_position > 768 AND y_position < 1227 AND x_position > 793 AND x_position < 1027) --11
OR (y_position > 718 AND y_position < 768 AND x_position > 281 AND x_position < 437) --12
) THEN
y_position <= y_position + 10;
ELSE
x_position <= x_position;
y_position <= y_position -5;
END IF;
ELSIF(count = 5000000 AND ps2_code = "00011100") THEN --A key
count <= 0;
IF((y_position > 0 AND y_position < 181 AND x_position > 0 and x_position < 512) --1
OR (y_position > 0 AND y_position < 437 AND x_position > 512 AND x_position < 693) --2
OR (y_position > 281 AND y_position < 437 AND x_position > 0 and x_position < 512) --3
OR (y_position > 437 AND y_position < 537 AND x_position > 0 AND x_position < 206) --4
OR (y_position > 537 AND y_position < 1227 AND x_position > 0 AND x_position < 181) --5
OR (y_position > 537 AND y_position < 718 AND x_position > 181 AND x_position < 437) --6
OR (y_position > 768 AND y_position < 1227 AND x_position > 281 AND x_position < 718) --7
OR (y_position > 537 AND y_position < 768 AND x_position > 537 AND x_position < 693) --8
OR (y_position > 537 AND y_position < 718 AND x_position > 693 AND x_position < 793) --9
OR (y_position > 537 AND y_position < 768 AND x_position > 793 AND x_position < 975) --10
OR (y_position > 768 AND y_position < 1227 AND x_position > 793 AND x_position < 1027) --11
OR (y_position > 718 AND y_position < 768 AND x_position > 281 AND x_position < 437) --12
) THEN
y_position <= y_position - 10;
ELSE
x_position <= x_position;
y_position <= y_position +5;
END IF;
END IF;
END IF;
END PROCESS;