Skip to content

Commit

Permalink
avoid overflowing btf stringtable during btf line adjustment (iovisor…
Browse files Browse the repository at this point in the history
…#2270)

For remapped files (the main bpf program file and helpers.h),
the llvm compiler does not have the source so bcc did the
adjustment/patching after the compilation for lines in .btf.ext
line_info.

If a particular line in the main file or helpers.h is referenced
in the line_info table, the line itself will be added to
string table. If too many lines are added into the string table,
the string table may become too big (>= 64KB), and libbpf/kernel
will reject it.

In my instance with a Facebook internal bpf program, after all
referenced lines are added, the string table is 67KB.

This patch added checking during string table adjustment
to avoid overflow against the kernel limit.

Signed-off-by: Yonghong Song <[email protected]>
  • Loading branch information
yonghong-song committed Mar 14, 2019
1 parent 3b04ac6 commit 6cf6361
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 8 deletions.
25 changes: 19 additions & 6 deletions src/cc/bcc_btf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,17 @@

namespace ebpf {

uint32_t BTFStringTable::addString(std::string S) {
int32_t BTFStringTable::addString(std::string S) {
// Check whether the string already exists.
for (auto &OffsetM : OffsetToIdMap) {
if (Table[OffsetM.second] == S)
return OffsetM.first;
}

// Make sure we do not overflow the string table.
if (OrigTblLen + Size + S.size() + 1 >= BTF_MAX_NAME_OFFSET)
return -1;

// Not find, add to the string table.
uint32_t Offset = Size;
OffsetToIdMap[Offset] = Table.size();
Expand Down Expand Up @@ -108,18 +113,26 @@ void BTF::adjust(uint8_t *btf_sec, uintptr_t btf_sec_size,
// Go through all line info. For any line number whose line is in the LineCaches,
// Correct the line_off and record the corresponding source line in BTFStringTable,
// which later will be merged into .BTF string section.
BTFStringTable new_strings;
while (linfo_len) {
BTFStringTable new_strings(orig_strings_len);
bool overflow = false;
while (!overflow && linfo_len) {
unsigned num_recs = linfo_s[1];
linfo_s += 2;
for (unsigned i = 0; i < num_recs; i++) {
for (unsigned i = 0; !overflow && i < num_recs; i++) {
struct bpf_line_info *linfo = (struct bpf_line_info *)linfo_s;
if (linfo->line_off == 0) {
for (auto it = LineCaches.begin(); it != LineCaches.end(); ++it) {
if (strcmp(strings + linfo->file_name_off, it->first.c_str()) == 0) {
unsigned line_num = BPF_LINE_INFO_LINE_NUM(linfo->line_col);
if (line_num > 0 && line_num <= it->second.size())
linfo->line_off = orig_strings_len + new_strings.addString(it->second[line_num - 1]);
if (line_num > 0 && line_num <= it->second.size()) {
int offset = new_strings.addString(it->second[line_num - 1]);
if (offset < 0) {
overflow = true;
warning(".BTF string table overflowed, some lines missing\n");
break;
}
linfo->line_off = orig_strings_len + offset;
}
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/cc/bcc_btf.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ namespace ebpf {
class BTFStringTable {
private:
uint32_t Size;
uint32_t OrigTblLen;
std::map<uint32_t, uint32_t> OffsetToIdMap;
std::vector<std::string> Table;

public:
BTFStringTable(): Size(0) {}
BTFStringTable(uint32_t TblLen): Size(0), OrigTblLen(TblLen) {}
uint32_t getSize() { return Size; }
std::vector<std::string> &getTable() { return Table; }
uint32_t addString(std::string Str);
int32_t addString(std::string Str);
};

class BTF {
Expand Down

0 comments on commit 6cf6361

Please sign in to comment.