Skip to content

Commit 264b2cc

Browse files
bcc: Use bpf_probe_read_user in tools and provide backward compatibility
s390 has overlapping address space for user and kernel. Hence separation of bpf_probe_read_user and bpf_probe_read_kernel is essential. Commit 6ae08ae3dea2 ("bpf: Add probe_read_{user, kernel} and probe_read_{user, kernel}_str helpers") introduced these changes into the kernel. However, bcc tools does not respect it. As a workaround, perform the following: 1. Use bpf_probe_read_user() explicitly in the bcc tools. 2. When kernel version < 5.5, perform the checks if the bpf_probe_read_user kernel helper is present in the backported kernel as well. If not found, then fallback from bpf_probe_read_user to bpf_probe_read. Signed-off-by: Sumanth Korikkar <[email protected]>
1 parent d2e8ea4 commit 264b2cc

File tree

3 files changed

+52
-8
lines changed

3 files changed

+52
-8
lines changed

src/cc/export/helpers.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,7 @@ static long long (*bpf_tcp_gen_syncookie)(struct bpf_sock *sk, void *ip,
602602
static int (*bpf_skb_output)(void *ctx, void *map, __u64 flags, void *data,
603603
__u64 size) =
604604
(void *)BPF_FUNC_skb_output;
605+
605606
static int (*bpf_probe_read_user)(void *dst, __u32 size,
606607
const void *unsafe_ptr) =
607608
(void *)BPF_FUNC_probe_read_user;
@@ -887,8 +888,8 @@ int bpf_usdt_readarg_p(int argc, struct pt_regs *ctx, void *buf, u64 len) asm("l
887888
#if defined(__TARGET_ARCH_x86)
888889
#define bpf_target_x86
889890
#define bpf_target_defined
890-
#elif defined(__TARGET_ARCH_s930x)
891-
#define bpf_target_s930x
891+
#elif defined(__TARGET_ARCH_s390x)
892+
#define bpf_target_s390x
892893
#define bpf_target_defined
893894
#elif defined(__TARGET_ARCH_arm64)
894895
#define bpf_target_arm64
@@ -905,7 +906,7 @@ int bpf_usdt_readarg_p(int argc, struct pt_regs *ctx, void *buf, u64 len) asm("l
905906
#if defined(__x86_64__)
906907
#define bpf_target_x86
907908
#elif defined(__s390x__)
908-
#define bpf_target_s930x
909+
#define bpf_target_s390x
909910
#elif defined(__aarch64__)
910911
#define bpf_target_arm64
911912
#elif defined(__powerpc__)
@@ -923,7 +924,7 @@ int bpf_usdt_readarg_p(int argc, struct pt_regs *ctx, void *buf, u64 len) asm("l
923924
#define PT_REGS_RC(ctx) ((ctx)->gpr[3])
924925
#define PT_REGS_IP(ctx) ((ctx)->nip)
925926
#define PT_REGS_SP(ctx) ((ctx)->gpr[1])
926-
#elif defined(bpf_target_s930x)
927+
#elif defined(bpf_target_s390x)
927928
#define PT_REGS_PARM1(x) ((x)->gprs[2])
928929
#define PT_REGS_PARM2(x) ((x)->gprs[3])
929930
#define PT_REGS_PARM3(x) ((x)->gprs[4])

src/cc/frontends/clang/b_frontend_action.cc

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "bcc_libbpf_inc.h"
3838

3939
#include "libbpf.h"
40+
#include "bcc_syms.h"
4041

4142
namespace ebpf {
4243

@@ -82,6 +83,30 @@ const char **get_call_conv(void) {
8283
return ret;
8384
}
8485

86+
static std::string check_bpf_probe_read_user(llvm::StringRef probe) {
87+
if (probe.str() == "bpf_probe_read_user" ||
88+
probe.str() == "bpf_probe_read_user_str") {
89+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 5, 0)
90+
return probe.str();
91+
#else
92+
// Check for probe_user symbols in backported kernels before fallback
93+
void *resolver = bcc_symcache_new(-1, nullptr);
94+
uint64_t addr = 0;
95+
bool found = bcc_symcache_resolve_name(resolver, nullptr,
96+
"bpf_probe_read_user", &addr) >= 0 ? true: false;
97+
if (found)
98+
return probe.str();
99+
100+
if (probe.str() == "bpf_probe_read_user") {
101+
return "bpf_probe_read";
102+
} else {
103+
return "bpf_probe_read_str";
104+
}
105+
#endif
106+
}
107+
return "";
108+
}
109+
85110
using std::map;
86111
using std::move;
87112
using std::set;
@@ -947,6 +972,22 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) {
947972
} else if (Call->getCalleeDecl()) {
948973
NamedDecl *Decl = dyn_cast<NamedDecl>(Call->getCalleeDecl());
949974
if (!Decl) return true;
975+
976+
string text;
977+
978+
std::string probe = check_bpf_probe_read_user(Decl->getName());
979+
if (probe != "") {
980+
vector<string> probe_args;
981+
982+
for (auto arg : Call->arguments())
983+
probe_args.push_back(
984+
rewriter_.getRewrittenText(expansionRange(arg->getSourceRange())));
985+
986+
text = probe + "(" + probe_args[0] + ", " + probe_args[1] + ", " +
987+
probe_args[2] + ")";
988+
rewriter_.ReplaceText(expansionRange(Call->getSourceRange()), text);
989+
}
990+
950991
if (AsmLabelAttr *A = Decl->getAttr<AsmLabelAttr>()) {
951992
// Functions with the tag asm("llvm.bpf.extra") are implemented in the
952993
// rewriter rather than as a macro since they may also include nested
@@ -959,10 +1000,10 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) {
9591000
}
9601001

9611002
vector<string> args;
1003+
9621004
for (auto arg : Call->arguments())
9631005
args.push_back(rewriter_.getRewrittenText(expansionRange(arg->getSourceRange())));
9641006

965-
string text;
9661007
if (Decl->getName() == "incr_cksum_l3") {
9671008
text = "bpf_l3_csum_replace_(" + fn_args_[0]->getName().str() + ", (u64)";
9681009
text += args[0] + ", " + args[1] + ", " + args[2] + ", sizeof(" + args[2] + "))";
@@ -994,8 +1035,10 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) {
9941035
text = "({ u64 __addr = 0x0; ";
9951036
text += "_bpf_readarg_" + current_fn_ + "_" + args[0] + "(" +
9961037
args[1] + ", &__addr, sizeof(__addr));";
997-
text += "bpf_probe_read(" + args[2] + ", " + args[3] +
998-
", (void *)__addr);";
1038+
1039+
text += check_bpf_probe_read_user(StringRef("bpf_probe_read_user"));
1040+
1041+
text += "(" + args[2] + ", " + args[3] + ", (void *)__addr);";
9991042
text += "})";
10001043
rewriter_.ReplaceText(expansionRange(Call->getSourceRange()), text);
10011044
} else if (Decl->getName() == "bpf_usdt_readarg") {

tools/ttysnoop.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def usage():
8080
// bpf_probe_read() can only use a fixed size, so truncate to count
8181
// in user space:
8282
struct data_t data = {};
83-
bpf_probe_read(&data.buf, BUFSIZE, (void *)buf);
83+
bpf_probe_read_user(&data.buf, BUFSIZE, (void *)buf);
8484
if (count > BUFSIZE)
8585
data.count = BUFSIZE;
8686
else

0 commit comments

Comments
 (0)