• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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