Revert "selftests/bpf: Add test for unstable CT lookup API"
[platform/kernel/linux-rpi.git] / tools / lib / bpf / gen_loader.c
1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2 /* Copyright (c) 2021 Facebook */
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <linux/filter.h>
8 #include "btf.h"
9 #include "bpf.h"
10 #include "libbpf.h"
11 #include "libbpf_internal.h"
12 #include "hashmap.h"
13 #include "bpf_gen_internal.h"
14 #include "skel_internal.h"
15
16 #define MAX_USED_MAPS 64
17 #define MAX_USED_PROGS 32
18
19 /* The following structure describes the stack layout of the loader program.
20  * In addition R6 contains the pointer to context.
21  * R7 contains the result of the last sys_bpf command (typically error or FD).
22  * R9 contains the result of the last sys_close command.
23  *
24  * Naming convention:
25  * ctx - bpf program context
26  * stack - bpf program stack
27  * blob - bpf_attr-s, strings, insns, map data.
28  *        All the bytes that loader prog will use for read/write.
29  */
30 struct loader_stack {
31         __u32 btf_fd;
32         __u32 map_fd[MAX_USED_MAPS];
33         __u32 prog_fd[MAX_USED_PROGS];
34         __u32 inner_map_fd;
35 };
36
37 #define stack_off(field) \
38         (__s16)(-sizeof(struct loader_stack) + offsetof(struct loader_stack, field))
39
40 #define attr_field(attr, field) (attr + offsetof(union bpf_attr, field))
41
42 static int realloc_insn_buf(struct bpf_gen *gen, __u32 size)
43 {
44         size_t off = gen->insn_cur - gen->insn_start;
45         void *insn_start;
46
47         if (gen->error)
48                 return gen->error;
49         if (size > INT32_MAX || off + size > INT32_MAX) {
50                 gen->error = -ERANGE;
51                 return -ERANGE;
52         }
53         insn_start = realloc(gen->insn_start, off + size);
54         if (!insn_start) {
55                 gen->error = -ENOMEM;
56                 free(gen->insn_start);
57                 gen->insn_start = NULL;
58                 return -ENOMEM;
59         }
60         gen->insn_start = insn_start;
61         gen->insn_cur = insn_start + off;
62         return 0;
63 }
64
65 static int realloc_data_buf(struct bpf_gen *gen, __u32 size)
66 {
67         size_t off = gen->data_cur - gen->data_start;
68         void *data_start;
69
70         if (gen->error)
71                 return gen->error;
72         if (size > INT32_MAX || off + size > INT32_MAX) {
73                 gen->error = -ERANGE;
74                 return -ERANGE;
75         }
76         data_start = realloc(gen->data_start, off + size);
77         if (!data_start) {
78                 gen->error = -ENOMEM;
79                 free(gen->data_start);
80                 gen->data_start = NULL;
81                 return -ENOMEM;
82         }
83         gen->data_start = data_start;
84         gen->data_cur = data_start + off;
85         return 0;
86 }
87
88 static void emit(struct bpf_gen *gen, struct bpf_insn insn)
89 {
90         if (realloc_insn_buf(gen, sizeof(insn)))
91                 return;
92         memcpy(gen->insn_cur, &insn, sizeof(insn));
93         gen->insn_cur += sizeof(insn);
94 }
95
96 static void emit2(struct bpf_gen *gen, struct bpf_insn insn1, struct bpf_insn insn2)
97 {
98         emit(gen, insn1);
99         emit(gen, insn2);
100 }
101
102 void bpf_gen__init(struct bpf_gen *gen, int log_level)
103 {
104         size_t stack_sz = sizeof(struct loader_stack);
105         int i;
106
107         gen->log_level = log_level;
108         /* save ctx pointer into R6 */
109         emit(gen, BPF_MOV64_REG(BPF_REG_6, BPF_REG_1));
110
111         /* bzero stack */
112         emit(gen, BPF_MOV64_REG(BPF_REG_1, BPF_REG_10));
113         emit(gen, BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -stack_sz));
114         emit(gen, BPF_MOV64_IMM(BPF_REG_2, stack_sz));
115         emit(gen, BPF_MOV64_IMM(BPF_REG_3, 0));
116         emit(gen, BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel));
117
118         /* jump over cleanup code */
119         emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0,
120                               /* size of cleanup code below */
121                               (stack_sz / 4) * 3 + 2));
122
123         /* remember the label where all error branches will jump to */
124         gen->cleanup_label = gen->insn_cur - gen->insn_start;
125         /* emit cleanup code: close all temp FDs */
126         for (i = 0; i < stack_sz; i += 4) {
127                 emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -stack_sz + i));
128                 emit(gen, BPF_JMP_IMM(BPF_JSLE, BPF_REG_1, 0, 1));
129                 emit(gen, BPF_EMIT_CALL(BPF_FUNC_sys_close));
130         }
131         /* R7 contains the error code from sys_bpf. Copy it into R0 and exit. */
132         emit(gen, BPF_MOV64_REG(BPF_REG_0, BPF_REG_7));
133         emit(gen, BPF_EXIT_INSN());
134 }
135
136 static int add_data(struct bpf_gen *gen, const void *data, __u32 size)
137 {
138         void *prev;
139
140         if (realloc_data_buf(gen, size))
141                 return 0;
142         prev = gen->data_cur;
143         memcpy(gen->data_cur, data, size);
144         gen->data_cur += size;
145         return prev - gen->data_start;
146 }
147
148 static int insn_bytes_to_bpf_size(__u32 sz)
149 {
150         switch (sz) {
151         case 8: return BPF_DW;
152         case 4: return BPF_W;
153         case 2: return BPF_H;
154         case 1: return BPF_B;
155         default: return -1;
156         }
157 }
158
159 /* *(u64 *)(blob + off) = (u64)(void *)(blob + data) */
160 static void emit_rel_store(struct bpf_gen *gen, int off, int data)
161 {
162         emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
163                                          0, 0, 0, data));
164         emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
165                                          0, 0, 0, off));
166         emit(gen, BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0));
167 }
168
169 /* *(u64 *)(blob + off) = (u64)(void *)(%sp + stack_off) */
170 static void emit_rel_store_sp(struct bpf_gen *gen, int off, int stack_off)
171 {
172         emit(gen, BPF_MOV64_REG(BPF_REG_0, BPF_REG_10));
173         emit(gen, BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, stack_off));
174         emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
175                                          0, 0, 0, off));
176         emit(gen, BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0));
177 }
178
179 static void move_ctx2blob(struct bpf_gen *gen, int off, int size, int ctx_off,
180                                    bool check_non_zero)
181 {
182         emit(gen, BPF_LDX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_0, BPF_REG_6, ctx_off));
183         if (check_non_zero)
184                 /* If value in ctx is zero don't update the blob.
185                  * For example: when ctx->map.max_entries == 0, keep default max_entries from bpf.c
186                  */
187                 emit(gen, BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3));
188         emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
189                                          0, 0, 0, off));
190         emit(gen, BPF_STX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_1, BPF_REG_0, 0));
191 }
192
193 static void move_stack2blob(struct bpf_gen *gen, int off, int size, int stack_off)
194 {
195         emit(gen, BPF_LDX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_0, BPF_REG_10, stack_off));
196         emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
197                                          0, 0, 0, off));
198         emit(gen, BPF_STX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_1, BPF_REG_0, 0));
199 }
200
201 static void move_stack2ctx(struct bpf_gen *gen, int ctx_off, int size, int stack_off)
202 {
203         emit(gen, BPF_LDX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_0, BPF_REG_10, stack_off));
204         emit(gen, BPF_STX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_6, BPF_REG_0, ctx_off));
205 }
206
207 static void emit_sys_bpf(struct bpf_gen *gen, int cmd, int attr, int attr_size)
208 {
209         emit(gen, BPF_MOV64_IMM(BPF_REG_1, cmd));
210         emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_2, BPF_PSEUDO_MAP_IDX_VALUE,
211                                          0, 0, 0, attr));
212         emit(gen, BPF_MOV64_IMM(BPF_REG_3, attr_size));
213         emit(gen, BPF_EMIT_CALL(BPF_FUNC_sys_bpf));
214         /* remember the result in R7 */
215         emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_0));
216 }
217
218 static bool is_simm16(__s64 value)
219 {
220         return value == (__s64)(__s16)value;
221 }
222
223 static void emit_check_err(struct bpf_gen *gen)
224 {
225         __s64 off = -(gen->insn_cur - gen->insn_start - gen->cleanup_label) / 8 - 1;
226
227         /* R7 contains result of last sys_bpf command.
228          * if (R7 < 0) goto cleanup;
229          */
230         if (is_simm16(off)) {
231                 emit(gen, BPF_JMP_IMM(BPF_JSLT, BPF_REG_7, 0, off));
232         } else {
233                 gen->error = -ERANGE;
234                 emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, -1));
235         }
236 }
237
238 /* reg1 and reg2 should not be R1 - R5. They can be R0, R6 - R10 */
239 static void emit_debug(struct bpf_gen *gen, int reg1, int reg2,
240                        const char *fmt, va_list args)
241 {
242         char buf[1024];
243         int addr, len, ret;
244
245         if (!gen->log_level)
246                 return;
247         ret = vsnprintf(buf, sizeof(buf), fmt, args);
248         if (ret < 1024 - 7 && reg1 >= 0 && reg2 < 0)
249                 /* The special case to accommodate common debug_ret():
250                  * to avoid specifying BPF_REG_7 and adding " r=%%d" to
251                  * prints explicitly.
252                  */
253                 strcat(buf, " r=%d");
254         len = strlen(buf) + 1;
255         addr = add_data(gen, buf, len);
256
257         emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
258                                          0, 0, 0, addr));
259         emit(gen, BPF_MOV64_IMM(BPF_REG_2, len));
260         if (reg1 >= 0)
261                 emit(gen, BPF_MOV64_REG(BPF_REG_3, reg1));
262         if (reg2 >= 0)
263                 emit(gen, BPF_MOV64_REG(BPF_REG_4, reg2));
264         emit(gen, BPF_EMIT_CALL(BPF_FUNC_trace_printk));
265 }
266
267 static void debug_regs(struct bpf_gen *gen, int reg1, int reg2, const char *fmt, ...)
268 {
269         va_list args;
270
271         va_start(args, fmt);
272         emit_debug(gen, reg1, reg2, fmt, args);
273         va_end(args);
274 }
275
276 static void debug_ret(struct bpf_gen *gen, const char *fmt, ...)
277 {
278         va_list args;
279
280         va_start(args, fmt);
281         emit_debug(gen, BPF_REG_7, -1, fmt, args);
282         va_end(args);
283 }
284
285 static void __emit_sys_close(struct bpf_gen *gen)
286 {
287         emit(gen, BPF_JMP_IMM(BPF_JSLE, BPF_REG_1, 0,
288                               /* 2 is the number of the following insns
289                                * * 6 is additional insns in debug_regs
290                                */
291                               2 + (gen->log_level ? 6 : 0)));
292         emit(gen, BPF_MOV64_REG(BPF_REG_9, BPF_REG_1));
293         emit(gen, BPF_EMIT_CALL(BPF_FUNC_sys_close));
294         debug_regs(gen, BPF_REG_9, BPF_REG_0, "close(%%d) = %%d");
295 }
296
297 static void emit_sys_close_stack(struct bpf_gen *gen, int stack_off)
298 {
299         emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, stack_off));
300         __emit_sys_close(gen);
301 }
302
303 static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off)
304 {
305         emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
306                                          0, 0, 0, blob_off));
307         emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0));
308         __emit_sys_close(gen);
309 }
310
311 int bpf_gen__finish(struct bpf_gen *gen)
312 {
313         int i;
314
315         emit_sys_close_stack(gen, stack_off(btf_fd));
316         for (i = 0; i < gen->nr_progs; i++)
317                 move_stack2ctx(gen,
318                                sizeof(struct bpf_loader_ctx) +
319                                sizeof(struct bpf_map_desc) * gen->nr_maps +
320                                sizeof(struct bpf_prog_desc) * i +
321                                offsetof(struct bpf_prog_desc, prog_fd), 4,
322                                stack_off(prog_fd[i]));
323         for (i = 0; i < gen->nr_maps; i++)
324                 move_stack2ctx(gen,
325                                sizeof(struct bpf_loader_ctx) +
326                                sizeof(struct bpf_map_desc) * i +
327                                offsetof(struct bpf_map_desc, map_fd), 4,
328                                stack_off(map_fd[i]));
329         emit(gen, BPF_MOV64_IMM(BPF_REG_0, 0));
330         emit(gen, BPF_EXIT_INSN());
331         pr_debug("gen: finish %d\n", gen->error);
332         if (!gen->error) {
333                 struct gen_loader_opts *opts = gen->opts;
334
335                 opts->insns = gen->insn_start;
336                 opts->insns_sz = gen->insn_cur - gen->insn_start;
337                 opts->data = gen->data_start;
338                 opts->data_sz = gen->data_cur - gen->data_start;
339         }
340         return gen->error;
341 }
342
343 void bpf_gen__free(struct bpf_gen *gen)
344 {
345         if (!gen)
346                 return;
347         free(gen->data_start);
348         free(gen->insn_start);
349         free(gen);
350 }
351
352 void bpf_gen__load_btf(struct bpf_gen *gen, const void *btf_raw_data,
353                        __u32 btf_raw_size)
354 {
355         int attr_size = offsetofend(union bpf_attr, btf_log_level);
356         int btf_data, btf_load_attr;
357         union bpf_attr attr;
358
359         memset(&attr, 0, attr_size);
360         pr_debug("gen: load_btf: size %d\n", btf_raw_size);
361         btf_data = add_data(gen, btf_raw_data, btf_raw_size);
362
363         attr.btf_size = btf_raw_size;
364         btf_load_attr = add_data(gen, &attr, attr_size);
365
366         /* populate union bpf_attr with user provided log details */
367         move_ctx2blob(gen, attr_field(btf_load_attr, btf_log_level), 4,
368                       offsetof(struct bpf_loader_ctx, log_level), false);
369         move_ctx2blob(gen, attr_field(btf_load_attr, btf_log_size), 4,
370                       offsetof(struct bpf_loader_ctx, log_size), false);
371         move_ctx2blob(gen, attr_field(btf_load_attr, btf_log_buf), 8,
372                       offsetof(struct bpf_loader_ctx, log_buf), false);
373         /* populate union bpf_attr with a pointer to the BTF data */
374         emit_rel_store(gen, attr_field(btf_load_attr, btf), btf_data);
375         /* emit BTF_LOAD command */
376         emit_sys_bpf(gen, BPF_BTF_LOAD, btf_load_attr, attr_size);
377         debug_ret(gen, "btf_load size %d", btf_raw_size);
378         emit_check_err(gen);
379         /* remember btf_fd in the stack, if successful */
380         emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7, stack_off(btf_fd)));
381 }
382
383 void bpf_gen__map_create(struct bpf_gen *gen,
384                          struct bpf_create_map_attr *map_attr, int map_idx)
385 {
386         int attr_size = offsetofend(union bpf_attr, btf_vmlinux_value_type_id);
387         bool close_inner_map_fd = false;
388         int map_create_attr;
389         union bpf_attr attr;
390
391         memset(&attr, 0, attr_size);
392         attr.map_type = map_attr->map_type;
393         attr.key_size = map_attr->key_size;
394         attr.value_size = map_attr->value_size;
395         attr.map_flags = map_attr->map_flags;
396         memcpy(attr.map_name, map_attr->name,
397                min((unsigned)strlen(map_attr->name), BPF_OBJ_NAME_LEN - 1));
398         attr.numa_node = map_attr->numa_node;
399         attr.map_ifindex = map_attr->map_ifindex;
400         attr.max_entries = map_attr->max_entries;
401         switch (attr.map_type) {
402         case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
403         case BPF_MAP_TYPE_CGROUP_ARRAY:
404         case BPF_MAP_TYPE_STACK_TRACE:
405         case BPF_MAP_TYPE_ARRAY_OF_MAPS:
406         case BPF_MAP_TYPE_HASH_OF_MAPS:
407         case BPF_MAP_TYPE_DEVMAP:
408         case BPF_MAP_TYPE_DEVMAP_HASH:
409         case BPF_MAP_TYPE_CPUMAP:
410         case BPF_MAP_TYPE_XSKMAP:
411         case BPF_MAP_TYPE_SOCKMAP:
412         case BPF_MAP_TYPE_SOCKHASH:
413         case BPF_MAP_TYPE_QUEUE:
414         case BPF_MAP_TYPE_STACK:
415         case BPF_MAP_TYPE_RINGBUF:
416                 break;
417         default:
418                 attr.btf_key_type_id = map_attr->btf_key_type_id;
419                 attr.btf_value_type_id = map_attr->btf_value_type_id;
420         }
421
422         pr_debug("gen: map_create: %s idx %d type %d value_type_id %d\n",
423                  attr.map_name, map_idx, map_attr->map_type, attr.btf_value_type_id);
424
425         map_create_attr = add_data(gen, &attr, attr_size);
426         if (attr.btf_value_type_id)
427                 /* populate union bpf_attr with btf_fd saved in the stack earlier */
428                 move_stack2blob(gen, attr_field(map_create_attr, btf_fd), 4,
429                                 stack_off(btf_fd));
430         switch (attr.map_type) {
431         case BPF_MAP_TYPE_ARRAY_OF_MAPS:
432         case BPF_MAP_TYPE_HASH_OF_MAPS:
433                 move_stack2blob(gen, attr_field(map_create_attr, inner_map_fd), 4,
434                                 stack_off(inner_map_fd));
435                 close_inner_map_fd = true;
436                 break;
437         default:
438                 break;
439         }
440         /* conditionally update max_entries */
441         if (map_idx >= 0)
442                 move_ctx2blob(gen, attr_field(map_create_attr, max_entries), 4,
443                               sizeof(struct bpf_loader_ctx) +
444                               sizeof(struct bpf_map_desc) * map_idx +
445                               offsetof(struct bpf_map_desc, max_entries),
446                               true /* check that max_entries != 0 */);
447         /* emit MAP_CREATE command */
448         emit_sys_bpf(gen, BPF_MAP_CREATE, map_create_attr, attr_size);
449         debug_ret(gen, "map_create %s idx %d type %d value_size %d value_btf_id %d",
450                   attr.map_name, map_idx, map_attr->map_type, attr.value_size,
451                   attr.btf_value_type_id);
452         emit_check_err(gen);
453         /* remember map_fd in the stack, if successful */
454         if (map_idx < 0) {
455                 /* This bpf_gen__map_create() function is called with map_idx >= 0
456                  * for all maps that libbpf loading logic tracks.
457                  * It's called with -1 to create an inner map.
458                  */
459                 emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7,
460                                       stack_off(inner_map_fd)));
461         } else if (map_idx != gen->nr_maps) {
462                 gen->error = -EDOM; /* internal bug */
463                 return;
464         } else {
465                 emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7,
466                                       stack_off(map_fd[map_idx])));
467                 gen->nr_maps++;
468         }
469         if (close_inner_map_fd)
470                 emit_sys_close_stack(gen, stack_off(inner_map_fd));
471 }
472
473 void bpf_gen__record_attach_target(struct bpf_gen *gen, const char *attach_name,
474                                    enum bpf_attach_type type)
475 {
476         const char *prefix;
477         int kind, ret;
478
479         btf_get_kernel_prefix_kind(type, &prefix, &kind);
480         gen->attach_kind = kind;
481         ret = snprintf(gen->attach_target, sizeof(gen->attach_target), "%s%s",
482                        prefix, attach_name);
483         if (ret >= sizeof(gen->attach_target))
484                 gen->error = -ENOSPC;
485 }
486
487 static void emit_find_attach_target(struct bpf_gen *gen)
488 {
489         int name, len = strlen(gen->attach_target) + 1;
490
491         pr_debug("gen: find_attach_tgt %s %d\n", gen->attach_target, gen->attach_kind);
492         name = add_data(gen, gen->attach_target, len);
493
494         emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
495                                          0, 0, 0, name));
496         emit(gen, BPF_MOV64_IMM(BPF_REG_2, len));
497         emit(gen, BPF_MOV64_IMM(BPF_REG_3, gen->attach_kind));
498         emit(gen, BPF_MOV64_IMM(BPF_REG_4, 0));
499         emit(gen, BPF_EMIT_CALL(BPF_FUNC_btf_find_by_name_kind));
500         emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_0));
501         debug_ret(gen, "find_by_name_kind(%s,%d)",
502                   gen->attach_target, gen->attach_kind);
503         emit_check_err(gen);
504         /* if successful, btf_id is in lower 32-bit of R7 and
505          * btf_obj_fd is in upper 32-bit
506          */
507 }
508
509 void bpf_gen__record_extern(struct bpf_gen *gen, const char *name, int kind,
510                             int insn_idx)
511 {
512         struct ksym_relo_desc *relo;
513
514         relo = libbpf_reallocarray(gen->relos, gen->relo_cnt + 1, sizeof(*relo));
515         if (!relo) {
516                 gen->error = -ENOMEM;
517                 return;
518         }
519         gen->relos = relo;
520         relo += gen->relo_cnt;
521         relo->name = name;
522         relo->kind = kind;
523         relo->insn_idx = insn_idx;
524         gen->relo_cnt++;
525 }
526
527 static void emit_relo(struct bpf_gen *gen, struct ksym_relo_desc *relo, int insns)
528 {
529         int name, insn, len = strlen(relo->name) + 1;
530
531         pr_debug("gen: emit_relo: %s at %d\n", relo->name, relo->insn_idx);
532         name = add_data(gen, relo->name, len);
533
534         emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
535                                          0, 0, 0, name));
536         emit(gen, BPF_MOV64_IMM(BPF_REG_2, len));
537         emit(gen, BPF_MOV64_IMM(BPF_REG_3, relo->kind));
538         emit(gen, BPF_MOV64_IMM(BPF_REG_4, 0));
539         emit(gen, BPF_EMIT_CALL(BPF_FUNC_btf_find_by_name_kind));
540         emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_0));
541         debug_ret(gen, "find_by_name_kind(%s,%d)", relo->name, relo->kind);
542         emit_check_err(gen);
543         /* store btf_id into insn[insn_idx].imm */
544         insn = insns + sizeof(struct bpf_insn) * relo->insn_idx +
545                 offsetof(struct bpf_insn, imm);
546         emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
547                                          0, 0, 0, insn));
548         emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_7, 0));
549         if (relo->kind == BTF_KIND_VAR) {
550                 /* store btf_obj_fd into insn[insn_idx + 1].imm */
551                 emit(gen, BPF_ALU64_IMM(BPF_RSH, BPF_REG_7, 32));
552                 emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_7,
553                                       sizeof(struct bpf_insn)));
554         }
555 }
556
557 static void emit_relos(struct bpf_gen *gen, int insns)
558 {
559         int i;
560
561         for (i = 0; i < gen->relo_cnt; i++)
562                 emit_relo(gen, gen->relos + i, insns);
563 }
564
565 static void cleanup_relos(struct bpf_gen *gen, int insns)
566 {
567         int i, insn;
568
569         for (i = 0; i < gen->relo_cnt; i++) {
570                 if (gen->relos[i].kind != BTF_KIND_VAR)
571                         continue;
572                 /* close fd recorded in insn[insn_idx + 1].imm */
573                 insn = insns +
574                         sizeof(struct bpf_insn) * (gen->relos[i].insn_idx + 1) +
575                         offsetof(struct bpf_insn, imm);
576                 emit_sys_close_blob(gen, insn);
577         }
578         if (gen->relo_cnt) {
579                 free(gen->relos);
580                 gen->relo_cnt = 0;
581                 gen->relos = NULL;
582         }
583 }
584
585 void bpf_gen__prog_load(struct bpf_gen *gen,
586                         struct bpf_prog_load_params *load_attr, int prog_idx)
587 {
588         int attr_size = offsetofend(union bpf_attr, fd_array);
589         int prog_load_attr, license, insns, func_info, line_info;
590         union bpf_attr attr;
591
592         memset(&attr, 0, attr_size);
593         pr_debug("gen: prog_load: type %d insns_cnt %zd\n",
594                  load_attr->prog_type, load_attr->insn_cnt);
595         /* add license string to blob of bytes */
596         license = add_data(gen, load_attr->license, strlen(load_attr->license) + 1);
597         /* add insns to blob of bytes */
598         insns = add_data(gen, load_attr->insns,
599                          load_attr->insn_cnt * sizeof(struct bpf_insn));
600
601         attr.prog_type = load_attr->prog_type;
602         attr.expected_attach_type = load_attr->expected_attach_type;
603         attr.attach_btf_id = load_attr->attach_btf_id;
604         attr.prog_ifindex = load_attr->prog_ifindex;
605         attr.kern_version = 0;
606         attr.insn_cnt = (__u32)load_attr->insn_cnt;
607         attr.prog_flags = load_attr->prog_flags;
608
609         attr.func_info_rec_size = load_attr->func_info_rec_size;
610         attr.func_info_cnt = load_attr->func_info_cnt;
611         func_info = add_data(gen, load_attr->func_info,
612                              attr.func_info_cnt * attr.func_info_rec_size);
613
614         attr.line_info_rec_size = load_attr->line_info_rec_size;
615         attr.line_info_cnt = load_attr->line_info_cnt;
616         line_info = add_data(gen, load_attr->line_info,
617                              attr.line_info_cnt * attr.line_info_rec_size);
618
619         memcpy(attr.prog_name, load_attr->name,
620                min((unsigned)strlen(load_attr->name), BPF_OBJ_NAME_LEN - 1));
621         prog_load_attr = add_data(gen, &attr, attr_size);
622
623         /* populate union bpf_attr with a pointer to license */
624         emit_rel_store(gen, attr_field(prog_load_attr, license), license);
625
626         /* populate union bpf_attr with a pointer to instructions */
627         emit_rel_store(gen, attr_field(prog_load_attr, insns), insns);
628
629         /* populate union bpf_attr with a pointer to func_info */
630         emit_rel_store(gen, attr_field(prog_load_attr, func_info), func_info);
631
632         /* populate union bpf_attr with a pointer to line_info */
633         emit_rel_store(gen, attr_field(prog_load_attr, line_info), line_info);
634
635         /* populate union bpf_attr fd_array with a pointer to stack where map_fds are saved */
636         emit_rel_store_sp(gen, attr_field(prog_load_attr, fd_array),
637                           stack_off(map_fd[0]));
638
639         /* populate union bpf_attr with user provided log details */
640         move_ctx2blob(gen, attr_field(prog_load_attr, log_level), 4,
641                       offsetof(struct bpf_loader_ctx, log_level), false);
642         move_ctx2blob(gen, attr_field(prog_load_attr, log_size), 4,
643                       offsetof(struct bpf_loader_ctx, log_size), false);
644         move_ctx2blob(gen, attr_field(prog_load_attr, log_buf), 8,
645                       offsetof(struct bpf_loader_ctx, log_buf), false);
646         /* populate union bpf_attr with btf_fd saved in the stack earlier */
647         move_stack2blob(gen, attr_field(prog_load_attr, prog_btf_fd), 4,
648                         stack_off(btf_fd));
649         if (gen->attach_kind) {
650                 emit_find_attach_target(gen);
651                 /* populate union bpf_attr with btf_id and btf_obj_fd found by helper */
652                 emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
653                                                  0, 0, 0, prog_load_attr));
654                 emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_7,
655                                       offsetof(union bpf_attr, attach_btf_id)));
656                 emit(gen, BPF_ALU64_IMM(BPF_RSH, BPF_REG_7, 32));
657                 emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_7,
658                                       offsetof(union bpf_attr, attach_btf_obj_fd)));
659         }
660         emit_relos(gen, insns);
661         /* emit PROG_LOAD command */
662         emit_sys_bpf(gen, BPF_PROG_LOAD, prog_load_attr, attr_size);
663         debug_ret(gen, "prog_load %s insn_cnt %d", attr.prog_name, attr.insn_cnt);
664         /* successful or not, close btf module FDs used in extern ksyms and attach_btf_obj_fd */
665         cleanup_relos(gen, insns);
666         if (gen->attach_kind) {
667                 emit_sys_close_blob(gen,
668                                     attr_field(prog_load_attr, attach_btf_obj_fd));
669                 gen->attach_kind = 0;
670         }
671         emit_check_err(gen);
672         /* remember prog_fd in the stack, if successful */
673         emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7,
674                               stack_off(prog_fd[gen->nr_progs])));
675         gen->nr_progs++;
676 }
677
678 void bpf_gen__map_update_elem(struct bpf_gen *gen, int map_idx, void *pvalue,
679                               __u32 value_size)
680 {
681         int attr_size = offsetofend(union bpf_attr, flags);
682         int map_update_attr, value, key;
683         union bpf_attr attr;
684         int zero = 0;
685
686         memset(&attr, 0, attr_size);
687         pr_debug("gen: map_update_elem: idx %d\n", map_idx);
688
689         value = add_data(gen, pvalue, value_size);
690         key = add_data(gen, &zero, sizeof(zero));
691
692         /* if (map_desc[map_idx].initial_value)
693          *    copy_from_user(value, initial_value, value_size);
694          */
695         emit(gen, BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6,
696                               sizeof(struct bpf_loader_ctx) +
697                               sizeof(struct bpf_map_desc) * map_idx +
698                               offsetof(struct bpf_map_desc, initial_value)));
699         emit(gen, BPF_JMP_IMM(BPF_JEQ, BPF_REG_3, 0, 4));
700         emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
701                                          0, 0, 0, value));
702         emit(gen, BPF_MOV64_IMM(BPF_REG_2, value_size));
703         emit(gen, BPF_EMIT_CALL(BPF_FUNC_copy_from_user));
704
705         map_update_attr = add_data(gen, &attr, attr_size);
706         move_stack2blob(gen, attr_field(map_update_attr, map_fd), 4,
707                         stack_off(map_fd[map_idx]));
708         emit_rel_store(gen, attr_field(map_update_attr, key), key);
709         emit_rel_store(gen, attr_field(map_update_attr, value), value);
710         /* emit MAP_UPDATE_ELEM command */
711         emit_sys_bpf(gen, BPF_MAP_UPDATE_ELEM, map_update_attr, attr_size);
712         debug_ret(gen, "update_elem idx %d value_size %d", map_idx, value_size);
713         emit_check_err(gen);
714 }
715
716 void bpf_gen__map_freeze(struct bpf_gen *gen, int map_idx)
717 {
718         int attr_size = offsetofend(union bpf_attr, map_fd);
719         int map_freeze_attr;
720         union bpf_attr attr;
721
722         memset(&attr, 0, attr_size);
723         pr_debug("gen: map_freeze: idx %d\n", map_idx);
724         map_freeze_attr = add_data(gen, &attr, attr_size);
725         move_stack2blob(gen, attr_field(map_freeze_attr, map_fd), 4,
726                         stack_off(map_fd[map_idx]));
727         /* emit MAP_FREEZE command */
728         emit_sys_bpf(gen, BPF_MAP_FREEZE, map_freeze_attr, attr_size);
729         debug_ret(gen, "map_freeze");
730         emit_check_err(gen);
731 }