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 <mjean...@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 _______________________________________________ lttng-dev mailing list lttng-dev@lists.lttng.org https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev