Hello community,

here is the log from the commit of package bcc for openSUSE:Factory checked in 
at 2018-06-20 15:34:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/bcc (Old)
 and      /work/SRC/openSUSE:Factory/.bcc.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "bcc"

Wed Jun 20 15:34:38 2018 rev:23 rq:617884 version:0.6.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/bcc/bcc.changes  2018-04-10 10:54:53.780740933 
+0200
+++ /work/SRC/openSUSE:Factory/.bcc.new/bcc.changes     2018-06-20 
15:34:42.518779500 +0200
@@ -1,0 +2,18 @@
+Tue Jun 19 09:45:55 UTC 2018 - [email protected]
+
+- Update to 0.6.0
+- Add upstream patches
+  + bcc-bpf_probe_read-fixes.patch
+  + bcc-fix-ext4slower.patch
+  + bcc-fix-tcpaccept.patch
+  + bcc-prevent-bpf_probe_read-MemberExpre-rewrite.patch
+- Drop upstreamed patches
+  + bcc-fix-build-for-llvm-5.0.1.patch
+  + bcc-fix-a-compilation-error-with-latest-llvm-clang-trunk.patch
+  + bcc-bsc1080085-backport-bytes-strings.patch
+  + bcc-bsc1080085-detect-slab-for-slabratetop.patch
+  + bcc-bsc1080085-fix-cachetop-py3-str.patch
+  + bcc-bsc1080085-fix-syscount-str.patch
+- Refresh bcc-python3.patch
+
+-------------------------------------------------------------------

Old:
----
  bcc-bsc1080085-backport-bytes-strings.patch
  bcc-bsc1080085-detect-slab-for-slabratetop.patch
  bcc-bsc1080085-fix-cachetop-py3-str.patch
  bcc-bsc1080085-fix-syscount-str.patch
  bcc-fix-a-compilation-error-with-latest-llvm-clang-trunk.patch
  bcc-fix-build-for-llvm-5.0.1.patch
  v0.5.0.tar.gz

New:
----
  bcc-bpf_probe_read-fixes.patch
  bcc-fix-ext4slower.patch
  bcc-fix-tcpaccept.patch
  bcc-prevent-bpf_probe_read-MemberExpre-rewrite.patch
  v0.6.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ bcc.spec ++++++
--- /var/tmp/diff_new_pack.DTm1qG/_old  2018-06-20 15:34:43.558741764 +0200
+++ /var/tmp/diff_new_pack.DTm1qG/_new  2018-06-20 15:34:43.562741620 +0200
@@ -16,7 +16,7 @@
 #
 
 
-%define libversion 0.5.0
+%define libversion 0.6.0
 %if 0%{?is_opensuse} == 1
 %ifarch %ix86 x86_64
 %{!?with_lua: %global with_lua 1}
@@ -28,7 +28,7 @@
 %endif
 
 Name:           bcc
-Version:        0.5.0
+Version:        0.6.0
 Release:        0
 Summary:        BPF Compiler Collection (BCC)
 License:        Apache-2.0
@@ -38,13 +38,11 @@
 Patch1:         %{name}-check_int128.patch
 Patch2:         %{name}-bsc1065593-llvm4-hack.patch
 Patch3:         %{name}-python3.patch
-Patch4:         %{name}-fix-build-for-llvm-5.0.1.patch
-Patch5:         %{name}-bsc1080085-backport-bytes-strings.patch
-Patch6:         %{name}-bsc1080085-fix-cachetop-py3-str.patch
-Patch7:         %{name}-bsc1080085-import-readline-from-lib.patch
-Patch8:         %{name}-bsc1080085-detect-slab-for-slabratetop.patch
-Patch9:         %{name}-bsc1080085-fix-syscount-str.patch
-Patch10:        
%{name}-fix-a-compilation-error-with-latest-llvm-clang-trunk.patch
+Patch4:         %{name}-bsc1080085-import-readline-from-lib.patch
+Patch5:         %{name}-bpf_probe_read-fixes.patch
+Patch6:         %{name}-fix-ext4slower.patch
+Patch7:         %{name}-prevent-bpf_probe_read-MemberExpre-rewrite.patch
+Patch8:         %{name}-fix-tcpaccept.patch
 ExcludeArch:    ppc s390
 BuildRequires:  bison
 BuildRequires:  cmake >= 2.8.7
@@ -177,8 +175,6 @@
 %patch6 -p1
 %patch7 -p1
 %patch8 -p1
-%patch9 -p1
-%patch10 -p1
 
 %build
 # Prevent the cpp examples from compilation and installation

++++++ bcc-bpf_probe_read-fixes.patch ++++++
>From 37f7fef27967ad5a1025112db6ec593a60a2c902 Mon Sep 17 00:00:00 2001
From: Paul Chaignon <[email protected]>
Date: Thu, 14 Jun 2018 02:14:59 +0200
Subject: [PATCH 1/3] profile: remove unnecessary bpf_probe_read call (#1822)

---
 tools/profile.py | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/tools/profile.py b/tools/profile.py
index 3040a48..ec5533f 100755
--- a/tools/profile.py
+++ b/tools/profile.py
@@ -153,9 +153,7 @@ int do_perf_event(struct bpf_perf_event_data *ctx) {
 
     if (key.kernel_stack_id >= 0) {
         // populate extras to fix the kernel stack
-        struct pt_regs regs = {};
-        bpf_probe_read(&regs, sizeof(regs), (void *)&ctx->regs);
-        u64 ip = PT_REGS_IP(&regs);
+        u64 ip = PT_REGS_IP(&ctx->regs);
         u64 page_offset;
 
         // if ip isn't sane, leave key ips as zero for later checking
-- 
2.17.1


>From f86f7e842eb9d892b5b46fa92bf231823ce533e3 Mon Sep 17 00:00:00 2001
From: Paul Chaignon <[email protected]>
Date: Thu, 14 Jun 2018 02:20:03 +0200
Subject: [PATCH 2/3] Skip dereferences inside bpf_probe_reads calls (#1824)

* Skip all dereferences inside bpf_probe_read calls

If the user decides to rely on a manual call to bpf_probe_read, we
don't try to rewrite its last argument.  This is needed as the
rewriter starts to recognize and rewrite more and more dereferences.

* tools: fix dereferences following 1a765a17
---
 src/cc/frontends/clang/b_frontend_action.cc | 5 +----
 tools/biosnoop.py                           | 3 ++-
 tools/filelife.py                           | 6 +++---
 tools/fileslower.py                         | 5 +++--
 tools/filetop.py                            | 7 ++++---
 tools/mdflush.py                            | 6 +++---
 tools/slabratetop.py                        | 3 ++-
 7 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/src/cc/frontends/clang/b_frontend_action.cc 
b/src/cc/frontends/clang/b_frontend_action.cc
index a1e1bda..ab9b6f4 100644
--- a/src/cc/frontends/clang/b_frontend_action.cc
+++ b/src/cc/frontends/clang/b_frontend_action.cc
@@ -281,10 +281,7 @@ bool ProbeVisitor::VisitCallExpr(CallExpr *Call) {
   if (VarDecl *V = dyn_cast<VarDecl>(Call->getCalleeDecl())) {
     if (V->getName() == "bpf_probe_read" && Call->getNumArgs() >= 3) {
       const Expr *E = Call->getArg(2)->IgnoreParenCasts();
-      if (const UnaryOperator *UnaryExpr = dyn_cast<UnaryOperator>(E)) {
-        if (UnaryExpr->getOpcode() == UO_AddrOf)
-          whitelist_.insert(E);
-      }
+      whitelist_.insert(E);
       return true;
     }
   }
diff --git a/tools/biosnoop.py b/tools/biosnoop.py
index 32d83e5..7f61180 100755
--- a/tools/biosnoop.py
+++ b/tools/biosnoop.py
@@ -94,8 +94,9 @@ int trace_req_completion(struct pt_regs *ctx, struct request 
*req)
         data.len = req->__data_len;
         data.sector = req->__sector;
         bpf_probe_read(&data.name, sizeof(data.name), valp->name);
+        struct gendisk *rq_disk = req->rq_disk;
         bpf_probe_read(&data.disk_name, sizeof(data.disk_name),
-                       req->rq_disk->disk_name);
+                       rq_disk->disk_name);
     }
 
 /*
diff --git a/tools/filelife.py b/tools/filelife.py
index 6756f31..0f4e269 100755
--- a/tools/filelife.py
+++ b/tools/filelife.py
@@ -84,14 +84,14 @@ int trace_unlink(struct pt_regs *ctx, struct inode *dir, 
struct dentry *dentry)
     delta = (bpf_ktime_get_ns() - *tsp) / 1000000;
     birth.delete(&dentry);
 
-    if (dentry->d_name.len == 0)
+    struct qstr d_name = dentry->d_name;
+    if (d_name.len == 0)
         return 0;
 
     if (bpf_get_current_comm(&data.comm, sizeof(data.comm)) == 0) {
         data.pid = pid;
         data.delta = delta;
-        bpf_probe_read(&data.fname, sizeof(data.fname),
-            (void *)dentry->d_name.name);
+        bpf_probe_read(&data.fname, sizeof(data.fname), d_name.name);
     }
 
     events.perf_submit(ctx, &data, sizeof(data));
diff --git a/tools/fileslower.py b/tools/fileslower.py
index 04e2e61..5caa4ca 100755
--- a/tools/fileslower.py
+++ b/tools/fileslower.py
@@ -111,8 +111,9 @@ static int trace_rw_entry(struct pt_regs *ctx, struct file 
*file,
     val.sz = count;
     val.ts = bpf_ktime_get_ns();
 
-    val.name_len = de->d_name.len;
-    bpf_probe_read(&val.name, sizeof(val.name), (void *)de->d_name.name);
+    struct qstr d_name = de->d_name;
+    val.name_len = d_name.len;
+    bpf_probe_read(&val.name, sizeof(val.name), d_name.name);
     bpf_get_current_comm(&val.comm, sizeof(val.comm));
     entryinfo.update(&pid, &val);
 
diff --git a/tools/filetop.py b/tools/filetop.py
index 8677665..454dfd8 100755
--- a/tools/filetop.py
+++ b/tools/filetop.py
@@ -100,14 +100,15 @@ static int do_entry(struct pt_regs *ctx, struct file 
*file,
     // skip I/O lacking a filename
     struct dentry *de = file->f_path.dentry;
     int mode = file->f_inode->i_mode;
-    if (de->d_name.len == 0 || TYPE_FILTER)
+    struct qstr d_name = de->d_name;
+    if (d_name.len == 0 || TYPE_FILTER)
         return 0;
 
     // store counts and sizes by pid & file
     struct info_t info = {.pid = pid};
     bpf_get_current_comm(&info.comm, sizeof(info.comm));
-    info.name_len = de->d_name.len;
-    bpf_probe_read(&info.name, sizeof(info.name), (void *)de->d_name.name);
+    info.name_len = d_name.len;
+    bpf_probe_read(&info.name, sizeof(info.name), d_name.name);
     if (S_ISREG(mode)) {
         info.type = 'R';
     } else if (S_ISSOCK(mode)) {
diff --git a/tools/mdflush.py b/tools/mdflush.py
index 15ad79e..1d29bf1 100755
--- a/tools/mdflush.py
+++ b/tools/mdflush.py
@@ -44,11 +44,11 @@ int kprobe__md_flush_request(struct pt_regs *ctx, void 
*mddev, struct bio *bio)
  * and maintenance burden.
  */
 #ifdef bio_dev
-    bpf_probe_read(&data.disk, sizeof(data.disk), bio->bi_disk->disk_name);
+    struct gendisk *bi_disk = bio->bi_disk;
 #else
-    bpf_probe_read(&data.disk, sizeof(data.disk),
-                   bio->bi_bdev->bd_disk->disk_name);
+    struct gendisk *bi_disk = bio->bi_bdev->bd_disk;
 #endif
+    bpf_probe_read(&data.disk, sizeof(data.disk), bi_disk->disk_name);
     events.perf_submit(ctx, &data, sizeof(data));
     return 0;
 }
diff --git a/tools/slabratetop.py b/tools/slabratetop.py
index f1911b0..101c585 100755
--- a/tools/slabratetop.py
+++ b/tools/slabratetop.py
@@ -87,7 +87,8 @@ BPF_HASH(counts, struct info_t, struct val_t);
 int kprobe__kmem_cache_alloc(struct pt_regs *ctx, struct kmem_cache *cachep)
 {
     struct info_t info = {};
-    bpf_probe_read(&info.name, sizeof(info.name), (void *)cachep->name);
+    const char *name = cachep->name;
+    bpf_probe_read(&info.name, sizeof(info.name), name);
 
     struct val_t *valp, zero = {};
     valp = counts.lookup_or_init(&info, &zero);
-- 
2.17.1


>From fe779f31cd0049e65815478bc5c76051a7821b66 Mon Sep 17 00:00:00 2001
From: Paul Chaignon <[email protected]>
Date: Thu, 14 Jun 2018 03:51:55 +0200
Subject: [PATCH 3/3] Trace external pointers through function returns (#1821)

* Trace external pointers through function returns

Surprisingly, the rewriter wasn't able to trace external pointers
returned by inlined functions until now.  This commit fixes it by
adding functions that return an external pointer to ProbeVisitor's
set of external pointers, along with the levels of indirection.

This change requires reversing a few traversals to visit called
functions before they are called.  Then, we check the presence of an
external pointer on return statements and retrieve that information
at the call expression.

* Tests dereferences of ext ptrs returned by inlined func

* tcpdrop: remove unnecessary bpf_probe_read calls

e783567a makes these calls unnecessary.
---
 src/cc/frontends/clang/b_frontend_action.cc | 73 ++++++++++++++++++++-
 src/cc/frontends/clang/b_frontend_action.h  |  2 +
 tests/python/test_clang.py                  | 68 +++++++++++++++++++
 tools/tcpdrop.py                            |  8 +--
 4 files changed, 145 insertions(+), 6 deletions(-)

diff --git a/src/cc/frontends/clang/b_frontend_action.cc 
b/src/cc/frontends/clang/b_frontend_action.cc
index ab9b6f4..dad1e29 100644
--- a/src/cc/frontends/clang/b_frontend_action.cc
+++ b/src/cc/frontends/clang/b_frontend_action.cc
@@ -107,6 +107,23 @@ class ProbeChecker : public 
RecursiveASTVisitor<ProbeChecker> {
       : ProbeChecker(arg, ptregs, is_transitive, false) {}
   bool VisitCallExpr(CallExpr *E) {
     needs_probe_ = false;
+
+    if (is_assign_) {
+      // We're looking for a function that returns an external pointer,
+      // regardless of the number of dereferences.
+      for(auto p : ptregs_) {
+        if (std::get<0>(p) == E->getDirectCallee()) {
+          needs_probe_ = true;
+          nb_derefs_ += std::get<1>(p);
+          return false;
+        }
+      }
+    } else {
+      tuple<Decl *, int> pt = make_tuple(E->getDirectCallee(), nb_derefs_);
+      if (ptregs_.find(pt) != ptregs_.end())
+        needs_probe_ = true;
+    }
+
     if (!track_helpers_)
       return false;
     if (VarDecl *V = dyn_cast<VarDecl>(E->getCalleeDecl()))
@@ -220,6 +237,12 @@ bool ProbeVisitor::assignsExtPtr(Expr *E, int *nbAddrOf) {
     return true;
   }
 
+  /* If the expression contains a call to another function, we need to visit
+  * that function first to know if a rewrite is necessary (i.e., if the
+  * function returns an external pointer). */
+  if (!TraverseStmt(E))
+    return false;
+
   ProbeChecker checker = ProbeChecker(E, ptregs_, track_helpers_,
                                       true);
   if (checker.is_transitive()) {
@@ -231,8 +254,8 @@ bool ProbeVisitor::assignsExtPtr(Expr *E, int *nbAddrOf) {
     return true;
   }
 
-  if (E->getStmtClass() == Stmt::CallExprClass) {
-    CallExpr *Call = dyn_cast<CallExpr>(E);
+  if (E->IgnoreParenCasts()->getStmtClass() == Stmt::CallExprClass) {
+    CallExpr *Call = dyn_cast<CallExpr>(E->IgnoreParenCasts());
     if (MemberExpr *Memb = 
dyn_cast<MemberExpr>(Call->getCallee()->IgnoreImplicit())) {
       StringRef memb_name = Memb->getMemberDecl()->getName();
       if (DeclRefExpr *Ref = dyn_cast<DeclRefExpr>(Memb->getBase())) {
@@ -301,12 +324,49 @@ bool ProbeVisitor::VisitCallExpr(CallExpr *Call) {
       }
       if (fn_visited_.find(F) == fn_visited_.end()) {
         fn_visited_.insert(F);
+        /* Maintains a stack of the number of dereferences for the external
+         * pointers returned by each function in the call stack or -1 if the
+         * function didn't return an external pointer. */
+        ptregs_returned_.push_back(-1);
         TraverseDecl(F);
+        int nb_derefs = ptregs_returned_.back();
+        ptregs_returned_.pop_back();
+        if (nb_derefs != -1) {
+          tuple<Decl *, int> pt = make_tuple(F, nb_derefs);
+          ptregs_.insert(pt);
+        }
       }
     }
   }
   return true;
 }
+bool ProbeVisitor::VisitReturnStmt(ReturnStmt *R) {
+  /* If this function wasn't called by another, there's no need to check the
+   * return statement for external pointers. */
+  if (ptregs_returned_.size() == 0)
+    return true;
+
+  /* Reverse order of traversals.  This is needed if, in the return statement,
+   * we're calling a function that's returning an external pointer: we need to
+   * know what the function is returning to decide what this function is
+   * returning. */
+  if (!TraverseStmt(R->getRetValue()))
+    return false;
+
+  ProbeChecker checker = ProbeChecker(R->getRetValue(), ptregs_,
+                                      track_helpers_, true);
+  if (checker.needs_probe()) {
+    int curr_nb_derefs = ptregs_returned_.back();
+    /* If the function returns external pointers with different levels of
+     * indirection, we handle the case with the highest level of indirection
+     * and leave it to the user to manually handle other cases. */
+    if (checker.get_nb_derefs() > curr_nb_derefs) {
+      ptregs_returned_.pop_back();
+      ptregs_returned_.push_back(checker.get_nb_derefs());
+    }
+  }
+  return true;
+}
 bool ProbeVisitor::VisitBinaryOperator(BinaryOperator *E) {
   if (!E->isAssignmentOp())
     return true;
@@ -359,6 +419,15 @@ bool ProbeVisitor::VisitMemberExpr(MemberExpr *E) {
     return false;
   }
 
+  /* If the base of the dereference is a call to another function, we need to
+   * visit that function first to know if a rewrite is necessary (i.e., if the
+   * function returns an external pointer). */
+  if (base->IgnoreParenCasts()->getStmtClass() == Stmt::CallExprClass) {
+    CallExpr *Call = dyn_cast<CallExpr>(base->IgnoreParenCasts());
+    if (!TraverseStmt(Call))
+      return false;
+  }
+
   // Checks to see if the expression references something that needs to be run
   // through bpf_probe_read.
   if (!ProbeChecker(base, ptregs_, track_helpers_).needs_probe())
diff --git a/src/cc/frontends/clang/b_frontend_action.h 
b/src/cc/frontends/clang/b_frontend_action.h
index 72498db..cf3cc59 100644
--- a/src/cc/frontends/clang/b_frontend_action.h
+++ b/src/cc/frontends/clang/b_frontend_action.h
@@ -98,6 +98,7 @@ class ProbeVisitor : public 
clang::RecursiveASTVisitor<ProbeVisitor> {
   bool VisitVarDecl(clang::VarDecl *Decl);
   bool TraverseStmt(clang::Stmt *S);
   bool VisitCallExpr(clang::CallExpr *Call);
+  bool VisitReturnStmt(clang::ReturnStmt *R);
   bool VisitBinaryOperator(clang::BinaryOperator *E);
   bool VisitUnaryOperator(clang::UnaryOperator *E);
   bool VisitMemberExpr(clang::MemberExpr *E);
@@ -120,6 +121,7 @@ class ProbeVisitor : public 
clang::RecursiveASTVisitor<ProbeVisitor> {
   std::set<clang::Decl *> &m_;
   clang::Decl *ctx_;
   bool track_helpers_;
+  std::list<int> ptregs_returned_;
 };
 
 // A helper class to the frontend action, walks the decls
diff --git a/tests/python/test_clang.py b/tests/python/test_clang.py
index e291a9f..19bbb7b 100755
--- a/tests/python/test_clang.py
+++ b/tests/python/test_clang.py
@@ -940,6 +940,74 @@ int test(struct __sk_buff *ctx) {
         b = BPF(text=text)
         fn = b.load_func("test", BPF.SCHED_CLS)
 
+    def test_probe_read_return(self):
+        text = """
+#define KBUILD_MODNAME "foo"
+#include <uapi/linux/ptrace.h>
+#include <linux/tcp.h>
+static inline unsigned char *my_skb_transport_header(struct sk_buff *skb) {
+    return skb->head + skb->transport_header;
+}
+int test(struct pt_regs *ctx, struct sock *sk, struct sk_buff *skb) {
+    struct tcphdr *th = (struct tcphdr *)my_skb_transport_header(skb);
+    return th->seq;
+}
+"""
+        b = BPF(text=text)
+        fn = b.load_func("test", BPF.KPROBE)
+
+    def test_probe_read_multiple_return(self):
+        text = """
+#define KBUILD_MODNAME "foo"
+#include <uapi/linux/ptrace.h>
+#include <linux/tcp.h>
+static inline u64 error_function() {
+    return 0;
+}
+static inline unsigned char *my_skb_transport_header(struct sk_buff *skb) {
+    if (skb)
+        return skb->head + skb->transport_header;
+    return (unsigned char *)error_function();
+}
+int test(struct pt_regs *ctx, struct sock *sk, struct sk_buff *skb) {
+    struct tcphdr *th = (struct tcphdr *)my_skb_transport_header(skb);
+    return th->seq;
+}
+"""
+        b = BPF(text=text)
+        fn = b.load_func("test", BPF.KPROBE)
+
+    def test_probe_read_return_expr(self):
+        text = """
+#define KBUILD_MODNAME "foo"
+#include <uapi/linux/ptrace.h>
+#include <linux/tcp.h>
+static inline unsigned char *my_skb_transport_header(struct sk_buff *skb) {
+    return skb->head + skb->transport_header;
+}
+int test(struct pt_regs *ctx, struct sock *sk, struct sk_buff *skb) {
+    u32 *seq = (u32 *)my_skb_transport_header(skb) + offsetof(struct tcphdr, 
seq);
+    return *seq;
+}
+"""
+        b = BPF(text=text)
+        fn = b.load_func("test", BPF.KPROBE)
+
+    def test_probe_read_return_call(self):
+        text = """
+#define KBUILD_MODNAME "foo"
+#include <uapi/linux/ptrace.h>
+#include <linux/tcp.h>
+static inline struct tcphdr *my_skb_transport_header(struct sk_buff *skb) {
+    return (struct tcphdr *)skb->head + skb->transport_header;
+}
+int test(struct pt_regs *ctx, struct sock *sk, struct sk_buff *skb) {
+    return my_skb_transport_header(skb)->seq;
+}
+"""
+        b = BPF(text=text)
+        fn = b.load_func("test", BPF.KPROBE)
+
 
 if __name__ == "__main__":
     main()
diff --git a/tools/tcpdrop.py b/tools/tcpdrop.py
index 77ad752..9667868 100755
--- a/tools/tcpdrop.py
+++ b/tools/tcpdrop.py
@@ -107,16 +107,16 @@ int trace_tcp_drop(struct pt_regs *ctx, struct sock *sk, 
struct sk_buff *skb)
     u8 tcpflags = 0;
     struct tcphdr *tcp = skb_to_tcphdr(skb);
     struct iphdr *ip = skb_to_iphdr(skb);
-    bpf_probe_read(&sport, sizeof(sport), &tcp->source);
-    bpf_probe_read(&dport, sizeof(dport), &tcp->dest);
+    sport = tcp->source;
+    dport = tcp->dest;
     bpf_probe_read(&tcpflags, sizeof(tcpflags), &tcp_flag_byte(tcp));
     sport = ntohs(sport);
     dport = ntohs(dport);
 
     if (family == AF_INET) {
         struct ipv4_data_t data4 = {.pid = pid, .ip = 4};
-        bpf_probe_read(&data4.saddr, sizeof(u32), &ip->saddr);
-        bpf_probe_read(&data4.daddr, sizeof(u32), &ip->daddr);
+        data4.saddr = ip->saddr;
+        data4.daddr = ip->daddr;
         data4.dport = dport;
         data4.sport = sport;
         data4.state = state;
-- 
2.17.1

++++++ bcc-fix-ext4slower.patch ++++++
>From e07f2ed3f2943f7886e22ba46b570c7c66e5b091 Mon Sep 17 00:00:00 2001
From: Joe Yin <[email protected]>
Date: Thu, 14 Jun 2018 12:21:46 +0800
Subject: [PATCH] Modify trace function from generic_file_read_iter() to
 ext4_file_read_iter() (#1818)

* modify ext4slower.py for 4.10+ version

* modify ext4slower.py for 4.10+ version

* #1818
---
 tools/ext4slower.py | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/tools/ext4slower.py b/tools/ext4slower.py
index 756d826..eb6430e 100755
--- a/tools/ext4slower.py
+++ b/tools/ext4slower.py
@@ -23,6 +23,7 @@
 #
 # 11-Feb-2016   Brendan Gregg   Created this.
 # 15-Oct-2016   Dina Goldshtein -p to filter by process ID.
+# 13-Jun-2018   Joe Yin modify generic_file_read_iter to ext4_file_read_iter.
 
 from __future__ import print_function
 from bcc import BPF
@@ -100,6 +101,9 @@ BPF_PERF_OUTPUT(events);
 // The current ext4 (Linux 4.5) uses generic_file_read_iter(), instead of it's
 // own function, for reads. So we need to trace that and then filter on ext4,
 // which I do by checking file->f_op.
+// The new Linux version (since form 4.10) uses ext4_file_read_iter(), And if 
the 'CONFIG_FS_DAX' 
+// is not set ,then ext4_file_read_iter() will call generic_file_read_iter(), 
else it will call 
+// ext4_dax_read_iter(), and trace generic_file_read_iter() will fail.
 int trace_read_entry(struct pt_regs *ctx, struct kiocb *iocb)
 {
     u64 id =  bpf_get_current_pid_tgid();
@@ -321,11 +325,17 @@ def print_event(cpu, data, size):
 b = BPF(text=bpf_text)
 
 # Common file functions. See earlier comment about generic_file_read_iter().
-b.attach_kprobe(event="generic_file_read_iter", fn_name="trace_read_entry")
+if BPF.get_kprobe_functions(b'ext4_file_read_iter'):
+    b.attach_kprobe(event="ext4_file_read_iter", fn_name="trace_read_entry")
+else:
+    b.attach_kprobe(event="generic_file_read_iter", fn_name="trace_read_entry")
 b.attach_kprobe(event="ext4_file_write_iter", fn_name="trace_write_entry")
 b.attach_kprobe(event="ext4_file_open", fn_name="trace_open_entry")
 b.attach_kprobe(event="ext4_sync_file", fn_name="trace_fsync_entry")
-b.attach_kretprobe(event="generic_file_read_iter", fn_name="trace_read_return")
+if BPF.get_kprobe_functions(b'ext4_file_read_iter'):
+    b.attach_kretprobe(event="ext4_file_read_iter", 
fn_name="trace_read_return")
+else:
+    b.attach_kretprobe(event="generic_file_read_iter", 
fn_name="trace_read_return")
 b.attach_kretprobe(event="ext4_file_write_iter", fn_name="trace_write_return")
 b.attach_kretprobe(event="ext4_file_open", fn_name="trace_open_return")
 b.attach_kretprobe(event="ext4_sync_file", fn_name="trace_fsync_return")
-- 
2.17.1

++++++ bcc-fix-tcpaccept.patch ++++++
>From 116bb40f314cacf369ccddaee494af4a5f6b7ab4 Mon Sep 17 00:00:00 2001
From: Joe Yin <[email protected]>
Date: Mon, 18 Jun 2018 23:34:52 +0800
Subject: [PATCH] Patch for tools/tcpaccept.py (#1834)

 fix socket protocol reading
---
 tools/tcpaccept.py | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/tools/tcpaccept.py b/tools/tcpaccept.py
index 52aefdf..8f33c8f 100755
--- a/tools/tcpaccept.py
+++ b/tools/tcpaccept.py
@@ -82,7 +82,37 @@ int kretprobe__inet_csk_accept(struct pt_regs *ctx)
     // check this is TCP
     u8 protocol = 0;
     // workaround for reading the sk_protocol bitfield:
-    bpf_probe_read(&protocol, 1, (void *)((long)&newsk->sk_wmem_queued) - 3);
+    
+    // Following comments add by Joe Yin:
+    // Unfortunately,it can not work since Linux 4.10,
+    // because the sk_wmem_queued is not following the bitfield of sk_protocol.
+    // And the following member is sk_gso_max_segs.
+    // So, we can use this:
+    // bpf_probe_read(&protocol, 1, (void *)((u64)&newsk->sk_gso_max_segs) - 
3);
+    // In order to  diff the pre-4.10 and 4.10+ ,introduce the variables 
gso_max_segs_offset,sk_lingertime, 
+    // sk_lingertime is closed to the gso_max_segs_offset,and  
+    // the offset between the two members is 4 
+
+    int gso_max_segs_offset = offsetof(struct sock, sk_gso_max_segs);
+    int sk_lingertime_offset = offsetof(struct sock, sk_lingertime);
+
+    if (sk_lingertime_offset - gso_max_segs_offset == 4) 
+        // 4.10+ with little endian
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+            bpf_probe_read(&protocol, 1, (void 
*)((u64)&newsk->sk_gso_max_segs) - 3);
+    else
+        // pre-4.10 with little endian
+            bpf_probe_read(&protocol, 1, (void *)((u64)&newsk->sk_wmem_queued) 
- 3);
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+        // 4.10+ with big endian
+            bpf_probe_read(&protocol, 1, (void 
*)((u64)&newsk->sk_gso_max_segs) - 1);
+    else
+        // pre-4.10 with big endian
+            bpf_probe_read(&protocol, 1, (void *)((u64)&newsk->sk_wmem_queued) 
- 1);
+#else
+# error "Fix your compiler's __BYTE_ORDER__?!"
+#endif
+
     if (protocol != IPPROTO_TCP)
         return 0;
 
-- 
2.17.1

++++++ bcc-prevent-bpf_probe_read-MemberExpre-rewrite.patch ++++++
>From 66d286358b0cfa982031412e3d562987cc8dc926 Mon Sep 17 00:00:00 2001
From: yonghong-song <[email protected]>
Date: Thu, 14 Jun 2018 07:11:42 -0700
Subject: [PATCH] prevent bpf_probe_read MemberExpr rewrite if not rewritable
 (#1827)

For the test case in this patch below,
 #define _(P) ({typeof(P) val = 0; bpf_probe_read(&val, sizeof(val), &P); val;})
 int count_tcp(struct pt_regs *ctx, struct sk_buff *skb) {
     return _(TCP_SKB_CB(skb)->tcp_gso_size);
 }

The clang AST will consider the whole `_(TCP_SKB_CB(skb)->tcp_gso_size)`
as a MemberExpr during AST traversal. However, it will consider
the start location of the member expression not rewritable.
Without this patch, we will get an error like below:
    /virtual/main.c:15:44: error: expected ';' after return statement
    return _(TCP_SKB_CB(skb)->tcp_gso_size)); _val; });
Basically, the start of bpf_probe_read() rewritingg failed but
later part succeeded, so the code becomes uncompilable.

Previously, we did not see such issues, but as rewriter got
more smarter this bug is exposed.

This patch fixed the issue by preventing rewriting the whole
expression if the start location for the member expression is
not rewritable.

Signed-off-by: Yonghong Song <[email protected]>
---
 src/cc/frontends/clang/b_frontend_action.cc |  3 +++
 tests/python/test_clang.py                  | 12 ++++++++++++
 2 files changed, 15 insertions(+)

diff --git a/src/cc/frontends/clang/b_frontend_action.cc 
b/src/cc/frontends/clang/b_frontend_action.cc
index dad1e29..2dff2b4 100644
--- a/src/cc/frontends/clang/b_frontend_action.cc
+++ b/src/cc/frontends/clang/b_frontend_action.cc
@@ -419,6 +419,9 @@ bool ProbeVisitor::VisitMemberExpr(MemberExpr *E) {
     return false;
   }
 
+  if (!rewriter_.isRewritable(E->getLocStart()))
+    return false;
+
   /* If the base of the dereference is a call to another function, we need to
    * visit that function first to know if a rewrite is necessary (i.e., if the
    * function returns an external pointer). */
diff --git a/tests/python/test_clang.py b/tests/python/test_clang.py
index 19bbb7b..e3fce6b 100755
--- a/tests/python/test_clang.py
+++ b/tests/python/test_clang.py
@@ -76,6 +76,18 @@ int count_foo(struct pt_regs *ctx, unsigned long a, unsigned 
long b) {
         b = BPF(text=text, debug=0)
         fn = b.load_func("count_foo", BPF.KPROBE)
 
+    def test_probe_read3(self):
+        text = """
+#define KBUILD_MODNAME "foo"
+#include <net/tcp.h>
+#define _(P) ({typeof(P) val = 0; bpf_probe_read(&val, sizeof(val), &P); val;})
+int count_tcp(struct pt_regs *ctx, struct sk_buff *skb) {
+    return _(TCP_SKB_CB(skb)->tcp_gso_size);
+}
+"""
+        b = BPF(text=text)
+        fn = b.load_func("count_tcp", BPF.KPROBE)
+
     def test_probe_read_whitelist1(self):
         text = """
 #define KBUILD_MODNAME "foo"
-- 
2.17.1

++++++ bcc-python3.patch ++++++
++++ 2462 lines (skipped)
++++ between /work/SRC/openSUSE:Factory/bcc/bcc-python3.patch
++++ and /work/SRC/openSUSE:Factory/.bcc.new/bcc-python3.patch

++++++ v0.5.0.tar.gz -> v0.6.0.tar.gz ++++++
++++ 25453 lines of diff (skipped)


Reply via email to