Permits mountsnoop to filter container using cgroup map or mount namespace.
authorFrancis Laniel <laniel_francis@privacyrequired.com>
Sun, 22 Aug 2021 18:23:23 +0000 (20:23 +0200)
committeryonghong-song <ys114321@gmail.com>
Mon, 6 Sep 2021 04:10:44 +0000 (21:10 -0700)
Signed-off-by: Francis Laniel <laniel_francis@privacyrequired.com>
src/python/bcc/containers.py
tools/mountsnoop.py

index 48c1fcc6de176be3f658a99e6ca13fc9a3f94299..5cb2269b46a0f2c96fd7890b4b17c2fc7cc7df91 100644 (file)
@@ -57,6 +57,20 @@ def _mntns_filter_func_writer(mntnsmap):
     #endif
         struct ns_common ns;
     };
+    /*
+     * To add mountsnoop support for --selector option, we need to call
+     * filter_by_containers().
+     * This function adds code which defines struct mnt_namespace.
+     * The problem is that this struct is also defined in mountsnoop BPF code.
+     * To avoid redefining it in mountnsoop code, we define
+     * MNT_NAMESPACE_DEFINED here.
+     * Then, in mountsnoop code, the struct mnt_namespace definition is guarded
+     * by:
+     * #ifndef MNT_NAMESPACE_DEFINED
+     * // ...
+     * #endif
+     */
+    #define MNT_NAMESPACE_DEFINED
 
     BPF_TABLE_PINNED("hash", u64, u32, mount_ns_set, 1024, "MOUNT_NS_PATH");
 
index 6a0eea1eb027672b5bf45938904b4ffdd8cc3449..a6d7ecee35fa8990b568e8474e9ea426b071f50d 100755 (executable)
@@ -13,6 +13,7 @@
 from __future__ import print_function
 import argparse
 import bcc
+from bcc.containers import filter_by_containers
 import ctypes
 import errno
 import functools
@@ -31,7 +32,14 @@ bpf_text = r"""
  * VFS and not installed in any kernel-devel packages. So, let's duplicate the
  * important part of the definition. There are actually more members in the
  * real struct, but we don't need them, and they're more likely to change.
+ *
+ * To add support for --selector option, we need to call filter_by_containers().
+ * But this function adds code which defines struct mnt_namespace.
+ * To avoid having this structure twice, we define MNT_NAMESPACE_DEFINED in
+ * filter_by_containers(), then here we check if macro is already defined before
+ * adding struct definition.
  */
+#ifndef MNT_NAMESPACE_DEFINED
 struct mnt_namespace {
     // This field was removed in https://github.com/torvalds/linux/commit/1a7b8969e664d6af328f00fe6eb7aabd61a71d13
     #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0)
@@ -39,6 +47,7 @@ struct mnt_namespace {
     #endif
     struct ns_common ns;
 };
+#endif /* !MNT_NAMESPACE_DEFINED */
 
 /*
  * XXX: this could really use first-class string support in BPF. target is a
@@ -100,6 +109,10 @@ int syscall__mount(struct pt_regs *ctx, char __user *source,
     struct nsproxy *nsproxy;
     struct mnt_namespace *mnt_ns;
 
+    if (container_should_be_filtered()) {
+        return 0;
+    }
+
     event.pid = bpf_get_current_pid_tgid() & 0xffffffff;
     event.tgid = bpf_get_current_pid_tgid() >> 32;
 
@@ -157,6 +170,10 @@ int syscall__umount(struct pt_regs *ctx, char __user *target, int flags)
     struct nsproxy *nsproxy;
     struct mnt_namespace *mnt_ns;
 
+    if (container_should_be_filtered()) {
+        return 0;
+    }
+
     event.pid = bpf_get_current_pid_tgid() & 0xffffffff;
     event.tgid = bpf_get_current_pid_tgid() >> 32;
 
@@ -416,10 +433,16 @@ def main():
         help=argparse.SUPPRESS)
     parser.add_argument("-P", "--parent_process", action="store_true",
         help="also snoop the parent process")
+    parser.add_argument("--cgroupmap",
+        help="trace cgroups in this BPF map only")
+    parser.add_argument("--mntnsmap",
+        help="trace mount namespaces in this BPF map only")
     args = parser.parse_args()
 
     mounts = {}
     umounts = {}
+    global bpf_text
+    bpf_text = filter_by_containers(args) + bpf_text
     if args.ebpf:
         print(bpf_text)
         exit()