1 // SPDX-License-Identifier: GPL-2.0
2 #include <stdio.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <fcntl.h>
6 #include <libelf.h>
7 #include <gelf.h>
8 #include <errno.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <stdbool.h>
12 #include <limits.h>
13 #include <stdlib.h>
14 #include <linux/bpf.h>
15 #include <bpf/bpf.h>
16 #include <assert.h>
17 #include <argp.h>
18 #include "keymap.h"
19 #include "bpf_load.h"
20
21 #ifdef ENABLE_NLS
22 # define _(string) gettext(string)
23 # include "gettext.h"
24 # include <locale.h>
25 # include <langinfo.h>
26 # include <iconv.h>
27 #else
28 # define _(string) string
29 #endif
30
31 #define LOG_BUF_SIZE (256 * 1024)
32
33 // This should match the struct in the raw BPF decoder
34 struct raw_pattern {
35 unsigned int scancode;
36 unsigned short raw[0];
37 };
38
39 // For the raw decoder, these values are calculated based on the raw
40 // patterns and need to be patched into the BPF
41 int max_length;
42 int trail_space;
43
44 char bpf_log_buf[LOG_BUF_SIZE];
45 extern int debug;
46
47 struct bpf_file {
48 Elf *elf;
49 char license[128];
50 bool processed_sec[128];
51 int map_fd[MAX_MAPS];
52 struct bpf_map_data map_data[MAX_MAPS];
53 int nr_maps;
54 int maps_shidx;
55 int dataidx;
56 int bssidx;
57 Elf_Data *data;
58 int strtabidx;
59 Elf_Data *symbols;
60 struct protocol_param *param;
61 char name[128];
62 };
63
load_and_attach(int lirc_fd,struct bpf_file * bpf_file,struct bpf_insn * prog,int size)64 static int load_and_attach(int lirc_fd, struct bpf_file *bpf_file, struct bpf_insn *prog, int size)
65 {
66 LIBBPF_OPTS(bpf_prog_load_opts, opts);
67 int fd, err, insn_cnt;
68
69 insn_cnt = size / sizeof(struct bpf_insn);
70
71 opts.expected_attach_type = BPF_LIRC_MODE2;
72 opts.log_buf = bpf_log_buf;
73 opts.log_size = LOG_BUF_SIZE;
74
75 fd = bpf_prog_load(BPF_PROG_TYPE_LIRC_MODE2, bpf_file->name,
76 bpf_file->license, prog, insn_cnt, &opts);
77 if (fd < 0) {
78 printf("bpf_load_program() err=%m\n%s", bpf_log_buf);
79 return -1;
80 }
81
82 err = bpf_prog_attach(fd, lirc_fd, BPF_LIRC_MODE2, 0);
83 if (err) {
84 printf("bpf_prog_attach: err=%m\n");
85 return -1;
86 }
87
88 return 0;
89 }
90
build_raw_map(struct bpf_map_data * map,struct raw_entry * raw,int numa_node)91 static int build_raw_map(struct bpf_map_data *map, struct raw_entry *raw, int numa_node)
92 {
93 int no_patterns, value_size, fd, key, i;
94 struct raw_entry *e;
95 struct raw_pattern *p;
96 LIBBPF_OPTS(bpf_map_create_opts, opts,
97 .map_flags = map->def.map_flags,
98 );
99
100 no_patterns = 0;
101
102 for (e = raw; e; e = e->next) {
103 if (e->raw_length > max_length)
104 max_length = e->raw_length;
105 no_patterns++;
106 }
107
108 // pattern needs a trailing 0 to mark the end of
109 // the pattern
110 max_length++;
111
112 value_size = sizeof(struct raw_pattern) + max_length * sizeof(short);
113
114 opts.numa_node = numa_node;
115 fd = bpf_map_create(map->def.type,
116 map->name,
117 map->def.key_size,
118 value_size,
119 no_patterns,
120 &opts);
121 if (fd < 0) {
122 printf(_("failed to create a map: %d %s\n"),
123 errno, strerror(errno));
124 return -1;
125 }
126
127 p = malloc(value_size);
128 if (!p) {
129 printf(_("Failed to allocate memory"));
130 return -1;
131 }
132
133 key = 0;
134
135 for (e = raw; e; e = e->next) {
136 p->scancode = e->scancode;
137 for (i = 0; i < e->raw_length; i++) {
138 p->raw[i] = e->raw[i];
139 if (i % 2 && e->raw[i] > trail_space)
140 trail_space = e->raw[i];
141 }
142
143 // Add trailing space and clear rest of the struct
144 while (i < max_length)
145 p->raw[i++] = 0;
146
147 if (bpf_map_update_elem(fd, &key, p, BPF_ANY)) {
148 printf(_("failed to update raw map: %d %s\n"),
149 errno, strerror(errno));
150 free(p);
151 return -1;
152 }
153
154 key++;
155 }
156 free(p);
157
158 // 1ms extra for trailing space. This also ensure that the
159 // trail_space is larger than largest space + margin in the
160 // decoder
161 trail_space += 1000;
162
163 return fd;
164 }
165
load_maps(struct bpf_file * bpf_file,struct raw_entry * raw)166 static int load_maps(struct bpf_file *bpf_file, struct raw_entry *raw)
167 {
168 struct bpf_map_data *maps = bpf_file->map_data;
169 int i, numa_node;
170
171 for (i = 0; i < bpf_file->nr_maps; i++) {
172 numa_node = maps[i].def.map_flags & BPF_F_NUMA_NODE ?
173 maps[i].def.numa_node : -1;
174
175 if (maps[i].def.type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
176 maps[i].def.type == BPF_MAP_TYPE_HASH_OF_MAPS) {
177 LIBBPF_OPTS(bpf_map_create_opts, opts,
178 .inner_map_fd = bpf_file->map_fd[maps[i].def.inner_map_idx],
179 .map_flags = maps[i].def.map_flags,
180 .numa_node = numa_node,
181 );
182
183 bpf_file->map_fd[i] = bpf_map_create(
184 maps[i].def.type,
185 maps[i].name,
186 maps[i].def.key_size,
187 4,
188 maps[i].def.max_entries,
189 &opts);
190 } else if (!strcmp(maps[i].name, "raw_map")) {
191 bpf_file->map_fd[i] = build_raw_map(&maps[i], raw, numa_node);
192 } else {
193 LIBBPF_OPTS(bpf_map_create_opts, opts,
194 .map_flags = maps[i].def.map_flags,
195 .numa_node = numa_node,
196 );
197
198 bpf_file->map_fd[i] = bpf_map_create(
199 maps[i].def.type,
200 maps[i].name,
201 maps[i].def.key_size,
202 maps[i].def.value_size,
203 maps[i].def.max_entries,
204 &opts);
205 }
206
207 if (bpf_file->map_fd[i] < 0) {
208 printf(_("failed to create a map: %d %s\n"),
209 errno, strerror(errno));
210 return 1;
211 }
212 maps[i].fd = bpf_file->map_fd[i];
213 }
214 return 0;
215 }
216
get_sec(Elf * elf,int i,GElf_Ehdr * ehdr,char ** shname,GElf_Shdr * shdr,Elf_Data ** data)217 static int get_sec(Elf *elf, int i, GElf_Ehdr *ehdr, char **shname,
218 GElf_Shdr *shdr, Elf_Data **data)
219 {
220 Elf_Scn *scn;
221
222 scn = elf_getscn(elf, i);
223 if (!scn)
224 return 1;
225
226 if (gelf_getshdr(scn, shdr) != shdr)
227 return 2;
228
229 *shname = elf_strptr(elf, ehdr->e_shstrndx, shdr->sh_name);
230 if (!*shname || !shdr->sh_size)
231 return 3;
232
233 *data = elf_getdata(scn, 0);
234 if (!*data || elf_getdata(scn, *data) != NULL)
235 return 4;
236
237 return 0;
238 }
239
parse_relo_and_apply(struct bpf_file * bpf_file,GElf_Shdr * shdr,struct bpf_insn * insn,Elf_Data * data)240 static int parse_relo_and_apply(struct bpf_file *bpf_file, GElf_Shdr *shdr,
241 struct bpf_insn *insn, Elf_Data *data)
242 {
243 int i, nrels;
244
245 nrels = shdr->sh_size / shdr->sh_entsize;
246
247 for (i = 0; i < nrels; i++) {
248 GElf_Sym sym;
249 GElf_Rel rel;
250 unsigned int insn_idx;
251 const char *sym_name;
252 bool match = false;
253 int map_idx;
254
255 gelf_getrel(data, i, &rel);
256
257 insn_idx = rel.r_offset / sizeof(struct bpf_insn);
258
259 gelf_getsym(bpf_file->symbols, GELF_R_SYM(rel.r_info), &sym);
260
261 sym_name = elf_strptr(bpf_file->elf, bpf_file->strtabidx, sym.st_name);
262
263 if (insn[insn_idx].code != (BPF_LD | BPF_IMM | BPF_DW)) {
264 printf(_("invalid relo for insn[%d].code 0x%x\n"),
265 insn_idx, insn[insn_idx].code);
266 return 1;
267 }
268
269 if (sym.st_shndx == bpf_file->maps_shidx) {
270 /* Match FD relocation against recorded map_data[] offset */
271 for (map_idx = 0; map_idx < bpf_file->nr_maps; map_idx++) {
272 if (bpf_file->map_data[map_idx].elf_offset == sym.st_value) {
273 match = true;
274 break;
275 }
276 }
277
278 if (match) {
279 insn[insn_idx].src_reg = BPF_PSEUDO_MAP_FD;
280 insn[insn_idx].imm = bpf_file->map_data[map_idx].fd;
281 continue;
282 }
283
284 printf(_("invalid relo for insn[%d] no map_data match\n"),
285 insn_idx);
286 return 1;
287 }
288 if (sym.st_shndx == bpf_file->dataidx || sym.st_shndx == bpf_file->bssidx) {
289 const char *raw = NULL;
290 int value = 0;
291
292 if (!bpf_param(bpf_file->param, sym_name, &value)) {
293 if (value < INT_MIN && value > UINT_MAX) {
294 printf(_("variable %s out of range: %s\n"), sym_name, raw);
295 return 1;
296 }
297 } else if (sym.st_shndx == bpf_file->dataidx) {
298 // Value is not overridden on command line
299 // or toml file. For the raw decoder, the
300 // max_length and trail_space needs to be
301 // patched in. Otherwise use value set in
302 // bpf object file from data section.
303 if (!strcmp(sym_name, "max_length") && max_length)
304 value = max_length;
305 else if (!strcmp(sym_name, "trail_space") && trail_space)
306 value = trail_space;
307 else
308 value = *(int*)((unsigned char*)bpf_file->data->d_buf + sym.st_value);
309 }
310
311 if (debug)
312 printf(_("patching insn[%d] with immediate %d for symbol %s\n"), insn_idx, value, sym_name);
313
314 // patch ld to mov immediate
315 insn[insn_idx].imm = value;
316 } else {
317 printf(_("symbol %s has unknown section %d\n"), sym_name, sym.st_shndx);
318 return 1;
319 }
320 }
321
322 return 0;
323 }
324
cmp_symbols(const void * l,const void * r)325 static int cmp_symbols(const void *l, const void *r)
326 {
327 const GElf_Sym *lsym = (const GElf_Sym *)l;
328 const GElf_Sym *rsym = (const GElf_Sym *)r;
329
330 if (lsym->st_value < rsym->st_value)
331 return -1;
332 if (lsym->st_value > rsym->st_value)
333 return 1;
334
335 return 0;
336 }
337
load_elf_maps_section(struct bpf_file * bpf_file)338 static int load_elf_maps_section(struct bpf_file *bpf_file)
339 {
340 int map_sz_elf, map_sz_copy;
341 bool validate_zero = false;
342 Elf_Data *data_maps;
343 int i, nr_maps;
344 GElf_Sym *sym;
345 Elf_Scn *scn;
346
347 if (bpf_file->maps_shidx < 0)
348 return -EINVAL;
349 if (!bpf_file->symbols)
350 return -EINVAL;
351
352 /* Get data for maps section via elf index */
353 scn = elf_getscn(bpf_file->elf, bpf_file->maps_shidx);
354 if (scn)
355 data_maps = elf_getdata(scn, NULL);
356 if (!scn || !data_maps) {
357 printf(_("Failed to get Elf_Data from maps section %d\n"),
358 bpf_file->maps_shidx);
359 return -EINVAL;
360 }
361
362 /* For each map get corrosponding symbol table entry */
363 sym = calloc(MAX_MAPS+1, sizeof(GElf_Sym));
364 for (i = 0, nr_maps = 0; i < bpf_file->symbols->d_size / sizeof(GElf_Sym); i++) {
365 assert(nr_maps < MAX_MAPS+1);
366 if (!gelf_getsym(bpf_file->symbols, i, &sym[nr_maps]))
367 continue;
368 if (sym[nr_maps].st_shndx != bpf_file->maps_shidx)
369 continue;
370 /* Only increment iif maps section */
371 nr_maps++;
372 }
373
374 /* Align to map_fd[] order, via sort on offset in sym.st_value */
375 qsort(sym, nr_maps, sizeof(GElf_Sym), cmp_symbols);
376
377 /* Keeping compatible with ELF maps section changes
378 * ------------------------------------------------
379 * The program size of struct bpf_load_map_def is known by loader
380 * code, but struct stored in ELF file can be different.
381 *
382 * Unfortunately sym[i].st_size is zero. To calculate the
383 * struct size stored in the ELF file, assume all struct have
384 * the same size, and simply divide with number of map
385 * symbols.
386 */
387 map_sz_elf = data_maps->d_size / nr_maps;
388 map_sz_copy = sizeof(struct bpf_load_map_def);
389 if (map_sz_elf < map_sz_copy) {
390 /*
391 * Backward compat, loading older ELF file with
392 * smaller struct, keeping remaining bytes zero.
393 */
394 map_sz_copy = map_sz_elf;
395 } else if (map_sz_elf > map_sz_copy) {
396 /*
397 * Forward compat, loading newer ELF file with larger
398 * struct with unknown features. Assume zero means
399 * feature not used. Thus, validate rest of struct
400 * data is zero.
401 */
402 validate_zero = true;
403 }
404
405 /* Memcpy relevant part of ELF maps data to loader maps */
406 for (i = 0; i < nr_maps; i++) {
407 unsigned char *addr, *end, *def;
408 const char *map_name;
409 struct bpf_map_data *maps = bpf_file->map_data;
410 size_t offset;
411
412 map_name = elf_strptr(bpf_file->elf, bpf_file->strtabidx, sym[i].st_name);
413 maps[i].name = strdup(map_name);
414 if (!maps[i].name) {
415 printf(_("strdup(%s): %s(%d)\n"), map_name,
416 strerror(errno), errno);
417 free(sym);
418 return -errno;
419 }
420
421 /* Symbol value is offset into ELF maps section data area */
422 offset = sym[i].st_value;
423 def = (unsigned char*)data_maps->d_buf + offset;
424 maps[i].elf_offset = offset;
425 memset(&maps[i].def, 0, sizeof(struct bpf_load_map_def));
426 memcpy(&maps[i].def, def, map_sz_copy);
427
428 /* Verify no newer features were requested */
429 if (validate_zero) {
430 addr = def + map_sz_copy;
431 end = def + map_sz_elf;
432 for (; addr < end; addr++) {
433 if (*addr != 0) {
434 free(sym);
435 return -EFBIG;
436 }
437 }
438 }
439 }
440
441 free(sym);
442 return nr_maps;
443 }
444
load_bpf_file(const char * path,int lirc_fd,struct protocol_param * param,struct raw_entry * raw)445 int load_bpf_file(const char *path, int lirc_fd, struct protocol_param *param,
446 struct raw_entry *raw)
447 {
448 struct bpf_file bpf_file = { .param = param };
449 int fd, i, ret;
450 Elf *elf;
451 GElf_Ehdr ehdr;
452 GElf_Shdr shdr, shdr_prog;
453 Elf_Data *data, *data_prog, *data_map = NULL;
454 char *shname, *shname_prog;
455 int nr_maps = 0;
456
457 if (elf_version(EV_CURRENT) == EV_NONE)
458 return 1;
459
460 fd = open(path, O_RDONLY, 0);
461 if (fd < 0)
462 return 1;
463
464 elf = elf_begin(fd, ELF_C_READ, NULL);
465
466 if (!elf)
467 return 1;
468
469 if (gelf_getehdr(elf, &ehdr) != &ehdr)
470 return 1;
471
472 bpf_file.elf = elf;
473
474 /* scan over all elf sections to get license and map info */
475 for (i = 1; i < ehdr.e_shnum; i++) {
476
477 if (get_sec(elf, i, &ehdr, &shname, &shdr, &data))
478 continue;
479
480 if (debug)
481 printf(_("section %d:%s data %p size %zd link %d flags %d\n"),
482 i, shname, data->d_buf, data->d_size,
483 shdr.sh_link, (int) shdr.sh_flags);
484
485 if (strcmp(shname, "license") == 0) {
486 bpf_file.processed_sec[i] = true;
487 memcpy(bpf_file.license, data->d_buf, data->d_size);
488 } else if (strcmp(shname, "lirc_mode2/maps") == 0 ||
489 strcmp(shname, "maps") == 0) {
490 int j;
491
492 bpf_file.maps_shidx = i;
493 data_map = data;
494 for (j = 0; j < MAX_MAPS; j++)
495 bpf_file.map_data[j].fd = -1;
496 } else if (strcmp(shname, ".data") == 0) {
497 bpf_file.dataidx = i;
498 bpf_file.data = data;
499 } else if (strcmp(shname, ".bss") == 0) {
500 bpf_file.bssidx = i;
501 } else if (shdr.sh_type == SHT_SYMTAB) {
502 bpf_file.strtabidx = shdr.sh_link;
503 bpf_file.symbols = data;
504 }
505 }
506
507 ret = 1;
508
509 if (!bpf_file.symbols) {
510 printf(_("missing SHT_SYMTAB section\n"));
511 goto done;
512 }
513
514 max_length = 0;
515 trail_space = 0;
516
517 if (data_map) {
518 bpf_file.nr_maps = load_elf_maps_section(&bpf_file);
519 if (bpf_file.nr_maps < 0) {
520 printf(_("Error: Failed loading ELF maps (errno:%d):%s\n"),
521 nr_maps, strerror(-nr_maps));
522 goto done;
523 }
524 if (load_maps(&bpf_file, raw))
525 goto done;
526
527 bpf_file.processed_sec[bpf_file.maps_shidx] = true;
528 }
529
530 /* process all relo sections, and rewrite bpf insns for maps */
531 for (i = 1; i < ehdr.e_shnum; i++) {
532 if (bpf_file.processed_sec[i])
533 continue;
534
535 if (get_sec(elf, i, &ehdr, &shname, &shdr, &data))
536 continue;
537
538 if (shdr.sh_type == SHT_REL) {
539 struct bpf_insn *insns;
540
541 /* locate prog sec that need map fixup (relocations) */
542 if (get_sec(elf, shdr.sh_info, &ehdr, &shname_prog,
543 &shdr_prog, &data_prog))
544 continue;
545
546 if (shdr_prog.sh_type != SHT_PROGBITS ||
547 !(shdr_prog.sh_flags & SHF_EXECINSTR))
548 continue;
549
550 if (strncmp(shname_prog, "lirc_mode2/", 11))
551 strncpy(bpf_file.name, shname_prog, sizeof(bpf_file.name) - 1);
552 else
553 strncpy(bpf_file.name, shname_prog + 11, sizeof(bpf_file.name) - 1);
554
555 insns = (struct bpf_insn *) data_prog->d_buf;
556 bpf_file.processed_sec[i] = true; /* relo section */
557
558 if (parse_relo_and_apply(&bpf_file, &shdr, insns, data))
559 continue;
560 }
561 }
562
563 /* load programs */
564 for (i = 1; i < ehdr.e_shnum; i++) {
565 if (bpf_file.processed_sec[i])
566 continue;
567
568 if (get_sec(elf, i, &ehdr, &shname, &shdr, &data))
569 continue;
570
571 if (shdr.sh_type != SHT_PROGBITS ||
572 !(shdr.sh_flags & SHF_EXECINSTR))
573 continue;
574
575 ret = load_and_attach(lirc_fd, &bpf_file, data->d_buf, data->d_size);
576 break;
577 }
578
579 done:
580 close(fd);
581 return ret;
582 }
583