blob: 8f139a3f5493e37077720012c694efd97f91bf4a [file] [log] [blame]
Joel Fernandesd76a2002018-10-16 13:19:58 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "LibBpfLoader"
18
19#include <errno.h>
20#include <linux/bpf.h>
21#include <linux/elf.h>
22#include <log/log.h>
23#include <stdint.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
Maciej Żenczykowski83f29772020-01-27 03:11:51 -080027#include <sys/stat.h>
Joel Fernandesd76a2002018-10-16 13:19:58 -070028#include <sys/utsname.h>
29#include <unistd.h>
30
Maciej Żenczykowski730a3862020-01-27 01:10:48 -080031#include "../progs/include/bpf_map_def.h"
Joel Fernandesd76a2002018-10-16 13:19:58 -070032#include "LoaderUtils.h"
33#include "include/libbpf_android.h"
34
35#include <cstdlib>
36#include <fstream>
37#include <iostream>
Connor O'Brien3278a162020-02-13 21:45:22 -080038#include <optional>
Joel Fernandesd76a2002018-10-16 13:19:58 -070039#include <string>
Christopher Ferrisc151c672019-02-01 15:31:26 -080040#include <vector>
Joel Fernandesd76a2002018-10-16 13:19:58 -070041
Steven Moreland4891e612020-01-10 15:35:52 -080042#include <android-base/properties.h>
Joel Fernandesd76a2002018-10-16 13:19:58 -070043#include <android-base/strings.h>
Connor O'Brien8d49fc72019-10-24 18:23:49 -070044#include <android-base/unique_fd.h>
Joel Fernandesd76a2002018-10-16 13:19:58 -070045
46#define BPF_FS_PATH "/sys/fs/bpf/"
47
48// Size of the BPF log buffer for verifier logging
49#define BPF_LOAD_LOG_SZ 0x1ffff
50
51using android::base::StartsWith;
Connor O'Brien8d49fc72019-10-24 18:23:49 -070052using android::base::unique_fd;
Joel Fernandesd76a2002018-10-16 13:19:58 -070053using std::ifstream;
54using std::ios;
Connor O'Brien3278a162020-02-13 21:45:22 -080055using std::optional;
Christopher Ferrisc151c672019-02-01 15:31:26 -080056using std::string;
Joel Fernandesd76a2002018-10-16 13:19:58 -070057using std::vector;
58
59namespace android {
60namespace bpf {
61
62typedef struct {
63 const char* name;
64 enum bpf_prog_type type;
65} sectionType;
66
67/*
68 * Map section name prefixes to program types, the section name will be:
69 * SEC(<prefix>/<name-of-program>)
70 * For example:
71 * SEC("tracepoint/sched_switch_func") where sched_switch_funcs
72 * is the name of the program, and tracepoint is the type.
73 */
74sectionType sectionNameTypes[] = {
Chenbo Feng5aee2f12018-12-26 16:14:05 -080075 {"kprobe", BPF_PROG_TYPE_KPROBE},
76 {"tracepoint", BPF_PROG_TYPE_TRACEPOINT},
77 {"skfilter", BPF_PROG_TYPE_SOCKET_FILTER},
78 {"cgroupskb", BPF_PROG_TYPE_CGROUP_SKB},
79 {"schedcls", BPF_PROG_TYPE_SCHED_CLS},
80 {"cgroupsock", BPF_PROG_TYPE_CGROUP_SOCK},
Joel Fernandesd76a2002018-10-16 13:19:58 -070081
82 /* End of table */
Chenbo Feng5aee2f12018-12-26 16:14:05 -080083 {"END", BPF_PROG_TYPE_UNSPEC},
Joel Fernandesd76a2002018-10-16 13:19:58 -070084};
85
86typedef struct {
87 enum bpf_prog_type type;
88 string name;
89 vector<char> data;
90 vector<char> rel_data;
Connor O'Brien3278a162020-02-13 21:45:22 -080091 optional<struct bpf_prog_def> prog_def;
Joel Fernandesd76a2002018-10-16 13:19:58 -070092
Connor O'Brien8d49fc72019-10-24 18:23:49 -070093 unique_fd prog_fd; /* fd after loading */
Joel Fernandesd76a2002018-10-16 13:19:58 -070094} codeSection;
95
Joel Fernandesd76a2002018-10-16 13:19:58 -070096static int readElfHeader(ifstream& elfFile, Elf64_Ehdr* eh) {
97 elfFile.seekg(0);
98 if (elfFile.fail()) return -1;
99
100 if (!elfFile.read((char*)eh, sizeof(*eh))) return -1;
101
102 return 0;
103}
104
105/* Reads all section header tables into an Shdr array */
106static int readSectionHeadersAll(ifstream& elfFile, vector<Elf64_Shdr>& shTable) {
107 Elf64_Ehdr eh;
108 int ret = 0;
109
110 ret = readElfHeader(elfFile, &eh);
111 if (ret) return ret;
112
113 elfFile.seekg(eh.e_shoff);
114 if (elfFile.fail()) return -1;
115
116 /* Read shdr table entries */
117 shTable.resize(eh.e_shnum);
118
119 if (!elfFile.read((char*)shTable.data(), (eh.e_shnum * eh.e_shentsize))) return -ENOMEM;
120
121 return 0;
122}
123
124/* Read a section by its index - for ex to get sec hdr strtab blob */
125static int readSectionByIdx(ifstream& elfFile, int id, vector<char>& sec) {
126 vector<Elf64_Shdr> shTable;
127 int entries, ret = 0;
128
129 ret = readSectionHeadersAll(elfFile, shTable);
130 if (ret) return ret;
131 entries = shTable.size();
132
133 elfFile.seekg(shTable[id].sh_offset);
134 if (elfFile.fail()) return -1;
135
136 sec.resize(shTable[id].sh_size);
137 if (!elfFile.read(sec.data(), shTable[id].sh_size)) return -1;
138
139 return 0;
140}
141
142/* Read whole section header string table */
143static int readSectionHeaderStrtab(ifstream& elfFile, vector<char>& strtab) {
144 Elf64_Ehdr eh;
145 int ret = 0;
146
147 ret = readElfHeader(elfFile, &eh);
148 if (ret) return ret;
149
150 ret = readSectionByIdx(elfFile, eh.e_shstrndx, strtab);
151 if (ret) return ret;
152
153 return 0;
154}
155
156/* Get name from offset in strtab */
157static int getSymName(ifstream& elfFile, int nameOff, string& name) {
158 int ret;
159 vector<char> secStrTab;
160
161 ret = readSectionHeaderStrtab(elfFile, secStrTab);
162 if (ret) return ret;
163
164 if (nameOff >= (int)secStrTab.size()) return -1;
165
166 name = string((char*)secStrTab.data() + nameOff);
167 return 0;
168}
169
170/* Reads a full section by name - example to get the GPL license */
171static int readSectionByName(const char* name, ifstream& elfFile, vector<char>& data) {
172 vector<char> secStrTab;
173 vector<Elf64_Shdr> shTable;
174 int ret;
175
176 ret = readSectionHeadersAll(elfFile, shTable);
177 if (ret) return ret;
178
179 ret = readSectionHeaderStrtab(elfFile, secStrTab);
180 if (ret) return ret;
181
182 for (int i = 0; i < (int)shTable.size(); i++) {
183 char* secname = secStrTab.data() + shTable[i].sh_name;
184 if (!secname) continue;
185
186 if (!strcmp(secname, name)) {
187 vector<char> dataTmp;
188 dataTmp.resize(shTable[i].sh_size);
189
190 elfFile.seekg(shTable[i].sh_offset);
191 if (elfFile.fail()) return -1;
192
193 if (!elfFile.read((char*)dataTmp.data(), shTable[i].sh_size)) return -1;
194
195 data = dataTmp;
196 return 0;
197 }
198 }
199 return -2;
200}
201
202static int readSectionByType(ifstream& elfFile, int type, vector<char>& data) {
203 int ret;
204 vector<Elf64_Shdr> shTable;
205
206 ret = readSectionHeadersAll(elfFile, shTable);
207 if (ret) return ret;
208
209 for (int i = 0; i < (int)shTable.size(); i++) {
210 if ((int)shTable[i].sh_type != type) continue;
211
212 vector<char> dataTmp;
213 dataTmp.resize(shTable[i].sh_size);
214
215 elfFile.seekg(shTable[i].sh_offset);
216 if (elfFile.fail()) return -1;
217
218 if (!elfFile.read((char*)dataTmp.data(), shTable[i].sh_size)) return -1;
219
220 data = dataTmp;
221 return 0;
222 }
223 return -2;
224}
225
226static bool symCompare(Elf64_Sym a, Elf64_Sym b) {
227 return (a.st_value < b.st_value);
228}
229
230static int readSymTab(ifstream& elfFile, int sort, vector<Elf64_Sym>& data) {
231 int ret, numElems;
232 Elf64_Sym* buf;
233 vector<char> secData;
234
235 ret = readSectionByType(elfFile, SHT_SYMTAB, secData);
236 if (ret) return ret;
237
238 buf = (Elf64_Sym*)secData.data();
239 numElems = (secData.size() / sizeof(Elf64_Sym));
240 data.assign(buf, buf + numElems);
241
242 if (sort) std::sort(data.begin(), data.end(), symCompare);
243 return 0;
244}
245
246static enum bpf_prog_type getSectionType(string& name) {
247 for (int i = 0; sectionNameTypes[i].type != BPF_PROG_TYPE_UNSPEC; i++)
248 if (StartsWith(name, sectionNameTypes[i].name)) return sectionNameTypes[i].type;
249
250 return BPF_PROG_TYPE_UNSPEC;
251}
252
253/* If ever needed
254static string getSectionName(enum bpf_prog_type type)
255{
256 for (int i = 0; sectionNameTypes[i].type != BPF_PROG_TYPE_UNSPEC; i++)
257 if (sectionNameTypes[i].type == type)
258 return std::string(sectionNameTypes[i].name);
259
260 return NULL;
261}
262*/
263
264static bool isRelSection(codeSection& cs, string& name) {
265 for (int i = 0; sectionNameTypes[i].type != BPF_PROG_TYPE_UNSPEC; i++) {
266 sectionType st = sectionNameTypes[i];
267
268 if (st.type != cs.type) continue;
269
270 if (StartsWith(name, std::string(".rel") + st.name + "/"))
271 return true;
272 else
273 return false;
274 }
275 return false;
276}
277
Connor O'Brien3278a162020-02-13 21:45:22 -0800278static int readProgDefs(ifstream& elfFile, vector<struct bpf_prog_def>& pd) {
279 vector<char> pdData;
280 int ret = readSectionByName("progs", elfFile, pdData);
281 if (ret == -2) return 0;
282 if (ret) return ret;
283
284 pd.resize(pdData.size() / sizeof(struct bpf_prog_def));
285 memcpy(pd.data(), pdData.data(), pdData.size());
286 return 0;
287}
288
289static int getSectionSymNames(ifstream& elfFile, const string& sectionName, vector<string>& names) {
290 int ret;
291 string name;
292 vector<Elf64_Sym> symtab;
293 vector<Elf64_Shdr> shTable;
294
295 ret = readSymTab(elfFile, 1 /* sort */, symtab);
296 if (ret) return ret;
297
298 /* Get index of section */
299 ret = readSectionHeadersAll(elfFile, shTable);
300 if (ret) return ret;
301
302 int sec_idx = -1;
303 for (int i = 0; i < (int)shTable.size(); i++) {
304 ret = getSymName(elfFile, shTable[i].sh_name, name);
305 if (ret) return ret;
306
307 if (!name.compare(sectionName)) {
308 sec_idx = i;
309 break;
310 }
311 }
312
313 /* No section found with matching name*/
314 if (sec_idx == -1) {
315 ALOGE("No %s section could be found in elf object\n", sectionName.c_str());
316 return -1;
317 }
318
319 for (int i = 0; i < (int)symtab.size(); i++) {
320 if (symtab[i].st_shndx == sec_idx) {
321 string s;
322 ret = getSymName(elfFile, symtab[i].st_name, s);
323 if (ret) return ret;
324 names.push_back(s);
325 }
326 }
327
328 return 0;
329}
330
Joel Fernandesd76a2002018-10-16 13:19:58 -0700331/* Read a section by its index - for ex to get sec hdr strtab blob */
332static int readCodeSections(ifstream& elfFile, vector<codeSection>& cs) {
333 vector<Elf64_Shdr> shTable;
334 int entries, ret = 0;
335
336 ret = readSectionHeadersAll(elfFile, shTable);
337 if (ret) return ret;
338 entries = shTable.size();
339
Connor O'Brien3278a162020-02-13 21:45:22 -0800340 vector<struct bpf_prog_def> pd;
341 ret = readProgDefs(elfFile, pd);
342 if (ret) return ret;
343 vector<string> progDefNames;
344 ret = getSectionSymNames(elfFile, "progs", progDefNames);
345 if (!pd.empty() && ret) return ret;
346
Joel Fernandesd76a2002018-10-16 13:19:58 -0700347 for (int i = 0; i < entries; i++) {
348 string name;
349 codeSection cs_temp;
350 cs_temp.type = BPF_PROG_TYPE_UNSPEC;
351
352 ret = getSymName(elfFile, shTable[i].sh_name, name);
353 if (ret) return ret;
354
355 enum bpf_prog_type ptype = getSectionType(name);
356 if (ptype != BPF_PROG_TYPE_UNSPEC) {
Connor O'Brien3278a162020-02-13 21:45:22 -0800357 string oldName = name;
Joel Fernandesd76a2002018-10-16 13:19:58 -0700358 deslash(name);
359 cs_temp.type = ptype;
360 cs_temp.name = name;
361
362 ret = readSectionByIdx(elfFile, i, cs_temp.data);
363 if (ret) return ret;
364 ALOGD("Loaded code section %d (%s)\n", i, name.c_str());
Connor O'Brien3278a162020-02-13 21:45:22 -0800365
366 vector<string> csSymNames;
367 ret = getSectionSymNames(elfFile, oldName, csSymNames);
368 if (ret || !csSymNames.size()) return ret;
369 for (size_t i = 0; i < progDefNames.size(); ++i) {
370 if (!progDefNames[i].compare(csSymNames[0] + "_def")) {
371 cs_temp.prog_def = pd[i];
372 break;
373 }
374 }
Joel Fernandesd76a2002018-10-16 13:19:58 -0700375 }
376
377 /* Check for rel section */
378 if (cs_temp.data.size() > 0 && i < entries) {
379 ret = getSymName(elfFile, shTable[i + 1].sh_name, name);
380 if (ret) return ret;
381
382 if (isRelSection(cs_temp, name)) {
383 ret = readSectionByIdx(elfFile, i + 1, cs_temp.rel_data);
384 if (ret) return ret;
385 ALOGD("Loaded relo section %d (%s)\n", i, name.c_str());
386 }
387 }
388
389 if (cs_temp.data.size() > 0) {
Connor O'Brien8d49fc72019-10-24 18:23:49 -0700390 cs.push_back(std::move(cs_temp));
Joel Fernandesd76a2002018-10-16 13:19:58 -0700391 ALOGD("Adding section %d to cs list\n", i);
392 }
393 }
394 return 0;
395}
396
397static int getSymNameByIdx(ifstream& elfFile, int index, string& name) {
398 vector<Elf64_Sym> symtab;
399 int ret = 0;
400
401 ret = readSymTab(elfFile, 0 /* !sort */, symtab);
402 if (ret) return ret;
403
404 if (index >= (int)symtab.size()) return -1;
405
406 return getSymName(elfFile, symtab[index].st_name, name);
407}
408
Connor O'Brien8d49fc72019-10-24 18:23:49 -0700409static int createMaps(const char* elfPath, ifstream& elfFile, vector<unique_fd>& mapFds) {
410 int ret;
Joel Fernandesd76a2002018-10-16 13:19:58 -0700411 vector<char> mdData;
412 vector<struct bpf_map_def> md;
413 vector<string> mapNames;
414 string fname = pathToFilename(string(elfPath), true);
415
416 ret = readSectionByName("maps", elfFile, mdData);
Steven Morelandc0905b42019-12-12 14:21:20 -0800417 if (ret == -2) return 0; // no maps to read
Joel Fernandesd76a2002018-10-16 13:19:58 -0700418 if (ret) return ret;
419 md.resize(mdData.size() / sizeof(struct bpf_map_def));
420 memcpy(md.data(), mdData.data(), mdData.size());
421
Connor O'Brien3278a162020-02-13 21:45:22 -0800422 ret = getSectionSymNames(elfFile, "maps", mapNames);
Joel Fernandesd76a2002018-10-16 13:19:58 -0700423 if (ret) return ret;
424
Joel Fernandesd76a2002018-10-16 13:19:58 -0700425 for (int i = 0; i < (int)mapNames.size(); i++) {
Connor O'Brien8d49fc72019-10-24 18:23:49 -0700426 unique_fd fd;
Joel Fernandesd76a2002018-10-16 13:19:58 -0700427 // Format of pin location is /sys/fs/bpf/map_<filename>_<mapname>
428 string mapPinLoc;
429 bool reuse = false;
430
431 mapPinLoc = string(BPF_FS_PATH) + "map_" + fname + "_" + string(mapNames[i]);
432 if (access(mapPinLoc.c_str(), F_OK) == 0) {
Connor O'Brien8d49fc72019-10-24 18:23:49 -0700433 fd.reset(bpf_obj_get(mapPinLoc.c_str()));
434 ALOGD("bpf_create_map reusing map %s, ret: %d\n", mapNames[i].c_str(), fd.get());
Joel Fernandesd76a2002018-10-16 13:19:58 -0700435 reuse = true;
436 } else {
Connor O'Brien8d49fc72019-10-24 18:23:49 -0700437 fd.reset(bpf_create_map(md[i].type, mapNames[i].c_str(), md[i].key_size, md[i].value_size,
438 md[i].max_entries, md[i].map_flags));
439 ALOGD("bpf_create_map name %s, ret: %d\n", mapNames[i].c_str(), fd.get());
Joel Fernandesd76a2002018-10-16 13:19:58 -0700440 }
441
442 if (fd < 0) return fd;
443 if (fd == 0) return -EINVAL;
444
445 if (!reuse) {
446 ret = bpf_obj_pin(fd, mapPinLoc.c_str());
Maciej Żenczykowski83f29772020-01-27 03:11:51 -0800447 if (ret) return -errno;
448 ret = chown(mapPinLoc.c_str(), (uid_t)md[i].uid, (gid_t)md[i].gid);
449 if (ret) return -errno;
450 ret = chmod(mapPinLoc.c_str(), md[i].mode);
451 if (ret) return -errno;
Joel Fernandesd76a2002018-10-16 13:19:58 -0700452 }
453
Connor O'Brien8d49fc72019-10-24 18:23:49 -0700454 mapFds.push_back(std::move(fd));
Joel Fernandesd76a2002018-10-16 13:19:58 -0700455 }
456
457 return ret;
458}
459
460/* For debugging, dump all instructions */
461static void dumpIns(char* ins, int size) {
462 for (int row = 0; row < size / 8; row++) {
463 ALOGE("%d: ", row);
464 for (int j = 0; j < 8; j++) {
465 ALOGE("%3x ", ins[(row * 8) + j]);
466 }
467 ALOGE("\n");
468 }
469}
470
471/* For debugging, dump all code sections from cs list */
472static void dumpAllCs(vector<codeSection>& cs) {
473 for (int i = 0; i < (int)cs.size(); i++) {
474 ALOGE("Dumping cs %d, name %s\n", int(i), cs[i].name.c_str());
475 dumpIns((char*)cs[i].data.data(), cs[i].data.size());
476 ALOGE("-----------\n");
477 }
478}
479
480static void applyRelo(void* insnsPtr, Elf64_Addr offset, int fd) {
481 int insnIndex;
482 struct bpf_insn *insn, *insns;
483
484 insns = (struct bpf_insn*)(insnsPtr);
485
486 insnIndex = offset / sizeof(struct bpf_insn);
487 insn = &insns[insnIndex];
488
489 ALOGD(
490 "applying relo to instruction at byte offset: %d, \
491 insn offset %d , insn %lx\n",
492 (int)offset, (int)insnIndex, *(unsigned long*)insn);
493
494 if (insn->code != (BPF_LD | BPF_IMM | BPF_DW)) {
495 ALOGE("Dumping all instructions till ins %d\n", insnIndex);
496 ALOGE("invalid relo for insn %d: code 0x%x\n", insnIndex, insn->code);
497 dumpIns((char*)insnsPtr, (insnIndex + 3) * 8);
498 return;
499 }
500
501 insn->imm = fd;
502 insn->src_reg = BPF_PSEUDO_MAP_FD;
503}
504
Connor O'Brien8d49fc72019-10-24 18:23:49 -0700505static void applyMapRelo(ifstream& elfFile, vector<unique_fd> &mapFds, vector<codeSection>& cs) {
Joel Fernandesd76a2002018-10-16 13:19:58 -0700506 vector<string> mapNames;
507
Connor O'Brien3278a162020-02-13 21:45:22 -0800508 int ret = getSectionSymNames(elfFile, "maps", mapNames);
Joel Fernandesd76a2002018-10-16 13:19:58 -0700509 if (ret) return;
510
511 for (int k = 0; k != (int)cs.size(); k++) {
512 Elf64_Rel* rel = (Elf64_Rel*)(cs[k].rel_data.data());
513 int n_rel = cs[k].rel_data.size() / sizeof(*rel);
514
515 for (int i = 0; i < n_rel; i++) {
516 int symIndex = ELF64_R_SYM(rel[i].r_info);
517 string symName;
518
519 ret = getSymNameByIdx(elfFile, symIndex, symName);
520 if (ret) return;
521
522 /* Find the map fd and apply relo */
523 for (int j = 0; j < (int)mapNames.size(); j++) {
524 if (!mapNames[j].compare(symName)) {
525 applyRelo(cs[k].data.data(), rel[i].r_offset, mapFds[j]);
526 break;
527 }
528 }
529 }
530 }
531}
532
Christopher Ferrisc151c672019-02-01 15:31:26 -0800533static int loadCodeSections(const char* elfPath, vector<codeSection>& cs, const string& license) {
Joel Fernandesd76a2002018-10-16 13:19:58 -0700534 int ret, fd, kvers;
535
536 if ((kvers = getMachineKvers()) < 0) return -1;
537
538 string fname = pathToFilename(string(elfPath), true);
539
540 for (int i = 0; i < (int)cs.size(); i++) {
541 string progPinLoc;
542 bool reuse = false;
543
544 // Format of pin location is
545 // /sys/fs/bpf/prog_<filename>_<mapname>
546 progPinLoc = string(BPF_FS_PATH) + "prog_" + fname + "_" + cs[i].name;
547 if (access(progPinLoc.c_str(), F_OK) == 0) {
548 fd = bpf_obj_get(progPinLoc.c_str());
549 ALOGD("New bpf prog load reusing prog %s, ret: %d\n", cs[i].name.c_str(), fd);
550 reuse = true;
551 } else {
552 vector<char> log_buf(BPF_LOAD_LOG_SZ, 0);
553
554 fd = bpf_prog_load(cs[i].type, cs[i].name.c_str(), (struct bpf_insn*)cs[i].data.data(),
555 cs[i].data.size(), license.c_str(), kvers, 0,
556 log_buf.data(), log_buf.size());
Steven Moreland804bca02019-12-12 17:21:23 -0800557 ALOGD("bpf_prog_load lib call for %s (%s) returned fd: %d (%s)\n", elfPath,
558 cs[i].name.c_str(), fd, (fd < 0 ? std::strerror(errno) : "no error"));
Joel Fernandesd76a2002018-10-16 13:19:58 -0700559
Maciej Żenczykowski524deef2020-02-11 11:12:37 -0800560 if (fd < 0) {
561 std::vector<std::string> lines = android::base::Split(log_buf.data(), "\n");
562
563 ALOGE("bpf_prog_load - BEGIN log_buf contents:");
564 for (const auto& line : lines) ALOGE("%s", line.c_str());
565 ALOGE("bpf_prog_load - END log_buf contents.");
566 }
Joel Fernandesd76a2002018-10-16 13:19:58 -0700567 }
568
569 if (fd < 0) return fd;
570 if (fd == 0) return -EINVAL;
571
572 if (!reuse) {
573 ret = bpf_obj_pin(fd, progPinLoc.c_str());
Connor O'Brien3278a162020-02-13 21:45:22 -0800574 if (ret) return -errno;
575 if (cs[i].prog_def.has_value()) {
576 if (chown(progPinLoc.c_str(), (uid_t)cs[i].prog_def->uid,
577 (gid_t)cs[i].prog_def->gid)) {
578 return -errno;
579 }
580 }
581 if (chmod(progPinLoc.c_str(), 0440)) return -errno;
Joel Fernandesd76a2002018-10-16 13:19:58 -0700582 }
583
Connor O'Brien8d49fc72019-10-24 18:23:49 -0700584 cs[i].prog_fd.reset(fd);
Joel Fernandesd76a2002018-10-16 13:19:58 -0700585 }
586
587 return 0;
588}
589
590int loadProg(const char* elfPath) {
591 vector<char> license;
592 vector<codeSection> cs;
Connor O'Brien8d49fc72019-10-24 18:23:49 -0700593 vector<unique_fd> mapFds;
Joel Fernandesd76a2002018-10-16 13:19:58 -0700594 int ret;
595
596 ifstream elfFile(elfPath, ios::in | ios::binary);
597 if (!elfFile.is_open()) return -1;
598
599 ret = readSectionByName("license", elfFile, license);
600 if (ret) {
601 ALOGE("Couldn't find license in %s\n", elfPath);
602 return ret;
603 } else {
604 ALOGD("Loading ELF object %s with license %s\n", elfPath, (char*)license.data());
605 }
606
607 ret = readCodeSections(elfFile, cs);
608 if (ret) {
609 ALOGE("Couldn't read all code sections in %s\n", elfPath);
610 return ret;
611 }
612
613 /* Just for future debugging */
614 if (0) dumpAllCs(cs);
615
616 ret = createMaps(elfPath, elfFile, mapFds);
617 if (ret) {
618 ALOGE("Failed to create maps: (ret=%d) in %s\n", ret, elfPath);
619 return ret;
620 }
621
622 for (int i = 0; i < (int)mapFds.size(); i++)
Connor O'Brien8d49fc72019-10-24 18:23:49 -0700623 ALOGD("map_fd found at %d is %d in %s\n", i, mapFds[i].get(), elfPath);
Joel Fernandesd76a2002018-10-16 13:19:58 -0700624
625 applyMapRelo(elfFile, mapFds, cs);
626
627 ret = loadCodeSections(elfPath, cs, string(license.data()));
628 if (ret) ALOGE("Failed to load programs, loadCodeSections ret=%d\n", ret);
629
630 return ret;
631}
632
Steven Moreland4891e612020-01-10 15:35:52 -0800633void waitForProgsLoaded() {
634 while (!android::base::WaitForProperty("bpf.progs_loaded", "1", std::chrono::seconds(5))) {
635 ALOGW("Waited 5s for bpf.progs_loaded, still waiting...");
636 }
637}
638
Joel Fernandesd76a2002018-10-16 13:19:58 -0700639} // namespace bpf
640} // namespace android