[lttng-dev] [PATCH lttng-modules 3/3] RFC: Add namespaces statedump

Michael Jeanson mjeanson at efficios.com
Thu Mar 1 17:39:10 EST 2018


Add a statedump event for each type of namespace.

The pid ns was already implemented as part of the lttng_statedump_process_state
event, move the "vtid" and "vpid" fields to the new
lttng_statedump_process_pid_ns event.

Signed-off-by: Michael Jeanson <mjeanson at efficios.com>
---
 .../events/lttng-module/lttng-statedump.h          | 137 ++++++++++++++++++---
 lttng-statedump-impl.c                             |  72 ++++++++++-
 wrapper/namespace.h                                |   6 +
 wrapper/user_namespace.h                           |  55 +++++++++
 4 files changed, 250 insertions(+), 20 deletions(-)

diff --git a/instrumentation/events/lttng-module/lttng-statedump.h b/instrumentation/events/lttng-module/lttng-statedump.h
index e7c528d..c315acd 100644
--- a/instrumentation/events/lttng-module/lttng-statedump.h
+++ b/instrumentation/events/lttng-module/lttng-statedump.h
@@ -6,15 +6,22 @@
 
 #include <probes/lttng-tracepoint-event.h>
 #include <linux/nsproxy.h>
+#include <linux/cgroup.h>
+#include <linux/ipc_namespace.h>
+#include <net/net_namespace.h>
 #include <linux/pid_namespace.h>
+#include <linux/user_namespace.h>
+#include <linux/utsname.h>
 #include <linux/types.h>
 #include <linux/version.h>
-
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0))
-#define lttng_proc_inum ns.inum
-#else
-#define lttng_proc_inum proc_inum
+#include <wrapper/namespace.h>
+#include <wrapper/user_namespace.h>
+
+#ifndef LTTNG_MNT_NS_MISSING_HEADER
+# ifndef ONCE_LTTNG_FS_MOUNT_H
+#  define ONCE_LTTNG_FS_MOUNT_H
+#  include <../fs/mount.h>
+# endif
 #endif
 
 LTTNG_TRACEPOINT_EVENT(lttng_statedump_start,
@@ -32,14 +39,11 @@ LTTNG_TRACEPOINT_EVENT(lttng_statedump_end,
 LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_state,
 	TP_PROTO(struct lttng_session *session,
 		struct task_struct *p,
-		int type, int mode, int submode, int status,
-		struct pid_namespace *pid_ns),
-	TP_ARGS(session, p, type, mode, submode, status, pid_ns),
+		int type, int mode, int submode, int status),
+	TP_ARGS(session, p, type, mode, submode, status),
 	TP_FIELDS(
 		ctf_integer(pid_t, tid, p->pid)
-		ctf_integer(pid_t, vtid, pid_ns ? task_pid_nr_ns(p, pid_ns) : 0)
 		ctf_integer(pid_t, pid, p->tgid)
-		ctf_integer(pid_t, vpid, pid_ns ? task_tgid_nr_ns(p, pid_ns) : 0)
 		ctf_integer(pid_t, ppid,
 			({
 				pid_t ret;
@@ -49,6 +53,78 @@ LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_state,
 				rcu_read_unlock();
 				ret;
 			}))
+		ctf_array_text(char, name, p->comm, TASK_COMM_LEN)
+		ctf_integer(int, type, type)
+		ctf_integer(int, mode, mode)
+		ctf_integer(int, submode, submode)
+		ctf_integer(int, status, status)
+		ctf_integer(unsigned int, cpu, task_cpu(p))
+	)
+)
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0))
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_cgroup_ns,
+	TP_PROTO(struct lttng_session *session,
+		struct task_struct *p,
+		struct cgroup_namespace *cgroup_ns),
+	TP_ARGS(session, p, cgroup_ns),
+	TP_FIELDS(
+		ctf_integer(pid_t, tid, p->pid)
+		ctf_integer(unsigned int, ns_inum, cgroup_ns ? cgroup_ns->lttng_ns_inum : 0)
+	)
+)
+#endif
+
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_ipc_ns,
+	TP_PROTO(struct lttng_session *session,
+		struct task_struct *p,
+		struct ipc_namespace *ipc_ns),
+	TP_ARGS(session, p, ipc_ns),
+	TP_FIELDS(
+		ctf_integer(pid_t, tid, p->pid)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+		ctf_integer(unsigned int, ns_inum, ipc_ns ? ipc_ns->lttng_ns_inum : 0)
+#endif
+	)
+)
+
+#if !defined(LTTNG_MNT_NS_MISSING_HEADER)
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_mnt_ns,
+	TP_PROTO(struct lttng_session *session,
+		struct task_struct *p,
+		struct mnt_namespace *mnt_ns),
+	TP_ARGS(session, p, mnt_ns),
+	TP_FIELDS(
+		ctf_integer(pid_t, tid, p->pid)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+		ctf_integer(unsigned int, ns_inum, mnt_ns ? mnt_ns->lttng_ns_inum : 0)
+#endif
+	)
+)
+#endif
+
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_net_ns,
+	TP_PROTO(struct lttng_session *session,
+		struct task_struct *p,
+		struct net *net_ns),
+	TP_ARGS(session, p, net_ns),
+	TP_FIELDS(
+		ctf_integer(pid_t, tid, p->pid)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+		ctf_integer(unsigned int, ns_inum, net_ns ? net_ns->lttng_ns_inum : 0)
+#endif
+	)
+)
+
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_pid_ns,
+	TP_PROTO(struct lttng_session *session,
+		struct task_struct *p,
+		struct pid_namespace *pid_ns),
+	TP_ARGS(session, p, pid_ns),
+	TP_FIELDS(
+		ctf_integer(pid_t, tid, p->pid)
+		ctf_integer(pid_t, vtid, pid_ns ? task_pid_nr_ns(p, pid_ns) : 0)
+		ctf_integer(pid_t, vpid, pid_ns ? task_tgid_nr_ns(p, pid_ns) : 0)
 		ctf_integer(pid_t, vppid,
 			({
 				struct task_struct *parent;
@@ -62,16 +138,41 @@ LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_state,
 				}
 				ret;
 			}))
-		ctf_array_text(char, name, p->comm, TASK_COMM_LEN)
-		ctf_integer(int, type, type)
-		ctf_integer(int, mode, mode)
-		ctf_integer(int, submode, submode)
-		ctf_integer(int, status, status)
 		ctf_integer(int, ns_level, pid_ns ? pid_ns->level : 0)
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
-		ctf_integer(unsigned int, ns_inum, pid_ns ? pid_ns->lttng_proc_inum : 0)
+		ctf_integer(unsigned int, ns_inum, pid_ns ? pid_ns->lttng_ns_inum : 0)
+#endif
+	)
+)
+
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_user_ns,
+	TP_PROTO(struct lttng_session *session,
+		struct task_struct *p,
+		struct user_namespace *user_ns),
+	TP_ARGS(session, p, user_ns),
+	TP_FIELDS(
+		ctf_integer(pid_t, tid, p->pid)
+		ctf_integer(uid_t, vuid, user_ns ? lttng_task_vuid(p, user_ns) : 0)
+		ctf_integer(gid_t, vgid, user_ns ? lttng_task_vgid(p, user_ns) : 0)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0))
+		ctf_integer(int, ns_level, user_ns ? user_ns->level : 0)
+#endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+		ctf_integer(unsigned int, ns_inum, user_ns ? user_ns->lttng_ns_inum : 0)
+#endif
+	)
+)
+
+LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_uts_ns,
+	TP_PROTO(struct lttng_session *session,
+		struct task_struct *p,
+		struct uts_namespace *uts_ns),
+	TP_ARGS(session, p, uts_ns),
+	TP_FIELDS(
+		ctf_integer(pid_t, tid, p->pid)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0))
+		ctf_integer(unsigned int, ns_inum, uts_ns ? uts_ns->lttng_ns_inum : 0)
 #endif
-		ctf_integer(unsigned int, cpu, task_cpu(p))
 	)
 )
 
diff --git a/lttng-statedump-impl.c b/lttng-statedump-impl.c
index 1c09e51..479bc47 100644
--- a/lttng-statedump-impl.c
+++ b/lttng-statedump-impl.c
@@ -52,6 +52,7 @@
 #include <wrapper/irqdesc.h>
 #include <wrapper/spinlock.h>
 #include <wrapper/fdtable.h>
+#include <wrapper/namespace.h>
 #include <wrapper/irq.h>
 #include <wrapper/tracepoint.h>
 #include <wrapper/genhd.h>
@@ -75,6 +76,17 @@ DEFINE_TRACE(lttng_statedump_interrupt);
 DEFINE_TRACE(lttng_statedump_file_descriptor);
 DEFINE_TRACE(lttng_statedump_start);
 DEFINE_TRACE(lttng_statedump_process_state);
+DEFINE_TRACE(lttng_statedump_process_pid_ns);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0))
+DEFINE_TRACE(lttng_statedump_process_cgroup_ns);
+#endif
+DEFINE_TRACE(lttng_statedump_process_ipc_ns);
+#ifndef LTTNG_MNT_NS_MISSING_HEADER
+DEFINE_TRACE(lttng_statedump_process_mnt_ns);
+#endif
+DEFINE_TRACE(lttng_statedump_process_net_ns);
+DEFINE_TRACE(lttng_statedump_process_user_ns);
+DEFINE_TRACE(lttng_statedump_process_uts_ns);
 DEFINE_TRACE(lttng_statedump_network_interface);
 
 struct lttng_fd_ctx {
@@ -381,6 +393,10 @@ int lttng_list_interrupts(struct lttng_session *session)
 #endif
 
 /*
+ * Statedump the task's namespaces using the proc filesystem inode number as
+ * the unique identifier. The user and pid ns are nested and will be dumped
+ * recursively.
+ *
  * Called with task lock held.
  */
 static
@@ -391,14 +407,62 @@ void lttng_statedump_process_ns(struct lttng_session *session,
 		enum lttng_execution_submode submode,
 		enum lttng_process_status status)
 {
+	struct nsproxy *proxy;
 	struct pid_namespace *pid_ns;
+	struct user_namespace *user_ns;
 
+	/*
+	 * The pid and user namespaces are special, they are nested and
+	 * accessed with specific functions instead of the nsproxy struct
+	 * like the other namespaces.
+	 */
 	pid_ns = task_active_pid_ns(p);
 	do {
-		trace_lttng_statedump_process_state(session,
-			p, type, mode, submode, status, pid_ns);
+		trace_lttng_statedump_process_pid_ns(session, p, pid_ns);
 		pid_ns = pid_ns->parent;
 	} while (pid_ns);
+
+
+	user_ns = task_cred_xxx(p, user_ns);
+	do {
+		trace_lttng_statedump_process_user_ns(session, p, user_ns);
+		user_ns = user_ns->lttng_user_ns_parent;
+	} while (user_ns);
+
+	/*
+	 * Back and forth on locking strategy within Linux upstream for nsproxy.
+	 * See Linux upstream commit 728dba3a39c66b3d8ac889ddbe38b5b1c264aec3
+	 * "namespaces: Use task_lock and not rcu to protect nsproxy"
+	 * for details.
+	 */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) || \
+		LTTNG_UBUNTU_KERNEL_RANGE(3,13,11,36, 3,14,0,0) || \
+		LTTNG_UBUNTU_KERNEL_RANGE(3,16,1,11, 3,17,0,0) || \
+		LTTNG_RHEL_KERNEL_RANGE(3,10,0,229,13,0, 3,11,0,0,0,0))
+	proxy = p->nsproxy;
+#else
+	rcu_read_lock();
+	proxy = task_nsproxy(p);
+#endif
+	if (proxy) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0))
+		trace_lttng_statedump_process_cgroup_ns(session, p, proxy->cgroup_ns);
+#endif
+		trace_lttng_statedump_process_ipc_ns(session, p, proxy->ipc_ns);
+#ifndef LTTNG_MNT_NS_MISSING_HEADER
+		trace_lttng_statedump_process_mnt_ns(session, p, proxy->mnt_ns);
+#endif
+		trace_lttng_statedump_process_net_ns(session, p, proxy->net_ns);
+		trace_lttng_statedump_process_uts_ns(session, p, proxy->uts_ns);
+	}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) || \
+		LTTNG_UBUNTU_KERNEL_RANGE(3,13,11,36, 3,14,0,0) || \
+		LTTNG_UBUNTU_KERNEL_RANGE(3,16,1,11, 3,17,0,0) || \
+		LTTNG_RHEL_KERNEL_RANGE(3,10,0,229,13,0, 3,11,0,0,0,0))
+	/* (nothing) */
+#else
+	rcu_read_unlock();
+#endif
 }
 
 static
@@ -450,6 +514,10 @@ int lttng_enumerate_process_states(struct lttng_session *session)
 				type = LTTNG_USER_THREAD;
 			else
 				type = LTTNG_KERNEL_THREAD;
+
+			trace_lttng_statedump_process_state(session,
+				p, type, mode, submode, status);
+
 			lttng_statedump_process_ns(session,
 				p, type, mode, submode, status);
 			task_unlock(p);
diff --git a/wrapper/namespace.h b/wrapper/namespace.h
index 7e82cba..977f14e 100644
--- a/wrapper/namespace.h
+++ b/wrapper/namespace.h
@@ -30,4 +30,10 @@
 #define lttng_ns_inum proc_inum
 #endif
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0))
+#define lttng_user_ns_parent parent
+#else
+#define lttng_user_ns_parent creator->user_ns
+#endif
+
 #endif /* _LTTNG_WRAPPER_NAMESPACE_H */
diff --git a/wrapper/user_namespace.h b/wrapper/user_namespace.h
index f1f4181..f0fa770 100644
--- a/wrapper/user_namespace.h
+++ b/wrapper/user_namespace.h
@@ -39,6 +39,30 @@
 #define lttng_current_vxxgid(xxx)				\
 	(from_kgid_munged(current_user_ns(), current_##xxx()))
 
+static inline
+uid_t lttng_task_vuid(struct task_struct *p, struct user_namespace *ns)
+{
+	uid_t uid;
+	kuid_t kuid;
+
+	kuid = task_cred_xxx(p, uid);
+	uid = from_kuid_munged(ns, kuid);
+
+	return uid;
+}
+
+static inline
+gid_t lttng_task_vgid(struct task_struct *p, struct user_namespace *ns)
+{
+	gid_t gid;
+	kgid_t kgid;
+
+	kgid = task_cred_xxx(p, gid);
+	gid = from_kgid_munged(ns, kgid);
+
+	return gid;
+}
+
 #else
 
 #define lttng_current_xxuid(xxx)	(current_##xxx())
@@ -50,6 +74,37 @@
 
 #define lttng_current_vxxgid(xxx)					\
 	(user_ns_map_gid(current_user_ns(), current_cred(), current_##xxx()))
+
+static inline
+uid_t lttng_task_vuid(struct task_struct *p, struct user_namespace *ns)
+{
+	uid_t uid;
+
+	/*
+	 * __task_cred requires the RCU readlock be held
+	 */
+	rcu_read_lock();
+	uid = user_ns_map_uid(ns, __task_cred(p), __task_cred(p)->uid);
+	rcu_read_unlock();
+
+	return uid;
+}
+
+static inline
+gid_t lttng_task_vgid(struct task_struct *p, struct user_namespace *ns)
+{
+	gid_t gid;
+
+	/*
+	 * __task_cred requires the RCU readlock be held
+	 */
+	rcu_read_lock();
+	gid = user_ns_map_gid(ns, __task_cred(p), __task_cred(p)->gid);
+	rcu_read_unlock();
+
+	return gid;
+}
+
 #endif
 
 #define lttng_current_uid()	(lttng_current_xxuid(uid))
-- 
2.7.4



More information about the lttng-dev mailing list