1 {
2 	/* This is equivalent to the following program:
3 	 *
4 	 *   r6 = skb->sk;
5 	 *   r7 = sk_fullsock(r6);
6 	 *   r0 = sk_fullsock(r6);
7 	 *   if (r0 == 0) return 0;    (a)
8 	 *   if (r0 != r7) return 0;   (b)
9 	 *   *r7->type;                (c)
10 	 *   return 0;
11 	 *
12 	 * It is safe to dereference r7 at point (c), because of (a) and (b).
13 	 * The test verifies that relation r0 == r7 is propagated from (b) to (c).
14 	 */
15 	"jne/jeq infer not null, PTR_TO_SOCKET_OR_NULL -> PTR_TO_SOCKET for JNE false branch",
16 	.insns = {
17 	/* r6 = skb->sk; */
18 	BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, offsetof(struct __sk_buff, sk)),
19 	/* if (r6 == 0) return 0; */
20 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 8),
21 	/* r7 = sk_fullsock(skb); */
22 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
23 	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
24 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
25 	/* r0 = sk_fullsock(skb); */
26 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
27 	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
28 	/* if (r0 == null) return 0; */
29 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
30 	/* if (r0 == r7) r0 = *(r7->type); */
31 	BPF_JMP_REG(BPF_JNE, BPF_REG_0, BPF_REG_7, 1), /* Use ! JNE ! */
32 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_sock, type)),
33 	/* return 0 */
34 	BPF_MOV64_IMM(BPF_REG_0, 0),
35 	BPF_EXIT_INSN(),
36 	},
37 	.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
38 	.result = ACCEPT,
39 	.result_unpriv = REJECT,
40 	.errstr_unpriv = "R7 pointer comparison",
41 },
42 {
43 	/* Same as above, but verify that another branch of JNE still
44 	 * prohibits access to PTR_MAYBE_NULL.
45 	 */
46 	"jne/jeq infer not null, PTR_TO_SOCKET_OR_NULL unchanged for JNE true branch",
47 	.insns = {
48 	/* r6 = skb->sk */
49 	BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, offsetof(struct __sk_buff, sk)),
50 	/* if (r6 == 0) return 0; */
51 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 9),
52 	/* r7 = sk_fullsock(skb); */
53 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
54 	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
55 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
56 	/* r0 = sk_fullsock(skb); */
57 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
58 	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
59 	/* if (r0 == null) return 0; */
60 	BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3),
61 	/* if (r0 == r7) return 0; */
62 	BPF_JMP_REG(BPF_JNE, BPF_REG_0, BPF_REG_7, 1), /* Use ! JNE ! */
63 	BPF_JMP_IMM(BPF_JA, 0, 0, 1),
64 	/* r0 = *(r7->type); */
65 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_sock, type)),
66 	/* return 0 */
67 	BPF_MOV64_IMM(BPF_REG_0, 0),
68 	BPF_EXIT_INSN(),
69 	},
70 	.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
71 	.result = REJECT,
72 	.errstr = "R7 invalid mem access 'sock_or_null'",
73 	.result_unpriv = REJECT,
74 	.errstr_unpriv = "R7 pointer comparison",
75 },
76 {
77 	/* Same as a first test, but not null should be inferred for JEQ branch */
78 	"jne/jeq infer not null, PTR_TO_SOCKET_OR_NULL -> PTR_TO_SOCKET for JEQ true branch",
79 	.insns = {
80 	/* r6 = skb->sk; */
81 	BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, offsetof(struct __sk_buff, sk)),
82 	/* if (r6 == null) return 0; */
83 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 9),
84 	/* r7 = sk_fullsock(skb); */
85 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
86 	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
87 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
88 	/* r0 = sk_fullsock(skb); */
89 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
90 	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
91 	/* if (r0 == null) return 0; */
92 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
93 	/* if (r0 != r7) return 0; */
94 	BPF_JMP_REG(BPF_JEQ, BPF_REG_0, BPF_REG_7, 1), /* Use ! JEQ ! */
95 	BPF_JMP_IMM(BPF_JA, 0, 0, 1),
96 	/* r0 = *(r7->type); */
97 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_sock, type)),
98 	/* return 0; */
99 	BPF_MOV64_IMM(BPF_REG_0, 0),
100 	BPF_EXIT_INSN(),
101 	},
102 	.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
103 	.result = ACCEPT,
104 	.result_unpriv = REJECT,
105 	.errstr_unpriv = "R7 pointer comparison",
106 },
107 {
108 	/* Same as above, but verify that another branch of JNE still
109 	 * prohibits access to PTR_MAYBE_NULL.
110 	 */
111 	"jne/jeq infer not null, PTR_TO_SOCKET_OR_NULL unchanged for JEQ false branch",
112 	.insns = {
113 	/* r6 = skb->sk; */
114 	BPF_LDX_MEM(BPF_DW, BPF_REG_6, BPF_REG_1, offsetof(struct __sk_buff, sk)),
115 	/* if (r6 == null) return 0; */
116 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 8),
117 	/* r7 = sk_fullsock(skb); */
118 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
119 	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
120 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
121 	/* r0 = sk_fullsock(skb); */
122 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
123 	BPF_EMIT_CALL(BPF_FUNC_sk_fullsock),
124 	/* if (r0 == null) return 0; */
125 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
126 	/* if (r0 != r7) r0 = *(r7->type); */
127 	BPF_JMP_REG(BPF_JEQ, BPF_REG_0, BPF_REG_7, 1), /* Use ! JEQ ! */
128 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_sock, type)),
129 	/* return 0; */
130 	BPF_MOV64_IMM(BPF_REG_0, 0),
131 	BPF_EXIT_INSN(),
132 	},
133 	.prog_type = BPF_PROG_TYPE_CGROUP_SKB,
134 	.result = REJECT,
135 	.errstr = "R7 invalid mem access 'sock_or_null'",
136 	.result_unpriv = REJECT,
137 	.errstr_unpriv = "R7 pointer comparison",
138 },
139 {
140 	/* Maps are treated in a different branch of `mark_ptr_not_null_reg`,
141 	 * so separate test for maps case.
142 	 */
143 	"jne/jeq infer not null, PTR_TO_MAP_VALUE_OR_NULL -> PTR_TO_MAP_VALUE",
144 	.insns = {
145 	/* r9 = &some stack to use as key */
146 	BPF_ST_MEM(BPF_W, BPF_REG_10, -8, 0),
147 	BPF_MOV64_REG(BPF_REG_9, BPF_REG_10),
148 	BPF_ALU64_IMM(BPF_ADD, BPF_REG_9, -8),
149 	/* r8 = process local map */
150 	BPF_LD_MAP_FD(BPF_REG_8, 0),
151 	/* r6 = map_lookup_elem(r8, r9); */
152 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
153 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_9),
154 	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
155 	BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
156 	/* r7 = map_lookup_elem(r8, r9); */
157 	BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
158 	BPF_MOV64_REG(BPF_REG_2, BPF_REG_9),
159 	BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
160 	BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
161 	/* if (r6 == 0) return 0; */
162 	BPF_JMP_IMM(BPF_JEQ, BPF_REG_6, 0, 2),
163 	/* if (r6 != r7) return 0; */
164 	BPF_JMP_REG(BPF_JNE, BPF_REG_6, BPF_REG_7, 1),
165 	/* read *r7; */
166 	BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, offsetof(struct bpf_xdp_sock, queue_id)),
167 	/* return 0; */
168 	BPF_MOV64_IMM(BPF_REG_0, 0),
169 	BPF_EXIT_INSN(),
170 	},
171 	.fixup_map_xskmap = { 3 },
172 	.prog_type = BPF_PROG_TYPE_XDP,
173 	.result = ACCEPT,
174 },
175