From 1965e6b461720f6e43ff77d71f1ea086d3da88d9 Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Tue, 12 Feb 2019 09:47:34 -0500 Subject: [PATCH] Add namespaces statedump 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 Signed-off-by: Mathieu Desnoyers --- .../events/lttng-module/lttng-statedump.h | 131 +++++++++++++++++- lttng-statedump-impl.c | 66 +++++++++ wrapper/namespace.h | 6 + wrapper/user_namespace.h | 55 ++++++++ 4 files changed, 253 insertions(+), 5 deletions(-) diff --git a/instrumentation/events/lttng-module/lttng-statedump.h b/instrumentation/events/lttng-module/lttng-statedump.h index 14ec1277..5ce94fa6 100644 --- a/instrumentation/events/lttng-module/lttng-statedump.h +++ b/instrumentation/events/lttng-module/lttng-statedump.h @@ -7,15 +7,22 @@ #include #include +#include +#include +#include #include +#include +#include #include #include +#include +#include - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)) -#define lttng_proc_inum ns.inum -#else -#define lttng_proc_inum proc_inum +#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, @@ -76,6 +83,120 @@ LTTNG_TRACEPOINT_EVENT(lttng_statedump_process_state, ) ) +#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; + pid_t ret = 0; + + if (pid_ns) { + rcu_read_lock(); + parent = rcu_dereference(p->real_parent); + ret = task_tgid_nr_ns(parent, pid_ns); + rcu_read_unlock(); + } + ret; + })) + 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_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 + ) +) + LTTNG_TRACEPOINT_EVENT(lttng_statedump_file_descriptor, TP_PROTO(struct lttng_session *session, struct task_struct *p, int fd, const char *filename, diff --git a/lttng-statedump-impl.c b/lttng-statedump-impl.c index dc037508..a707c775 100644 --- a/lttng-statedump-impl.c +++ b/lttng-statedump-impl.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,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); #ifdef LTTNG_HAVE_STATEDUMP_CPU_TOPOLOGY DEFINE_TRACE(lttng_statedump_cpu_topology); @@ -388,6 +400,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 @@ -398,14 +414,64 @@ 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 diff --git a/wrapper/namespace.h b/wrapper/namespace.h index 36dbf4c0..0e7833e1 100644 --- a/wrapper/namespace.h +++ b/wrapper/namespace.h @@ -18,4 +18,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 701f3189..851674b0 100644 --- a/wrapper/user_namespace.h +++ b/wrapper/user_namespace.h @@ -27,6 +27,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()) @@ -38,6 +62,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.34.1