endif()
endif()
-add_library(bcc-shared SHARED bpf_common.cc bpf_module.cc libbpf.c perf_reader.c table_storage.cc shared_table.cc bpffs_table.cc json_map_decl_visitor.cc exported_files.cc bcc_elf.c bcc_perf_map.c bcc_proc.c bcc_syms.cc usdt_args.cc usdt.cc common.cc BPF.cc BPFTable.cc)
+add_library(bcc-shared SHARED bpf_common.cc bpf_module.cc libbpf.c perf_reader.c
+ table_storage.cc shared_table.cc bpffs_table.cc json_map_decl_visitor.cc
+ exported_files.cc bcc_elf.c bcc_perf_map.c bcc_proc.c bcc_syms.cc ns_guard.cc
+ usdt_args.cc usdt.cc common.cc BPF.cc BPFTable.cc)
set_target_properties(bcc-shared PROPERTIES VERSION ${REVISION_LAST} SOVERSION 0)
set_target_properties(bcc-shared PROPERTIES OUTPUT_NAME bcc)
-add_library(bcc-loader-static STATIC libbpf.c perf_reader.c bcc_elf.c bcc_perf_map.c bcc_proc.c bcc_syms.cc)
-add_library(bcc-static STATIC bpf_common.cc bpf_module.cc shared_table.cc bpffs_table.cc json_map_decl_visitor.cc table_storage.cc exported_files.cc usdt_args.cc usdt.cc common.cc BPF.cc BPFTable.cc)
+add_library(bcc-loader-static STATIC libbpf.c perf_reader.c bcc_elf.c
+ bcc_perf_map.c bcc_proc.c bcc_syms.cc ns_guard.cc)
+add_library(bcc-static STATIC bpf_common.cc bpf_module.cc shared_table.cc
+ bpffs_table.cc json_map_decl_visitor.cc table_storage.cc exported_files.cc
+ usdt_args.cc usdt.cc common.cc BPF.cc BPFTable.cc)
set_target_properties(bcc-static PROPERTIES OUTPUT_NAME bcc)
set(llvm_raw_libs bitwriter bpfcodegen irreader linker
return true;
}
-ProcMountNS::ProcMountNS(int pid) {
- if (pid < 0)
- return;
-
- ebpf::FileDesc self_fd;
- ebpf::FileDesc target_fd;
- char path[256];
- int res;
-
- res = std::snprintf(path, 256, "/proc/self/ns/mnt");
- if (res <= 0 || res >= 256)
- return;
- if ((self_fd = open(path, O_RDONLY)) < 0)
- return;
-
- res = std::snprintf(path, 256, "/proc/%d/ns/mnt", pid);
- if (res <= 0 || res >= 256)
- return;
- if ((target_fd = open(path, O_RDONLY)) < 0)
- return;
-
- struct stat self_stat, target_stat;
- if (fstat(self_fd, &self_stat) != 0)
- return;
- if (fstat(target_fd, &target_stat) != 0)
- return;
-
- if (self_stat.st_ino == target_stat.st_ino)
- // Both current and target Process are in same mount namespace
- return;
-
- self_fd_ = std::move(self_fd);
- target_fd_ = std::move(target_fd);
-}
-
-ProcMountNSGuard::ProcMountNSGuard(ProcMountNS *mount_ns)
- : mount_ns_instance_(nullptr), mount_ns_(mount_ns), entered_(false) {
- init();
-}
-
-ProcMountNSGuard::ProcMountNSGuard(int pid)
- : mount_ns_instance_(pid > 0 ? new ProcMountNS(pid) : nullptr),
- mount_ns_(mount_ns_instance_.get()),
- entered_(false) {
- init();
-}
-
-void ProcMountNSGuard::init() {
- if (!mount_ns_ || mount_ns_->self_fd_ < 0 || mount_ns_->target_fd_ < 0)
- return;
-
- if (setns(mount_ns_->target_fd_, CLONE_NEWNS) == 0)
- entered_ = true;
-}
-
-ProcMountNSGuard::~ProcMountNSGuard() {
- if (mount_ns_ && entered_ && mount_ns_->self_fd_ >= 0)
- setns(mount_ns_->self_fd_, CLONE_NEWNS);
-}
-
ProcSyms::ProcSyms(int pid, struct bcc_symbol_option *option)
: pid_(pid), procstat_(pid), mount_ns_instance_(new ProcMountNS(pid_)) {
if (option)
--- /dev/null
+/*
+ * Copyright (c) 2017 Facebook, Inc.
+ * Copyright (c) 2017 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <string>
+
+#include "ns_guard.h"
+
+ProcMountNS::ProcMountNS(int pid) {
+ if (pid < 0)
+ return;
+
+ std::string target_path = "/proc/" + std::to_string(pid) + "/ns/mnt";
+ ebpf::FileDesc target_fd(open(target_path.c_str(), O_RDONLY));
+ ebpf::FileDesc self_fd(open("/proc/self/ns/mnt", O_RDONLY));
+
+ if (self_fd < 0 || target_fd < 0)
+ return;
+
+ struct stat self_stat, target_stat;
+ if (fstat(self_fd, &self_stat) != 0)
+ return;
+ if (fstat(target_fd, &target_stat) != 0)
+ return;
+
+ if (self_stat.st_ino == target_stat.st_ino)
+ // Both current and target Process are in same mount namespace
+ return;
+
+ self_fd_ = std::move(self_fd);
+ target_fd_ = std::move(target_fd);
+}
+
+ProcMountNSGuard::ProcMountNSGuard(ProcMountNS *mount_ns)
+ : mount_ns_instance_(nullptr), mount_ns_(mount_ns), entered_(false) {
+ init();
+}
+
+ProcMountNSGuard::ProcMountNSGuard(int pid)
+ : mount_ns_instance_(pid > 0 ? new ProcMountNS(pid) : nullptr),
+ mount_ns_(mount_ns_instance_.get()),
+ entered_(false) {
+ init();
+}
+
+void ProcMountNSGuard::init() {
+ if (!mount_ns_ || mount_ns_->self() < 0 || mount_ns_->target() < 0)
+ return;
+
+ if (setns(mount_ns_->target(), CLONE_NEWNS) == 0)
+ entered_ = true;
+}
+
+ProcMountNSGuard::~ProcMountNSGuard() {
+ if (mount_ns_ && entered_ && mount_ns_->self() >= 0)
+ setns(mount_ns_->self(), CLONE_NEWNS);
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Facebook, Inc.
+ * Copyright (c) 2017 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include "file_desc.h"
+
+class ProcMountNSGuard;
+
+// ProcMountNS opens an fd corresponding to the current mount namespace and the
+// mount namespace of the target process.
+// The fds will remain uninitialized (<0) if the open fails, or if the current
+// and target namespaces are identical.
+class ProcMountNS {
+ public:
+ explicit ProcMountNS(int pid);
+ int self() const { return self_fd_; }
+ int target() const { return target_fd_; }
+
+ private:
+ ebpf::FileDesc self_fd_;
+ ebpf::FileDesc target_fd_;
+};
+
+// ProcMountNSGuard switches to the target mount namespace and restores the
+// original upon going out of scope.
+class ProcMountNSGuard {
+ public:
+ explicit ProcMountNSGuard(ProcMountNS *mount_ns);
+ explicit ProcMountNSGuard(int pid);
+
+ ~ProcMountNSGuard();
+
+ private:
+ void init();
+
+ std::unique_ptr<ProcMountNS> mount_ns_instance_;
+ ProcMountNS *mount_ns_;
+ bool entered_;
+};
#include <unordered_set>
#include <vector>
-#include "file_desc.h"
#include "bcc_syms.h"
+#include "file_desc.h"
+#include "ns_guard.h"
class ProcStat {
std::string procfs_;
virtual void refresh();
};
-class ProcMountNSGuard;
-class ProcSyms;
-
-class ProcMountNS {
-private:
- explicit ProcMountNS(int pid);
-
- ebpf::FileDesc self_fd_;
- ebpf::FileDesc target_fd_;
-
- friend class ProcMountNSGuard;
- friend class ProcSyms;
-};
-
-class ProcMountNSGuard {
-public:
- explicit ProcMountNSGuard(ProcMountNS *mount_ns);
- explicit ProcMountNSGuard(int pid);
-
- ~ProcMountNSGuard();
-
-private:
- void init();
-
- std::unique_ptr<ProcMountNS> mount_ns_instance_;
- ProcMountNS *mount_ns_;
- bool entered_;
-};
-
class ProcSyms : SymbolCache {
struct Symbol {
Symbol(const std::string *name, uint64_t start, uint64_t size)